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