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