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