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