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