001 /* XMLInputFactory.java --
002 Copyright (C) 2005,2006,2009 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038 package javax.xml.stream;
039
040 import java.io.BufferedReader;
041 import java.io.File;
042 import java.io.FileInputStream;
043 import java.io.InputStream;
044 import java.io.InputStreamReader;
045 import java.io.IOException;
046 import java.io.Reader;
047 import java.util.Properties;
048 import javax.xml.stream.util.XMLEventAllocator;
049 import 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 */
129 public 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 }