1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 2001-2004 The Apache Software Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.parsers;
  58. import java.io.IOException;
  59. import java.util.Locale;
  60. import com.sun.org.apache.xerces.internal.impl.Constants;
  61. import com.sun.org.apache.xerces.internal.xs.PSVIProvider;
  62. import com.sun.org.apache.xerces.internal.util.EntityResolverWrapper;
  63. import com.sun.org.apache.xerces.internal.util.EntityResolver2Wrapper;
  64. import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper;
  65. import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter;
  66. import com.sun.org.apache.xerces.internal.util.SymbolHash;
  67. import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  68. import com.sun.org.apache.xerces.internal.xni.Augmentations;
  69. import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  70. import com.sun.org.apache.xerces.internal.xni.QName;
  71. import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  72. import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  73. import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  74. import com.sun.org.apache.xerces.internal.xni.XMLString;
  75. import com.sun.org.apache.xerces.internal.xni.XNIException;
  76. import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  77. import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  78. import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
  79. import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  80. import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
  81. import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
  82. import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
  83. import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
  84. import org.xml.sax.AttributeList;
  85. import org.xml.sax.Attributes;
  86. import org.xml.sax.ext.Attributes2;
  87. import org.xml.sax.ContentHandler;
  88. import org.xml.sax.DTDHandler;
  89. import org.xml.sax.DocumentHandler;
  90. import org.xml.sax.EntityResolver;
  91. import org.xml.sax.ErrorHandler;
  92. import org.xml.sax.InputSource;
  93. import org.xml.sax.Locator;
  94. import org.xml.sax.ext.Locator2Impl;
  95. import org.xml.sax.ext.Locator2;
  96. import org.xml.sax.Parser;
  97. import org.xml.sax.SAXException;
  98. import org.xml.sax.SAXNotRecognizedException;
  99. import org.xml.sax.SAXNotSupportedException;
  100. import org.xml.sax.SAXParseException;
  101. import org.xml.sax.XMLReader;
  102. import org.xml.sax.ext.DeclHandler;
  103. import org.xml.sax.ext.EntityResolver2;
  104. import org.xml.sax.ext.LexicalHandler;
  105. import org.xml.sax.helpers.LocatorImpl;
  106. /**
  107. * This is the base class of all SAX parsers. It implements both the
  108. * SAX1 and SAX2 parser functionality, while the actual pipeline is
  109. * defined in the parser configuration.
  110. *
  111. * @author Arnaud Le Hors, IBM
  112. * @author Andy Clark, IBM
  113. *
  114. * @version $Id: AbstractSAXParser.java,v 1.54 2004/04/07 15:42:05 mrglavas Exp $
  115. */
  116. public abstract class AbstractSAXParser
  117. extends AbstractXMLDocumentParser
  118. implements PSVIProvider, // PSVI
  119. Parser, XMLReader // SAX1, SAX2
  120. {
  121. //
  122. // Constants
  123. //
  124. // features
  125. /** Feature identifier: namespaces. */
  126. protected static final String NAMESPACES =
  127. Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
  128. /** Feature identifier: namespace prefixes. */
  129. protected static final String NAMESPACE_PREFIXES =
  130. Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
  131. /** Feature id: string interning. */
  132. protected static final String STRING_INTERNING =
  133. Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
  134. /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
  135. // this is not meant to be a recognized feature, but we need it here to use
  136. // if it is already a recognized feature for the pipeline
  137. protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
  138. Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
  139. /** Recognized features. */
  140. private static final String[] RECOGNIZED_FEATURES = {
  141. NAMESPACES,
  142. NAMESPACE_PREFIXES,
  143. STRING_INTERNING,
  144. };
  145. // properties
  146. /** Property id: lexical handler. */
  147. protected static final String LEXICAL_HANDLER =
  148. Constants.SAX_PROPERTY_PREFIX + Constants.LEXICAL_HANDLER_PROPERTY;
  149. /** Property id: declaration handler. */
  150. protected static final String DECLARATION_HANDLER =
  151. Constants.SAX_PROPERTY_PREFIX + Constants.DECLARATION_HANDLER_PROPERTY;
  152. /** Property id: DOM node. */
  153. protected static final String DOM_NODE =
  154. Constants.SAX_PROPERTY_PREFIX + Constants.DOM_NODE_PROPERTY;
  155. /** Recognized properties. */
  156. private static final String[] RECOGNIZED_PROPERTIES = {
  157. LEXICAL_HANDLER,
  158. DECLARATION_HANDLER,
  159. DOM_NODE,
  160. };
  161. //
  162. // Data
  163. //
  164. // features
  165. /** Namespaces. */
  166. protected boolean fNamespaces;
  167. /** Namespace prefixes. */
  168. protected boolean fNamespacePrefixes = false;
  169. /** Lexical handler parameter entities. */
  170. protected boolean fLexicalHandlerParameterEntities = true;
  171. // parser handlers
  172. /** Content handler. */
  173. protected ContentHandler fContentHandler;
  174. /** Document handler. */
  175. protected DocumentHandler fDocumentHandler;
  176. /** Namespace context */
  177. protected NamespaceContext fNamespaceContext;
  178. /** DTD handler. */
  179. protected org.xml.sax.DTDHandler fDTDHandler;
  180. /** Decl handler. */
  181. protected DeclHandler fDeclHandler;
  182. /** Lexical handler. */
  183. protected LexicalHandler fLexicalHandler;
  184. protected QName fQName = new QName();
  185. protected boolean resolve_dtd_uris = true;
  186. protected boolean startDocumentCalled = false;
  187. protected boolean resolverType = true;
  188. protected boolean locatorType = false;
  189. protected boolean attributeType = true;
  190. protected boolean isStandalone = false;
  191. // state
  192. /**
  193. * True if a parse is in progress. This state is needed because
  194. * some features/properties cannot be set while parsing (e.g.
  195. * validation and namespaces).
  196. */
  197. protected boolean fParseInProgress = false;
  198. // track the version of the document being parsed
  199. protected String fVersion;
  200. // temp vars
  201. private final AttributesProxy fAttributesProxy = new AttributesProxy();
  202. private Augmentations fAugmentations = null;
  203. // temporary buffer for sending normalized values
  204. // REVISIT: what should be the size of the buffer?
  205. private static final int BUFFER_SIZE = 20;
  206. private char[] fCharBuffer = new char[BUFFER_SIZE];
  207. // allows us to keep track of whether an attribute has
  208. // been declared twice, so that we can avoid exposing the
  209. // second declaration to any registered DeclHandler
  210. protected SymbolHash fDeclaredAttrs = null;
  211. //
  212. // Constructors
  213. //
  214. /** Default constructor. */
  215. protected AbstractSAXParser(XMLParserConfiguration config) {
  216. super(config);
  217. config.addRecognizedFeatures(RECOGNIZED_FEATURES);
  218. config.addRecognizedProperties(RECOGNIZED_PROPERTIES);
  219. try {
  220. config.setFeature(ALLOW_UE_AND_NOTATION_EVENTS, false);
  221. }
  222. catch (XMLConfigurationException e) {
  223. // it wasn't a recognized feature, so we don't worry about it
  224. }
  225. } // <init>(XMLParserConfiguration)
  226. //
  227. // XMLDocumentHandler methods
  228. //
  229. /**
  230. * The start of the document.
  231. *
  232. * @param locator The document locator, or null if the document
  233. * location cannot be reported during the parsing
  234. * of this document. However, it is <em>strongly</em>
  235. * recommended that a locator be supplied that can
  236. * at least report the system identifier of the
  237. * document.
  238. * @param encoding The auto-detected IANA encoding name of the entity
  239. * stream. This value will be null in those situations
  240. * where the entity encoding is not auto-detected (e.g.
  241. * internal entities or a document entity that is
  242. * parsed from a java.io.Reader).
  243. * @param namespaceContext
  244. * The namespace context in effect at the
  245. * start of this document.
  246. * This object represents the current context.
  247. * Implementors of this class are responsible
  248. * for copying the namespace bindings from the
  249. * the current context (and its parent contexts)
  250. * if that information is important.
  251. * @param augs Additional information that may include infoset augmentations
  252. *
  253. * @throws XNIException Thrown by handler to signal an error.
  254. */
  255. public void startDocument(XMLLocator locator, String encoding,
  256. NamespaceContext namespaceContext, Augmentations augs)
  257. throws XNIException {
  258. fNamespaceContext = namespaceContext;
  259. startDocumentCalled = true;
  260. try {
  261. // SAX1
  262. if (fDocumentHandler != null) {
  263. if (locator != null) {
  264. fDocumentHandler.setDocumentLocator(new LocatorProxy(locator));
  265. }
  266. fDocumentHandler.startDocument();
  267. }
  268. // SAX2
  269. if (fContentHandler != null) {
  270. if (locator != null) {
  271. locatorType = true;
  272. fContentHandler.setDocumentLocator(new LocatorProxy(locator));
  273. }
  274. fContentHandler.startDocument();
  275. }
  276. }
  277. catch (SAXException e) {
  278. throw new XNIException(e);
  279. }
  280. } // startDocument(locator,encoding,augs)
  281. /**
  282. * Notifies of the presence of an XMLDecl line in the document. If
  283. * present, this method will be called immediately following the
  284. * startDocument call.
  285. *
  286. * @param version The XML version.
  287. * @param encoding The IANA encoding name of the document, or null if
  288. * not specified.
  289. * @param standalone The standalone value, or null if not specified.
  290. * @param augs Additional information that may include infoset augmentations
  291. *
  292. * @throws XNIException Thrown by handler to signal an error.
  293. */
  294. public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
  295. throws XNIException {
  296. // the version need only be set once; if
  297. // document's XML 1.0|1.1, that's how it'll stay
  298. fVersion = version;
  299. if(standalone != null && standalone.equalsIgnoreCase("yes"))
  300. isStandalone = true;
  301. else
  302. isStandalone = false;
  303. } // xmlDecl(String,String,String)
  304. /**
  305. * Notifies of the presence of the DOCTYPE line in the document.
  306. *
  307. * @param rootElement The name of the root element.
  308. * @param publicId The public identifier if an external DTD or null
  309. * if the external DTD is specified using SYSTEM.
  310. * @param systemId The system identifier if an external DTD, null
  311. * otherwise.
  312. * @param augs Additional information that may include infoset augmentations
  313. *
  314. * @throws XNIException Thrown by handler to signal an error.
  315. */
  316. public void doctypeDecl(String rootElement,
  317. String publicId, String systemId, Augmentations augs)
  318. throws XNIException {
  319. fInDTD = true;
  320. try {
  321. // SAX2 extension
  322. if (fLexicalHandler != null) {
  323. fLexicalHandler.startDTD(rootElement, publicId, systemId);
  324. }
  325. }
  326. catch (SAXException e) {
  327. throw new XNIException(e);
  328. }
  329. // is there a DeclHandler?
  330. if(fDeclHandler != null) {
  331. fDeclaredAttrs = new SymbolHash();
  332. }
  333. } // doctypeDecl(String,String,String)
  334. /**
  335. * This method notifies of the start of an entity. The DTD has the
  336. * pseudo-name of "[dtd]" parameter entity names start with '%'; and
  337. * general entity names are just the entity name.
  338. * <p>
  339. * <strong>Note:</strong> Since the document is an entity, the handler
  340. * will be notified of the start of the document entity by calling the
  341. * startEntity method with the entity name "[xml]" <em>before</em> calling
  342. * the startDocument method. When exposing entity boundaries through the
  343. * SAX API, the document entity is never reported, however.
  344. * <p>
  345. * <strong>Note:</strong> This method is not called for entity references
  346. * appearing as part of attribute values.
  347. *
  348. * @param name The name of the entity.
  349. * @param identifier The resource identifier.
  350. * @param encoding The auto-detected IANA encoding name of the entity
  351. * stream. This value will be null in those situations
  352. * where the entity encoding is not auto-detected (e.g.
  353. * internal parameter entities).
  354. * @param augs Additional information that may include infoset augmentations
  355. *
  356. * @throws XNIException Thrown by handler to signal an error.
  357. */
  358. public void startGeneralEntity(String name, XMLResourceIdentifier identifier,
  359. String encoding, Augmentations augs)
  360. throws XNIException {
  361. try {
  362. // Only report startEntity if this entity was actually read.
  363. if (augs != null && Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
  364. // report skipped entity to content handler
  365. if (fContentHandler != null) {
  366. fContentHandler.skippedEntity(name);
  367. }
  368. }
  369. else {
  370. // SAX2 extension
  371. if (fLexicalHandler != null) {
  372. fLexicalHandler.startEntity(name);
  373. }
  374. }
  375. }
  376. catch (SAXException e) {
  377. throw new XNIException(e);
  378. }
  379. } // startGeneralEntity(String,String,String,String,String)
  380. /**
  381. * This method notifies the end of an entity. The DTD has the pseudo-name
  382. * of "[dtd]" parameter entity names start with '%'; and general entity
  383. * names are just the entity name.
  384. * <p>
  385. * <strong>Note:</strong> Since the document is an entity, the handler
  386. * will be notified of the end of the document entity by calling the
  387. * endEntity method with the entity name "[xml]" <em>after</em> calling
  388. * the endDocument method. When exposing entity boundaries through the
  389. * SAX API, the document entity is never reported, however.
  390. * <p>
  391. * <strong>Note:</strong> This method is not called for entity references
  392. * appearing as part of attribute values.
  393. *
  394. * @param name The name of the entity.
  395. * @param augs Additional information that may include infoset augmentations
  396. *
  397. * @throws XNIException Thrown by handler to signal an error.
  398. */
  399. public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
  400. try {
  401. // Only report endEntity if this entity was actually read.
  402. if (augs == null || !Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
  403. // SAX2 extension
  404. if (fLexicalHandler != null) {
  405. fLexicalHandler.endEntity(name);
  406. }
  407. }
  408. }
  409. catch (SAXException e) {
  410. throw new XNIException(e);
  411. }
  412. } // endEntity(String)
  413. /**
  414. * The start of an element. If the document specifies the start element
  415. * by using an empty tag, then the startElement method will immediately
  416. * be followed by the endElement method, with no intervening methods.
  417. *
  418. * @param element The name of the element.
  419. * @param attributes The element attributes.
  420. * @param augs Additional information that may include infoset augmentations
  421. *
  422. * @throws XNIException Thrown by handler to signal an error.
  423. */
  424. public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
  425. throws XNIException {
  426. try {
  427. // SAX1
  428. if (fDocumentHandler != null) {
  429. // REVISIT: should we support schema-normalized-value for SAX1 events
  430. //
  431. fAttributesProxy.setAttributes(attributes);
  432. fDocumentHandler.startElement(element.rawname, fAttributesProxy);
  433. }
  434. // SAX2
  435. if (fContentHandler != null) {
  436. if (fNamespaces) {
  437. // send prefix mapping events
  438. startNamespaceMapping();
  439. // REVISIT: It should not be necessary to iterate over the attribute
  440. // list when the set of [namespace attributes] is empty for this
  441. // element. This should be computable from the NamespaceContext, but
  442. // since we currently don't report the mappings for the xml prefix
  443. // we cannot use the declared prefix count for the current context
  444. // to skip this section. -- mrglavas
  445. int len = attributes.getLength();
  446. for (int i = len - 1; i >= 0; --i) {
  447. attributes.getName(i, fQName);
  448. if ((fQName.prefix == XMLSymbols.PREFIX_XMLNS) ||
  449. (fQName.rawname == XMLSymbols.PREFIX_XMLNS)) {
  450. if (!fNamespacePrefixes) {
  451. // remove namespace declaration attributes
  452. attributes.removeAttributeAt(i);
  453. }
  454. else {
  455. // localpart should be empty string as per SAX documentation:
  456. // http://www.saxproject.org/?selected=namespaces
  457. fQName.prefix = "";
  458. fQName.uri = "";
  459. fQName.localpart = "";
  460. attributes.setName(i, fQName);
  461. }
  462. }
  463. }
  464. }
  465. fAugmentations = augs;
  466. String uri = element.uri != null ? element.uri : "";
  467. String localpart = fNamespaces ? element.localpart : "";
  468. fAttributesProxy.setAttributes(attributes);
  469. fContentHandler.startElement(uri, localpart, element.rawname,
  470. fAttributesProxy);
  471. }
  472. }
  473. catch (SAXException e) {
  474. throw new XNIException(e);
  475. }
  476. } // startElement(QName,XMLAttributes)
  477. /**
  478. * Character content.
  479. *
  480. * @param text The content.
  481. * @param augs Additional information that may include infoset augmentations
  482. *
  483. * @throws XNIException Thrown by handler to signal an error.
  484. */
  485. public void characters(XMLString text, Augmentations augs) throws XNIException {
  486. // if type is union (XML Schema) it is possible that we receive
  487. // character call with empty data
  488. if (text.length == 0) {
  489. return;
  490. }
  491. try {
  492. // SAX1
  493. if (fDocumentHandler != null) {
  494. // REVISIT: should we support schema-normalized-value for SAX1 events
  495. //
  496. fDocumentHandler.characters(text.ch, text.offset, text.length);
  497. }
  498. // SAX2
  499. if (fContentHandler != null) {
  500. fContentHandler.characters(text.ch, text.offset, text.length);
  501. }
  502. }
  503. catch (SAXException e) {
  504. throw new XNIException(e);
  505. }
  506. } // characters(XMLString)
  507. /**
  508. * Ignorable whitespace. For this method to be called, the document
  509. * source must have some way of determining that the text containing
  510. * only whitespace characters should be considered ignorable. For
  511. * example, the validator can determine if a length of whitespace
  512. * characters in the document are ignorable based on the element
  513. * content model.
  514. *
  515. * @param text The ignorable whitespace.
  516. * @param augs Additional information that may include infoset augmentations
  517. *
  518. * @throws XNIException Thrown by handler to signal an error.
  519. */
  520. public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
  521. try {
  522. // SAX1
  523. if (fDocumentHandler != null) {
  524. fDocumentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
  525. }
  526. // SAX2
  527. if (fContentHandler != null) {
  528. fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
  529. }
  530. }
  531. catch (SAXException e) {
  532. throw new XNIException(e);
  533. }
  534. } // ignorableWhitespace(XMLString)
  535. /**
  536. * The end of an element.
  537. *
  538. * @param element The name of the element.
  539. * @param augs Additional information that may include infoset augmentations
  540. *
  541. * @throws XNIException Thrown by handler to signal an error.
  542. */
  543. public void endElement(QName element, Augmentations augs) throws XNIException {
  544. try {
  545. // SAX1
  546. if (fDocumentHandler != null) {
  547. fDocumentHandler.endElement(element.rawname);
  548. }
  549. // SAX2
  550. if (fContentHandler != null) {
  551. fAugmentations = augs;
  552. String uri = element.uri != null ? element.uri : "";
  553. String localpart = fNamespaces ? element.localpart : "";
  554. fContentHandler.endElement(uri, localpart,
  555. element.rawname);
  556. if (fNamespaces) {
  557. endNamespaceMapping();
  558. }
  559. }
  560. }
  561. catch (SAXException e) {
  562. throw new XNIException(e);
  563. }
  564. } // endElement(QName)
  565. /**
  566. * The start of a CDATA section.
  567. * @param augs Additional information that may include infoset augmentations
  568. *
  569. * @throws XNIException Thrown by handler to signal an error.
  570. */
  571. public void startCDATA(Augmentations augs) throws XNIException {
  572. try {
  573. // SAX2 extension
  574. if (fLexicalHandler != null) {
  575. fLexicalHandler.startCDATA();
  576. }
  577. }
  578. catch (SAXException e) {
  579. throw new XNIException(e);
  580. }
  581. } // startCDATA()
  582. /**
  583. * The end of a CDATA section.
  584. * @param augs Additional information that may include infoset augmentations
  585. *
  586. * @throws XNIException Thrown by handler to signal an error.
  587. */
  588. public void endCDATA(Augmentations augs) throws XNIException {
  589. try {
  590. // SAX2 extension
  591. if (fLexicalHandler != null) {
  592. fLexicalHandler.endCDATA();
  593. }
  594. }
  595. catch (SAXException e) {
  596. throw new XNIException(e);
  597. }
  598. } // endCDATA()
  599. /**
  600. * A comment.
  601. *
  602. * @param text The text in the comment.
  603. * @param augs Additional information that may include infoset augmentations
  604. *
  605. * @throws XNIException Thrown by application to signal an error.
  606. */
  607. public void comment(XMLString text, Augmentations augs) throws XNIException {
  608. try {
  609. // SAX2 extension
  610. if (fLexicalHandler != null) {
  611. fLexicalHandler.comment(text.ch, 0, text.length);
  612. }
  613. }
  614. catch (SAXException e) {
  615. throw new XNIException(e);
  616. }
  617. } // comment(XMLString)
  618. /**
  619. * A processing instruction. Processing instructions consist of a
  620. * target name and, optionally, text data. The data is only meaningful
  621. * to the application.
  622. * <p>
  623. * Typically, a processing instruction's data will contain a series
  624. * of pseudo-attributes. These pseudo-attributes follow the form of
  625. * element attributes but are <strong>not</strong> parsed or presented
  626. * to the application as anything other than text. The application is
  627. * responsible for parsing the data.
  628. *
  629. * @param target The target.
  630. * @param data The data or null if none specified.
  631. * @param augs Additional information that may include infoset augmentations
  632. *
  633. * @throws XNIException Thrown by handler to signal an error.
  634. */
  635. public void processingInstruction(String target, XMLString data, Augmentations augs)
  636. throws XNIException {
  637. //
  638. // REVISIT - I keep running into SAX apps that expect
  639. // null data to be an empty string, which is contrary
  640. // to the comment for this method in the SAX API.
  641. //
  642. try {
  643. // SAX1
  644. if (fDocumentHandler != null) {
  645. fDocumentHandler.processingInstruction(target,
  646. data.toString());
  647. }
  648. // SAX2
  649. if (fContentHandler != null) {
  650. fContentHandler.processingInstruction(target, data.toString());
  651. }
  652. }
  653. catch (SAXException e) {
  654. throw new XNIException(e);
  655. }
  656. } // processingInstruction(String,XMLString)
  657. /**
  658. * The end of the document.
  659. * @param augs Additional information that may include infoset augmentations
  660. *
  661. * @throws XNIException Thrown by handler to signal an error.
  662. */
  663. public void endDocument(Augmentations augs) throws XNIException {
  664. try {
  665. // SAX1
  666. if (fDocumentHandler != null) {
  667. fDocumentHandler.endDocument();
  668. }
  669. // SAX2
  670. if (fContentHandler != null) {
  671. fContentHandler.endDocument();
  672. }
  673. }
  674. catch (SAXException e) {
  675. throw new XNIException(e);
  676. }
  677. } // endDocument()
  678. //
  679. // XMLDTDHandler methods
  680. //
  681. /**
  682. * The start of the DTD external subset.
  683. *
  684. * @param augs Additional information that may include infoset
  685. * augmentations.
  686. *
  687. * @throws XNIException Thrown by handler to signal an error.
  688. */
  689. public void startExternalSubset(XMLResourceIdentifier identifier,
  690. Augmentations augs) throws XNIException {
  691. startParameterEntity("[dtd]", null, null, augs);
  692. }
  693. /**
  694. * The end of the DTD external subset.
  695. *
  696. * @param augs Additional information that may include infoset
  697. * augmentations.
  698. *
  699. * @throws XNIException Thrown by handler to signal an error.
  700. */
  701. public void endExternalSubset(Augmentations augs) throws XNIException {
  702. endParameterEntity("[dtd]", augs);
  703. }
  704. /**
  705. * This method notifies of the start of parameter entity. The DTD has the
  706. * pseudo-name of "[dtd]" parameter entity names start with '%'; and
  707. * general entity names are just the entity name.
  708. * <p>
  709. * <strong>Note:</strong> Since the document is an entity, the handler
  710. * will be notified of the start of the document entity by calling the
  711. * startEntity method with the entity name "[xml]" <em>before</em> calling
  712. * the startDocument method. When exposing entity boundaries through the
  713. * SAX API, the document entity is never reported, however.
  714. * <p>
  715. * <strong>Note:</strong> This method is not called for entity references
  716. * appearing as part of attribute values.
  717. *
  718. * @param name The name of the parameter entity.
  719. * @param identifier The resource identifier.
  720. * @param encoding The auto-detected IANA encoding name of the entity
  721. * stream. This value will be null in those situations
  722. * where the entity encoding is not auto-detected (e.g.
  723. * internal parameter entities).
  724. * @param augs Additional information that may include infoset
  725. * augmentations.
  726. *
  727. * @throws XNIException Thrown by handler to signal an error.
  728. */
  729. public void startParameterEntity(String name,
  730. XMLResourceIdentifier identifier,
  731. String encoding, Augmentations augs)
  732. throws XNIException {
  733. try {
  734. // Only report startEntity if this entity was actually read.
  735. if (augs != null && Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
  736. // report skipped entity to content handler
  737. if (fContentHandler != null) {
  738. fContentHandler.skippedEntity(name);
  739. }
  740. }
  741. else {
  742. // SAX2 extension
  743. if (fLexicalHandler != null && fLexicalHandlerParameterEntities) {
  744. fLexicalHandler.startEntity(name);
  745. }
  746. }
  747. }
  748. catch (SAXException e) {
  749. throw new XNIException(e);
  750. }
  751. } // startParameterEntity(String,identifier,String,Augmentation)
  752. /**
  753. * This method notifies the end of an entity. The DTD has the pseudo-name
  754. * of "[dtd]" parameter entity names start with '%'; and general entity
  755. * names are just the entity name.
  756. * <p>
  757. * <strong>Note:</strong> Since the document is an entity, the handler
  758. * will be notified of the end of the document entity by calling the
  759. * endEntity method with the entity name "[xml]" <em>after</em> calling
  760. * the endDocument method. When exposing entity boundaries through the
  761. * SAX API, the document entity is never reported, however.
  762. * <p>
  763. * <strong>Note:</strong> This method is not called for entity references
  764. * appearing as part of attribute values.
  765. *
  766. * @param name The name of the parameter entity.
  767. * @param augs Additional information that may include infoset
  768. * augmentations.
  769. *
  770. * @throws XNIException Thrown by handler to signal an error.
  771. */
  772. public void endParameterEntity(String name, Augmentations augs) throws XNIException {
  773. try {
  774. // Only report endEntity if this entity was actually read.
  775. if (augs == null || !Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
  776. // SAX2 extension
  777. if (fLexicalHandler != null && fLexicalHandlerParameterEntities) {
  778. fLexicalHandler.endEntity(name);
  779. }
  780. }
  781. }
  782. catch (SAXException e) {
  783. throw new XNIException(e);
  784. }
  785. } // endEntity(String)
  786. /**
  787. * An element declaration.
  788. *
  789. * @param name The name of the element.
  790. * @param contentModel The element content model.
  791. *
  792. * @param augs Additional information that may include infoset
  793. * augmentations.
  794. *
  795. * @throws XNIException Thrown by handler to signal an error.
  796. */
  797. public void elementDecl(String name, String contentModel, Augmentations augs)
  798. throws XNIException {
  799. try {
  800. // SAX2 extension
  801. if (fDeclHandler != null) {
  802. fDeclHandler.elementDecl(name, contentModel);
  803. }
  804. }
  805. catch (SAXException e) {
  806. throw new XNIException(e);
  807. }
  808. } // elementDecl(String,String, Augmentations)
  809. /**
  810. * An attribute declaration.
  811. *
  812. * @param elementName The name of the element that this attribute
  813. * is associated with.
  814. * @param attributeName The name of the attribute.
  815. * @param type The attribute type. This value will be one of
  816. * the following: "CDATA", "ENTITY", "ENTITIES",
  817. * "ENUMERATION", "ID", "IDREF", "IDREFS",
  818. * "NMTOKEN", "NMTOKENS", or "NOTATION".
  819. * @param enumeration If the type has the value "ENUMERATION" or
  820. * "NOTATION", this array holds the allowed attribute
  821. * values; otherwise, this array is null.
  822. * @param defaultType The attribute default type. This value will be
  823. * one of the following: "#FIXED", "#IMPLIED",
  824. * "#REQUIRED", or null.
  825. * @param defaultValue The attribute default value, or null if no
  826. * default value is specified.
  827. *
  828. * @param nonNormalizedDefaultValue The attribute default value with no normalization
  829. * performed, or null if no default value is specified.
  830. * @param augs Additional information that may include infoset
  831. * augmentations.
  832. *
  833. * @throws XNIException Thrown by handler to signal an error.
  834. */
  835. public void attributeDecl(String elementName, String attributeName,
  836. String type, String[] enumeration,
  837. String defaultType, XMLString defaultValue,
  838. XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
  839. try {
  840. // SAX2 extension
  841. if (fDeclHandler != null) {
  842. // used as a key to detect duplicate attribute definitions.
  843. String elemAttr = new StringBuffer(elementName).append("<").append(attributeName).toString();
  844. if(fDeclaredAttrs.get(elemAttr) != null) {
  845. // we aren't permitted to return duplicate attribute definitions
  846. return;
  847. }
  848. fDeclaredAttrs.put(elemAttr, Boolean.TRUE);
  849. if (type.equals("NOTATION") ||
  850. type.equals("ENUMERATION")) {
  851. StringBuffer str = new StringBuffer();
  852. if (type.equals("NOTATION")) {
  853. str.append(type);
  854. str.append(" (");
  855. }
  856. else {
  857. str.append("(");
  858. }
  859. for (int i = 0; i < enumeration.length; i++) {
  860. str.append(enumeration[i]);
  861. if (i < enumeration.length - 1) {
  862. str.append('|');
  863. }
  864. }
  865. str.append(')');
  866. type = str.toString();
  867. }
  868. String value = (defaultValue==null) ? null : defaultValue.toString();
  869. fDeclHandler.attributeDecl(elementName, attributeName,
  870. type, defaultType, value);
  871. }
  872. }
  873. catch (SAXException e) {
  874. throw new XNIException(e);
  875. }
  876. } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
  877. /**
  878. * An internal entity declaration.
  879. *
  880. * @param name The name of the entity. Parameter entity names start with
  881. * '%', whereas the name of a general entity is just the
  882. * entity name.
  883. * @param text The value of the entity.
  884. * @param nonNormalizedText The non-normalized value of the entity. This
  885. * value contains the same sequence of characters that was in
  886. * the internal entity declaration, without any entity
  887. * references expanded.
  888. *
  889. * @param augs Additional information that may include infoset
  890. * augmentations.
  891. *
  892. * @throws XNIException Thrown by handler to signal an error.
  893. */
  894. public void internalEntityDecl(String name, XMLString text,
  895. XMLString nonNormalizedText,
  896. Augmentations augs) throws XNIException {
  897. try {
  898. // SAX2 extensions
  899. if (fDeclHandler != null) {
  900. fDeclHandler.internalEntityDecl(name, text.toString());
  901. }
  902. }
  903. catch (SAXException e) {
  904. throw new XNIException(e);
  905. }
  906. } // internalEntityDecl(String,XMLString,XMLString)
  907. /**
  908. * An external entity declaration.
  909. *
  910. * @param name The name of the entity. Parameter entity names start
  911. * with '%', whereas the name of a general entity is just
  912. * the entity name.
  913. * @param identifier An object containing all location information
  914. * pertinent to this entity.
  915. * @param augs Additional information that may include infoset
  916. * augmentations.
  917. *
  918. * @throws XNIException Thrown by handler to signal an error.
  919. */
  920. public void externalEntityDecl(String name, XMLResourceIdentifier identifier,
  921. Augmentations augs) throws XNIException {
  922. String publicId = identifier.getPublicId();
  923. String literalSystemId = identifier.getLiteralSystemId();
  924. String expandedSystemId = identifier.getExpandedSystemId();
  925. try {
  926. // SAX2 extension
  927. if (fDeclHandler != null) {
  928. fDeclHandler.externalEntityDecl(name, publicId, ((resolve_dtd_uris) ? expandedSystemId : literalSystemId));
  929. }
  930. }
  931. catch (SAXException e) {
  932. throw new XNIException(e);
  933. }
  934. } // externalEntityDecl(String,,XMLResourceIdentifier, Augmentations)
  935. /**
  936. * An unparsed entity declaration.
  937. *
  938. * @param name The name of the entity.
  939. * @param identifier An object containing all location information
  940. * pertinent to this entity.
  941. * @param notation The name of the notation.
  942. *
  943. * @param augs Additional information that may include infoset
  944. * augmentations.
  945. *
  946. * @throws XNIException Thrown by handler to signal an error.
  947. */
  948. public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier,
  949. String notation,
  950. Augmentations augs) throws XNIException {
  951. String publicId = identifier.getPublicId();
  952. String expandedSystemId = identifier.getExpandedSystemId();
  953. String literalSystemId = identifier.getLiteralSystemId();
  954. try {
  955. // SAX2 extension
  956. if (fDTDHandler != null) {
  957. fDTDHandler.unparsedEntityDecl(name, publicId,
  958. ((resolve_dtd_uris) ? expandedSystemId : literalSystemId), notation);
  959. }
  960. }
  961. catch (SAXException e) {
  962. throw new XNIException(e);
  963. }
  964. } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
  965. /**
  966. * A notation declaration
  967. *
  968. * @param name The name of the notation.
  969. * @param identifier An object containing all location information
  970. * pertinent to this notation.
  971. * @param augs Additional information that may include infoset
  972. * augmentations.
  973. *
  974. * @throws XNIException Thrown by handler to signal an error.
  975. */
  976. public void notationDecl(String name, XMLResourceIdentifier identifier,
  977. Augmentations augs) throws XNIException {
  978. String publicId = identifier.getPublicId();
  979. String expandedSystemId = identifier.getExpandedSystemId();
  980. String literalSystemId = identifier.getLiteralSystemId();
  981. try {
  982. // SAX1 and SAX2
  983. if (fDTDHandler != null) {
  984. fDTDHandler.notationDecl(name, publicId, ((resolve_dtd_uris) ? expandedSystemId : literalSystemId));
  985. }
  986. }
  987. catch (SAXException e) {
  988. throw new XNIException(e);
  989. }
  990. } // notationDecl(String,XMLResourceIdentifier, Augmentations)
  991. /**
  992. * The end of the DTD.
  993. *
  994. * @param augs Additional information that may include infoset
  995. * augmentations.
  996. *
  997. * @throws XNIException Thrown by handler to signal an error.
  998. */
  999. public void endDTD(Augmentations augs) throws XNIException {
  1000. fInDTD = false;
  1001. try {
  1002. // SAX2 extension
  1003. if (fLexicalHandler != null) {
  1004. fLexicalHandler.endDTD();
  1005. }
  1006. }
  1007. catch (SAXException e) {
  1008. throw new XNIException(e);
  1009. }
  1010. if(fDeclaredAttrs != null) {
  1011. // help out the GC
  1012. fDeclaredAttrs.clear();
  1013. }
  1014. } // endDTD()
  1015. //
  1016. // Parser and XMLReader methods
  1017. //
  1018. /**
  1019. * Parses the input source specified by the given system identifier.
  1020. * <p>
  1021. * This method is equivalent to the following:
  1022. * <pre>
  1023. * parse(new InputSource(systemId));
  1024. * </pre>
  1025. *
  1026. * @param systemId The system identifier (URI).
  1027. *
  1028. * @exception org.xml.sax.SAXException Throws exception on SAX error.
  1029. * @exception java.io.IOException Throws exception on i/o error.
  1030. */
  1031. public void parse(String systemId) throws SAXException, IOException {
  1032. // parse document
  1033. XMLInputSource source = new XMLInputSource(null, systemId, null);
  1034. try {
  1035. parse(source);
  1036. }
  1037. // wrap XNI exceptions as SAX exceptions
  1038. catch (XMLParseException e) {
  1039. Exception ex = e.getException();
  1040. if (ex == null) {
  1041. // must be a parser exception; mine it for locator info and throw
  1042. // a SAXParseException
  1043. locatorType = true;
  1044. LocatorImpl locatorImpl = new LocatorImpl(){
  1045. public String getXMLVersion() {
  1046. return fVersion;
  1047. }
  1048. // since XMLParseExceptions know nothing about encoding,
  1049. // we cannot return anything meaningful in this context.
  1050. // We *could* consult the LocatorProxy, but the
  1051. // application can do this itself if it wishes to possibly
  1052. // be mislead.
  1053. public String getEncoding() {
  1054. return null;
  1055. }
  1056. };
  1057. locatorImpl.setPublicId(e.getPublicId());
  1058. locatorImpl.setSystemId(e.getExpandedSystemId());
  1059. locatorImpl.setLineNumber(e.getLineNumber());
  1060. locatorImpl.setColumnNumber(e.getColumnNumber());
  1061. throw new SAXParseException(e.getMessage(), locatorImpl);
  1062. }
  1063. if (ex instanceof SAXException) {
  1064. // why did we create an XMLParseException?
  1065. throw (SAXException)ex;
  1066. }
  1067. if (ex instanceof IOException) {
  1068. throw (IOException)ex;
  1069. }
  1070. throw new SAXException(ex);
  1071. }
  1072. catch (XNIException e) {
  1073. Exception ex = e.getException();
  1074. if (ex == null) {
  1075. throw new SAXException(e.getMessage());
  1076. }
  1077. if (ex instanceof SAXException) {
  1078. throw (SAXException)ex;
  1079. }
  1080. if (ex instanceof IOException) {
  1081. throw (IOException)ex;
  1082. }
  1083. throw new SAXException(ex);
  1084. }
  1085. } // parse(String)
  1086. /**
  1087. * parse
  1088. *
  1089. * @param inputSource
  1090. *
  1091. * @exception org.xml.sax.SAXException
  1092. * @exception java.io.IOException
  1093. */
  1094. public void parse(InputSource inputSource)
  1095. throws SAXException, IOException {
  1096. // parse document
  1097. try {
  1098. XMLInputSource xmlInputSource =
  1099. new XMLInputSource(inputSource.getPublicId(),
  1100. inputSource.getSystemId(),
  1101. null);
  1102. xmlInputSource.setByteStream(inputSource.getByteStream());
  1103. xmlInputSource.setCharacterStream(inputSource.getCharacterStream());
  1104. xmlInputSource.setEncoding(inputSource.getEncoding());
  1105. parse(xmlInputSource);
  1106. }
  1107. // wrap XNI exceptions as SAX exceptions
  1108. catch (XMLParseException e) {
  1109. Exception ex = e.getException();
  1110. if (ex == null) {
  1111. // must be a parser exception; mine it for locator info and throw
  1112. // a SAXParseException
  1113. locatorType = true;
  1114. LocatorImpl locatorImpl = new LocatorImpl() {
  1115. public String getXMLVersion() {
  1116. return fVersion;
  1117. }
  1118. // since XMLParseExceptions know nothing about encoding,
  1119. // we cannot return anything meaningful in this context.
  1120. // We *could* consult the LocatorProxy, but the
  1121. // application can do this itself if it wishes to possibly
  1122. // be mislead.
  1123. public String getEncoding() {
  1124. return null;
  1125. }
  1126. };
  1127. locatorImpl.setPublicId(e.getPublicId());
  1128. locatorImpl.setSystemId(e.getExpandedSystemId());
  1129. locatorImpl.setLineNumber(e.getLineNumber());
  1130. locatorImpl.setColumnNumber(e.getColumnNumber());
  1131. throw new SAXParseException(e.getMessage(), locatorImpl);
  1132. }
  1133. if (ex instanceof SAXException) {
  1134. // why did we create an XMLParseException?
  1135. throw (SAXException)ex;
  1136. }
  1137. if (ex instanceof IOException) {
  1138. throw (IOException)ex;
  1139. }
  1140. throw new SAXException(ex);
  1141. }
  1142. catch (XNIException e) {
  1143. Exception ex = e.getException();
  1144. if (ex == null) {
  1145. throw new SAXException(e.getMessage());
  1146. }
  1147. if (ex instanceof SAXException) {
  1148. throw (SAXException)ex;
  1149. }
  1150. if (ex instanceof IOException) {
  1151. throw (IOException)ex;
  1152. }
  1153. throw new SAXException(ex);
  1154. }
  1155. } // parse(InputSource)
  1156. /**
  1157. * Sets the resolver used to resolve external entities. The EntityResolver
  1158. * interface supports resolution of public and system identifiers.
  1159. *
  1160. * @param resolver The new entity resolver. Passing a null value will
  1161. * uninstall the currently installed resolver.
  1162. */
  1163. public void setEntityResolver(EntityResolver resolver) {
  1164. try {
  1165. if(resolver instanceof EntityResolver2){
  1166. resolverType = true;
  1167. fConfiguration.setProperty(ENTITY_RESOLVER, new EntityResolver2Wrapper((EntityResolver2)resolver));
  1168. }else
  1169. fConfiguration.setProperty(ENTITY_RESOLVER, new EntityResolverWrapper(resolver));
  1170. }
  1171. catch (XMLConfigurationException e) {
  1172. // do nothing
  1173. }
  1174. } // setEntityResolver(EntityResolver)
  1175. /**
  1176. * Return the current entity resolver.
  1177. *
  1178. * @return The current entity resolver, or null if none
  1179. * has been registered.
  1180. * @see #setEntityResolver
  1181. */
  1182. public EntityResolver getEntityResolver() {
  1183. EntityResolver entityResolver = null;
  1184. try {
  1185. XMLEntityResolver xmlEntityResolver =
  1186. (XMLEntityResolver)fConfiguration.getProperty(ENTITY_RESOLVER);
  1187. if (xmlEntityResolver != null){
  1188. if( xmlEntityResolver instanceof EntityResolverWrapper) {
  1189. entityResolver = ((EntityResolverWrapper)xmlEntityResolver).getEntityResolver();
  1190. }else if(xmlEntityResolver instanceof EntityResolver2Wrapper){
  1191. entityResolver = ((EntityResolver2Wrapper)xmlEntityResolver).getEntityResolver();
  1192. }
  1193. }
  1194. }catch (XMLConfigurationException e) {
  1195. // do nothing
  1196. }
  1197. return entityResolver;
  1198. } // getEntityResolver():EntityResolver
  1199. /**
  1200. * Allow an application to register an error event handler.
  1201. *
  1202. * <p>If the application does not register an error handler, all
  1203. * error events reported by the SAX parser will be silently
  1204. * ignored; however, normal processing may not continue. It is
  1205. * highly recommended that all SAX applications implement an
  1206. * error handler to avoid unexpected bugs.</p>
  1207. *
  1208. * <p>Applications may register a new or different handler in the
  1209. * middle of a parse, and the SAX parser must begin using the new
  1210. * handler immediately.</p>
  1211. *
  1212. * @param errorHandler The error handler.
  1213. * @see #getErrorHandler
  1214. */
  1215. public void setErrorHandler(ErrorHandler errorHandler) {
  1216. try {
  1217. fConfiguration.setProperty(ERROR_HANDLER,
  1218. new ErrorHandlerWrapper(errorHandler));
  1219. }
  1220. catch (XMLConfigurationException e) {
  1221. // do nothing
  1222. }
  1223. } // setErrorHandler(ErrorHandler)
  1224. /**
  1225. * Return the current error handler.
  1226. *
  1227. * @return The current error handler, or null if none
  1228. * has been registered.
  1229. * @see #setErrorHandler
  1230. */
  1231. public ErrorHandler getErrorHandler() {
  1232. ErrorHandler errorHandler = null;
  1233. try {
  1234. XMLErrorHandler xmlErrorHandler =
  1235. (XMLErrorHandler)fConfiguration.getProperty(ERROR_HANDLER);
  1236. if (xmlErrorHandler != null &&
  1237. xmlErrorHandler instanceof ErrorHandlerWrapper) {
  1238. errorHandler = ((ErrorHandlerWrapper)xmlErrorHandler).getErrorHandler();
  1239. }
  1240. }
  1241. catch (XMLConfigurationException e) {
  1242. // do nothing
  1243. }
  1244. return errorHandler;
  1245. } // getErrorHandler():ErrorHandler
  1246. /**
  1247. * Set the locale to use for messages.
  1248. *
  1249. * @param locale The locale object to use for localization of messages.
  1250. *
  1251. * @exception SAXException An exception thrown if the parser does not
  1252. * support the specified locale.
  1253. *
  1254. * @see org.xml.sax.Parser
  1255. */
  1256. public void setLocale(Locale locale) throws SAXException {
  1257. //REVISIT:this methods is not part of SAX2 interfaces, we should throw exception
  1258. //if any application uses SAX2 and sets locale also. -nb
  1259. fConfiguration.setLocale(locale);
  1260. } // setLocale(Locale)
  1261. /**
  1262. * Allow an application to register a DTD event handler.
  1263. * <p>
  1264. * If the application does not register a DTD handler, all DTD
  1265. * events reported by the SAX parser will be silently ignored.
  1266. * <p>
  1267. * Applications may register a new or different handler in the
  1268. * middle of a parse, and the SAX parser must begin using the new
  1269. * handler immediately.
  1270. *
  1271. * @param dtdHandler The DTD handler.
  1272. *
  1273. *
  1274. * @see #getDTDHandler
  1275. */
  1276. public void setDTDHandler(DTDHandler dtdHandler) {
  1277. fDTDHandler = dtdHandler;
  1278. } // setDTDHandler(DTDHandler)
  1279. //
  1280. // Parser methods
  1281. //
  1282. /**
  1283. * Allow an application to register a document event handler.
  1284. * <p>
  1285. * If the application does not register a document handler, all
  1286. * document events reported by the SAX parser will be silently
  1287. * ignored (this is the default behaviour implemented by
  1288. * HandlerBase).
  1289. * <p>
  1290. * Applications may register a new or different handler in the
  1291. * middle of a parse, and the SAX parser must begin using the new
  1292. * handler immediately.
  1293. *
  1294. * @param documentHandler The document handler.
  1295. */
  1296. public void setDocumentHandler(DocumentHandler documentHandler) {
  1297. fDocumentHandler = documentHandler;
  1298. } // setDocumentHandler(DocumentHandler)
  1299. //
  1300. // XMLReader methods
  1301. //
  1302. /**
  1303. * Allow an application to register a content event handler.
  1304. * <p>
  1305. * If the application does not register a content handler, all
  1306. * content events reported by the SAX parser will be silently
  1307. * ignored.
  1308. * <p>
  1309. * Applications may register a new or different handler in the
  1310. * middle of a parse, and the SAX parser must begin using the new
  1311. * handler immediately.
  1312. *
  1313. * @param contentHandler The content handler.
  1314. *
  1315. * @see #getContentHandler
  1316. */
  1317. public void setContentHandler(ContentHandler contentHandler) {
  1318. fContentHandler = contentHandler;
  1319. } // setContentHandler(ContentHandler)
  1320. /**
  1321. * Return the current content handler.
  1322. *
  1323. * @return The current content handler, or null if none
  1324. * has been registered.
  1325. *
  1326. * @see #setContentHandler
  1327. */
  1328. public ContentHandler getContentHandler() {
  1329. return fContentHandler;
  1330. } // getContentHandler():ContentHandler
  1331. /**
  1332. * Return the current DTD handler.
  1333. *
  1334. * @return The current DTD handler, or null if none
  1335. * has been registered.
  1336. * @see #setDTDHandler
  1337. */
  1338. public DTDHandler getDTDHandler() {
  1339. return fDTDHandler;
  1340. } // getDTDHandler():DTDHandler
  1341. /**
  1342. * Set the state of any feature in a SAX2 parser. The parser
  1343. * might not recognize the feature, and if it does recognize
  1344. * it, it might not be able to fulfill the request.
  1345. *
  1346. * @param featureId The unique identifier (URI) of the feature.
  1347. * @param state The requested state of the feature (true or false).
  1348. *
  1349. * @exception SAXNotRecognizedException If the
  1350. * requested feature is not known.
  1351. * @exception SAXNotSupportedException If the
  1352. * requested feature is known, but the requested
  1353. * state is not supported.
  1354. */
  1355. public void setFeature(String featureId, boolean state)
  1356. throws SAXNotRecognizedException, SAXNotSupportedException {
  1357. try {
  1358. //
  1359. // SAX2 Features
  1360. //
  1361. if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
  1362. final int suffixLength = featureId.length() - Constants.SAX_FEATURE_PREFIX.length();
  1363. // http://xml.org/sax/features/namespaces
  1364. if (suffixLength == Constants.NAMESPACES_FEATURE.length() &&
  1365. featureId.endsWith(Constants.NAMESPACES_FEATURE)) {
  1366. fConfiguration.setFeature(featureId, state);
  1367. fNamespaces = state;
  1368. return;
  1369. }
  1370. // http://xml.org/sax/features/namespace-prefixes
  1371. // controls the reporting of raw prefixed names and Namespace
  1372. // declarations (xmlns* attributes): when this feature is false
  1373. // (the default), raw prefixed names may optionally be reported,
  1374. // and xmlns* attributes must not be reported.
  1375. //
  1376. if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE.length() &&
  1377. featureId.endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) {
  1378. fConfiguration.setFeature(featureId, state);
  1379. fNamespacePrefixes = state;
  1380. return;
  1381. }
  1382. // http://xml.org/sax/features/string-interning
  1383. // controls the use of java.lang.String#intern() for strings
  1384. // passed to SAX handlers.
  1385. //
  1386. if (suffixLength == Constants.STRING_INTERNING_FEATURE.length() &&
  1387. featureId.endsWith(Constants.STRING_INTERNING_FEATURE)) {
  1388. if (!state) {
  1389. throw new SAXNotSupportedException(
  1390. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1391. "false-not-supported", new Object [] {featureId}));
  1392. }
  1393. return;
  1394. }
  1395. // http://xml.org/sax/features/lexical-handler/parameter-entities
  1396. // controls whether the beginning and end of parameter entities
  1397. // will be reported to the LexicalHandler.
  1398. //
  1399. if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE.length() &&
  1400. featureId.endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) {
  1401. fLexicalHandlerParameterEntities = state;
  1402. return;
  1403. }
  1404. if(suffixLength == Constants.RESOLVE_DTD_URIS_FEATURE.length() && featureId.endsWith(Constants.RESOLVE_DTD_URIS_FEATURE)){
  1405. resolve_dtd_uris = state;
  1406. fConfiguration.setFeature(featureId, state);
  1407. return;
  1408. }
  1409. if((suffixLength == Constants.XML_11_FEATURE.length() &&
  1410. featureId.endsWith(Constants.XML_11_FEATURE)) ||
  1411. (suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE.length() &&
  1412. featureId.endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE))||
  1413. (suffixLength == Constants.USE_LOCATOR2_FEATURE.length() &&
  1414. featureId.endsWith(Constants.USE_LOCATOR2_FEATURE))||
  1415. (suffixLength == Constants.USE_ATTRIBUTES2_FEATURE.length() &&
  1416. featureId.endsWith(Constants.USE_ATTRIBUTES2_FEATURE))||
  1417. (suffixLength == Constants.IS_STANDALONE_FEATURE.length() &&
  1418. featureId.endsWith(Constants.IS_STANDALONE_FEATURE))
  1419. ){
  1420. throw new SAXNotSupportedException(
  1421. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1422. "feature-read-only", new Object [] {featureId}));
  1423. }
  1424. //
  1425. // Drop through and perform default processing
  1426. //
  1427. }
  1428. //
  1429. // Xerces Features
  1430. //
  1431. /*
  1432. else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
  1433. String feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
  1434. //
  1435. // Drop through and perform default processing
  1436. //
  1437. }
  1438. */
  1439. //
  1440. // Default handling
  1441. //
  1442. fConfiguration.setFeature(featureId, state);
  1443. }
  1444. catch (XMLConfigurationException e) {
  1445. String identifier = e.getIdentifier();
  1446. if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
  1447. throw new SAXNotRecognizedException(
  1448. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1449. "feature-not-recognized", new Object [] {identifier}));
  1450. }
  1451. else {
  1452. throw new SAXNotSupportedException(
  1453. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1454. "feature-not-supported", new Object [] {identifier}));
  1455. }
  1456. }
  1457. } // setFeature(String,boolean)
  1458. /**
  1459. * Query the state of a feature.
  1460. *
  1461. * Query the current state of any feature in a SAX2 parser. The
  1462. * parser might not recognize the feature.
  1463. *
  1464. * @param featureId The unique identifier (URI) of the feature
  1465. * being set.
  1466. * @return The current state of the feature.
  1467. * @exception org.xml.sax.SAXNotRecognizedException If the
  1468. * requested feature is not known.
  1469. * @exception SAXNotSupportedException If the
  1470. * requested feature is known but not supported.
  1471. */
  1472. public boolean getFeature(String featureId)
  1473. throws SAXNotRecognizedException, SAXNotSupportedException {
  1474. try {
  1475. //
  1476. // SAX2 Features
  1477. //
  1478. if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
  1479. final int suffixLength = featureId.length() - Constants.SAX_FEATURE_PREFIX.length();
  1480. // http://xml.org/sax/features/namespace-prefixes
  1481. // controls the reporting of raw prefixed names and Namespace
  1482. // declarations (xmlns* attributes): when this feature is false
  1483. // (the default), raw prefixed names may optionally be reported,
  1484. // and xmlns* attributes must not be reported.
  1485. //
  1486. if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE.length() &&
  1487. featureId.endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) {
  1488. boolean state = fConfiguration.getFeature(featureId);
  1489. return state;
  1490. }
  1491. // http://xml.org/sax/features/string-interning
  1492. // controls the use of java.lang.String#intern() for strings
  1493. // passed to SAX handlers.
  1494. //
  1495. if (suffixLength == Constants.STRING_INTERNING_FEATURE.length() &&
  1496. featureId.endsWith(Constants.STRING_INTERNING_FEATURE)) {
  1497. return true;
  1498. }
  1499. // http://xml.org/sax/features/lexical-handler/parameter-entities
  1500. // controls whether the beginning and end of parameter entities
  1501. // will be reported to the LexicalHandler.
  1502. //
  1503. if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE.length() &&
  1504. featureId.endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) {
  1505. return fLexicalHandlerParameterEntities;
  1506. }
  1507. if(suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE.length() &&
  1508. featureId.endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE)){
  1509. return resolverType;
  1510. }
  1511. if(suffixLength == Constants.USE_LOCATOR2_FEATURE.length() && featureId.endsWith(Constants.USE_LOCATOR2_FEATURE)){
  1512. return locatorType;
  1513. }
  1514. if(suffixLength == Constants.USE_ATTRIBUTES2_FEATURE.length() && featureId.endsWith(Constants.USE_ATTRIBUTES2_FEATURE)){
  1515. return attributeType;
  1516. }
  1517. if(suffixLength == Constants.IS_STANDALONE_FEATURE.length() && featureId.endsWith(Constants.IS_STANDALONE_FEATURE)){
  1518. return isStandalone;
  1519. }
  1520. //
  1521. // Drop through and perform default processing
  1522. //
  1523. }
  1524. //
  1525. // Xerces Features
  1526. //
  1527. /*
  1528. else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
  1529. //
  1530. // Drop through and perform default processing
  1531. //
  1532. }
  1533. */
  1534. return fConfiguration.getFeature(featureId);
  1535. }
  1536. catch (XMLConfigurationException e) {
  1537. String identifier = e.getIdentifier();
  1538. if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
  1539. throw new SAXNotRecognizedException(
  1540. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1541. "feature-not-recognized", new Object [] {identifier}));
  1542. }
  1543. else {
  1544. throw new SAXNotSupportedException(
  1545. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1546. "feature-not-supported", new Object [] {identifier}));
  1547. }
  1548. }
  1549. } // getFeature(String):boolean
  1550. /**
  1551. * Set the value of any property in a SAX2 parser. The parser
  1552. * might not recognize the property, and if it does recognize
  1553. * it, it might not support the requested value.
  1554. *
  1555. * @param propertyId The unique identifier (URI) of the property
  1556. * being set.
  1557. * @param value The value to which the property is being set.
  1558. *
  1559. * @exception SAXNotRecognizedException If the
  1560. * requested property is not known.
  1561. * @exception SAXNotSupportedException If the
  1562. * requested property is known, but the requested
  1563. * value is not supported.
  1564. */
  1565. public void setProperty(String propertyId, Object value)
  1566. throws SAXNotRecognizedException, SAXNotSupportedException {
  1567. try {
  1568. //
  1569. // SAX2 core properties
  1570. //
  1571. if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
  1572. final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
  1573. //
  1574. // http://xml.org/sax/properties/lexical-handler
  1575. // Value type: org.xml.sax.ext.LexicalHandler
  1576. // Access: read/write, pre-parse only
  1577. // Set the lexical event handler.
  1578. //
  1579. if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY.length() &&
  1580. propertyId.endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) {
  1581. try {
  1582. setLexicalHandler((LexicalHandler)value);
  1583. }
  1584. catch (ClassCastException e) {
  1585. throw new SAXNotSupportedException(
  1586. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1587. "incompatible-class", new Object [] {propertyId, "org.xml.sax.ext.LexicalHandler"}));
  1588. }
  1589. return;
  1590. }
  1591. //
  1592. // http://xml.org/sax/properties/declaration-handler
  1593. // Value type: org.xml.sax.ext.DeclHandler
  1594. // Access: read/write, pre-parse only
  1595. // Set the DTD declaration event handler.
  1596. //
  1597. if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY.length() &&
  1598. propertyId.endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) {
  1599. try {
  1600. setDeclHandler((DeclHandler)value);
  1601. }
  1602. catch (ClassCastException e) {
  1603. throw new SAXNotSupportedException(
  1604. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1605. "incompatible-class", new Object [] {propertyId, "org.xml.sax.ext.DeclHandler"}));
  1606. }
  1607. return;
  1608. }
  1609. //
  1610. // http://xml.org/sax/properties/dom-node
  1611. // Value type: DOM Node
  1612. // Access: read-only
  1613. // Get the DOM node currently being visited, if the SAX parser is
  1614. // iterating over a DOM tree. If the parser recognises and
  1615. // supports this property but is not currently visiting a DOM
  1616. // node, it should return null (this is a good way to check for
  1617. // availability before the parse begins).
  1618. //
  1619. if (suffixLength == Constants.DOM_NODE_PROPERTY.length() &&
  1620. propertyId.endsWith(Constants.DOM_NODE_PROPERTY)) {
  1621. throw new SAXNotSupportedException(
  1622. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1623. "property-read-only", new Object [] {propertyId}));
  1624. }
  1625. if(suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY.length() && propertyId.endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY)){
  1626. throw new SAXNotSupportedException(
  1627. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1628. "property-read-only", new Object [] {propertyId}));
  1629. }
  1630. //
  1631. // Drop through and perform default processing
  1632. //
  1633. }
  1634. //
  1635. // Xerces Properties
  1636. //
  1637. /*
  1638. else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
  1639. //
  1640. // Drop through and perform default processing
  1641. //
  1642. }
  1643. */
  1644. //
  1645. // Perform default processing
  1646. //
  1647. fConfiguration.setProperty(propertyId, value);
  1648. }
  1649. catch (XMLConfigurationException e) {
  1650. String identifier = e.getIdentifier();
  1651. if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
  1652. throw new SAXNotRecognizedException(
  1653. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1654. "property-not-recognized", new Object [] {identifier}));
  1655. }
  1656. else {
  1657. throw new SAXNotSupportedException(
  1658. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1659. "property-not-supported", new Object [] {identifier}));
  1660. }
  1661. }
  1662. } // setProperty(String,Object)
  1663. /**
  1664. * Query the value of a property.
  1665. *
  1666. * Return the current value of a property in a SAX2 parser.
  1667. * The parser might not recognize the property.
  1668. *
  1669. * @param propertyId The unique identifier (URI) of the property
  1670. * being set.
  1671. * @return The current value of the property.
  1672. * @exception org.xml.sax.SAXNotRecognizedException If the
  1673. * requested property is not known.
  1674. * @exception SAXNotSupportedException If the
  1675. * requested property is known but not supported.
  1676. */
  1677. public Object getProperty(String propertyId)
  1678. throws SAXNotRecognizedException, SAXNotSupportedException {
  1679. try {
  1680. //
  1681. // SAX2 core properties
  1682. //
  1683. if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
  1684. final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
  1685. //
  1686. // http://xml.org/sax/properties/lexical-handler
  1687. // Value type: org.xml.sax.ext.LexicalHandler
  1688. // Access: read/write, pre-parse only
  1689. // Set the lexical event handler.
  1690. //
  1691. if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY.length() &&
  1692. propertyId.endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) {
  1693. return getLexicalHandler();
  1694. }
  1695. //
  1696. // http://xml.org/sax/properties/declaration-handler
  1697. // Value type: org.xml.sax.ext.DeclHandler
  1698. // Access: read/write, pre-parse only
  1699. // Set the DTD declaration event handler.
  1700. //
  1701. if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY.length() &&
  1702. propertyId.endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) {
  1703. return getDeclHandler();
  1704. }
  1705. //
  1706. // http://xml.org/sax/properties/dom-node
  1707. // Value type: DOM Node
  1708. // Access: read-only
  1709. // Get the DOM node currently being visited, if the SAX parser is
  1710. // iterating over a DOM tree. If the parser recognises and
  1711. // supports this property but is not currently visiting a DOM
  1712. // node, it should return null (this is a good way to check for
  1713. // availability before the parse begins).
  1714. //
  1715. if (suffixLength == Constants.DOM_NODE_PROPERTY.length() &&
  1716. propertyId.endsWith(Constants.DOM_NODE_PROPERTY)) {
  1717. // we are not iterating a DOM tree
  1718. throw new SAXNotSupportedException(
  1719. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1720. "dom-node-read-not-supported", null));
  1721. }
  1722. if(suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY.length() &&
  1723. propertyId.endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY)){
  1724. if(startDocumentCalled){
  1725. return fVersion;
  1726. }else{
  1727. throw new SAXNotSupportedException(
  1728. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1729. "start-document-not-called", new Object [] {propertyId}));
  1730. }
  1731. }
  1732. //
  1733. // Drop through and perform default processing
  1734. //
  1735. }
  1736. //
  1737. // Xerces properties
  1738. //
  1739. /*
  1740. else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
  1741. //
  1742. // Drop through and perform default processing
  1743. //
  1744. }
  1745. */
  1746. //
  1747. // Perform default processing
  1748. //
  1749. return fConfiguration.getProperty(propertyId);
  1750. }
  1751. catch (XMLConfigurationException e) {
  1752. String identifier = e.getIdentifier();
  1753. if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
  1754. throw new SAXNotRecognizedException(
  1755. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1756. "property-not-recognized", new Object [] {identifier}));
  1757. }
  1758. else {
  1759. throw new SAXNotSupportedException(
  1760. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1761. "property-not-supported", new Object [] {identifier}));
  1762. }
  1763. }
  1764. } // getProperty(String):Object
  1765. //
  1766. // Protected methods
  1767. //
  1768. // SAX2 core properties
  1769. /**
  1770. * Set the DTD declaration event handler.
  1771. * <p>
  1772. * This method is the equivalent to the property:
  1773. * <pre>
  1774. * http://xml.org/sax/properties/declaration-handler
  1775. * </pre>
  1776. *
  1777. * @param handler The new handler.
  1778. *
  1779. * @see #getDeclHandler
  1780. * @see #setProperty
  1781. */
  1782. protected void setDeclHandler(DeclHandler handler)
  1783. throws SAXNotRecognizedException, SAXNotSupportedException {
  1784. if (fParseInProgress) {
  1785. throw new SAXNotSupportedException(
  1786. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1787. "property-not-parsing-supported",
  1788. new Object [] {"http://xml.org/sax/properties/declaration-handler"}));
  1789. }
  1790. fDeclHandler = handler;
  1791. } // setDeclHandler(DeclHandler)
  1792. /**
  1793. * Returns the DTD declaration event handler.
  1794. *
  1795. * @see #setDeclHandler
  1796. */
  1797. protected DeclHandler getDeclHandler()
  1798. throws SAXNotRecognizedException, SAXNotSupportedException {
  1799. return fDeclHandler;
  1800. } // getDeclHandler():DeclHandler
  1801. /**
  1802. * Set the lexical event handler.
  1803. * <p>
  1804. * This method is the equivalent to the property:
  1805. * <pre>
  1806. * http://xml.org/sax/properties/lexical-handler
  1807. * </pre>
  1808. *
  1809. * @param handler lexical event handler
  1810. *
  1811. * @see #getLexicalHandler
  1812. * @see #setProperty
  1813. */
  1814. protected void setLexicalHandler(LexicalHandler handler)
  1815. throws SAXNotRecognizedException, SAXNotSupportedException {
  1816. if (fParseInProgress) {
  1817. throw new SAXNotSupportedException(
  1818. SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
  1819. "property-not-parsing-supported",
  1820. new Object [] {"http://xml.org/sax/properties/lexical-handler"}));
  1821. }
  1822. fLexicalHandler = handler;
  1823. } // setLexicalHandler(LexicalHandler)
  1824. /**
  1825. * Returns the lexical handler.
  1826. *
  1827. * @see #setLexicalHandler
  1828. */
  1829. protected LexicalHandler getLexicalHandler()
  1830. throws SAXNotRecognizedException, SAXNotSupportedException {
  1831. return fLexicalHandler;
  1832. } // getLexicalHandler():LexicalHandler
  1833. /**
  1834. * Send startPrefixMapping events
  1835. */
  1836. protected final void startNamespaceMapping() throws SAXException{
  1837. int count = fNamespaceContext.getDeclaredPrefixCount();
  1838. if (count > 0) {
  1839. String prefix = null;
  1840. String uri = null;
  1841. for (int i = 0; i < count; i++) {
  1842. prefix = fNamespaceContext.getDeclaredPrefixAt(i);
  1843. uri = fNamespaceContext.getURI(prefix);
  1844. fContentHandler.startPrefixMapping(prefix,
  1845. (uri == null) ? "" : uri);
  1846. }
  1847. }
  1848. }
  1849. /**
  1850. * Send endPrefixMapping events
  1851. */
  1852. protected final void endNamespaceMapping() throws SAXException {
  1853. int count = fNamespaceContext.getDeclaredPrefixCount();
  1854. if (count > 0) {
  1855. for (int i = 0; i < count; i++) {
  1856. fContentHandler.endPrefixMapping(fNamespaceContext.getDeclaredPrefixAt(i));
  1857. }
  1858. }
  1859. }
  1860. //
  1861. // XMLDocumentParser methods
  1862. //
  1863. /**
  1864. * Reset all components before parsing.
  1865. *
  1866. * @throws XNIException Thrown if an error occurs during initialization.
  1867. */
  1868. public void reset() throws XNIException {
  1869. super.reset();
  1870. // reset state
  1871. fInDTD = false;
  1872. fVersion = "1.0";
  1873. // features
  1874. fNamespaces = fConfiguration.getFeature(NAMESPACES);
  1875. fNamespacePrefixes = fConfiguration.getFeature(NAMESPACE_PREFIXES);
  1876. fAugmentations = null;
  1877. fDeclaredAttrs = null;
  1878. } // reset()
  1879. //
  1880. // Classes
  1881. //
  1882. protected class LocatorProxy
  1883. implements Locator2 {
  1884. //
  1885. // Data
  1886. //
  1887. /** XML locator. */
  1888. protected XMLLocator fLocator;
  1889. //
  1890. // Constructors
  1891. //
  1892. /** Constructs an XML locator proxy. */
  1893. public LocatorProxy(XMLLocator locator) {
  1894. fLocator = locator;
  1895. }
  1896. //
  1897. // Locator methods
  1898. //
  1899. /** Public identifier. */
  1900. public String getPublicId() {
  1901. return fLocator.getPublicId();
  1902. }
  1903. /** System identifier. */
  1904. public String getSystemId() {
  1905. return fLocator.getExpandedSystemId();
  1906. }
  1907. /** Line number. */
  1908. public int getLineNumber() {
  1909. return fLocator.getLineNumber();
  1910. }
  1911. /** Column number. */
  1912. public int getColumnNumber() {
  1913. return fLocator.getColumnNumber();
  1914. }
  1915. // Locator2 methods
  1916. public String getXMLVersion() {
  1917. return fVersion;
  1918. }
  1919. public String getEncoding() {
  1920. return fLocator.getEncoding();
  1921. }
  1922. } // class LocatorProxy
  1923. protected static final class AttributesProxy
  1924. implements AttributeList, Attributes2 {
  1925. //
  1926. // Data
  1927. //
  1928. /** XML attributes. */
  1929. protected XMLAttributes fAttributes;
  1930. //
  1931. // Public methods
  1932. //
  1933. /** Sets the XML attributes. */
  1934. public void setAttributes(XMLAttributes attributes) {
  1935. fAttributes = attributes;
  1936. } // setAttributes(XMLAttributes)
  1937. public int getLength() {
  1938. return fAttributes.getLength();
  1939. }
  1940. public String getName(int i) {
  1941. return fAttributes.getQName(i);
  1942. }
  1943. public String getQName(int index) {
  1944. return fAttributes.getQName(index);
  1945. }
  1946. public String getURI(int index) {
  1947. // REVISIT: this hides the fact that internally we use
  1948. // null instead of empty string
  1949. // SAX requires URI to be a string or an empty string
  1950. String uri= fAttributes.getURI(index);
  1951. return uri != null ? uri : "";
  1952. }
  1953. public String getLocalName(int index) {
  1954. return fAttributes.getLocalName(index);
  1955. }
  1956. public String getType(int i) {
  1957. return fAttributes.getType(i);
  1958. }
  1959. public String getType(String name) {
  1960. return fAttributes.getType(name);
  1961. }
  1962. public String getType(String uri, String localName) {
  1963. return uri.equals("") ? fAttributes.getType(null, localName) :
  1964. fAttributes.getType(uri, localName);
  1965. }
  1966. public String getValue(int i) {
  1967. return fAttributes.getValue(i);
  1968. }
  1969. public String getValue(String name) {
  1970. return fAttributes.getValue(name);
  1971. }
  1972. public String getValue(String uri, String localName) {
  1973. return uri.equals("") ? fAttributes.getValue(null, localName) :
  1974. fAttributes.getValue(uri, localName);
  1975. }
  1976. public int getIndex(String qName) {
  1977. return fAttributes.getIndex(qName);
  1978. }
  1979. public int getIndex(String uri, String localPart) {
  1980. return uri.equals("") ? fAttributes.getIndex(null, localPart) :
  1981. fAttributes.getIndex(uri, localPart);
  1982. }
  1983. // Attributes2 methods
  1984. // REVISIT: Localize exception messages. -- mrglavas
  1985. public boolean isDeclared(int index) {
  1986. if (index < 0 || index >= fAttributes.getLength()) {
  1987. throw new ArrayIndexOutOfBoundsException(index);
  1988. }
  1989. return Boolean.TRUE.equals(
  1990. fAttributes.getAugmentations(index).getItem(
  1991. Constants.ATTRIBUTE_DECLARED));
  1992. }
  1993. public boolean isDeclared(String qName) {
  1994. int index = getIndex(qName);
  1995. if (index == -1) {
  1996. throw new IllegalArgumentException(qName);
  1997. }
  1998. return Boolean.TRUE.equals(
  1999. fAttributes.getAugmentations(index).getItem(
  2000. Constants.ATTRIBUTE_DECLARED));
  2001. }
  2002. public boolean isDeclared(String uri, String localName) {
  2003. int index = getIndex(uri, localName);
  2004. if (index == -1) {
  2005. throw new IllegalArgumentException(localName);
  2006. }
  2007. return Boolean.TRUE.equals(
  2008. fAttributes.getAugmentations(index).getItem(
  2009. Constants.ATTRIBUTE_DECLARED));
  2010. }
  2011. public boolean isSpecified(int index) {
  2012. if (index < 0 || index >= fAttributes.getLength()) {
  2013. throw new ArrayIndexOutOfBoundsException(index);
  2014. }
  2015. return fAttributes.isSpecified(index);
  2016. }
  2017. public boolean isSpecified(String qName) {
  2018. int index = getIndex(qName);
  2019. if (index == -1) {
  2020. throw new IllegalArgumentException(qName);
  2021. }
  2022. return fAttributes.isSpecified(index);
  2023. }
  2024. public boolean isSpecified(String uri, String localName) {
  2025. int index = getIndex(uri, localName);
  2026. if (index == -1) {
  2027. throw new IllegalArgumentException(localName);
  2028. }
  2029. return fAttributes.isSpecified(index);
  2030. }
  2031. } // class AttributesProxy
  2032. // PSVIProvider methods
  2033. public ElementPSVI getElementPSVI(){
  2034. return (fAugmentations != null)?(ElementPSVI)fAugmentations.getItem(Constants.ELEMENT_PSVI):null;
  2035. }
  2036. public AttributePSVI getAttributePSVI(int index){
  2037. return (AttributePSVI)fAttributesProxy.fAttributes.getAugmentations(index).getItem(Constants.ATTRIBUTE_PSVI);
  2038. }
  2039. public AttributePSVI getAttributePSVIByName(String uri,
  2040. String localname){
  2041. return (AttributePSVI)fAttributesProxy.fAttributes.getAugmentations(uri, localname).getItem(Constants.ATTRIBUTE_PSVI);
  2042. }
  2043. } // class AbstractSAXParser