001/* XMLInputFactory.java -- 
002   Copyright (C) 2005,2006  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   */
210  public static XMLInputFactory newInstance(String factoryId,
211                                            ClassLoader classLoader)
212    throws FactoryConfigurationError
213  {
214    ClassLoader loader = classLoader;
215    if (loader == null)
216      {
217        loader = Thread.currentThread().getContextClassLoader();
218      }
219    if (loader == null)
220      {
221        loader = XMLInputFactory.class.getClassLoader();
222      }
223    String className = null;
224    int count = 0;
225    do
226      {
227        className = getFactoryClassName(loader, count++);
228        if (className != null)
229          {
230            try
231              {
232                Class<?> t = (loader != null) ? loader.loadClass(className) :
233                  Class.forName(className);
234                return (XMLInputFactory) t.newInstance();
235              }
236            catch (ClassNotFoundException e)
237              {
238                className = null;
239              }
240            catch (Exception e)
241              {
242                throw new FactoryConfigurationError(e,
243                     "error instantiating class " + className);
244              }
245          }
246      }
247    while (className == null && count < 3);
248    return new gnu.xml.stream.XMLInputFactoryImpl();
249  }
250
251  private static String getFactoryClassName(ClassLoader loader, int attempt)
252  {
253    final String propertyName = "javax.xml.stream.XMLInputFactory";
254    switch (attempt)
255      {
256        case 0:
257          return System.getProperty(propertyName);
258        case 1:
259          try
260            {
261              File file = new File(System.getProperty("java.home"));
262              file = new File(file, "lib");
263              file = new File(file, "stax.properties");
264              InputStream in = new FileInputStream(file);
265              Properties props = new Properties();
266              props.load(in);
267              in.close();
268              return props.getProperty(propertyName);
269            }
270          catch (IOException e)
271            {
272              return null;
273            }
274        case 2:
275          try
276            {
277              String serviceKey = "/META-INF/services/" + propertyName;
278              InputStream in = (loader != null) ?
279                 loader.getResourceAsStream(serviceKey) :
280                XMLInputFactory.class.getResourceAsStream(serviceKey);
281              if (in != null)
282                {
283                  BufferedReader r =
284                     new BufferedReader(new InputStreamReader(in));
285                  String ret = r.readLine();
286                  r.close();
287                  return ret;
288                }
289            }
290          catch (IOException e)
291            {
292            }
293          return null;
294        default:
295          return null;
296      }
297  }
298
299  /**
300   * Creates a new stream reader.
301   */
302  public abstract XMLStreamReader createXMLStreamReader(Reader reader)
303    throws XMLStreamException;
304
305  /**
306   * Creates a new stream reader.
307   */
308  public abstract XMLStreamReader createXMLStreamReader(Source source)
309    throws XMLStreamException;
310
311  /**
312   * Creates a new stream reader.
313   */
314  public abstract XMLStreamReader createXMLStreamReader(InputStream stream)
315    throws XMLStreamException;
316
317  /**
318   * Creates a new stream reader.
319   */
320  public abstract XMLStreamReader createXMLStreamReader(InputStream stream,
321                                                        String encoding)
322    throws XMLStreamException;
323
324  /**
325   * Creates a new stream reader.
326   */
327  public abstract XMLStreamReader createXMLStreamReader(String systemId,
328                                                        InputStream stream)
329    throws XMLStreamException;
330
331  /**
332   * Creates a new stream reader.
333   */
334  public abstract XMLStreamReader createXMLStreamReader(String systemId,
335                                                        Reader reader)
336    throws XMLStreamException;
337
338  /**
339   * Creates a new event reader.
340   */
341  public abstract XMLEventReader createXMLEventReader(Reader reader)
342    throws XMLStreamException;
343
344  /**
345   * Creates a new event reader.
346   */
347  public abstract XMLEventReader createXMLEventReader(String systemId,
348                                                      Reader reader)
349    throws XMLStreamException;
350  
351  /**
352   * Creates a new event reader.
353   */
354  public abstract XMLEventReader createXMLEventReader(XMLStreamReader reader)
355    throws XMLStreamException;
356
357  /**
358   * Creates a new event reader.
359   */
360  public abstract XMLEventReader createXMLEventReader(Source source)
361    throws XMLStreamException;
362
363  /**
364   * Creates a new event reader.
365   */
366  public abstract XMLEventReader createXMLEventReader(InputStream stream)
367    throws XMLStreamException;
368
369  /**
370   * Creates a new event reader.
371   */
372  public abstract XMLEventReader createXMLEventReader(InputStream stream,
373                                                      String encoding)
374    throws XMLStreamException;
375
376  /**
377   * Creates a new event reader.
378   */
379  public abstract XMLEventReader createXMLEventReader(String systemId,
380                                                      InputStream stream)
381    throws XMLStreamException;
382
383  /**
384   * Create a new filtered reader.
385   */
386  public abstract XMLStreamReader createFilteredReader(XMLStreamReader reader,
387                                                       StreamFilter filter)
388    throws XMLStreamException;
389
390  /**
391   * Create a new filtered reader.
392   */
393  public abstract XMLEventReader createFilteredReader(XMLEventReader reader,
394                                                      EventFilter filter)
395    throws XMLStreamException;
396
397  /**
398   * Returns the entity resolver.
399   */
400  public abstract XMLResolver getXMLResolver();
401
402  /**
403   * Sets the entity resolver.
404   */
405  public abstract void setXMLResolver(XMLResolver resolver);
406
407  /**
408   * Returns the error reporter.
409   */
410  public abstract XMLReporter getXMLReporter();
411
412  /**
413   * Sets the error reporter.
414   */
415  public abstract void setXMLReporter(XMLReporter reporter);
416
417  /**
418   * Sets the implementation-specific property of the given name.
419   * @exception IllegalArgumentException if the property is not supported
420   */
421  public abstract void setProperty(String name, Object value)
422    throws IllegalArgumentException;
423
424  /**
425   * Returns the implementation-specific property of the given name.
426   * @exception IllegalArgumentException if the property is not supported
427   */
428  public abstract Object getProperty(String name)
429    throws IllegalArgumentException;
430
431  /**
432   * Indicates whether the specified property is supported.
433   */
434  public abstract boolean isPropertySupported(String name);
435
436  /**
437   * Sets the event allocator.
438   */
439  public abstract void setEventAllocator(XMLEventAllocator allocator);
440
441  /**
442   * Returns the event allocator.
443   */
444  public abstract XMLEventAllocator getEventAllocator();
445
446}
447