📄 saxwriter.java
字号:
package com.thoughtworks.xstream.io.xml;import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.io.HierarchicalStreamWriter;import com.thoughtworks.xstream.io.StreamException;import org.xml.sax.ContentHandler;import org.xml.sax.DTDHandler;import org.xml.sax.EntityResolver;import org.xml.sax.ErrorHandler;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.SAXNotRecognizedException;import org.xml.sax.SAXNotSupportedException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.AttributesImpl;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Map;/** * A SAX {@link org.xml.sax.XMLReader parser} that acts as an XStream * {@link HierarchicalStreamWriter} to enable direct generation of * a SAX event flow from the XStream serialization of a list of * list of Java objects. * <p/> * As a custom SAX parser, this class ignores the arguments of the * two standard parse methods ({@link #parse(java.lang.String)} and * {@link #parse(org.xml.sax.InputSource)}) but relies on a * proprietary SAX property {@link #SOURCE_OBJECT_LIST_PROPERTY} to * define the list of objects to serialize.</p> * <p/> * Configuration of this SAX parser is achieved through the standard * {@link #setProperty SAX property mecanism}. While specific setter * methods require direct access to the parser instance, SAX * properties support configuration settings to be propagated through * a chain of {@link org.xml.sax.XMLFilter filters} down to the * underlying parser object.</p> * <p/> * This mecanism shall be used to configure the * {@link #SOURCE_OBJECT_LIST_PROPERTY objects to be serialized} as * well as the {@link #CONFIGURED_XSTREAM_PROPERTY XStream facade}.</p> * * @author Laurent Bihanic */public final class SaxWriter implements HierarchicalStreamWriter, XMLReader { /** * The {@link #setProperty SAX property} to configure the XStream * facade to be used for object serialization. If the property * is not set, a new XStream facade will be allocated for each * parse. */ public final static String CONFIGURED_XSTREAM_PROPERTY = "http://com.thoughtworks.xstream/sax/property/configured-xstream"; /** * The {@link #setProperty SAX property} to configure the list of * Java objects to serialize. Setting this property prior * invoking one of the parse() methods is mandatory. * * @see #parse(java.lang.String) * @see #parse(org.xml.sax.InputSource) */ public final static String SOURCE_OBJECT_LIST_PROPERTY = "http://com.thoughtworks.xstream/sax/property/source-object-list"; //========================================================================= // SAX XMLReader interface support //========================================================================= /** * The SAX EntityResolver associated to this XMLReader. */ private EntityResolver entityResolver = null; /** * The SAX DTDHandler associated to this XMLReader. */ private DTDHandler dtdHandler = null; /** * The SAX ContentHandler associated to this XMLReader. */ private ContentHandler contentHandler = null; /** * The SAX ErrorHandler associated to this XMLReader. */ private ErrorHandler errorHandler = null; /** * The SAX features defined for this XMLReader. * <p/> * This class does not define any feature (yet) and ignores * the SAX mandatory feature. Thus, this member is present * only to support the mandatory feature setting and retrieval * logic defined by SAX.</p> */ private Map features = new HashMap(); /** * The SAX properties defined for this XMLReader. */ private final Map properties = new HashMap(); private final boolean includeEnclosingDocument; public SaxWriter(boolean includeEnclosingDocument) { this.includeEnclosingDocument = includeEnclosingDocument; } public SaxWriter() { this(true); } //------------------------------------------------------------------------- // Configuration //------------------------------------------------------------------------- /** * Sets the state of a feature. * <p/> * The feature name is any fully-qualified URI.</p> * <p/> * All XMLReaders are required to support setting * <code>http://xml.org/sax/features/namespaces</code> to * <code>true</code> and * <code>http://xml.org/sax/features/namespace-prefixes</code> to * <code>false</code>.</p> * <p/> * Some feature values may be immutable or mutable only * in specific contexts, such as before, during, or after * a parse.</p> * <p/> * <strong>Note</strong>: This implemention only supports the two * mandatory SAX features.</p> * * @param name the feature name, which is a fully-qualified URI. * @param value the requested state of the feature (true or false). * @throws SAXNotRecognizedException when the XMLReader does not * recognize the feature name. * @see #getFeature */ public void setFeature(String name, boolean value) throws SAXNotRecognizedException { if ((name.equals("http://xml.org/sax/features/namespaces")) || (name.equals("http://xml.org/sax/features/namespace-prefixes"))) { this.features.put(name, value ? Boolean.TRUE : Boolean.FALSE); // JDK 1.3 friendly } else { throw new SAXNotRecognizedException(name); } } /** * Looks up the value of a feature. * <p/> * The feature name is any fully-qualified URI. It is * possible for an XMLReader to recognize a feature name but * to be unable to return its value; this is especially true * in the case of an adapter for a SAX1 Parser, which has * no way of knowing whether the underlying parser is * performing validation or expanding external entities.</p> * <p/> * All XMLReaders are required to recognize the * <code>http://xml.org/sax/features/namespaces</code> and the * <code>http://xml.org/sax/features/namespace-prefixes</code> feature * names.</p> * <p/> * Some feature values may be available only in specific * contexts, such as before, during, or after a parse.</p> * <p/> * Implementors are free (and encouraged) to invent their own * features, using names built on their own URIs.</p> * * @param name the feature name, which is a fully-qualified URI. * @return the current state of the feature (true or false). * @throws SAXNotRecognizedException when the XMLReader does not * recognize the feature name. * @see #setFeature */ public boolean getFeature(String name) throws SAXNotRecognizedException { if ((name.equals("http://xml.org/sax/features/namespaces")) || (name.equals("http://xml.org/sax/features/namespace-prefixes"))) { Boolean value = (Boolean) (this.features.get(name)); if (value == null) { value = Boolean.FALSE; } return value.booleanValue(); } else { throw new SAXNotRecognizedException(name); } } /** * Sets the value of a property. * <p/> * The property name is any fully-qualified URI. It is * possible for an XMLReader to recognize a property name but * to be unable to set its value.</p> * <p/> * XMLReaders are not required to recognize setting any * specific property names, though a core set is provided with * SAX2.</p> * <p/> * Some property values may be immutable or mutable only * in specific contexts, such as before, during, or after * a parse.</p> * <p/> * This method is also the standard mechanism for setting * extended handlers.</p> * <p/> * <strong>Note</strong>: This implemention only supports two * (proprietary) properties: {@link #CONFIGURED_XSTREAM_PROPERTY} * and {@link #SOURCE_OBJECT_LIST_PROPERTY}.</p> * * @param name the property name, which is a fully-qualified URI. * @param value the requested value for the property. * @throws SAXNotRecognizedException when the XMLReader does not * recognize the property name. * @throws SAXNotSupportedException when the XMLReader recognizes * the property name but cannot set * the requested value. * @see #getProperty */ public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException { if (name.equals(CONFIGURED_XSTREAM_PROPERTY)) { if (!(value instanceof XStream)) { throw new SAXNotSupportedException("Value for property \"" + CONFIGURED_XSTREAM_PROPERTY + "\" must be a non-null XStream object"); } } else if (name.equals(SOURCE_OBJECT_LIST_PROPERTY)) { if (value instanceof List) { List list = (List) value; if (list.isEmpty()) { throw new SAXNotSupportedException("Value for property \"" + SOURCE_OBJECT_LIST_PROPERTY + "\" shall not be an empty list"); } else { // Perform a copy of the list to prevent the application to // modify its content while the parse is being performed. value = Collections.unmodifiableList(new ArrayList(list)); } } else { throw new SAXNotSupportedException("Value for property \"" + SOURCE_OBJECT_LIST_PROPERTY + "\" must be a non-null List object"); } } else { throw new SAXNotRecognizedException(name); } this.properties.put(name, value); } /** * Looks up the value of a property. * <p/> * The property name is any fully-qualified URI. It is * possible for an XMLReader to recognize a property name but * to be unable to return its state.</p> * <p/> * XMLReaders are not required to recognize any specific * property names, though an initial core set is documented for * SAX2.</p> * <p/> * Some property values may be available only in specific * contexts, such as before, during, or after a parse.</p> * <p/> * Implementors are free (and encouraged) to invent their own properties, * using names built on their own URIs.</p> * * @param name the property name, which is a fully-qualified URI. * @return the current value of the property. * @throws SAXNotRecognizedException when the XMLReader does not * recognize the property name. * @see #getProperty */ public Object getProperty(String name) throws SAXNotRecognizedException { if ((name.equals(CONFIGURED_XSTREAM_PROPERTY)) || (name.equals(SOURCE_OBJECT_LIST_PROPERTY))) { return this.properties.get(name); } else { throw new SAXNotRecognizedException(name); } } //--------------------------------------------------------------------- // Event handlers //--------------------------------------------------------------------- /** * Allows an application to register an entity resolver. * <p/> * If the application does not register an entity resolver, * the XMLReader will perform its own default resolution.</p> * <p/> * Applications may register a new or different resolver in the * middle of a parse, and the SAX parser must begin using the new * resolver immediately.</p> * * @param resolver the entity resolver. * @throws NullPointerException if the resolver argument is * <code>null</code>. * @see #getEntityResolver */ public void setEntityResolver(EntityResolver resolver) { if (resolver == null) { throw new NullPointerException("resolver"); } this.entityResolver = resolver; return; } /** * Returns the current entity resolver. * * @return the current entity resolver, or <code>null</code> if none * has been registered. * @see #setEntityResolver */ public EntityResolver getEntityResolver() { return this.entityResolver; } /** * Allows an application to register a DTD event handler. * <p/> * If the application does not register a DTD handler, all DTD * events reported by the SAX parser will be silently ignored.</p> * <p/> * Applications may register a new or different handler in the * middle of a parse, and the SAX parser must begin using the new * handler immediately.</p> *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -