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