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