Source for gnu.xml.pipeline.EventFilter

   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: }