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