001/* XMLInputFactory.java --
002   Copyright (C) 2005,2006,2009  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.xml.stream;
039
040import java.io.BufferedReader;
041import java.io.File;
042import java.io.FileInputStream;
043import java.io.InputStream;
044import java.io.InputStreamReader;
045import java.io.IOException;
046import java.io.Reader;
047import java.util.Properties;
048import javax.xml.stream.util.XMLEventAllocator;
049import javax.xml.transform.Source;
050
051/**
052 * Factory for creating stream and event readers from various kinds of input
053 * source.
054 * <h3>Parameters</h3>
055 * <table>
056 * <tr>
057 * <th>Name</th>
058 * <th>Description</th>
059 * <th>Type</th>
060 * <th>Default</th>
061 * <th>Required</th>
062 * </tr>
063 * <tr>
064 * <td>javax.xml.stream.isValidating</td>
065 * <td>Controls DTD validation</td>
066 * <td>Boolean</td>
067 * <td>Boolean.FALSE</td>
068 * <td>no</td>
069 * </tr>
070 * <tr>
071 * <td>javax.xml.stream.isNamespaceAware</td>
072 * <td>Controls namespace processing for XML 1.0</td>
073 * <td>Boolean</td>
074 * <td>Boolean.TRUE</td>
075 * <td>true is required, false is optional</td>
076 * </tr>
077 * <tr>
078 * <td>javax.xml.stream.isCoalescing</td>
079 * <td>Controls coalescing (normalization of adjacent character data)</td>
080 * <td>Boolean</td>
081 * <td>Boolean.FALSE</td>
082 * <td>yes</td>
083 * </tr>
084 * <tr>
085 * <td>javax.xml.stream.isReplacingEntityReferences</td>
086 * <td>Controls replacement of entity references with their replacement
087 * text</td>
088 * <td>Boolean</td>
089 * <td>Boolean.TRUE</td>
090 * <td>yes</td>
091 * </tr>
092 * <tr>
093 * <td>javax.xml.stream.isSupportingExternalEntities</td>
094 * <td>Controls whether to resolve external entities</td>
095 * <td>Boolean</td>
096 * <td>not specified</td>
097 * <td>yes</td>
098 * </tr>
099 * <tr>
100 * <td>javax.xml.stream.supportDTD</td>
101 * <td>Controls whether to support DTDs</td>
102 * <td>Boolean</td>
103 * <td>Boolean.TRUE</td>
104 * <td>yes</td>
105 * </tr>
106 * <tr>
107 * <td>javax.xml.stream.reporter</td>
108 * <td></td>
109 * <td>javax.xml.stream.XMLReporter</td>
110 * <td></td>
111 * <td>yes</td>
112 * </tr>
113 * <tr>
114 * <td>javax.xml.stream.resolver</td>
115 * <td></td>
116 * <td>javax.xml.stream.XMLResolver</td>
117 * <td></td>
118 * <td>yes</td>
119 * </tr>
120 * <tr>
121 * <td>javax.xml.stream.allocator</td>
122 * <td></td>
123 * <td>javax.xml.stream.util.XMLEventAllocator</td>
124 * <td></td>
125 * <td>yes</td>
126 * </tr>
127 * </table>
128 */
129public abstract class XMLInputFactory
130{
131
132  /**
133   * Property used to control namespace support.
134   */
135  public static final String IS_NAMESPACE_AWARE =
136    "javax.xml.stream.isNamespaceAware";
137
138  /**
139   * Property used to control DTD validation.
140   */
141  public static final String IS_VALIDATING = "javax.xml.stream.isValidating";
142
143  /**
144   * Property used to control whether to coalesce adjacent text events.
145   */
146  public static final String IS_COALESCING = "javax.xml.stream.isCoalescing";
147
148  /**
149   * Property used to control whether to replace entity references with
150   * their replacement text.
151   */
152  public static final String IS_REPLACING_ENTITY_REFERENCES =
153    "javax.xml.stream.isReplacingEntityReferences";
154
155  /**
156   * Property used to control whether to resolve external entities.
157   */
158  public static final String IS_SUPPORTING_EXTERNAL_ENTITIES =
159    "javax.xml.stream.isSupportingExternalEntities";
160
161  /**
162   * Property used to indicate whether to support DTDs.
163   */
164  public static final String SUPPORT_DTD = "javax.xml.stream.supportDTD";
165
166  /**
167   * Property used to control the error reporter implementation.
168   */
169  public static final String REPORTER = "javax.xml.stream.reporter";
170
171  /**
172   * Property used to control the entity resolver implementation.
173   */
174  public static final String RESOLVER = "javax.xml.stream.resolver";
175
176  /**
177   * Property used to control the event allocator implementation.
178   */
179  public static final String ALLOCATOR = "javax.xml.stream.allocator";
180
181  protected XMLInputFactory()
182  {
183  }
184
185  /**
186   * Creates a new factory instance.
187   * @see #newInstance(String,ClassLoader)
188   */
189  public static XMLInputFactory newInstance()
190    throws FactoryConfigurationError
191  {
192    return newInstance(null, null);
193  }
194
195  /**
196   * Creates a new factory instance.
197   * The implementation class to load is the first found in the following
198   * locations:
199   * <ol>
200   * <li>the <code>javax.xml.stream.XMLInputFactory</code> system
201   * property</li>
202   * <li>the above named property value in the
203   * <code><i>$JAVA_HOME</i>/lib/stax.properties</code> file</li>
204   * <li>the class name specified in the
205   * <code>META-INF/services/javax.xml.stream.XMLInputFactory</code>
206   * system resource</li>
207   * <li>the default factory class</li>
208   * </ol>
209   * @param factoryId name of the factory, same as a property name
210   * @param classLoader the class loader to use
211   * @return the factory implementation
212   * @exception FactoryConfigurationError if an instance of this factory
213   * cannot be loaded
214   */
215  public static XMLInputFactory newInstance(String factoryId,
216                                            ClassLoader classLoader)
217    throws FactoryConfigurationError
218  {
219    ClassLoader loader = classLoader;
220    if (loader == null)
221      {
222        loader = Thread.currentThread().getContextClassLoader();
223      }
224    if (loader == null)
225      {
226        loader = XMLInputFactory.class.getClassLoader();
227      }
228    String className = null;
229    int count = 0;
230    do
231      {
232        className = getFactoryClassName(loader, count++);
233        if (className != null)
234          {
235            try
236              {
237                Class<?> t = (loader != null) ? loader.loadClass(className) :
238                  Class.forName(className);
239                return (XMLInputFactory) t.newInstance();
240              }
241            catch (ClassNotFoundException e)
242              {
243                className = null;
244              }
245            catch (Exception e)
246              {
247                throw new FactoryConfigurationError(e,
248                     "error instantiating class " + className);
249              }
250          }
251      }
252    while (className == null && count < 3);
253    return new gnu.xml.stream.XMLInputFactoryImpl();
254  }
255
256  private static String getFactoryClassName(ClassLoader loader, int attempt)
257  {
258    final String propertyName = "javax.xml.stream.XMLInputFactory";
259    switch (attempt)
260      {
261        case 0:
262          return System.getProperty(propertyName);
263        case 1:
264          try
265            {
266              File file = new File(System.getProperty("java.home"));
267              file = new File(file, "lib");
268              file = new File(file, "stax.properties");
269              InputStream in = new FileInputStream(file);
270              Properties props = new Properties();
271              props.load(in);
272              in.close();
273              return props.getProperty(propertyName);
274            }
275          catch (IOException e)
276            {
277              return null;
278            }
279        case 2:
280          try
281            {
282              String serviceKey = "/META-INF/services/" + propertyName;
283              InputStream in = (loader != null) ?
284                 loader.getResourceAsStream(serviceKey) :
285                XMLInputFactory.class.getResourceAsStream(serviceKey);
286              if (in != null)
287                {
288                  BufferedReader r =
289                     new BufferedReader(new InputStreamReader(in));
290                  String ret = r.readLine();
291                  r.close();
292                  return ret;
293                }
294            }
295          catch (IOException e)
296            {
297            }
298          return null;
299        default:
300          return null;
301      }
302  }
303
304  /**
305   * Creates a new stream reader.
306   */
307  public abstract XMLStreamReader createXMLStreamReader(Reader reader)
308    throws XMLStreamException;
309
310  /**
311   * Creates a new stream reader.
312   */
313  public abstract XMLStreamReader createXMLStreamReader(Source source)
314    throws XMLStreamException;
315
316  /**
317   * Creates a new stream reader.
318   */
319  public abstract XMLStreamReader createXMLStreamReader(InputStream stream)
320    throws XMLStreamException;
321
322  /**
323   * Creates a new stream reader.
324   */
325  public abstract XMLStreamReader createXMLStreamReader(InputStream stream,
326                                                        String encoding)
327    throws XMLStreamException;
328
329  /**
330   * Creates a new stream reader.
331   */
332  public abstract XMLStreamReader createXMLStreamReader(String systemId,
333                                                        InputStream stream)
334    throws XMLStreamException;
335
336  /**
337   * Creates a new stream reader.
338   */
339  public abstract XMLStreamReader createXMLStreamReader(String systemId,
340                                                        Reader reader)
341    throws XMLStreamException;
342
343  /**
344   * Creates a new event reader.
345   */
346  public abstract XMLEventReader createXMLEventReader(Reader reader)
347    throws XMLStreamException;
348
349  /**
350   * Creates a new event reader.
351   */
352  public abstract XMLEventReader createXMLEventReader(String systemId,
353                                                      Reader reader)
354    throws XMLStreamException;
355
356  /**
357   * Creates a new event reader.
358   */
359  public abstract XMLEventReader createXMLEventReader(XMLStreamReader reader)
360    throws XMLStreamException;
361
362  /**
363   * Creates a new event reader.
364   */
365  public abstract XMLEventReader createXMLEventReader(Source source)
366    throws XMLStreamException;
367
368  /**
369   * Creates a new event reader.
370   */
371  public abstract XMLEventReader createXMLEventReader(InputStream stream)
372    throws XMLStreamException;
373
374  /**
375   * Creates a new event reader.
376   */
377  public abstract XMLEventReader createXMLEventReader(InputStream stream,
378                                                      String encoding)
379    throws XMLStreamException;
380
381  /**
382   * Creates a new event reader.
383   */
384  public abstract XMLEventReader createXMLEventReader(String systemId,
385                                                      InputStream stream)
386    throws XMLStreamException;
387
388  /**
389   * Create a new filtered reader.
390   */
391  public abstract XMLStreamReader createFilteredReader(XMLStreamReader reader,
392                                                       StreamFilter filter)
393    throws XMLStreamException;
394
395  /**
396   * Create a new filtered reader.
397   */
398  public abstract XMLEventReader createFilteredReader(XMLEventReader reader,
399                                                      EventFilter filter)
400    throws XMLStreamException;
401
402  /**
403   * Returns the entity resolver.
404   */
405  public abstract XMLResolver getXMLResolver();
406
407  /**
408   * Sets the entity resolver.
409   */
410  public abstract void setXMLResolver(XMLResolver resolver);
411
412  /**
413   * Returns the error reporter.
414   */
415  public abstract XMLReporter getXMLReporter();
416
417  /**
418   * Sets the error reporter.
419   */
420  public abstract void setXMLReporter(XMLReporter reporter);
421
422  /**
423   * Sets the implementation-specific property of the given name.
424   * @exception IllegalArgumentException if the property is not supported
425   */
426  public abstract void setProperty(String name, Object value)
427    throws IllegalArgumentException;
428
429  /**
430   * Returns the implementation-specific property of the given name.
431   * @exception IllegalArgumentException if the property is not supported
432   */
433  public abstract Object getProperty(String name)
434    throws IllegalArgumentException;
435
436  /**
437   * Indicates whether the specified property is supported.
438   */
439  public abstract boolean isPropertySupported(String name);
440
441  /**
442   * Sets the event allocator.
443   */
444  public abstract void setEventAllocator(XMLEventAllocator allocator);
445
446  /**
447   * Returns the event allocator.
448   */
449  public abstract XMLEventAllocator getEventAllocator();
450
451}