View Javadoc

1   package net.sf.tomp.xtcl.filter;
2   
3   import org.xml.sax.Attributes;
4   import org.xml.sax.ContentHandler;
5   import org.xml.sax.DTDHandler;
6   import org.xml.sax.EntityResolver;
7   import org.xml.sax.ErrorHandler;
8   import org.xml.sax.InputSource;
9   import org.xml.sax.Locator;
10  import org.xml.sax.SAXException;
11  import org.xml.sax.SAXNotRecognizedException;
12  import org.xml.sax.SAXNotSupportedException;
13  import org.xml.sax.SAXParseException;
14  import org.xml.sax.XMLReader;
15  import org.xml.sax.ext.LexicalHandler;
16  
17  import java.io.IOException;
18  
19  /***
20   * DOCUMENT ME!
21   *
22   * @author tomp
23   */
24  public class XTFilterImpl implements XTFilter
25  {
26      ////////////////////////////////////////////////////////////////////
27      // Internal state.
28      ////////////////////////////////////////////////////////////////////
29  
30      /*** DOCUMENT ME! */
31      protected XMLReader parent = null;
32  
33      /*** DOCUMENT ME! */
34      protected Locator locator = null;
35  
36      /*** DOCUMENT ME! */
37      protected EntityResolver entityResolver = null;
38  
39      /*** DOCUMENT ME! */
40      protected DTDHandler dtdHandler = null;
41  
42      /*** DOCUMENT ME! */
43      protected ContentHandler contentHandler = null;
44  
45      /*** DOCUMENT ME! */
46      protected ErrorHandler errorHandler = null;
47  
48      /*** DOCUMENT ME! */
49      protected LexicalHandler lexicalHandler = null;
50  
51      ////////////////////////////////////////////////////////////////////
52      // Constructors.
53      ////////////////////////////////////////////////////////////////////
54  
55      /***
56       * Construct an empty XML filter, with no parent.
57       * <p>
58       * This filter will have no parent: you must assign a parent before you
59       * start a parse or do any configuration with setFeature or setProperty,
60       * unless you use this as a pure event consumer rather than as an {@link
61       * XMLReader}.
62       * </p>
63       *
64       * @see org.xml.sax.XMLReader#setFeature
65       * @see org.xml.sax.XMLReader#setProperty
66       * @see #setParent
67       */
68      public XTFilterImpl()
69      {
70          super();
71      }
72  
73      /***
74       * Construct an XML filter with the specified parent.
75       *
76       * @param parent DOCUMENT ME!
77       * @see #setParent
78       * @see #getParent
79       */
80      public XTFilterImpl(XMLReader parent)
81      {
82          super();
83          setParent(parent);
84      }
85  
86      //protected Map params = new HashMap();
87      public void setParameter(String k, Object v)
88      {
89          //params.put(k, v);
90          //System.out.println("Setting param "+k+"="+v);
91          throw new UnsupportedOperationException("Cannot set parameters to "
92              + this);
93      }
94  
95      ////////////////////////////////////////////////////////////////////
96      // Implementation of org.xml.sax.XMLFilter.
97      ////////////////////////////////////////////////////////////////////
98  
99      /***
100      * Set the parent reader.
101      * <p>
102      * This is the {@link org.xml.sax.XMLReader XMLReader}from which this
103      * filter will obtain its events and to which it will pass its configuration
104      * requests. The parent may itself be another filter.
105      * </p>
106      * <p>
107      * If there is no parent reader set, any attempt to parse or to set or get a
108      * feature or property will fail.
109      * </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      * 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     // Implementation of org.xml.sax.XMLReader.
132     ////////////////////////////////////////////////////////////////////
133 
134     /***
135      * Set the value of a feature.
136      * <p>
137      * This will always fail if the parent is null.
138      * </p>
139      *
140      * @param name The feature name.
141      * @param value The requested feature value.
142      * @exception SAXNotRecognizedException If the feature value can't be
143      *                assigned or retrieved from the parent.
144      * @exception SAXNotSupportedException When the parent recognizes the
145      *                feature name but cannot set the requested value.
146      */
147     public void setFeature(String name, boolean value)
148         throws SAXNotRecognizedException, SAXNotSupportedException
149     {
150         if (parent != null)
151         {
152             parent.setFeature(name, value);
153         }
154         else
155         {
156             throw new SAXNotRecognizedException("Feature: " + name);
157         }
158     }
159 
160     /***
161      * Look up the value of a feature.
162      * <p>
163      * This will always fail if the parent is null.
164      * </p>
165      *
166      * @param name The feature name.
167      * @return The current value of the feature.
168      * @exception SAXNotRecognizedException If the feature value can't be
169      *                assigned or retrieved from the parent.
170      * @exception SAXNotSupportedException When the parent recognizes the
171      *                feature name but cannot determine its value at this time.
172      */
173     public boolean getFeature(String name)
174         throws SAXNotRecognizedException, SAXNotSupportedException
175     {
176         if (parent != null)
177         {
178             return parent.getFeature(name);
179         }
180         else
181         {
182             throw new SAXNotRecognizedException("Feature: " + name);
183         }
184     }
185 
186     /***
187      * Set the value of a property.
188      * <p>
189      * This will always fail if the parent is null.
190      * </p>
191      *
192      * @param name The property name.
193      * @param value The requested property value.
194      * @exception SAXNotRecognizedException If the property value can't be
195      *                assigned or retrieved from the parent.
196      * @exception SAXNotSupportedException When the parent recognizes the
197      *                property name but cannot set the requested value.
198      */
199     public void setProperty(String name, Object value)
200         throws SAXNotRecognizedException, SAXNotSupportedException
201     {
202         if ("http://xml.org/sax/properties/lexical-handler".equals(name))
203         {
204             setLexicalHandler((LexicalHandler) value);
205         }
206         else if (parent != null)
207         {
208             parent.setProperty(name, value);
209         }
210         else
211         {
212             throw new SAXNotRecognizedException("Property: " + name);
213         }
214     }
215 
216     /***
217      * Look up the value of a property.
218      *
219      * @param name The property name.
220      * @return The current value of the property.
221      * @exception SAXNotRecognizedException If the property value can't be
222      *                assigned or retrieved from the parent.
223      * @exception SAXNotSupportedException When the parent recognizes the
224      *                property name but cannot determine its value at this time.
225      */
226     public Object getProperty(String name)
227         throws SAXNotRecognizedException, SAXNotSupportedException
228     {
229         if ("http://xml.org/sax/properties/lexical-handler".equals(name))
230         {
231             return getLexicalHandler();
232         }
233         else if (parent != null)
234         {
235             return parent.getProperty(name);
236         }
237         else
238         {
239             throw new SAXNotRecognizedException("Property: " + name);
240         }
241     }
242 
243     /***
244      * Set the entity resolver.
245      *
246      * @param resolver The new entity resolver.
247      */
248     public void setEntityResolver(EntityResolver resolver)
249     {
250         entityResolver = resolver;
251     }
252 
253     /***
254      * Get the current entity resolver.
255      *
256      * @return The current entity resolver, or null if none was set.
257      */
258     public EntityResolver getEntityResolver()
259     {
260         return entityResolver;
261     }
262 
263     /***
264      * Set the DTD event handler.
265      *
266      * @param handler The new DTD handler.
267      */
268     public void setDTDHandler(DTDHandler handler)
269     {
270         dtdHandler = handler;
271     }
272 
273     /***
274      * Get the current DTD event handler.
275      *
276      * @return The current DTD handler, or null if none was set.
277      */
278     public DTDHandler getDTDHandler()
279     {
280         return dtdHandler;
281     }
282 
283     /***
284      * Set the content event handler.
285      *
286      * @param handler The new content handler.
287      */
288     public void setContentHandler(ContentHandler handler)
289     {
290         //System.out.println(""+this+".setContentHandler="+handler);
291         contentHandler = handler;
292     }
293 
294     /***
295      * Get the content event handler.
296      *
297      * @return The current content handler, or null if none was set.
298      */
299     public ContentHandler getContentHandler()
300     {
301         //System.out.println(""+this+".getContentHandler=>"+contentHandler);
302         return contentHandler;
303     }
304 
305     /***
306      * Set the lexical event handler.
307      *
308      * @param handler The new lexical handler.
309      */
310     public void setLexicalHandler(LexicalHandler handler)
311     {
312         //System.out.println(""+this+".setContentHandler="+handler);
313         lexicalHandler = handler;
314     }
315 
316     /***
317      * Get the lexical event handler.
318      *
319      * @return The current lexical handler, or null if none was set.
320      */
321     public LexicalHandler getLexicalHandler()
322     {
323         //System.out.println(""+this+".getContentHandler=>"+contentHandler);
324         return lexicalHandler;
325     }
326 
327     /***
328      * Set the error event handler.
329      *
330      * @param handler The new error handler.
331      */
332     public void setErrorHandler(ErrorHandler handler)
333     {
334         errorHandler = handler;
335     }
336 
337     /***
338      * Get the current error event handler.
339      *
340      * @return The current error handler, or null if none was set.
341      */
342     public ErrorHandler getErrorHandler()
343     {
344         return errorHandler;
345     }
346 
347     /***
348      * Parse a document.
349      *
350      * @param input The input source for the document entity.
351      * @exception SAXException Any SAX exception, possibly wrapping another
352      *                exception.
353      * @exception IOException An IO exception from the parser, possibly from a
354      *                byte stream or character stream supplied by the
355      *                application.
356      */
357     public void parse(InputSource input)
358         throws SAXException, IOException
359     {
360         setupParse();
361 
362         //System.out.println("XTFilterImpl "+this+" will
363         // parse="+input.getSystemId());
364         parent.parse(input);
365     }
366 
367     /***
368      * Parse a document.
369      *
370      * @param systemId The system identifier as a fully-qualified URI.
371      * @exception SAXException Any SAX exception, possibly wrapping another
372      *                exception.
373      * @exception IOException An IO exception from the parser, possibly from a
374      *                byte stream or character stream supplied by the
375      *                application.
376      */
377     public void parse(String systemId)
378         throws SAXException, IOException
379     {
380         parse(new InputSource(systemId));
381     }
382 
383     ////////////////////////////////////////////////////////////////////
384     // Implementation of org.xml.sax.EntityResolver.
385     ////////////////////////////////////////////////////////////////////
386 
387     /***
388      * Filter an external entity resolution.
389      *
390      * @param publicId The entity's public identifier, or null.
391      * @param systemId The entity's system identifier.
392      * @return A new InputSource or null for the default.
393      * @exception SAXException The client may throw an exception during
394      *                processing.
395      * @exception IOException The client may throw an I/O-related exception
396      *                while obtaining the new InputSource.
397      */
398     public InputSource resolveEntity(String publicId, String systemId)
399         throws SAXException, IOException
400     {
401         if (entityResolver != null)
402         {
403             return entityResolver.resolveEntity(publicId, systemId);
404         }
405         else
406         {
407             return null;
408         }
409     }
410 
411     ////////////////////////////////////////////////////////////////////
412     // Implementation of org.xml.sax.DTDHandler.
413     ////////////////////////////////////////////////////////////////////
414 
415     /***
416      * Filter a notation declaration event.
417      *
418      * @param name The notation name.
419      * @param publicId The notation's public identifier, or null.
420      * @param systemId The notation's system identifier, or null.
421      * @exception SAXException The client may throw an exception during
422      *                processing.
423      */
424     public void notationDecl(String name, String publicId, String systemId)
425         throws SAXException
426     {
427         if (dtdHandler != null)
428         {
429             dtdHandler.notationDecl(name, publicId, systemId);
430         }
431     }
432 
433     /***
434      * Filter an unparsed entity declaration event.
435      *
436      * @param name The entity name.
437      * @param publicId The entity's public identifier, or null.
438      * @param systemId The entity's system identifier, or null.
439      * @param notationName The name of the associated notation.
440      * @exception SAXException The client may throw an exception during
441      *                processing.
442      */
443     public void unparsedEntityDecl(String name, String publicId,
444         String systemId, String notationName)
445         throws SAXException
446     {
447         if (dtdHandler != null)
448         {
449             dtdHandler.unparsedEntityDecl(name, publicId, systemId, notationName);
450         }
451     }
452 
453     ////////////////////////////////////////////////////////////////////
454     // Implementation of org.xml.sax.ContentHandler.
455     ////////////////////////////////////////////////////////////////////
456 
457     /***
458      * Filter a new document locator event.
459      *
460      * @param locator The document locator.
461      */
462     public void setDocumentLocator(Locator locator)
463     {
464         if ((locator == null) || (locator.getSystemId() == null))
465         {
466             //System.out.println("+++"+this+".(trying
467             // to)setDocumentLocator=null");
468             return;
469         }
470 
471         //System.out.println("+++"+this+".setDocumentLocator.getSystemId="+locator.getSystemId());
472         this.locator = locator;
473 
474         if (contentHandler != null)
475         {
476             //contentHandler.setDocumentLocator(locator);
477         }
478     }
479 
480     public Locator getDocumentLocator()
481     {
482         return locator;
483     }
484 
485     /***
486      * Filter a start document event.
487      *
488      * @exception SAXException The client may throw an exception during
489      *                processing.
490      */
491     public void startDocument()
492         throws SAXException
493     {
494         //System.out.println(""+this+".startDocument");
495         if (contentHandler != null)
496         {
497             contentHandler.startDocument();
498         }
499     }
500 
501     /***
502      * Filter an end document event.
503      *
504      * @exception SAXException The client may throw an exception during
505      *                processing.
506      */
507     public void endDocument()
508         throws SAXException
509     {
510         //System.out.println("--- XTFilterImpl "+this+".endDocument,
511         // ch="+contentHandler);
512         if (contentHandler != null)
513         {
514             contentHandler.endDocument();
515         }
516     }
517 
518     /***
519      * Filter a start Namespace prefix mapping event.
520      *
521      * @param prefix The Namespace prefix.
522      * @param uri The Namespace URI.
523      * @exception SAXException The client may throw an exception during
524      *                processing.
525      */
526     public void startPrefixMapping(String prefix, String uri)
527         throws SAXException
528     {
529         if (contentHandler != null)
530         {
531             contentHandler.startPrefixMapping(prefix, uri);
532         }
533     }
534 
535     /***
536      * Filter an end Namespace prefix mapping event.
537      *
538      * @param prefix The Namespace prefix.
539      * @exception SAXException The client may throw an exception during
540      *                processing.
541      */
542     public void endPrefixMapping(String prefix)
543         throws SAXException
544     {
545         if (contentHandler != null)
546         {
547             contentHandler.endPrefixMapping(prefix);
548         }
549     }
550 
551     /***
552      * Filter a start element event.
553      *
554      * @param uri The element's Namespace URI, or the empty string.
555      * @param localName The element's local name, or the empty string.
556      * @param qName The element's qualified (prefixed) name, or the empty
557      *            string.
558      * @param atts The element's attributes.
559      * @exception SAXException The client may throw an exception during
560      *                processing.
561      */
562     public void startElement(String uri, String localName, String qName,
563         Attributes atts) throws SAXException
564     {
565         if (contentHandler != null)
566         {
567             contentHandler.startElement(uri, localName, qName, atts);
568         }
569     }
570 
571     /***
572      * Filter an end element event.
573      *
574      * @param uri The element's Namespace URI, or the empty string.
575      * @param localName The element's local name, or the empty string.
576      * @param qName The element's qualified (prefixed) name, or the empty
577      *            string.
578      * @exception SAXException The client may throw an exception during
579      *                processing.
580      */
581     public void endElement(String uri, String localName, String qName)
582         throws SAXException
583     {
584         if (contentHandler != null)
585         {
586             contentHandler.endElement(uri, localName, qName);
587         }
588     }
589 
590     /***
591      * Filter a character data event.
592      *
593      * @param ch An array of characters.
594      * @param start The starting position in the array.
595      * @param length The number of characters to use from the array.
596      * @exception SAXException The client may throw an exception during
597      *                processing.
598      */
599     public void characters(char[] ch, int start, int length)
600         throws SAXException
601     {
602         if (contentHandler != null)
603         {
604             contentHandler.characters(ch, start, length);
605         }
606     }
607 
608     /***
609      * Filter an ignorable whitespace event.
610      *
611      * @param ch An array of characters.
612      * @param start The starting position in the array.
613      * @param length The number of characters to use from the array.
614      * @exception SAXException The client may throw an exception during
615      *                processing.
616      */
617     public void ignorableWhitespace(char[] ch, int start, int length)
618         throws SAXException
619     {
620         if (contentHandler != null)
621         {
622             contentHandler.ignorableWhitespace(ch, start, length);
623         }
624     }
625 
626     /***
627      * Filter a processing instruction event.
628      *
629      * @param target The processing instruction target.
630      * @param data The text following the target.
631      * @exception SAXException The client may throw an exception during
632      *                processing.
633      */
634     public void processingInstruction(String target, String data)
635         throws SAXException
636     {
637         if (contentHandler != null)
638         {
639             contentHandler.processingInstruction(target, data);
640         }
641     }
642 
643     /***
644      * Filter a skipped entity event.
645      *
646      * @param name The name of the skipped entity.
647      * @exception SAXException The client may throw an exception during
648      *                processing.
649      */
650     public void skippedEntity(String name)
651         throws SAXException
652     {
653         if (contentHandler != null)
654         {
655             contentHandler.skippedEntity(name);
656         }
657     }
658 
659     ////////////////////////////////////////////////////////////////////
660     // Implementation of org.xml.sax.ErrorHandler.
661     ////////////////////////////////////////////////////////////////////
662 
663     /***
664      * Filter a warning event.
665      *
666      * @param e The warning as an exception.
667      * @exception SAXException The client may throw an exception during
668      *                processing.
669      */
670     public void warning(SAXParseException e)
671         throws SAXException
672     {
673         if (errorHandler != null)
674         {
675             errorHandler.warning(e);
676         }
677     }
678 
679     /***
680      * Filter an error event.
681      *
682      * @param e The error as an exception.
683      * @exception SAXException The client may throw an exception during
684      *                processing.
685      */
686     public void error(SAXParseException e)
687         throws SAXException
688     {
689         if (errorHandler != null)
690         {
691             errorHandler.error(e);
692         }
693     }
694 
695     /***
696      * Filter a fatal error event.
697      *
698      * @param e The error as an exception.
699      * @exception SAXException The client may throw an exception during
700      *                processing.
701      */
702     public void fatalError(SAXParseException e)
703         throws SAXException
704     {
705         if (errorHandler != null)
706         {
707             errorHandler.fatalError(e);
708         }
709     }
710 
711     ////////////////////////////////////////////////////////////////////
712     // Implementation of the LexicalHandler.
713     ////////////////////////////////////////////////////////////////////
714 
715     /***
716      * Callback interface for SAX (part of LexicalHandler interface): not for
717      * application use
718      *
719      * @param ch DOCUMENT ME!
720      * @param start DOCUMENT ME!
721      * @param length DOCUMENT ME!
722      * @throws SAXException DOCUMENT ME!
723      */
724     public void comment(char[] ch, int start, int length)
725         throws SAXException
726     {
727         if (lexicalHandler != null)
728         {
729             lexicalHandler.comment(ch, start, length);
730         }
731     }
732 
733     // No-op methods to satisfy lexical handler interface
734 
735     /***
736      * Register the start of the DTD. Comments in the DTD are skipped because
737      * they are not part of the XPath data model
738      *
739      * @param name DOCUMENT ME!
740      * @param publicId DOCUMENT ME!
741      * @param systemId DOCUMENT ME!
742      * @throws SAXException DOCUMENT ME!
743      */
744     public void startDTD(String name, String publicId, String systemId)
745         throws SAXException
746     {
747         if (lexicalHandler != null)
748         {
749             lexicalHandler.startDTD(name, publicId, systemId);
750         }
751     }
752 
753     /***
754      * Register the end of the DTD. Comments in the DTD are skipped because they
755      * are not part of the XPath data model
756      *
757      * @throws SAXException DOCUMENT ME!
758      */
759     public void endDTD() throws SAXException
760     {
761         if (lexicalHandler != null)
762         {
763             lexicalHandler.endDTD();
764         }
765     }
766 
767     /***
768      * DOCUMENT ME!
769      *
770      * @param name DOCUMENT ME!
771      * @throws SAXException DOCUMENT ME!
772      */
773     public void startEntity(String name)
774         throws SAXException
775     {
776         if (lexicalHandler != null)
777         {
778             lexicalHandler.startEntity(name);
779         }
780     }
781 
782     /***
783      * DOCUMENT ME!
784      *
785      * @param name DOCUMENT ME!
786      * @throws SAXException DOCUMENT ME!
787      */
788     public void endEntity(String name)
789         throws SAXException
790     {
791         if (lexicalHandler != null)
792         {
793             lexicalHandler.endEntity(name);
794         }
795     }
796 
797     /***
798      * DOCUMENT ME!
799      *
800      * @throws SAXException DOCUMENT ME!
801      */
802     public void startCDATA() throws SAXException
803     {
804         if (lexicalHandler != null)
805         {
806             lexicalHandler.startCDATA();
807         }
808     }
809 
810     /***
811      * DOCUMENT ME!
812      *
813      * @throws SAXException DOCUMENT ME!
814      */
815     public void endCDATA() throws SAXException
816     {
817         if (lexicalHandler != null)
818         {
819             lexicalHandler.endCDATA();
820         }
821     }
822 
823     ////////////////////////////////////////////////////////////////////
824     // Internal methods.
825     ////////////////////////////////////////////////////////////////////
826 
827     /***
828      * Set up before a parse.
829      * <p>
830      * Before every parse, check whether the parent is non-null, and re-register
831      * the filter for all of the events.
832      * </p>
833      *
834      * @throws SAXException DOCUMENT ME!
835      * @throws NullPointerException DOCUMENT ME!
836      */
837     protected void setupParse()
838         throws SAXException
839     {
840         if (parent == null)
841         {
842             throw new NullPointerException("No parent for filter " + this);
843         }
844 
845         parent.setEntityResolver(this);
846         parent.setDTDHandler(this);
847         parent.setContentHandler(this);
848 
849         //System.out.println(parent+".setContentHandler("+this);
850         parent.setErrorHandler(this);
851 
852         try
853         {
854             parent.setProperty("http://xml.org/sax/properties/lexical-handler",
855                 this);
856         }
857         catch (SAXException se)
858         {
859             //se.printStackTrace();
860         }
861     }
862 }
863 
864 
865 /*
866  * The contents of this file are subject to the Mozilla Public License Version
867  * 1.1 (the "License"); you may not use this file except in compliance with the
868  * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
869  * Software distributed under the License is distributed on an "AS IS" basis,
870  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
871  * the specific language governing rights and limitations under the License. The
872  * Original Code is: all this file. The Initial Developer of the Original Code
873  * is: Tomas Pitner, Masaryk University in Brno, Czech Republic. Contributor(s):
874  */