Frames | No Frames |
1: /* EventFilter.java -- 2: Copyright (C) 1999,2000,2001 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package gnu.xml.pipeline; 39: 40: import java.lang.reflect.InvocationTargetException; 41: import java.lang.reflect.Method; 42: 43: import org.xml.sax.*; 44: import org.xml.sax.ext.*; 45: import org.xml.sax.helpers.XMLFilterImpl; 46: 47: import gnu.xml.aelfred2.ContentHandler2; 48: 49: /** 50: * A customizable event consumer, used to assemble various kinds of filters 51: * using SAX handlers and an optional second consumer. It can be constructed 52: * in two ways: <ul> 53: * 54: * <li> To serve as a passthrough, sending all events to a second consumer. 55: * The second consumer may be identified through {@link #getNext}. 56: * 57: * <li> To serve as a dead end, with all handlers null; 58: * {@link #getNext} returns null. 59: * 60: * </ul> 61: * 62: * <p> Additionally, SAX handlers may be assigned, which completely replace 63: * the "upstream" view (through {@link EventConsumer}) of handlers, initially 64: * null or the "next" consumer provided to the constructor. To make 65: * it easier to build specialized filter classes, this class implements 66: * all the standard SAX consumer handlers, and those implementations 67: * delegate "downstream" to the consumer accessed by {@link #getNext}. 68: * 69: * <p> The simplest way to create a custom a filter class is to create a 70: * subclass which overrides one or more handler interface methods. The 71: * constructor for that subclass then registers itself as a handler for 72: * those interfaces using a call such as <em>setContentHandler(this)</em>, 73: * so the "upstream" view of event delivery is modified from the state 74: * established in the base class constructor. That way, 75: * the overridden methods intercept those event callbacks 76: * as they go "downstream", and 77: * all other event callbacks will pass events to any next consumer. 78: * Overridden methods may invoke superclass methods (perhaps after modifying 79: * parameters) if they wish to delegate such calls. Such subclasses 80: * should use {@link #getErrorHandler} to report errors using the 81: * common error reporting mechanism. 82: * 83: * <p> Another important technique is to construct a filter consisting 84: * of only a few specific types of handler. For example, one could easily 85: * prune out lexical events or various declarations by providing handlers 86: * which don't pass those events downstream, or by providing null handlers. 87: * 88: * <hr /> 89: * 90: * <p> This may be viewed as the consumer oriented analogue of the SAX2 91: * {@link org.xml.sax.helpers.XMLFilterImpl XMLFilterImpl} class. 92: * Key differences include: <ul> 93: * 94: * <li> This fully separates consumer and producer roles: it 95: * does not implement the producer side <em>XMLReader</em> or 96: * <em>EntityResolver</em> interfaces, so it can only be used 97: * in "push" mode (it has no <em>parse()</em> methods). 98: * 99: * <li> "Extension" handlers are fully supported, enabling a 100: * richer set of application requirements. 101: * And it implements {@link EventConsumer}, which groups related 102: * consumer methods together, rather than leaving them separated. 103: * 104: * <li> The chaining which is visible is "downstream" to the next 105: * consumer, not "upstream" to the preceding producer. 106: * It supports "fan-in", where 107: * a consumer can be fed by several producers. (For "fan-out", 108: * see the {@link TeeConsumer} class.) 109: * 110: * <li> Event chaining is set up differently. It is intended to 111: * work "upstream" from terminus towards producer, during filter 112: * construction, as described above. 113: * This is part of an early binding model: 114: * events don't need to pass through stages which ignore them. 115: * 116: * <li> ErrorHandler support is separated, on the grounds that 117: * pipeline stages need to share the same error handling policy. 118: * For the same reason, error handler setup goes "downstream": 119: * when error handlers get set, they are passed to subsequent 120: * consumers. 121: * 122: * </ul> 123: * 124: * <p> The {@link #chainTo chainTo()} convenience routine supports chaining to 125: * an XMLFilterImpl, in its role as a limited functionality event 126: * consumer. Its event producer role ({@link XMLFilter}) is ignored. 127: * 128: * <hr /> 129: * 130: * <p> The {@link #bind bind()} routine may be used associate event pipelines 131: * with any kind of {@link XMLReader} that will produce the events. 132: * Such pipelines don't necessarily need to have any members which are 133: * implemented using this class. That routine has some intelligence 134: * which supports automatic changes to parser feature flags, letting 135: * event piplines become largely independent of the particular feature 136: * sets of parsers. 137: * 138: * @author David Brownell 139: */ 140: public class EventFilter 141: implements EventConsumer, ContentHandler2, DTDHandler, 142: LexicalHandler, DeclHandler 143: { 144: // SAX handlers 145: private ContentHandler docHandler, docNext; 146: private DTDHandler dtdHandler, dtdNext; 147: private LexicalHandler lexHandler, lexNext; 148: private DeclHandler declHandler, declNext; 149: // and ideally, one more for the stuff SAX2 doesn't show 150: 151: private Locator locator; 152: private EventConsumer next; 153: private ErrorHandler errHandler; 154: 155: 156: /** SAX2 URI prefix for standard feature flags. */ 157: public static final String FEATURE_URI 158: = "http://xml.org/sax/features/"; 159: /** SAX2 URI prefix for standard properties (mostly for handlers). */ 160: public static final String PROPERTY_URI 161: = "http://xml.org/sax/properties/"; 162: 163: /** SAX2 property identifier for {@link DeclHandler} events */ 164: public static final String DECL_HANDLER 165: = PROPERTY_URI + "declaration-handler"; 166: /** SAX2 property identifier for {@link LexicalHandler} events */ 167: public static final String LEXICAL_HANDLER 168: = PROPERTY_URI + "lexical-handler"; 169: 170: // 171: // These class objects will be null if the relevant class isn't linked. 172: // Small configurations (pJava and some kinds of embedded systems) need 173: // to facilitate smaller executables. So "instanceof" is undesirable 174: // when bind() sees if it can remove some stages. 175: // 176: // SECURITY NOTE: assuming all these classes are part of the same sealed 177: // package, there's no problem saving these in the instance of this class 178: // that's associated with "this" class loader. But that wouldn't be true 179: // for classes in another package. 180: // 181: private static boolean loaded; 182: private static Class nsClass; 183: private static Class validClass; 184: private static Class wfClass; 185: private static Class xincClass; 186: 187: static ClassLoader getClassLoader () 188: { 189: Method m = null; 190: 191: try { 192: m = Thread.class.getMethod("getContextClassLoader", null); 193: } catch (NoSuchMethodException e) { 194: // Assume that we are running JDK 1.1, use the current ClassLoader 195: return EventFilter.class.getClassLoader(); 196: } 197: 198: try { 199: return (ClassLoader) m.invoke(Thread.currentThread(), null); 200: } catch (IllegalAccessException e) { 201: // assert(false) 202: throw new UnknownError(e.getMessage()); 203: } catch (InvocationTargetException e) { 204: // assert(e.getTargetException() instanceof SecurityException) 205: throw new UnknownError(e.getMessage()); 206: } 207: } 208: 209: static Class loadClass (ClassLoader classLoader, String className) 210: { 211: try { 212: if (classLoader == null) 213: return Class.forName(className); 214: else 215: return classLoader.loadClass(className); 216: } catch (Exception e) { 217: return null; 218: } 219: } 220: 221: static private void loadClasses () 222: { 223: ClassLoader loader = getClassLoader (); 224: 225: nsClass = loadClass (loader, "gnu.xml.pipeline.NSFilter"); 226: validClass = loadClass (loader, "gnu.xml.pipeline.ValidationConsumer"); 227: wfClass = loadClass (loader, "gnu.xml.pipeline.WellFormednessFilter"); 228: xincClass = loadClass (loader, "gnu.xml.pipeline.XIncludeFilter"); 229: loaded = true; 230: } 231: 232: 233: /** 234: * Binds the standard SAX2 handlers from the specified consumer 235: * pipeline to the specified producer. These handlers include the core 236: * {@link ContentHandler} and {@link DTDHandler}, plus the extension 237: * {@link DeclHandler} and {@link LexicalHandler}. Any additional 238: * application-specific handlers need to be bound separately. 239: * The {@link ErrorHandler} is handled differently: the producer's 240: * error handler is passed through to the consumer pipeline. 241: * The producer is told to include namespace prefix information if it 242: * can, since many pipeline stages need that Infoset information to 243: * work well. 244: * 245: * <p> At the head of the pipeline, certain standard event filters are 246: * recognized and handled specially. This facilitates construction 247: * of processing pipelines that work regardless of the capabilities 248: * of the XMLReader implementation in use; for example, it permits 249: * validating output of a {@link gnu.xml.util.DomParser}. <ul> 250: * 251: * <li> {@link NSFilter} will be removed if the producer can be 252: * told not to discard namespace data, using the "namespace-prefixes" 253: * feature flag. 254: * 255: * <li> {@link ValidationConsumer} will be removed if the producer 256: * can be told to validate, using the "validation" feature flag. 257: * 258: * <li> {@link WellFormednessFilter} is always removed, on the 259: * grounds that no XMLReader is permitted to producee malformed 260: * event streams and this would just be processing overhead. 261: * 262: * <li> {@link XIncludeFilter} stops the special handling, except 263: * that it's told about the "namespace-prefixes" feature of the 264: * event producer so that the event stream is internally consistent. 265: * 266: * <li> The first consumer which is not one of those classes stops 267: * such special handling. This means that if you want to force 268: * one of those filters to be used, you could just precede it with 269: * an instance of {@link EventFilter} configured as a pass-through. 270: * You might need to do that if you are using an {@link NSFilter} 271: * subclass to fix names found in attributes or character data. 272: * 273: * </ul> 274: * 275: * <p> Other than that, this method works with any kind of event consumer, 276: * not just event filters. Note that in all cases, the standard handlers 277: * are assigned; any previous handler assignments for the handler will 278: * be overridden. 279: * 280: * @param producer will deliver events to the specified consumer 281: * @param consumer pipeline supplying event handlers to be associated 282: * with the producer (may not be null) 283: */ 284: public static void bind (XMLReader producer, EventConsumer consumer) 285: { 286: Class klass = null; 287: boolean prefixes; 288: 289: if (!loaded) 290: loadClasses (); 291: 292: // DOM building, printing, layered validation, and other 293: // things don't work well when prefix info is discarded. 294: // Include it by default, whenever possible. 295: try { 296: producer.setFeature (FEATURE_URI + "namespace-prefixes", 297: true); 298: prefixes = true; 299: } catch (SAXException e) { 300: prefixes = false; 301: } 302: 303: // NOTE: This loop doesn't use "instanceof", since that 304: // would prevent compiling/linking without those classes 305: // being present. 306: while (consumer != null) { 307: klass = consumer.getClass (); 308: 309: // we might have already changed this problematic SAX2 default. 310: if (nsClass != null && nsClass.isAssignableFrom (klass)) { 311: if (!prefixes) 312: break; 313: consumer = ((EventFilter)consumer).getNext (); 314: 315: // the parser _might_ do DTD validation by default ... 316: // if not, maybe we can change this setting. 317: } else if (validClass != null 318: && validClass.isAssignableFrom (klass)) { 319: try { 320: producer.setFeature (FEATURE_URI + "validation", 321: true); 322: consumer = ((ValidationConsumer)consumer).getNext (); 323: } catch (SAXException e) { 324: break; 325: } 326: 327: // parsers are required not to have such bugs 328: } else if (wfClass != null && wfClass.isAssignableFrom (klass)) { 329: consumer = ((WellFormednessFilter)consumer).getNext (); 330: 331: // stop on the first pipeline stage we can't remove 332: } else 333: break; 334: 335: if (consumer == null) 336: klass = null; 337: } 338: 339: // the actual setting here doesn't matter as much 340: // as that producer and consumer agree 341: if (xincClass != null && klass != null 342: && xincClass.isAssignableFrom (klass)) 343: ((XIncludeFilter)consumer).setSavingPrefixes (prefixes); 344: 345: // Some SAX parsers can't handle null handlers -- bleech 346: DefaultHandler2 h = new DefaultHandler2 (); 347: 348: if (consumer != null && consumer.getContentHandler () != null) 349: producer.setContentHandler (consumer.getContentHandler ()); 350: else 351: producer.setContentHandler (h); 352: if (consumer != null && consumer.getDTDHandler () != null) 353: producer.setDTDHandler (consumer.getDTDHandler ()); 354: else 355: producer.setDTDHandler (h); 356: 357: try { 358: Object dh; 359: 360: if (consumer != null) 361: dh = consumer.getProperty (DECL_HANDLER); 362: else 363: dh = null; 364: if (dh == null) 365: dh = h; 366: producer.setProperty (DECL_HANDLER, dh); 367: } catch (Exception e) { /* ignore */ } 368: try { 369: Object lh; 370: 371: if (consumer != null) 372: lh = consumer.getProperty (LEXICAL_HANDLER); 373: else 374: lh = null; 375: if (lh == null) 376: lh = h; 377: producer.setProperty (LEXICAL_HANDLER, lh); 378: } catch (Exception e) { /* ignore */ } 379: 380: // this binding goes the other way around 381: if (producer.getErrorHandler () == null) 382: producer.setErrorHandler (h); 383: if (consumer != null) 384: consumer.setErrorHandler (producer.getErrorHandler ()); 385: } 386: 387: /** 388: * Initializes all handlers to null. 389: */ 390: // constructor used by PipelineFactory 391: public EventFilter () { } 392: 393: 394: /** 395: * Handlers that are not otherwise set will default to those from 396: * the specified consumer, making it easy to pass events through. 397: * If the consumer is null, all handlers are initialzed to null. 398: */ 399: // constructor used by PipelineFactory 400: public EventFilter (EventConsumer consumer) 401: { 402: if (consumer == null) 403: return; 404: 405: next = consumer; 406: 407: // We delegate through the "xxNext" handlers, and 408: // report the "xxHandler" ones on our input side. 409: 410: // Normally a subclass would both override handler 411: // methods and register itself as the "xxHandler". 412: 413: docHandler = docNext = consumer.getContentHandler (); 414: dtdHandler = dtdNext = consumer.getDTDHandler (); 415: try { 416: declHandler = declNext = (DeclHandler) 417: consumer.getProperty (DECL_HANDLER); 418: } catch (SAXException e) { /* leave value null */ } 419: try { 420: lexHandler = lexNext = (LexicalHandler) 421: consumer.getProperty (LEXICAL_HANDLER); 422: } catch (SAXException e) { /* leave value null */ } 423: } 424: 425: /** 426: * Treats the XMLFilterImpl as a limited functionality event consumer, 427: * by arranging to deliver events to it; this lets such classes be 428: * "wrapped" as pipeline stages. 429: * 430: * <p> <em>Upstream Event Setup:</em> 431: * If no handlers have been assigned to this EventFilter, then the 432: * handlers from specified XMLFilterImpl are returned from this 433: * {@link EventConsumer}: the XMLFilterImpl is just "wrapped". 434: * Otherwise the specified handlers will be returned. 435: * 436: * <p> <em>Downstream Event Setup:</em> 437: * Subclasses may chain event delivery to the specified XMLFilterImpl 438: * by invoking the appropiate superclass methods, 439: * as if their constructor passed a "next" EventConsumer to the 440: * constructor for this class. 441: * If this EventFilter has an ErrorHandler, it is assigned as 442: * the error handler for the XMLFilterImpl, just as would be 443: * done for a next stage implementing {@link EventConsumer}. 444: * 445: * @param next the next downstream component of the pipeline. 446: * @exception IllegalStateException if the "next" consumer has 447: * already been set through the constructor. 448: */ 449: public void chainTo (XMLFilterImpl next) 450: { 451: if (this.next != null) 452: throw new IllegalStateException (); 453: 454: docNext = next.getContentHandler (); 455: if (docHandler == null) 456: docHandler = docNext; 457: dtdNext = next.getDTDHandler (); 458: if (dtdHandler == null) 459: dtdHandler = dtdNext; 460: 461: try { 462: declNext = (DeclHandler) next.getProperty (DECL_HANDLER); 463: if (declHandler == null) 464: declHandler = declNext; 465: } catch (SAXException e) { /* leave value null */ } 466: try { 467: lexNext = (LexicalHandler) next.getProperty (LEXICAL_HANDLER); 468: if (lexHandler == null) 469: lexHandler = lexNext; 470: } catch (SAXException e) { /* leave value null */ } 471: 472: if (errHandler != null) 473: next.setErrorHandler (errHandler); 474: } 475: 476: /** 477: * Records the error handler that should be used by this stage, and 478: * passes it "downstream" to any subsequent stage. 479: */ 480: final public void setErrorHandler (ErrorHandler handler) 481: { 482: errHandler = handler; 483: if (next != null) 484: next.setErrorHandler (handler); 485: } 486: 487: /** 488: * Returns the error handler assigned this filter stage, or null 489: * if no such assigment has been made. 490: */ 491: final public ErrorHandler getErrorHandler () 492: { 493: return errHandler; 494: } 495: 496: 497: /** 498: * Returns the next event consumer in sequence; or null if there 499: * is no such handler. 500: */ 501: final public EventConsumer getNext () 502: { return next; } 503: 504: 505: /** 506: * Assigns the content handler to use; a null handler indicates 507: * that these events will not be forwarded. 508: * This overrides the previous settting for this handler, which was 509: * probably pointed to the next consumer by the base class constructor. 510: */ 511: final public void setContentHandler (ContentHandler h) 512: { 513: docHandler = h; 514: } 515: 516: /** Returns the content handler being used. */ 517: final public ContentHandler getContentHandler () 518: { 519: return docHandler; 520: } 521: 522: /** 523: * Assigns the DTD handler to use; a null handler indicates 524: * that these events will not be forwarded. 525: * This overrides the previous settting for this handler, which was 526: * probably pointed to the next consumer by the base class constructor. 527: */ 528: final public void setDTDHandler (DTDHandler h) 529: { dtdHandler = h; } 530: 531: /** Returns the dtd handler being used. */ 532: final public DTDHandler getDTDHandler () 533: { 534: return dtdHandler; 535: } 536: 537: /** 538: * Stores the property, normally a handler; a null handler indicates 539: * that these events will not be forwarded. 540: * This overrides the previous handler settting, which was probably 541: * pointed to the next consumer by the base class constructor. 542: */ 543: final public void setProperty (String id, Object o) 544: throws SAXNotRecognizedException, SAXNotSupportedException 545: { 546: try { 547: Object value = getProperty (id); 548: 549: if (value == o) 550: return; 551: if (DECL_HANDLER.equals (id)) { 552: declHandler = (DeclHandler) o; 553: return; 554: } 555: if (LEXICAL_HANDLER.equals (id)) { 556: lexHandler = (LexicalHandler) o; 557: return; 558: } 559: throw new SAXNotSupportedException (id); 560: 561: } catch (ClassCastException e) { 562: throw new SAXNotSupportedException (id); 563: } 564: } 565: 566: /** Retrieves a property of unknown intent (usually a handler) */ 567: final public Object getProperty (String id) 568: throws SAXNotRecognizedException 569: { 570: if (DECL_HANDLER.equals (id)) 571: return declHandler; 572: if (LEXICAL_HANDLER.equals (id)) 573: return lexHandler; 574: 575: throw new SAXNotRecognizedException (id); 576: } 577: 578: /** 579: * Returns any locator provided to the next consumer, if this class 580: * (or a subclass) is handling {@link ContentHandler } events. 581: */ 582: public Locator getDocumentLocator () 583: { return locator; } 584: 585: 586: // CONTENT HANDLER DELEGATIONS 587: 588: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 589: public void setDocumentLocator (Locator locator) 590: { 591: this.locator = locator; 592: if (docNext != null) 593: docNext.setDocumentLocator (locator); 594: } 595: 596: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 597: public void startDocument () throws SAXException 598: { 599: if (docNext != null) 600: docNext.startDocument (); 601: } 602: 603: public void xmlDecl(String version, String encoding, boolean standalone, 604: String inputEncoding) 605: throws SAXException 606: { 607: if (docNext != null && docNext instanceof ContentHandler2) 608: { 609: ((ContentHandler2) docNext).xmlDecl(version, encoding, standalone, 610: inputEncoding); 611: } 612: } 613: 614: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 615: public void skippedEntity (String name) throws SAXException 616: { 617: if (docNext != null) 618: docNext.skippedEntity (name); 619: } 620: 621: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 622: public void processingInstruction (String target, String data) 623: throws SAXException 624: { 625: if (docNext != null) 626: docNext.processingInstruction (target, data); 627: } 628: 629: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 630: public void characters (char ch [], int start, int length) 631: throws SAXException 632: { 633: if (docNext != null) 634: docNext.characters (ch, start, length); 635: } 636: 637: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 638: public void ignorableWhitespace (char ch [], int start, int length) 639: throws SAXException 640: { 641: if (docNext != null) 642: docNext.ignorableWhitespace (ch, start, length); 643: } 644: 645: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 646: public void startPrefixMapping (String prefix, String uri) 647: throws SAXException 648: { 649: if (docNext != null) 650: docNext.startPrefixMapping (prefix, uri); 651: } 652: 653: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 654: public void startElement ( 655: String uri, String localName, 656: String qName, Attributes atts 657: ) throws SAXException 658: { 659: if (docNext != null) 660: docNext.startElement (uri, localName, qName, atts); 661: } 662: 663: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 664: public void endElement (String uri, String localName, String qName) 665: throws SAXException 666: { 667: if (docNext != null) 668: docNext.endElement (uri, localName, qName); 669: } 670: 671: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 672: public void endPrefixMapping (String prefix) throws SAXException 673: { 674: if (docNext != null) 675: docNext.endPrefixMapping (prefix); 676: } 677: 678: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 679: public void endDocument () throws SAXException 680: { 681: if (docNext != null) 682: docNext.endDocument (); 683: locator = null; 684: } 685: 686: 687: // DTD HANDLER DELEGATIONS 688: 689: /** <b>SAX1:</b> passes this callback to the next consumer, if any */ 690: public void unparsedEntityDecl ( 691: String name, 692: String publicId, 693: String systemId, 694: String notationName 695: ) throws SAXException 696: { 697: if (dtdNext != null) 698: dtdNext.unparsedEntityDecl (name, publicId, systemId, notationName); 699: } 700: 701: /** <b>SAX1:</b> passes this callback to the next consumer, if any */ 702: public void notationDecl (String name, String publicId, String systemId) 703: throws SAXException 704: { 705: if (dtdNext != null) 706: dtdNext.notationDecl (name, publicId, systemId); 707: } 708: 709: 710: // LEXICAL HANDLER DELEGATIONS 711: 712: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 713: public void startDTD (String name, String publicId, String systemId) 714: throws SAXException 715: { 716: if (lexNext != null) 717: lexNext.startDTD (name, publicId, systemId); 718: } 719: 720: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 721: public void endDTD () 722: throws SAXException 723: { 724: if (lexNext != null) 725: lexNext.endDTD (); 726: } 727: 728: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 729: public void comment (char ch [], int start, int length) 730: throws SAXException 731: { 732: if (lexNext != null) 733: lexNext.comment (ch, start, length); 734: } 735: 736: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 737: public void startCDATA () 738: throws SAXException 739: { 740: if (lexNext != null) 741: lexNext.startCDATA (); 742: } 743: 744: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 745: public void endCDATA () 746: throws SAXException 747: { 748: if (lexNext != null) 749: lexNext.endCDATA (); 750: } 751: 752: /** 753: * <b>SAX2:</b> passes this callback to the next consumer, if any. 754: */ 755: public void startEntity (String name) 756: throws SAXException 757: { 758: if (lexNext != null) 759: lexNext.startEntity (name); 760: } 761: 762: /** 763: * <b>SAX2:</b> passes this callback to the next consumer, if any. 764: */ 765: public void endEntity (String name) 766: throws SAXException 767: { 768: if (lexNext != null) 769: lexNext.endEntity (name); 770: } 771: 772: 773: // DECLARATION HANDLER DELEGATIONS 774: 775: 776: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 777: public void elementDecl (String name, String model) 778: throws SAXException 779: { 780: if (declNext != null) 781: declNext.elementDecl (name, model); 782: } 783: 784: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 785: public void attributeDecl (String eName, String aName, 786: String type, String mode, String value) 787: throws SAXException 788: { 789: if (declNext != null) 790: declNext.attributeDecl (eName, aName, type, mode, value); 791: } 792: 793: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 794: public void externalEntityDecl (String name, 795: String publicId, String systemId) 796: throws SAXException 797: { 798: if (declNext != null) 799: declNext.externalEntityDecl (name, publicId, systemId); 800: } 801: 802: /** <b>SAX2:</b> passes this callback to the next consumer, if any */ 803: public void internalEntityDecl (String name, String value) 804: throws SAXException 805: { 806: if (declNext != null) 807: declNext.internalEntityDecl (name, value); 808: } 809: }