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 getClassLoader()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 loadClass(ClassLoader classLoader, String className)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 loadClasses()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 */ bind(XMLReader producer, EventConsumer consumer)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 EventFilter()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 EventFilter(EventConsumer consumer)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 */ chainTo(XMLFilterImpl next)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 */ setErrorHandler(ErrorHandler handler)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 */ getErrorHandler()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 */ getNext()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 */ setContentHandler(ContentHandler h)509 final public void setContentHandler (ContentHandler h) 510 { 511 docHandler = h; 512 } 513 514 /** Returns the content handler being used. */ getContentHandler()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 */ setDTDHandler(DTDHandler h)526 final public void setDTDHandler (DTDHandler h) 527 { dtdHandler = h; } 528 529 /** Returns the dtd handler being used. */ getDTDHandler()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 */ setProperty(String id, Object o)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) */ getProperty(String id)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 */ getDocumentLocator()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 */ setDocumentLocator(Locator locator)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 */ startDocument()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 */ skippedEntity(String name)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 */ processingInstruction(String target, String data)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 */ characters(char ch [], int start, int length)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 */ ignorableWhitespace(char ch [], int start, int length)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 */ startPrefixMapping(String prefix, String uri)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 */ startElement( String uri, String localName, String qName, Attributes atts )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 */ endElement(String uri, String localName, String qName)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 */ endPrefixMapping(String prefix)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 */ endDocument()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 */ unparsedEntityDecl( String name, String publicId, String systemId, String notationName )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 */ notationDecl(String name, String publicId, String systemId)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 */ startDTD(String name, String publicId, String systemId)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 */ endDTD()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 */ comment(char ch [], int start, int length)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 */ startCDATA()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 */ endCDATA()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 */ startEntity(String name)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 */ endEntity(String name)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 */ elementDecl(String name, String model)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 */ attributeDecl(String eName, String aName, String type, String mode, String value)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 */ externalEntityDecl(String name, String publicId, String systemId)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 */ internalEntityDecl(String name, String value)790 public void internalEntityDecl (String name, String value) 791 throws SAXException 792 { 793 if (declNext != null) 794 declNext.internalEntityDecl (name, value); 795 } 796 } 797