001: /*
002: * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
003: * Copyright (C) 2005 - Javolution (http://javolution.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package javolution.xml.stream;
010:
011: import java.io.InputStream;
012: import java.io.Reader;
013: import j2me.util.Map;
014: import javolution.context.ObjectFactory;
015: import javolution.lang.Configurable;
016:
017: /**
018: * <p> The class represents the factory for getting {@link XMLStreamReader}
019: * intances.
020: *
021: * <p> The {@link #newInstance() default implementation} automatically
022: * {@link ObjectFactory#recycle recycles} any reader which has been
023: * {@link XMLStreamReader#close() closed}.</p>
024: *
025: * <P> Usage example:[code]
026: *
027: * // Lets read a CharSequence input.
028: * String xml = "...";
029: * CharSequenceReader in = new CharSequenceReader().setInput(xml);
030:
031: * // Creates a factory of readers coalescing adjacent character data.
032: * XMLInputFactory factory = XMLInputFactory.newInstance();
033: * factory.setProperty(XMLInputFactory.IS_COALESCING, true);
034: *
035: * // Creates a new reader (potentially recycled).
036: * XMLStreamReader reader = factory.createXMLStreamReader(in);
037: *
038: * // Parses XML.
039: * for (int e=reader.next(); e != XMLStreamConstants.END_DOCUMENT; e = reader.next()) {
040: * switch (e) { // Event.
041: * ...
042: * }
043: * }
044: * reader.close(); // Automatically recycles this writer.
045: * in.close(); // Underlying input should be closed explicitly.
046: * [/code]</p>
047: *
048: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
049: * @version 4.0, September 4, 2006
050: */
051: public abstract class XMLInputFactory {
052:
053: /**
054: * Holds the XMLInputFactory default implementation (configurable).
055: */
056: public static final Configurable/*<Class<? extends XMLInputFactory>>*/
057: DEFAULT = new Configurable/*<Class<? extends XMLInputFactory>>*/(
058: Default.CLASS);
059:
060: /**
061: * The property that requires the parser to coalesce adjacent character data
062: * sections (type: <code>Boolean</code>, default: <code>FALSE</code>)
063: */
064: public static final String IS_COALESCING = "javolution.xml.stream.isCoalescing";
065:
066: /**
067: * Property used to specify additional entities to be recognized by the
068: * readers (type: <code>java.util.Map</code>, default: <code>null</code>).
069: * For example:[code]
070: * FastMap<String, String> HTML_ENTITIES = new FastMap<String, String>();
071: * HTML_ENTITIES.put("nbsp", " ");
072: * HTML_ENTITIES.put("copy", "©");
073: * HTML_ENTITIES.put("eacute", "é");
074: * ...
075: * XMLInputFactory factory = XMLInputFactory.newInstance();
076: * factory.setProperty(ENTITIES, HTML_ENTITIES);
077: * [/code]
078: */
079: public static final String ENTITIES = "javolution.xml.stream.entities";
080:
081: /**
082: * Default constructor.
083: */
084: protected XMLInputFactory() {
085: }
086:
087: /**
088: * Returns a new instance of the {@link #DEFAULT} input factory
089: * implementation which may be configurated by the user
090: * (see {@link #setProperty(String, Object)}). The input factory
091: * instance is allocated through {@link ObjectFactory#getInstance(Class)}.
092: *
093: * @return a new factory instance.
094: */
095: public static XMLInputFactory newInstance() {
096: Class cls = (Class) DEFAULT.get();
097: return (XMLInputFactory) ObjectFactory.getInstance(cls)
098: .object();
099: }
100:
101: /**
102: * Returns a XML stream reader for the specified I/O reader.
103: *
104: * @param reader the XML data to read from.
105: * @throws XMLStreamException
106: */
107: public abstract XMLStreamReader createXMLStreamReader(Reader reader)
108: throws XMLStreamException;
109:
110: /**
111: * Returns a XML stream reader for the specified input stream
112: * (encoding autodetected).
113: *
114: * @param stream the input stream to read from.
115: * @throws XMLStreamException
116: */
117: public abstract XMLStreamReader createXMLStreamReader(
118: InputStream stream) throws XMLStreamException;
119:
120: /**
121: * Returns a XML stream reader for the specified input stream using the
122: * specified encoding.
123: *
124: * @param stream the input stream to read from.
125: * @param encoding the character encoding of the stream.
126: * @throws XMLStreamException
127: */
128: public abstract XMLStreamReader createXMLStreamReader(
129: InputStream stream, String encoding)
130: throws XMLStreamException;
131:
132: /**
133: * Allows the user to set specific feature/property on the underlying
134: * implementation. The underlying implementation is not required to support
135: * every setting of every property in the specification and may use
136: * <code>IllegalArgumentException</code> to signal that an unsupported
137: * property may not be set with the specified value.
138: *
139: * @param name the name of the property.
140: * @param value the value of the property
141: * @throws IllegalArgumentException if the property is not supported.
142: */
143: public abstract void setProperty(String name, Object value)
144: throws IllegalArgumentException;
145:
146: /**
147: * Gets the value of a feature/property from the underlying implementation.
148: *
149: * @param name the name of the property (may not be null).
150: * @return the value of the property.
151: * @throws IllegalArgumentException if the property is not supported.
152: */
153: public abstract Object getProperty(String name)
154: throws IllegalArgumentException;
155:
156: /**
157: * Queries the set of properties that this factory supports.
158: *
159: * @param name the name of the property.
160: * @return <code>true</code> if the property is supported;
161: * <code>false</code> otherwise.
162: */
163: public abstract boolean isPropertySupported(String name);
164:
165: /**
166: * This class represents the default factory implementation.
167: */
168: private static final class Default extends XMLInputFactory {
169:
170: static final Class CLASS = new Default().getClass();
171:
172: Map _entities = null;
173:
174: // Implements XMLInputFactory abstract method.
175: public XMLStreamReader createXMLStreamReader(Reader reader)
176: throws XMLStreamException {
177: XMLStreamReaderImpl xmlReader = newReader();
178: xmlReader.setInput(reader);
179: return xmlReader;
180: }
181:
182: // Implements XMLInputFactory abstract method.
183: public XMLStreamReader createXMLStreamReader(InputStream stream)
184: throws XMLStreamException {
185: XMLStreamReaderImpl xmlReader = newReader();
186: xmlReader.setInput(stream);
187: return xmlReader;
188: }
189:
190: // Implements XMLInputFactory abstract method.
191: public XMLStreamReader createXMLStreamReader(
192: InputStream stream, String encoding)
193: throws XMLStreamException {
194: XMLStreamReaderImpl xmlReader = newReader();
195: xmlReader.setInput(stream, encoding);
196: return xmlReader;
197: }
198:
199: // Implements XMLInputFactory abstract method.
200: public void setProperty(String name, Object value)
201: throws IllegalArgumentException {
202: if (name.equals(IS_COALESCING)) {
203: // Do nothing, always coalescing.
204: } else if (name.equals(ENTITIES)) {
205: _entities = (Map) value;
206: } else {
207: throw new IllegalArgumentException("Property: " + name
208: + " not supported");
209: }
210: }
211:
212: // Implements XMLInputFactory abstract method.
213: public Object getProperty(String name)
214: throws IllegalArgumentException {
215: if (name.equals(IS_COALESCING)) {
216: return new Boolean(true);
217: } else if (name.equals(ENTITIES)) {
218: return _entities;
219: } else {
220: throw new IllegalArgumentException("Property: " + name
221: + " not supported");
222: }
223: }
224:
225: // Implements XMLInputFactory abstract method.
226: public boolean isPropertySupported(String name) {
227: return name.equals(IS_COALESCING) || name.equals(ENTITIES);
228: }
229:
230: private XMLStreamReaderImpl newReader() {
231: XMLStreamReaderImpl xmlReader = (XMLStreamReaderImpl) XML_READER_FACTORY
232: .object();
233: if (_entities != null) {
234: xmlReader.setEntities(_entities);
235: }
236: xmlReader._objectFactory = XML_READER_FACTORY;
237: return xmlReader;
238: }
239: }
240:
241: private static ObjectFactory XML_READER_FACTORY = new ObjectFactory() {
242:
243: protected Object create() {
244: return new XMLStreamReaderImpl();
245: }
246:
247: protected void cleanup(Object obj) {
248: ((XMLStreamReaderImpl) obj).reset();
249: }
250: };
251:
252: // Allows instances of private classes to be factory produced.
253: static {
254: ObjectFactory.setInstance(new ObjectFactory() {
255: protected Object create() {
256: return new Default();
257: }
258: }, Default.CLASS);
259: }
260: }
|