| /* EventFilter.java -- |
| Copyright (C) 1999,2000,2001 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| package gnu.xml.pipeline; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| import org.xml.sax.*; |
| import org.xml.sax.ext.*; |
| import org.xml.sax.helpers.XMLFilterImpl; |
| |
| import gnu.xml.aelfred2.ContentHandler2; |
| |
| /** |
| * A customizable event consumer, used to assemble various kinds of filters |
| * using SAX handlers and an optional second consumer. It can be constructed |
| * in two ways: <ul> |
| * |
| * <li> To serve as a passthrough, sending all events to a second consumer. |
| * The second consumer may be identified through {@link #getNext}. |
| * |
| * <li> To serve as a dead end, with all handlers null; |
| * {@link #getNext} returns null. |
| * |
| * </ul> |
| * |
| * <p> Additionally, SAX handlers may be assigned, which completely replace |
| * the "upstream" view (through {@link EventConsumer}) of handlers, initially |
| * null or the "next" consumer provided to the constructor. To make |
| * it easier to build specialized filter classes, this class implements |
| * all the standard SAX consumer handlers, and those implementations |
| * delegate "downstream" to the consumer accessed by {@link #getNext}. |
| * |
| * <p> The simplest way to create a custom a filter class is to create a |
| * subclass which overrides one or more handler interface methods. The |
| * constructor for that subclass then registers itself as a handler for |
| * those interfaces using a call such as <em>setContentHandler(this)</em>, |
| * so the "upstream" view of event delivery is modified from the state |
| * established in the base class constructor. That way, |
| * the overridden methods intercept those event callbacks |
| * as they go "downstream", and |
| * all other event callbacks will pass events to any next consumer. |
| * Overridden methods may invoke superclass methods (perhaps after modifying |
| * parameters) if they wish to delegate such calls. Such subclasses |
| * should use {@link #getErrorHandler} to report errors using the |
| * common error reporting mechanism. |
| * |
| * <p> Another important technique is to construct a filter consisting |
| * of only a few specific types of handler. For example, one could easily |
| * prune out lexical events or various declarations by providing handlers |
| * which don't pass those events downstream, or by providing null handlers. |
| * |
| * <hr /> |
| * |
| * <p> This may be viewed as the consumer oriented analogue of the SAX2 |
| * {@link org.xml.sax.helpers.XMLFilterImpl XMLFilterImpl} class. |
| * Key differences include: <ul> |
| * |
| * <li> This fully separates consumer and producer roles: it |
| * does not implement the producer side <em>XMLReader</em> or |
| * <em>EntityResolver</em> interfaces, so it can only be used |
| * in "push" mode (it has no <em>parse()</em> methods). |
| * |
| * <li> "Extension" handlers are fully supported, enabling a |
| * richer set of application requirements. |
| * And it implements {@link EventConsumer}, which groups related |
| * consumer methods together, rather than leaving them separated. |
| * |
| * <li> The chaining which is visible is "downstream" to the next |
| * consumer, not "upstream" to the preceding producer. |
| * It supports "fan-in", where |
| * a consumer can be fed by several producers. (For "fan-out", |
| * see the {@link TeeConsumer} class.) |
| * |
| * <li> Event chaining is set up differently. It is intended to |
| * work "upstream" from terminus towards producer, during filter |
| * construction, as described above. |
| * This is part of an early binding model: |
| * events don't need to pass through stages which ignore them. |
| * |
| * <li> ErrorHandler support is separated, on the grounds that |
| * pipeline stages need to share the same error handling policy. |
| * For the same reason, error handler setup goes "downstream": |
| * when error handlers get set, they are passed to subsequent |
| * consumers. |
| * |
| * </ul> |
| * |
| * <p> The {@link #chainTo chainTo()} convenience routine supports chaining to |
| * an XMLFilterImpl, in its role as a limited functionality event |
| * consumer. Its event producer role ({@link XMLFilter}) is ignored. |
| * |
| * <hr /> |
| * |
| * <p> The {@link #bind bind()} routine may be used associate event pipelines |
| * with any kind of {@link XMLReader} that will produce the events. |
| * Such pipelines don't necessarily need to have any members which are |
| * implemented using this class. That routine has some intelligence |
| * which supports automatic changes to parser feature flags, letting |
| * event piplines become largely independent of the particular feature |
| * sets of parsers. |
| * |
| * @author David Brownell |
| */ |
| public class EventFilter |
| implements EventConsumer, ContentHandler2, DTDHandler, |
| LexicalHandler, DeclHandler |
| { |
| // SAX handlers |
| private ContentHandler docHandler, docNext; |
| private DTDHandler dtdHandler, dtdNext; |
| private LexicalHandler lexHandler, lexNext; |
| private DeclHandler declHandler, declNext; |
| // and ideally, one more for the stuff SAX2 doesn't show |
| |
| private Locator locator; |
| private EventConsumer next; |
| private ErrorHandler errHandler; |
| |
| |
| /** SAX2 URI prefix for standard feature flags. */ |
| public static final String FEATURE_URI |
| = "http://xml.org/sax/features/"; |
| /** SAX2 URI prefix for standard properties (mostly for handlers). */ |
| public static final String PROPERTY_URI |
| = "http://xml.org/sax/properties/"; |
| |
| /** SAX2 property identifier for {@link DeclHandler} events */ |
| public static final String DECL_HANDLER |
| = PROPERTY_URI + "declaration-handler"; |
| /** SAX2 property identifier for {@link LexicalHandler} events */ |
| public static final String LEXICAL_HANDLER |
| = PROPERTY_URI + "lexical-handler"; |
| |
| // |
| // These class objects will be null if the relevant class isn't linked. |
| // Small configurations (pJava and some kinds of embedded systems) need |
| // to facilitate smaller executables. So "instanceof" is undesirable |
| // when bind() sees if it can remove some stages. |
| // |
| // SECURITY NOTE: assuming all these classes are part of the same sealed |
| // package, there's no problem saving these in the instance of this class |
| // that's associated with "this" class loader. But that wouldn't be true |
| // for classes in another package. |
| // |
| private static boolean loaded; |
| private static Class nsClass; |
| private static Class validClass; |
| private static Class wfClass; |
| private static Class xincClass; |
| |
| static ClassLoader getClassLoader () |
| { |
| Method m = null; |
| |
| try { |
| m = Thread.class.getMethod("getContextClassLoader", null); |
| } catch (NoSuchMethodException e) { |
| // Assume that we are running JDK 1.1, use the current ClassLoader |
| return EventFilter.class.getClassLoader(); |
| } |
| |
| try { |
| return (ClassLoader) m.invoke(Thread.currentThread(), null); |
| } catch (IllegalAccessException e) { |
| // assert(false) |
| throw new UnknownError(e.getMessage()); |
| } catch (InvocationTargetException e) { |
| // assert(e.getTargetException() instanceof SecurityException) |
| throw new UnknownError(e.getMessage()); |
| } |
| } |
| |
| static Class loadClass (ClassLoader classLoader, String className) |
| { |
| try { |
| if (classLoader == null) |
| return Class.forName(className); |
| else |
| return classLoader.loadClass(className); |
| } catch (Exception e) { |
| return null; |
| } |
| } |
| |
| static private void loadClasses () |
| { |
| ClassLoader loader = getClassLoader (); |
| |
| nsClass = loadClass (loader, "gnu.xml.pipeline.NSFilter"); |
| validClass = loadClass (loader, "gnu.xml.pipeline.ValidationConsumer"); |
| wfClass = loadClass (loader, "gnu.xml.pipeline.WellFormednessFilter"); |
| xincClass = loadClass (loader, "gnu.xml.pipeline.XIncludeFilter"); |
| loaded = true; |
| } |
| |
| |
| /** |
| * Binds the standard SAX2 handlers from the specified consumer |
| * pipeline to the specified producer. These handlers include the core |
| * {@link ContentHandler} and {@link DTDHandler}, plus the extension |
| * {@link DeclHandler} and {@link LexicalHandler}. Any additional |
| * application-specific handlers need to be bound separately. |
| * The {@link ErrorHandler} is handled differently: the producer's |
| * error handler is passed through to the consumer pipeline. |
| * The producer is told to include namespace prefix information if it |
| * can, since many pipeline stages need that Infoset information to |
| * work well. |
| * |
| * <p> At the head of the pipeline, certain standard event filters are |
| * recognized and handled specially. This facilitates construction |
| * of processing pipelines that work regardless of the capabilities |
| * of the XMLReader implementation in use; for example, it permits |
| * validating output of a {@link gnu.xml.util.DomParser}. <ul> |
| * |
| * <li> {@link NSFilter} will be removed if the producer can be |
| * told not to discard namespace data, using the "namespace-prefixes" |
| * feature flag. |
| * |
| * <li> {@link ValidationConsumer} will be removed if the producer |
| * can be told to validate, using the "validation" feature flag. |
| * |
| * <li> {@link WellFormednessFilter} is always removed, on the |
| * grounds that no XMLReader is permitted to producee malformed |
| * event streams and this would just be processing overhead. |
| * |
| * <li> {@link XIncludeFilter} stops the special handling, except |
| * that it's told about the "namespace-prefixes" feature of the |
| * event producer so that the event stream is internally consistent. |
| * |
| * <li> The first consumer which is not one of those classes stops |
| * such special handling. This means that if you want to force |
| * one of those filters to be used, you could just precede it with |
| * an instance of {@link EventFilter} configured as a pass-through. |
| * You might need to do that if you are using an {@link NSFilter} |
| * subclass to fix names found in attributes or character data. |
| * |
| * </ul> |
| * |
| * <p> Other than that, this method works with any kind of event consumer, |
| * not just event filters. Note that in all cases, the standard handlers |
| * are assigned; any previous handler assignments for the handler will |
| * be overridden. |
| * |
| * @param producer will deliver events to the specified consumer |
| * @param consumer pipeline supplying event handlers to be associated |
| * with the producer (may not be null) |
| */ |
| public static void bind (XMLReader producer, EventConsumer consumer) |
| { |
| Class klass = null; |
| boolean prefixes; |
| |
| if (!loaded) |
| loadClasses (); |
| |
| // DOM building, printing, layered validation, and other |
| // things don't work well when prefix info is discarded. |
| // Include it by default, whenever possible. |
| try { |
| producer.setFeature (FEATURE_URI + "namespace-prefixes", |
| true); |
| prefixes = true; |
| } catch (SAXException e) { |
| prefixes = false; |
| } |
| |
| // NOTE: This loop doesn't use "instanceof", since that |
| // would prevent compiling/linking without those classes |
| // being present. |
| while (consumer != null) { |
| klass = consumer.getClass (); |
| |
| // we might have already changed this problematic SAX2 default. |
| if (nsClass != null && nsClass.isAssignableFrom (klass)) { |
| if (!prefixes) |
| break; |
| consumer = ((EventFilter)consumer).getNext (); |
| |
| // the parser _might_ do DTD validation by default ... |
| // if not, maybe we can change this setting. |
| } else if (validClass != null |
| && validClass.isAssignableFrom (klass)) { |
| try { |
| producer.setFeature (FEATURE_URI + "validation", |
| true); |
| consumer = ((ValidationConsumer)consumer).getNext (); |
| } catch (SAXException e) { |
| break; |
| } |
| |
| // parsers are required not to have such bugs |
| } else if (wfClass != null && wfClass.isAssignableFrom (klass)) { |
| consumer = ((WellFormednessFilter)consumer).getNext (); |
| |
| // stop on the first pipeline stage we can't remove |
| } else |
| break; |
| |
| if (consumer == null) |
| klass = null; |
| } |
| |
| // the actual setting here doesn't matter as much |
| // as that producer and consumer agree |
| if (xincClass != null && klass != null |
| && xincClass.isAssignableFrom (klass)) |
| ((XIncludeFilter)consumer).setSavingPrefixes (prefixes); |
| |
| // Some SAX parsers can't handle null handlers -- bleech |
| DefaultHandler2 h = new DefaultHandler2 (); |
| |
| if (consumer != null && consumer.getContentHandler () != null) |
| producer.setContentHandler (consumer.getContentHandler ()); |
| else |
| producer.setContentHandler (h); |
| if (consumer != null && consumer.getDTDHandler () != null) |
| producer.setDTDHandler (consumer.getDTDHandler ()); |
| else |
| producer.setDTDHandler (h); |
| |
| try { |
| Object dh; |
| |
| if (consumer != null) |
| dh = consumer.getProperty (DECL_HANDLER); |
| else |
| dh = null; |
| if (dh == null) |
| dh = h; |
| producer.setProperty (DECL_HANDLER, dh); |
| } catch (Exception e) { /* ignore */ } |
| try { |
| Object lh; |
| |
| if (consumer != null) |
| lh = consumer.getProperty (LEXICAL_HANDLER); |
| else |
| lh = null; |
| if (lh == null) |
| lh = h; |
| producer.setProperty (LEXICAL_HANDLER, lh); |
| } catch (Exception e) { /* ignore */ } |
| |
| // this binding goes the other way around |
| if (producer.getErrorHandler () == null) |
| producer.setErrorHandler (h); |
| if (consumer != null) |
| consumer.setErrorHandler (producer.getErrorHandler ()); |
| } |
| |
| /** |
| * Initializes all handlers to null. |
| */ |
| // constructor used by PipelineFactory |
| public EventFilter () { } |
| |
| |
| /** |
| * Handlers that are not otherwise set will default to those from |
| * the specified consumer, making it easy to pass events through. |
| * If the consumer is null, all handlers are initialzed to null. |
| */ |
| // constructor used by PipelineFactory |
| public EventFilter (EventConsumer consumer) |
| { |
| if (consumer == null) |
| return; |
| |
| next = consumer; |
| |
| // We delegate through the "xxNext" handlers, and |
| // report the "xxHandler" ones on our input side. |
| |
| // Normally a subclass would both override handler |
| // methods and register itself as the "xxHandler". |
| |
| docHandler = docNext = consumer.getContentHandler (); |
| dtdHandler = dtdNext = consumer.getDTDHandler (); |
| try { |
| declHandler = declNext = (DeclHandler) |
| consumer.getProperty (DECL_HANDLER); |
| } catch (SAXException e) { /* leave value null */ } |
| try { |
| lexHandler = lexNext = (LexicalHandler) |
| consumer.getProperty (LEXICAL_HANDLER); |
| } catch (SAXException e) { /* leave value null */ } |
| } |
| |
| /** |
| * Treats the XMLFilterImpl as a limited functionality event consumer, |
| * by arranging to deliver events to it; this lets such classes be |
| * "wrapped" as pipeline stages. |
| * |
| * <p> <em>Upstream Event Setup:</em> |
| * If no handlers have been assigned to this EventFilter, then the |
| * handlers from specified XMLFilterImpl are returned from this |
| * {@link EventConsumer}: the XMLFilterImpl is just "wrapped". |
| * Otherwise the specified handlers will be returned. |
| * |
| * <p> <em>Downstream Event Setup:</em> |
| * Subclasses may chain event delivery to the specified XMLFilterImpl |
| * by invoking the appropiate superclass methods, |
| * as if their constructor passed a "next" EventConsumer to the |
| * constructor for this class. |
| * If this EventFilter has an ErrorHandler, it is assigned as |
| * the error handler for the XMLFilterImpl, just as would be |
| * done for a next stage implementing {@link EventConsumer}. |
| * |
| * @param next the next downstream component of the pipeline. |
| * @exception IllegalStateException if the "next" consumer has |
| * already been set through the constructor. |
| */ |
| public void chainTo (XMLFilterImpl next) |
| { |
| if (this.next != null) |
| throw new IllegalStateException (); |
| |
| docNext = next.getContentHandler (); |
| if (docHandler == null) |
| docHandler = docNext; |
| dtdNext = next.getDTDHandler (); |
| if (dtdHandler == null) |
| dtdHandler = dtdNext; |
| |
| try { |
| declNext = (DeclHandler) next.getProperty (DECL_HANDLER); |
| if (declHandler == null) |
| declHandler = declNext; |
| } catch (SAXException e) { /* leave value null */ } |
| try { |
| lexNext = (LexicalHandler) next.getProperty (LEXICAL_HANDLER); |
| if (lexHandler == null) |
| lexHandler = lexNext; |
| } catch (SAXException e) { /* leave value null */ } |
| |
| if (errHandler != null) |
| next.setErrorHandler (errHandler); |
| } |
| |
| /** |
| * Records the error handler that should be used by this stage, and |
| * passes it "downstream" to any subsequent stage. |
| */ |
| final public void setErrorHandler (ErrorHandler handler) |
| { |
| errHandler = handler; |
| if (next != null) |
| next.setErrorHandler (handler); |
| } |
| |
| /** |
| * Returns the error handler assigned this filter stage, or null |
| * if no such assigment has been made. |
| */ |
| final public ErrorHandler getErrorHandler () |
| { |
| return errHandler; |
| } |
| |
| |
| /** |
| * Returns the next event consumer in sequence; or null if there |
| * is no such handler. |
| */ |
| final public EventConsumer getNext () |
| { return next; } |
| |
| |
| /** |
| * Assigns the content handler to use; a null handler indicates |
| * that these events will not be forwarded. |
| * This overrides the previous settting for this handler, which was |
| * probably pointed to the next consumer by the base class constructor. |
| */ |
| final public void setContentHandler (ContentHandler h) |
| { |
| docHandler = h; |
| } |
| |
| /** Returns the content handler being used. */ |
| final public ContentHandler getContentHandler () |
| { |
| return docHandler; |
| } |
| |
| /** |
| * Assigns the DTD handler to use; a null handler indicates |
| * that these events will not be forwarded. |
| * This overrides the previous settting for this handler, which was |
| * probably pointed to the next consumer by the base class constructor. |
| */ |
| final public void setDTDHandler (DTDHandler h) |
| { dtdHandler = h; } |
| |
| /** Returns the dtd handler being used. */ |
| final public DTDHandler getDTDHandler () |
| { |
| return dtdHandler; |
| } |
| |
| /** |
| * Stores the property, normally a handler; a null handler indicates |
| * that these events will not be forwarded. |
| * This overrides the previous handler settting, which was probably |
| * pointed to the next consumer by the base class constructor. |
| */ |
| final public void setProperty (String id, Object o) |
| throws SAXNotRecognizedException, SAXNotSupportedException |
| { |
| try { |
| Object value = getProperty (id); |
| |
| if (value == o) |
| return; |
| if (DECL_HANDLER.equals (id)) { |
| declHandler = (DeclHandler) o; |
| return; |
| } |
| if (LEXICAL_HANDLER.equals (id)) { |
| lexHandler = (LexicalHandler) o; |
| return; |
| } |
| throw new SAXNotSupportedException (id); |
| |
| } catch (ClassCastException e) { |
| throw new SAXNotSupportedException (id); |
| } |
| } |
| |
| /** Retrieves a property of unknown intent (usually a handler) */ |
| final public Object getProperty (String id) |
| throws SAXNotRecognizedException |
| { |
| if (DECL_HANDLER.equals (id)) |
| return declHandler; |
| if (LEXICAL_HANDLER.equals (id)) |
| return lexHandler; |
| |
| throw new SAXNotRecognizedException (id); |
| } |
| |
| /** |
| * Returns any locator provided to the next consumer, if this class |
| * (or a subclass) is handling {@link ContentHandler } events. |
| */ |
| public Locator getDocumentLocator () |
| { return locator; } |
| |
| |
| // CONTENT HANDLER DELEGATIONS |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void setDocumentLocator (Locator locator) |
| { |
| this.locator = locator; |
| if (docNext != null) |
| docNext.setDocumentLocator (locator); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void startDocument () throws SAXException |
| { |
| if (docNext != null) |
| docNext.startDocument (); |
| } |
| |
| public void xmlDecl(String version, String encoding, boolean standalone, |
| String inputEncoding) |
| throws SAXException |
| { |
| if (docNext != null && docNext instanceof ContentHandler2) |
| { |
| ((ContentHandler2) docNext).xmlDecl(version, encoding, standalone, |
| inputEncoding); |
| } |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void skippedEntity (String name) throws SAXException |
| { |
| if (docNext != null) |
| docNext.skippedEntity (name); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void processingInstruction (String target, String data) |
| throws SAXException |
| { |
| if (docNext != null) |
| docNext.processingInstruction (target, data); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void characters (char ch [], int start, int length) |
| throws SAXException |
| { |
| if (docNext != null) |
| docNext.characters (ch, start, length); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void ignorableWhitespace (char ch [], int start, int length) |
| throws SAXException |
| { |
| if (docNext != null) |
| docNext.ignorableWhitespace (ch, start, length); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void startPrefixMapping (String prefix, String uri) |
| throws SAXException |
| { |
| if (docNext != null) |
| docNext.startPrefixMapping (prefix, uri); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void startElement ( |
| String uri, String localName, |
| String qName, Attributes atts |
| ) throws SAXException |
| { |
| if (docNext != null) |
| docNext.startElement (uri, localName, qName, atts); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void endElement (String uri, String localName, String qName) |
| throws SAXException |
| { |
| if (docNext != null) |
| docNext.endElement (uri, localName, qName); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void endPrefixMapping (String prefix) throws SAXException |
| { |
| if (docNext != null) |
| docNext.endPrefixMapping (prefix); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void endDocument () throws SAXException |
| { |
| if (docNext != null) |
| docNext.endDocument (); |
| locator = null; |
| } |
| |
| |
| // DTD HANDLER DELEGATIONS |
| |
| /** <b>SAX1:</b> passes this callback to the next consumer, if any */ |
| public void unparsedEntityDecl ( |
| String name, |
| String publicId, |
| String systemId, |
| String notationName |
| ) throws SAXException |
| { |
| if (dtdNext != null) |
| dtdNext.unparsedEntityDecl (name, publicId, systemId, notationName); |
| } |
| |
| /** <b>SAX1:</b> passes this callback to the next consumer, if any */ |
| public void notationDecl (String name, String publicId, String systemId) |
| throws SAXException |
| { |
| if (dtdNext != null) |
| dtdNext.notationDecl (name, publicId, systemId); |
| } |
| |
| |
| // LEXICAL HANDLER DELEGATIONS |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void startDTD (String name, String publicId, String systemId) |
| throws SAXException |
| { |
| if (lexNext != null) |
| lexNext.startDTD (name, publicId, systemId); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void endDTD () |
| throws SAXException |
| { |
| if (lexNext != null) |
| lexNext.endDTD (); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void comment (char ch [], int start, int length) |
| throws SAXException |
| { |
| if (lexNext != null) |
| lexNext.comment (ch, start, length); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void startCDATA () |
| throws SAXException |
| { |
| if (lexNext != null) |
| lexNext.startCDATA (); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void endCDATA () |
| throws SAXException |
| { |
| if (lexNext != null) |
| lexNext.endCDATA (); |
| } |
| |
| /** |
| * <b>SAX2:</b> passes this callback to the next consumer, if any. |
| */ |
| public void startEntity (String name) |
| throws SAXException |
| { |
| if (lexNext != null) |
| lexNext.startEntity (name); |
| } |
| |
| /** |
| * <b>SAX2:</b> passes this callback to the next consumer, if any. |
| */ |
| public void endEntity (String name) |
| throws SAXException |
| { |
| if (lexNext != null) |
| lexNext.endEntity (name); |
| } |
| |
| |
| // DECLARATION HANDLER DELEGATIONS |
| |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void elementDecl (String name, String model) |
| throws SAXException |
| { |
| if (declNext != null) |
| declNext.elementDecl (name, model); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void attributeDecl (String eName, String aName, |
| String type, String mode, String value) |
| throws SAXException |
| { |
| if (declNext != null) |
| declNext.attributeDecl (eName, aName, type, mode, value); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void externalEntityDecl (String name, |
| String publicId, String systemId) |
| throws SAXException |
| { |
| if (declNext != null) |
| declNext.externalEntityDecl (name, publicId, systemId); |
| } |
| |
| /** <b>SAX2:</b> passes this callback to the next consumer, if any */ |
| public void internalEntityDecl (String name, String value) |
| throws SAXException |
| { |
| if (declNext != null) |
| declNext.internalEntityDecl (name, value); |
| } |
| } |