eventfilter.java

来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· Java 代码 · 共 787 行 · 第 1/2 页

JAVA
787
字号
/* * Copyright (C) 1999-2001 David Brownell *  * This file is part of GNU JAXP, a library. * * GNU JAXP 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 of the License, or * (at your option) any later version. *  * GNU JAXP 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * As a special exception, if you link this library with other files to * produce an executable, this library does not by itself cause the * resulting executable to be covered by the GNU General Public License. * This exception does not however invalidate any other reasons why the * executable file might be covered by the GNU General Public License.  */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;/** * 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, ContentHandler, 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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?