1. // XMLFilterImpl.java - base SAX2 filter implementation.
  2. // http://www.saxproject.org
  3. // Written by David Megginson
  4. // NO WARRANTY! This class is in the Public Domain.
  5. // $Id: XMLFilterImpl.java,v 1.2.22.1 2004/05/01 08:34:46 jsuttor Exp $
  6. package org.xml.sax.helpers;
  7. import java.io.IOException;
  8. import org.xml.sax.XMLReader;
  9. import org.xml.sax.XMLFilter;
  10. import org.xml.sax.InputSource;
  11. import org.xml.sax.Locator;
  12. import org.xml.sax.Attributes;
  13. import org.xml.sax.EntityResolver;
  14. import org.xml.sax.DTDHandler;
  15. import org.xml.sax.ContentHandler;
  16. import org.xml.sax.ErrorHandler;
  17. import org.xml.sax.SAXException;
  18. import org.xml.sax.SAXParseException;
  19. import org.xml.sax.SAXNotSupportedException;
  20. import org.xml.sax.SAXNotRecognizedException;
  21. /**
  22. * Base class for deriving an XML filter.
  23. *
  24. * <blockquote>
  25. * <em>This module, both source code and documentation, is in the
  26. * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
  27. * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
  28. * for further information.
  29. * </blockquote>
  30. *
  31. * <p>This class is designed to sit between an {@link org.xml.sax.XMLReader
  32. * XMLReader} and the client application's event handlers. By default, it
  33. * does nothing but pass requests up to the reader and events
  34. * on to the handlers unmodified, but subclasses can override
  35. * specific methods to modify the event stream or the configuration
  36. * requests as they pass through.</p>
  37. *
  38. * @since SAX 2.0
  39. * @author David Megginson
  40. * @version 2.0.1 (sax2r2)
  41. * @see org.xml.sax.XMLFilter
  42. * @see org.xml.sax.XMLReader
  43. * @see org.xml.sax.EntityResolver
  44. * @see org.xml.sax.DTDHandler
  45. * @see org.xml.sax.ContentHandler
  46. * @see org.xml.sax.ErrorHandler
  47. */
  48. public class XMLFilterImpl
  49. implements XMLFilter, EntityResolver, DTDHandler, ContentHandler, ErrorHandler
  50. {
  51. ////////////////////////////////////////////////////////////////////
  52. // Constructors.
  53. ////////////////////////////////////////////////////////////////////
  54. /**
  55. * Construct an empty XML filter, with no parent.
  56. *
  57. * <p>This filter will have no parent: you must assign a parent
  58. * before you start a parse or do any configuration with
  59. * setFeature or setProperty, unless you use this as a pure event
  60. * consumer rather than as an {@link XMLReader}.</p>
  61. *
  62. * @see org.xml.sax.XMLReader#setFeature
  63. * @see org.xml.sax.XMLReader#setProperty
  64. * @see #setParent
  65. */
  66. public XMLFilterImpl ()
  67. {
  68. super();
  69. }
  70. /**
  71. * Construct an XML filter with the specified parent.
  72. *
  73. * @see #setParent
  74. * @see #getParent
  75. */
  76. public XMLFilterImpl (XMLReader parent)
  77. {
  78. super();
  79. setParent(parent);
  80. }
  81. ////////////////////////////////////////////////////////////////////
  82. // Implementation of org.xml.sax.XMLFilter.
  83. ////////////////////////////////////////////////////////////////////
  84. /**
  85. * Set the parent reader.
  86. *
  87. * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which
  88. * this filter will obtain its events and to which it will pass its
  89. * configuration requests. The parent may itself be another filter.</p>
  90. *
  91. * <p>If there is no parent reader set, any attempt to parse
  92. * or to set or get a feature or property will fail.</p>
  93. *
  94. * @param parent The parent XML reader.
  95. * @see #getParent
  96. */
  97. public void setParent (XMLReader parent)
  98. {
  99. this.parent = parent;
  100. }
  101. /**
  102. * Get the parent reader.
  103. *
  104. * @return The parent XML reader, or null if none is set.
  105. * @see #setParent
  106. */
  107. public XMLReader getParent ()
  108. {
  109. return parent;
  110. }
  111. ////////////////////////////////////////////////////////////////////
  112. // Implementation of org.xml.sax.XMLReader.
  113. ////////////////////////////////////////////////////////////////////
  114. /**
  115. * Set the value of a feature.
  116. *
  117. * <p>This will always fail if the parent is null.</p>
  118. *
  119. * @param name The feature name.
  120. * @param value The requested feature value.
  121. * @exception org.xml.sax.SAXNotRecognizedException If the feature
  122. * value can't be assigned or retrieved from the parent.
  123. * @exception org.xml.sax.SAXNotSupportedException When the
  124. * parent recognizes the feature name but
  125. * cannot set the requested value.
  126. */
  127. public void setFeature (String name, boolean value)
  128. throws SAXNotRecognizedException, SAXNotSupportedException
  129. {
  130. if (parent != null) {
  131. parent.setFeature(name, value);
  132. } else {
  133. throw new SAXNotRecognizedException("Feature: " + name);
  134. }
  135. }
  136. /**
  137. * Look up the value of a feature.
  138. *
  139. * <p>This will always fail if the parent is null.</p>
  140. *
  141. * @param name The feature name.
  142. * @return The current value of the feature.
  143. * @exception org.xml.sax.SAXNotRecognizedException If the feature
  144. * value can't be assigned or retrieved from the parent.
  145. * @exception org.xml.sax.SAXNotSupportedException When the
  146. * parent recognizes the feature name but
  147. * cannot determine its value at this time.
  148. */
  149. public boolean getFeature (String name)
  150. throws SAXNotRecognizedException, SAXNotSupportedException
  151. {
  152. if (parent != null) {
  153. return parent.getFeature(name);
  154. } else {
  155. throw new SAXNotRecognizedException("Feature: " + name);
  156. }
  157. }
  158. /**
  159. * Set the value of a property.
  160. *
  161. * <p>This will always fail if the parent is null.</p>
  162. *
  163. * @param name The property name.
  164. * @param value The requested property value.
  165. * @exception org.xml.sax.SAXNotRecognizedException If the property
  166. * value can't be assigned or retrieved from the parent.
  167. * @exception org.xml.sax.SAXNotSupportedException When the
  168. * parent recognizes the property name but
  169. * cannot set the requested value.
  170. */
  171. public void setProperty (String name, Object value)
  172. throws SAXNotRecognizedException, SAXNotSupportedException
  173. {
  174. if (parent != null) {
  175. parent.setProperty(name, value);
  176. } else {
  177. throw new SAXNotRecognizedException("Property: " + name);
  178. }
  179. }
  180. /**
  181. * Look up the value of a property.
  182. *
  183. * @param name The property name.
  184. * @return The current value of the property.
  185. * @exception org.xml.sax.SAXNotRecognizedException If the property
  186. * value can't be assigned or retrieved from the parent.
  187. * @exception org.xml.sax.SAXNotSupportedException When the
  188. * parent recognizes the property name but
  189. * cannot determine its value at this time.
  190. */
  191. public Object getProperty (String name)
  192. throws SAXNotRecognizedException, SAXNotSupportedException
  193. {
  194. if (parent != null) {
  195. return parent.getProperty(name);
  196. } else {
  197. throw new SAXNotRecognizedException("Property: " + name);
  198. }
  199. }
  200. /**
  201. * Set the entity resolver.
  202. *
  203. * @param resolver The new entity resolver.
  204. */
  205. public void setEntityResolver (EntityResolver resolver)
  206. {
  207. entityResolver = resolver;
  208. }
  209. /**
  210. * Get the current entity resolver.
  211. *
  212. * @return The current entity resolver, or null if none was set.
  213. */
  214. public EntityResolver getEntityResolver ()
  215. {
  216. return entityResolver;
  217. }
  218. /**
  219. * Set the DTD event handler.
  220. *
  221. * @param handler the new DTD handler
  222. */
  223. public void setDTDHandler (DTDHandler handler)
  224. {
  225. dtdHandler = handler;
  226. }
  227. /**
  228. * Get the current DTD event handler.
  229. *
  230. * @return The current DTD handler, or null if none was set.
  231. */
  232. public DTDHandler getDTDHandler ()
  233. {
  234. return dtdHandler;
  235. }
  236. /**
  237. * Set the content event handler.
  238. *
  239. * @param handler the new content handler
  240. */
  241. public void setContentHandler (ContentHandler handler)
  242. {
  243. contentHandler = handler;
  244. }
  245. /**
  246. * Get the content event handler.
  247. *
  248. * @return The current content handler, or null if none was set.
  249. */
  250. public ContentHandler getContentHandler ()
  251. {
  252. return contentHandler;
  253. }
  254. /**
  255. * Set the error event handler.
  256. *
  257. * @param handler the new error handler
  258. */
  259. public void setErrorHandler (ErrorHandler handler)
  260. {
  261. errorHandler = handler;
  262. }
  263. /**
  264. * Get the current error event handler.
  265. *
  266. * @return The current error handler, or null if none was set.
  267. */
  268. public ErrorHandler getErrorHandler ()
  269. {
  270. return errorHandler;
  271. }
  272. /**
  273. * Parse a document.
  274. *
  275. * @param input The input source for the document entity.
  276. * @exception org.xml.sax.SAXException Any SAX exception, possibly
  277. * wrapping another exception.
  278. * @exception java.io.IOException An IO exception from the parser,
  279. * possibly from a byte stream or character stream
  280. * supplied by the application.
  281. */
  282. public void parse (InputSource input)
  283. throws SAXException, IOException
  284. {
  285. setupParse();
  286. parent.parse(input);
  287. }
  288. /**
  289. * Parse a document.
  290. *
  291. * @param systemId The system identifier as a fully-qualified URI.
  292. * @exception org.xml.sax.SAXException Any SAX exception, possibly
  293. * wrapping another exception.
  294. * @exception java.io.IOException An IO exception from the parser,
  295. * possibly from a byte stream or character stream
  296. * supplied by the application.
  297. */
  298. public void parse (String systemId)
  299. throws SAXException, IOException
  300. {
  301. parse(new InputSource(systemId));
  302. }
  303. ////////////////////////////////////////////////////////////////////
  304. // Implementation of org.xml.sax.EntityResolver.
  305. ////////////////////////////////////////////////////////////////////
  306. /**
  307. * Filter an external entity resolution.
  308. *
  309. * @param publicId The entity's public identifier, or null.
  310. * @param systemId The entity's system identifier.
  311. * @return A new InputSource or null for the default.
  312. * @exception org.xml.sax.SAXException The client may throw
  313. * an exception during processing.
  314. * @exception java.io.IOException The client may throw an
  315. * I/O-related exception while obtaining the
  316. * new InputSource.
  317. */
  318. public InputSource resolveEntity (String publicId, String systemId)
  319. throws SAXException, IOException
  320. {
  321. if (entityResolver != null) {
  322. return entityResolver.resolveEntity(publicId, systemId);
  323. } else {
  324. return null;
  325. }
  326. }
  327. ////////////////////////////////////////////////////////////////////
  328. // Implementation of org.xml.sax.DTDHandler.
  329. ////////////////////////////////////////////////////////////////////
  330. /**
  331. * Filter a notation declaration event.
  332. *
  333. * @param name The notation name.
  334. * @param publicId The notation's public identifier, or null.
  335. * @param systemId The notation's system identifier, or null.
  336. * @exception org.xml.sax.SAXException The client may throw
  337. * an exception during processing.
  338. */
  339. public void notationDecl (String name, String publicId, String systemId)
  340. throws SAXException
  341. {
  342. if (dtdHandler != null) {
  343. dtdHandler.notationDecl(name, publicId, systemId);
  344. }
  345. }
  346. /**
  347. * Filter an unparsed entity declaration event.
  348. *
  349. * @param name The entity name.
  350. * @param publicId The entity's public identifier, or null.
  351. * @param systemId The entity's system identifier, or null.
  352. * @param notationName The name of the associated notation.
  353. * @exception org.xml.sax.SAXException The client may throw
  354. * an exception during processing.
  355. */
  356. public void unparsedEntityDecl (String name, String publicId,
  357. String systemId, String notationName)
  358. throws SAXException
  359. {
  360. if (dtdHandler != null) {
  361. dtdHandler.unparsedEntityDecl(name, publicId, systemId,
  362. notationName);
  363. }
  364. }
  365. ////////////////////////////////////////////////////////////////////
  366. // Implementation of org.xml.sax.ContentHandler.
  367. ////////////////////////////////////////////////////////////////////
  368. /**
  369. * Filter a new document locator event.
  370. *
  371. * @param locator The document locator.
  372. */
  373. public void setDocumentLocator (Locator locator)
  374. {
  375. this.locator = locator;
  376. if (contentHandler != null) {
  377. contentHandler.setDocumentLocator(locator);
  378. }
  379. }
  380. /**
  381. * Filter a start document event.
  382. *
  383. * @exception org.xml.sax.SAXException The client may throw
  384. * an exception during processing.
  385. */
  386. public void startDocument ()
  387. throws SAXException
  388. {
  389. if (contentHandler != null) {
  390. contentHandler.startDocument();
  391. }
  392. }
  393. /**
  394. * Filter an end document event.
  395. *
  396. * @exception org.xml.sax.SAXException The client may throw
  397. * an exception during processing.
  398. */
  399. public void endDocument ()
  400. throws SAXException
  401. {
  402. if (contentHandler != null) {
  403. contentHandler.endDocument();
  404. }
  405. }
  406. /**
  407. * Filter a start Namespace prefix mapping event.
  408. *
  409. * @param prefix The Namespace prefix.
  410. * @param uri The Namespace URI.
  411. * @exception org.xml.sax.SAXException The client may throw
  412. * an exception during processing.
  413. */
  414. public void startPrefixMapping (String prefix, String uri)
  415. throws SAXException
  416. {
  417. if (contentHandler != null) {
  418. contentHandler.startPrefixMapping(prefix, uri);
  419. }
  420. }
  421. /**
  422. * Filter an end Namespace prefix mapping event.
  423. *
  424. * @param prefix The Namespace prefix.
  425. * @exception org.xml.sax.SAXException The client may throw
  426. * an exception during processing.
  427. */
  428. public void endPrefixMapping (String prefix)
  429. throws SAXException
  430. {
  431. if (contentHandler != null) {
  432. contentHandler.endPrefixMapping(prefix);
  433. }
  434. }
  435. /**
  436. * Filter a start element event.
  437. *
  438. * @param uri The element's Namespace URI, or the empty string.
  439. * @param localName The element's local name, or the empty string.
  440. * @param qName The element's qualified (prefixed) name, or the empty
  441. * string.
  442. * @param atts The element's attributes.
  443. * @exception org.xml.sax.SAXException The client may throw
  444. * an exception during processing.
  445. */
  446. public void startElement (String uri, String localName, String qName,
  447. Attributes atts)
  448. throws SAXException
  449. {
  450. if (contentHandler != null) {
  451. contentHandler.startElement(uri, localName, qName, atts);
  452. }
  453. }
  454. /**
  455. * Filter an end element event.
  456. *
  457. * @param uri The element's Namespace URI, or the empty string.
  458. * @param localName The element's local name, or the empty string.
  459. * @param qName The element's qualified (prefixed) name, or the empty
  460. * string.
  461. * @exception org.xml.sax.SAXException The client may throw
  462. * an exception during processing.
  463. */
  464. public void endElement (String uri, String localName, String qName)
  465. throws SAXException
  466. {
  467. if (contentHandler != null) {
  468. contentHandler.endElement(uri, localName, qName);
  469. }
  470. }
  471. /**
  472. * Filter a character data event.
  473. *
  474. * @param ch An array of characters.
  475. * @param start The starting position in the array.
  476. * @param length The number of characters to use from the array.
  477. * @exception org.xml.sax.SAXException The client may throw
  478. * an exception during processing.
  479. */
  480. public void characters (char ch[], int start, int length)
  481. throws SAXException
  482. {
  483. if (contentHandler != null) {
  484. contentHandler.characters(ch, start, length);
  485. }
  486. }
  487. /**
  488. * Filter an ignorable whitespace event.
  489. *
  490. * @param ch An array of characters.
  491. * @param start The starting position in the array.
  492. * @param length The number of characters to use from the array.
  493. * @exception org.xml.sax.SAXException The client may throw
  494. * an exception during processing.
  495. */
  496. public void ignorableWhitespace (char ch[], int start, int length)
  497. throws SAXException
  498. {
  499. if (contentHandler != null) {
  500. contentHandler.ignorableWhitespace(ch, start, length);
  501. }
  502. }
  503. /**
  504. * Filter a processing instruction event.
  505. *
  506. * @param target The processing instruction target.
  507. * @param data The text following the target.
  508. * @exception org.xml.sax.SAXException The client may throw
  509. * an exception during processing.
  510. */
  511. public void processingInstruction (String target, String data)
  512. throws SAXException
  513. {
  514. if (contentHandler != null) {
  515. contentHandler.processingInstruction(target, data);
  516. }
  517. }
  518. /**
  519. * Filter a skipped entity event.
  520. *
  521. * @param name The name of the skipped entity.
  522. * @exception org.xml.sax.SAXException The client may throw
  523. * an exception during processing.
  524. */
  525. public void skippedEntity (String name)
  526. throws SAXException
  527. {
  528. if (contentHandler != null) {
  529. contentHandler.skippedEntity(name);
  530. }
  531. }
  532. ////////////////////////////////////////////////////////////////////
  533. // Implementation of org.xml.sax.ErrorHandler.
  534. ////////////////////////////////////////////////////////////////////
  535. /**
  536. * Filter a warning event.
  537. *
  538. * @param e The warning as an exception.
  539. * @exception org.xml.sax.SAXException The client may throw
  540. * an exception during processing.
  541. */
  542. public void warning (SAXParseException e)
  543. throws SAXException
  544. {
  545. if (errorHandler != null) {
  546. errorHandler.warning(e);
  547. }
  548. }
  549. /**
  550. * Filter an error event.
  551. *
  552. * @param e The error as an exception.
  553. * @exception org.xml.sax.SAXException The client may throw
  554. * an exception during processing.
  555. */
  556. public void error (SAXParseException e)
  557. throws SAXException
  558. {
  559. if (errorHandler != null) {
  560. errorHandler.error(e);
  561. }
  562. }
  563. /**
  564. * Filter a fatal error event.
  565. *
  566. * @param e The error as an exception.
  567. * @exception org.xml.sax.SAXException The client may throw
  568. * an exception during processing.
  569. */
  570. public void fatalError (SAXParseException e)
  571. throws SAXException
  572. {
  573. if (errorHandler != null) {
  574. errorHandler.fatalError(e);
  575. }
  576. }
  577. ////////////////////////////////////////////////////////////////////
  578. // Internal methods.
  579. ////////////////////////////////////////////////////////////////////
  580. /**
  581. * Set up before a parse.
  582. *
  583. * <p>Before every parse, check whether the parent is
  584. * non-null, and re-register the filter for all of the
  585. * events.</p>
  586. */
  587. private void setupParse ()
  588. {
  589. if (parent == null) {
  590. throw new NullPointerException("No parent for filter");
  591. }
  592. parent.setEntityResolver(this);
  593. parent.setDTDHandler(this);
  594. parent.setContentHandler(this);
  595. parent.setErrorHandler(this);
  596. }
  597. ////////////////////////////////////////////////////////////////////
  598. // Internal state.
  599. ////////////////////////////////////////////////////////////////////
  600. private XMLReader parent = null;
  601. private Locator locator = null;
  602. private EntityResolver entityResolver = null;
  603. private DTDHandler dtdHandler = null;
  604. private ContentHandler contentHandler = null;
  605. private ErrorHandler errorHandler = null;
  606. }
  607. // end of XMLFilterImpl.java