001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.utils;
007:
008: import java.io.IOException;
009:
010: import org.xml.sax.Attributes;
011: import org.xml.sax.ContentHandler;
012: import org.xml.sax.DTDHandler;
013: import org.xml.sax.EntityResolver;
014: import org.xml.sax.ErrorHandler;
015: import org.xml.sax.InputSource;
016: import org.xml.sax.Locator;
017: import org.xml.sax.SAXException;
018: import org.xml.sax.SAXParseException;
019: import org.xml.sax.XMLReader;
020: import org.xml.sax.ext.LexicalHandler;
021:
022: /**
023: * This is a remake of <code>org.xml.sax.helpers.XMLFilterImpl</code>
024: * that allows for downward chaining of LexicalHandlers, and further extensions.
025: * <p>Some of the behavior is slightly different from that of hte XMLFilterImpl.
026: * For example this implementation allows to set null handlers. It also redirects parent's handlers
027: * right after instantiation or setParent() invokation, not just at the parse().</p>
028: * @see org.xml.sax.helpers.XMLFilterImpl
029: */
030: public class SAX2DuplicatingFilterImpl extends SAX2FilterImpl {
031:
032: // Internal state
033: protected EntityResolver entityResolver2 = null;
034: protected DTDHandler dtdHandler2 = null;
035: protected ContentHandler contentHandler2 = null;
036: protected ErrorHandler errorHandler2 = null;
037: protected LexicalHandler lexicalHandler2 = null;
038:
039: // Constructors
040:
041: /**
042: * Construct an empty XML filter, with no parent.
043: *
044: * <p>This filter will have no parent: you must assign a parent
045: * before you start a parse or do any configuration with
046: * setFeature or setProperty.</p>
047: *
048: * @see org.xml.sax.XMLReader#setFeature
049: * @see org.xml.sax.XMLReader#setProperty
050: */
051: public SAX2DuplicatingFilterImpl() {
052: super ();
053: }
054:
055: /**
056: * Construct an XML filter with the specified parent.
057: *
058: * @see #setParent(XMLReader)
059: * @see #getParent()
060: */
061: public SAX2DuplicatingFilterImpl(XMLReader parent) {
062: super ();
063: setParent(parent);
064: }
065:
066: /**
067: * Construct an XML filter with the specified children handlers.
068: * @see #setContentHandler(ContentHandler)
069: * @see #setDTDHandler(DTDHandler)
070: * @see #setErrorHandler(ErrorHandler)
071: * @see #setEntityResolver(EntityResolver)
072: * @see #setLexicalHandler(LexicalHandler)
073: */
074: public SAX2DuplicatingFilterImpl(ContentHandler ch,
075: EntityResolver er, ErrorHandler eh, LexicalHandler lh,
076: DTDHandler dh, ContentHandler ch2, EntityResolver er2,
077: ErrorHandler eh2, LexicalHandler lh2, DTDHandler dh2) {
078: super (ch, er, eh, lh, dh);
079: setContentHandler2(ch2);
080: setErrorHandler2(eh2);
081: setDTDHandler2(dh2);
082: setLexicalHandler2(lh2);
083: }
084:
085: /**
086: * Try to imply all of the handlers from ContentHandler alone.
087: */
088: public SAX2DuplicatingFilterImpl(ContentHandler ch,
089: ContentHandler ch2) {
090: super (ch);
091: setAllHandlers(ch, ch2);
092: }
093:
094: /**
095: * Try to imply all of the handlers from ContentHandler alone.
096: */
097: public void setAllHandlers(ContentHandler ch, ContentHandler ch2) {
098: super .setAllHandlers(ch);
099: setContentHandler2(ch2);
100: if (ch2 instanceof ErrorHandler) {
101: setErrorHandler2((ErrorHandler) ch2);
102: }
103: if (ch2 instanceof DTDHandler) {
104: setDTDHandler2((DTDHandler) ch2);
105: }
106: if (ch2 instanceof LexicalHandler) {
107: setLexicalHandler2((LexicalHandler) ch2);
108: }
109: }
110:
111: ////////////////////////////////////////////////////////////////////
112: // Implementation of org.xml.sax.XMLReader.
113: ////////////////////////////////////////////////////////////////////
114:
115: /**
116: * Set the DTD event handler.
117: *
118: * @param handler The new DTD handler.
119: * @see org.xml.sax.XMLReader#setDTDHandler
120: */
121: public void setDTDHandler2(DTDHandler handler) {
122: dtdHandler2 = handler;
123: }
124:
125: /**
126: * Get the current DTD event handler.
127: *
128: * @return The current DTD handler, or null if none was set.
129: * @see org.xml.sax.XMLReader#getDTDHandler
130: */
131: public DTDHandler getDTDHandler2() {
132: return dtdHandler2;
133: }
134:
135: /**
136: * Set the content event handler.
137: *
138: * @param handler The new content handler.
139: * @see org.xml.sax.XMLReader#setContentHandler
140: */
141: public void setContentHandler2(ContentHandler handler) {
142: contentHandler2 = handler;
143: }
144:
145: /**
146: * Get the content event handler.
147: *
148: * @return The current content handler, or null if none was set.
149: * @see org.xml.sax.XMLReader#getContentHandler
150: */
151: public ContentHandler getContentHandler2() {
152: return contentHandler2;
153: }
154:
155: /**
156: * Set the error event handler.
157: *
158: * @param handler The new error handler.
159: * @see org.xml.sax.XMLReader#setErrorHandler
160: */
161: public void setErrorHandler2(ErrorHandler handler) {
162: errorHandler2 = handler;
163: }
164:
165: /**
166: * Set the lexical handler.
167: *
168: * @param handler The new lexical handler.
169: */
170: public void setLexicalHandler2(LexicalHandler handler) {
171: this .lexicalHandler2 = handler;
172: /*
173: if(lexicalHandler2!=null) {
174: try {
175: parent.setProperty("http://xml.org/sax/handlers/LexicalHandler",this);
176: } catch (SAXNotRecognizedException e1) {}
177: catch (SAXNotSupportedException e2) {};
178: }
179: */
180: }
181:
182: /**
183: * Get the current error event handler.
184: *
185: * @return The current error handler, or null if none was set.
186: * @see org.xml.sax.XMLReader#getErrorHandler
187: */
188: public ErrorHandler getErrorHandler2() {
189: return errorHandler2;
190: }
191:
192: ////////////////////////////////////////////////////////////////////
193: // Implementation of org.xml.sax.ext.LexicalHandler.
194: ////////////////////////////////////////////////////////////////////
195:
196: /**
197: * Filter startDTD event.
198: * @param name The document type name.
199: * @param publicId The declared public identifier for the
200: * external DTD subset, or null if none was declared.
201: * @param systemId The declared system identifier for the
202: * external DTD subset, or null if none was declared.
203: * @exception SAXException The application may raise an
204: * exception.
205: * @see #endDTD
206: * @see #startEntity
207: */
208: public void startDTD(String name, String publicId, String systemId)
209: throws SAXException {
210: if (lexicalHandler != null) {
211: lexicalHandler.startDTD(name, publicId, systemId);
212: }
213: if (lexicalHandler2 != null) {
214: lexicalHandler2.startDTD(name, publicId, systemId);
215: }
216: }
217:
218: /**
219: * Filter endDTD event
220: *
221: * @exception SAXException The application may raise an exception.
222: * @see #startDTD
223: */
224: public void endDTD() throws SAXException {
225: if (lexicalHandler != null) {
226: lexicalHandler.endDTD();
227: }
228: if (lexicalHandler2 != null) {
229: lexicalHandler2.endDTD();
230: }
231: }
232:
233: /**
234: * Filter startEntity event.
235: *
236: * @param name The name of the entity. If it is a parameter
237: * entity, the name will begin with '%'.
238: * @exception SAXException The application may raise an exception.
239: * @see #endEntity
240: * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
241: * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
242: */
243: public void startEntity(String name) throws SAXException {
244: if (lexicalHandler != null) {
245: lexicalHandler.startEntity(name);
246: }
247: if (lexicalHandler2 != null) {
248: lexicalHandler2.startEntity(name);
249: }
250: }
251:
252: /**
253: * Filter endEntity event.
254: *
255: * @param name The name of the entity that is ending.
256: * @exception SAXException The application may raise an exception.
257: * @see #startEntity
258: */
259: public void endEntity(String name) throws SAXException {
260: if (lexicalHandler != null) {
261: lexicalHandler.endEntity(name);
262: }
263: if (lexicalHandler2 != null) {
264: lexicalHandler2.endEntity(name);
265: }
266: }
267:
268: /**
269: * Filter startCDATA event.
270: *
271: * @exception SAXException The application may raise an exception.
272: * @see #endCDATA
273: */
274: public void startCDATA() throws SAXException {
275: if (lexicalHandler != null) {
276: lexicalHandler.startCDATA();
277: }
278: if (lexicalHandler2 != null) {
279: lexicalHandler2.startCDATA();
280: }
281: }
282:
283: /**
284: * Filter endCDATA event.
285: *
286: * @exception SAXException The application may raise an exception.
287: * @see #startCDATA
288: */
289: public void endCDATA() throws SAXException {
290: if (lexicalHandler != null) {
291: lexicalHandler.endCDATA();
292: }
293: if (lexicalHandler2 != null) {
294: lexicalHandler2.endCDATA();
295: }
296: }
297:
298: /**
299: * Filter comment event.
300: *
301: * @param ch An array holding the characters in the comment.
302: * @param start The starting position in the array.
303: * @param length The number of characters to use from the array.
304: * @exception SAXException The application may raise an exception.
305: */
306: public void comment(char ch[], int start, int length)
307: throws SAXException {
308: if (lexicalHandler != null) {
309: lexicalHandler.comment(ch, start, length);
310: }
311: if (lexicalHandler2 != null) {
312: lexicalHandler2.comment(ch, start, length);
313: }
314: }
315:
316: ////////////////////////////////////////////////////////////////////
317: // Implementation of org.xml.sax.EntityResolver.
318: ////////////////////////////////////////////////////////////////////
319:
320: /**
321: * Filter an external entity resolution.
322: *
323: * @param publicId The entity's public identifier, or null.
324: * @param systemId The entity's system identifier.
325: * @return A new InputSource or null for the default.
326: * @exception org.xml.sax.SAXException The client may throw
327: * an exception during processing.
328: * @exception java.io.IOException The client may throw an
329: * I/O-related exception while obtaining the
330: * new InputSource.
331: * @see org.xml.sax.EntityResolver#resolveEntity
332: */
333: public InputSource resolveEntity(String publicId, String systemId)
334: throws SAXException, IOException {
335: if (entityResolver != null) {
336: return entityResolver.resolveEntity(publicId, systemId);
337: } else {
338: return null;
339: }
340: }
341:
342: ////////////////////////////////////////////////////////////////////
343: // Implementation of org.xml.sax.DTDHandler.
344: ////////////////////////////////////////////////////////////////////
345:
346: /**
347: * Filter a notation declaration event.
348: *
349: * @param name The notation name.
350: * @param publicId The notation's public identifier, or null.
351: * @param systemId The notation's system identifier, or null.
352: * @exception org.xml.sax.SAXException The client may throw
353: * an exception during processing.
354: * @see org.xml.sax.DTDHandler#notationDecl
355: */
356: public void notationDecl(String name, String publicId,
357: String systemId) throws SAXException {
358: if (dtdHandler != null) {
359: dtdHandler.notationDecl(name, publicId, systemId);
360: }
361: if (dtdHandler2 != null) {
362: dtdHandler2.notationDecl(name, publicId, systemId);
363: }
364: }
365:
366: /**
367: * Filter an unparsed entity declaration event.
368: *
369: * @param name The entity name.
370: * @param publicId The entity's public identifier, or null.
371: * @param systemId The entity's system identifier, or null.
372: * @param notationName The name of the associated notation.
373: * @exception org.xml.sax.SAXException The client may throw
374: * an exception during processing.
375: * @see org.xml.sax.DTDHandler#unparsedEntityDecl
376: */
377: public void unparsedEntityDecl(String name, String publicId,
378: String systemId, String notationName) throws SAXException {
379: if (dtdHandler != null) {
380: dtdHandler.unparsedEntityDecl(name, publicId, systemId,
381: notationName);
382: }
383: if (dtdHandler2 != null) {
384: dtdHandler.unparsedEntityDecl(name, publicId, systemId,
385: notationName);
386: }
387: }
388:
389: ////////////////////////////////////////////////////////////////////
390: // Implementation of org.xml.sax.ContentHandler.
391: ////////////////////////////////////////////////////////////////////
392:
393: /**
394: * Filter a new document locator event.
395: *
396: * @param locator The document locator.
397: * @see org.xml.sax.ContentHandler#setDocumentLocator
398: */
399: public void setDocumentLocator(Locator locator) {
400: this .locator = locator;
401: if (contentHandler != null) {
402: contentHandler.setDocumentLocator(locator);
403: }
404: if (contentHandler2 != null) {
405: contentHandler2.setDocumentLocator(locator);
406: }
407: }
408:
409: /**
410: * Filter a start document event.
411: *
412: * @exception org.xml.sax.SAXException The client may throw
413: * an exception during processing.
414: * @see org.xml.sax.ContentHandler#startDocument
415: */
416: public void startDocument() throws SAXException {
417: if (contentHandler != null) {
418: contentHandler.startDocument();
419: }
420: if (contentHandler2 != null) {
421: contentHandler2.startDocument();
422: }
423: }
424:
425: /**
426: * Filter an end document event.
427: *
428: * @exception org.xml.sax.SAXException The client may throw
429: * an exception during processing.
430: * @see org.xml.sax.ContentHandler#endDocument
431: */
432: public void endDocument() throws SAXException {
433: if (log.isTraceEnabled()) {
434: log.trace("ending document");
435: }
436:
437: if (contentHandler != null) {
438: contentHandler.endDocument();
439: }
440: if (contentHandler2 != null) {
441: contentHandler2.endDocument();
442: }
443: }
444:
445: /**
446: * Filter a start Namespace prefix mapping event.
447: *
448: * @param prefix The Namespace prefix.
449: * @param uri The Namespace URI.
450: * @exception org.xml.sax.SAXException The client may throw
451: * an exception during processing.
452: * @see org.xml.sax.ContentHandler#startPrefixMapping
453: */
454: public void startPrefixMapping(String prefix, String uri)
455: throws SAXException {
456: if (contentHandler != null) {
457: contentHandler.startPrefixMapping(prefix, uri);
458: }
459: if (contentHandler2 != null) {
460: contentHandler2.startPrefixMapping(prefix, uri);
461: }
462: }
463:
464: /**
465: * Filter an end Namespace prefix mapping event.
466: *
467: * @param prefix The Namespace prefix.
468: * @exception org.xml.sax.SAXException The client may throw
469: * an exception during processing.
470: * @see org.xml.sax.ContentHandler#endPrefixMapping
471: */
472: public void endPrefixMapping(String prefix) throws SAXException {
473: if (contentHandler != null) {
474: contentHandler.endPrefixMapping(prefix);
475: }
476: if (contentHandler2 != null) {
477: contentHandler2.endPrefixMapping(prefix);
478: }
479: }
480:
481: /**
482: * Filter a start element event.
483: *
484: * @param uri The element's Namespace URI, or the empty string.
485: * @param localName The element's local name, or the empty string.
486: * @param qName The element's qualified (prefixed) name, or the empty
487: * string.
488: * @param atts The element's attributes.
489: * @exception org.xml.sax.SAXException The client may throw
490: * an exception during processing.
491: * @see org.xml.sax.ContentHandler#startElement
492: */
493: public void startElement(String uri, String localName,
494: String qName, Attributes atts) throws SAXException {
495: if (contentHandler != null) {
496: contentHandler.startElement(uri, localName, qName, atts);
497: }
498: if (contentHandler2 != null) {
499: contentHandler2.startElement(uri, localName, qName, atts);
500: }
501: }
502:
503: /**
504: * Filter an end element event.
505: *
506: * @param uri The element's Namespace URI, or the empty string.
507: * @param localName The element's local name, or the empty string.
508: * @param qName The element's qualified (prefixed) name, or the empty
509: * string.
510: * @exception org.xml.sax.SAXException The client may throw
511: * an exception during processing.
512: * @see org.xml.sax.ContentHandler#endElement
513: */
514: public void endElement(String uri, String localName, String qName)
515: throws SAXException {
516: if (contentHandler != null) {
517: contentHandler.endElement(uri, localName, qName);
518: }
519: if (contentHandler2 != null) {
520: contentHandler2.endElement(uri, localName, qName);
521: }
522: }
523:
524: /**
525: * Filter a character data event.
526: *
527: * @param ch An array of characters.
528: * @param start The starting position in the array.
529: * @param length The number of characters to use from the array.
530: * @exception org.xml.sax.SAXException The client may throw
531: * an exception during processing.
532: * @see org.xml.sax.ContentHandler#characters
533: */
534: public void characters(char ch[], int start, int length)
535: throws SAXException {
536: if (contentHandler != null) {
537: contentHandler.characters(ch, start, length);
538: }
539: if (contentHandler2 != null) {
540: contentHandler2.characters(ch, start, length);
541: }
542: }
543:
544: /**
545: * Filter an ignorable whitespace event.
546: *
547: * @param ch An array of characters.
548: * @param start The starting position in the array.
549: * @param length The number of characters to use from the array.
550: * @exception org.xml.sax.SAXException The client may throw
551: * an exception during processing.
552: * @see org.xml.sax.ContentHandler#ignorableWhitespace
553: */
554: public void ignorableWhitespace(char ch[], int start, int length)
555: throws SAXException {
556: if (contentHandler != null) {
557: contentHandler.ignorableWhitespace(ch, start, length);
558: }
559: if (contentHandler2 != null) {
560: contentHandler2.ignorableWhitespace(ch, start, length);
561: }
562: }
563:
564: /**
565: * Filter a processing instruction event.
566: *
567: * @param target The processing instruction target.
568: * @param data The text following the target.
569: * @exception org.xml.sax.SAXException The client may throw
570: * an exception during processing.
571: * @see org.xml.sax.ContentHandler#processingInstruction
572: */
573: public void processingInstruction(String target, String data)
574: throws SAXException {
575: if (contentHandler != null) {
576: contentHandler.processingInstruction(target, data);
577: }
578: if (contentHandler2 != null) {
579: contentHandler2.processingInstruction(target, data);
580: }
581: }
582:
583: /**
584: * Filter a skipped entity event.
585: *
586: * @param name The name of the skipped entity.
587: * @exception org.xml.sax.SAXException The client may throw
588: * an exception during processing.
589: * @see org.xml.sax.ContentHandler#skippedEntity
590: */
591: public void skippedEntity(String name) throws SAXException {
592: if (contentHandler != null) {
593: contentHandler.skippedEntity(name);
594: }
595: if (contentHandler2 != null) {
596: contentHandler2.skippedEntity(name);
597: }
598: }
599:
600: ////////////////////////////////////////////////////////////////////
601: // Implementation of org.xml.sax.ErrorHandler.
602: ////////////////////////////////////////////////////////////////////
603:
604: /**
605: * Filter a warning event.
606: *
607: * @param e The nwarning as an exception.
608: * @exception org.xml.sax.SAXException The client may throw
609: * an exception during processing.
610: * @see org.xml.sax.ErrorHandler#warning
611: */
612: public void warning(SAXParseException e) throws SAXException {
613: log.warn("SAX2DuplicatingFilterImpl.warning()", e);
614:
615: if (errorHandler != null) {
616: errorHandler.warning(e);
617: }
618: if (errorHandler2 != null) {
619: errorHandler2.warning(e);
620: }
621: }
622:
623: /**
624: * Filter an error event.
625: *
626: * @param e The error as an exception.
627: * @exception org.xml.sax.SAXException The client may throw
628: * an exception during processing.
629: * @see org.xml.sax.ErrorHandler#error
630: */
631: public void error(SAXParseException e) throws SAXException {
632: log.error("SAX2DuplicatingFilterImpl.error()", e);
633: if (errorHandler != null) {
634: errorHandler.error(e);
635: }
636: if (errorHandler2 != null) {
637: errorHandler2.error(e);
638: }
639: }
640:
641: /**
642: * Filter a fatal error event.
643: *
644: * @param e The error as an exception.
645: * @exception org.xml.sax.SAXException The client may throw
646: * an exception during processing.
647: * @see org.xml.sax.ErrorHandler#fatalError
648: */
649: public void fatalError(SAXParseException e) throws SAXException {
650: log.fatal("SAX2DuplicatingFilterImpl.fatalError()", e);
651:
652: if (errorHandler != null) {
653: errorHandler.fatalError(e);
654: }
655: if (errorHandler2 != null) {
656: errorHandler2.fatalError(e);
657: }
658: }
659:
660: }
|