View Javadoc
1   /*
2    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3    *
4    * This code is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU General Public License version 2 only, as
6    * published by the Free Software Foundation.  Oracle designates this
7    * particular file as subject to the "Classpath" exception as provided
8    * by Oracle in the LICENSE file that accompanied this code.
9    *
10   * This code is distributed in the hope that it will be useful, but WITHOUT
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13   * version 2 for more details (a copy is included in the LICENSE file that
14   * accompanied this code).
15   *
16   * You should have received a copy of the GNU General Public License version
17   * 2 along with this work; if not, write to the Free Software Foundation,
18   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19   *
20   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21   * or visit www.oracle.com if you need additional information or have any
22   * questions.
23   */
24  
25  /*
26   * Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved.
27   */
28  
29  package javax.xml.stream;
30  
31  import javax.xml.transform.Result;
32  
33  /**
34   * Defines an abstract implementation of a factory for
35   * getting XMLEventWriters and XMLStreamWriters.
36   *
37   * The following table defines the standard properties of this specification.
38   * Each property varies in the level of support required by each implementation.
39   * The level of support required is described in the 'Required' column.
40   *
41   *     <table border="2" rules="all" cellpadding="4">
42   *     <thead>
43   *      <tr>
44   *        <th align="center" colspan="2">
45   *          Configuration parameters
46   *        </th>
47   *      </tr>
48   *    </thead>
49   *    <tbody>
50   *      <tr>
51   *        <th>Property Name</th>
52   *        <th>Behavior</th>
53   *        <th>Return type</th>
54   *        <th>Default Value</th>
55   *        <th>Required</th>
56   *              </tr>
57   *         <tr><td>javax.xml.stream.isRepairingNamespaces</td><td>defaults prefixes on the output side</td><td>Boolean</td><td>False</td><td>Yes</td></tr>
58   *      </tbody>
59   *   </table>
60   *
61   * <p>The following paragraphs describe the namespace and prefix repair algorithm:</p>
62   *
63   * <p>The property can be set with the following code line:
64   * <code>setProperty("javax.xml.stream.isRepairingNamespaces",new Boolean(true|false));</code></p>
65   *
66   * <p>This property specifies that the writer default namespace prefix declarations.
67   * The default value is false. </p>
68   *
69   * <p>If a writer isRepairingNamespaces it will create a namespace declaration
70   * on the current StartElement for
71   * any attribute that does not
72   * currently have a namespace declaration in scope.  If the StartElement
73   * has a uri but no prefix specified a prefix will be assigned, if the prefix
74   * has not been declared in a parent of the current StartElement it will be declared
75   * on the current StartElement.  If the defaultNamespace is bound and in scope
76   * and the default namespace matches the URI of the attribute or StartElement
77   * QName no prefix will be assigned.</p>
78   *
79   * <p>If an element or attribute name has a prefix, but is not
80   * bound to any namespace URI, then the prefix will be removed
81   * during serialization.</p>
82   *
83   * <p>If element and/or attribute names in the same start or
84   * empty-element tag are bound to different namespace URIs and
85   * are using the same prefix then the element or the first
86   * occurring attribute retains the original prefix and the
87   * following attributes have their prefixes replaced with a
88   * new prefix that is bound to the namespace URIs of those
89   * attributes. </p>
90   *
91   * <p>If an element or attribute name uses a prefix that is
92   * bound to a different URI than that inherited from the
93   * namespace context of the parent of that element and there
94   * is no namespace declaration in the context of the current
95   * element then such a namespace declaration is added. </p>
96   *
97   * <p>If an element or attribute name is bound to a prefix and
98   * there is a namespace declaration that binds that prefix
99   * to a different URI then that namespace declaration is
100  * either removed if the correct mapping is inherited from
101  * the parent context of that element, or changed to the
102  * namespace URI of the element or attribute using that prefix.</p>
103  *
104  * @version 1.2
105  * @author Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
106  * @see XMLInputFactory
107  * @see XMLEventWriter
108  * @see XMLStreamWriter
109  * @since 1.6
110  */
111 public abstract class XMLOutputFactory {
112   /**
113    * Property used to set prefix defaulting on the output side
114    */
115   public static final String IS_REPAIRING_NAMESPACES=
116     "javax.xml.stream.isRepairingNamespaces";
117 
118   static final String DEFAULIMPL = "com.sun.xml.internal.stream.XMLOutputFactoryImpl";
119 
120   protected XMLOutputFactory(){}
121 
122   /**
123    * Creates a new instance of the factory in exactly the same manner as the
124    * {@link #newFactory()} method.
125    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
126    */
127   public static XMLOutputFactory newInstance()
128     throws FactoryConfigurationError
129   {
130     return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL);
131   }
132 
133   /**
134    * Create a new instance of the factory.
135    * <p>
136    * This static method creates a new factory instance. This method uses the
137    * following ordered lookup procedure to determine the XMLOutputFactory
138    * implementation class to load:
139    * </p>
140    * <ul>
141    * <li>
142    *   Use the javax.xml.stream.XMLOutputFactory system property.
143    * </li>
144    * <li>
145    *   Use the properties file "lib/stax.properties" in the JRE directory.
146    *     This configuration file is in standard java.util.Properties format
147    *     and contains the fully qualified name of the implementation class
148    *     with the key being the system property defined above.
149    * </li>
150    * <li>
151    *   Use the service-provider loading facilities, defined by the
152    *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
153    *   implementation of the service using the {@linkplain
154    *   java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}:
155    *   the service-provider loading facility will use the {@linkplain
156    *   java.lang.Thread#getContextClassLoader() current thread's context class loader}
157    *   to attempt to load the service. If the context class
158    *   loader is null, the {@linkplain
159    *   ClassLoader#getSystemClassLoader() system class loader} will be used.
160    * </li>
161    * <li>
162    *   Otherwise, the system-default implementation is returned.
163    * </li>
164    * <p>
165    * Once an application has obtained a reference to a XMLOutputFactory it
166    * can use the factory to configure and obtain stream instances.
167    * </p>
168    * <p>
169    * Note that this is a new method that replaces the deprecated newInstance() method.
170    *   No changes in behavior are defined by this replacement method relative to the
171    *   deprecated method.
172    * </p>
173    * @throws FactoryConfigurationError in case of {@linkplain
174    *   java.util.ServiceConfigurationError service configuration error} or if
175    *   the implementation is not available or cannot be instantiated.
176    */
177   public static XMLOutputFactory newFactory()
178     throws FactoryConfigurationError
179   {
180     return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL);
181   }
182 
183   /**
184    * Create a new instance of the factory.
185    *
186    * @param factoryId             Name of the factory to find, same as
187    *                              a property name
188    * @param classLoader           classLoader to use
189    * @return the factory implementation
190    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
191    *
192    * @deprecated  This method has been deprecated because it returns an
193    *              instance of XMLInputFactory, which is of the wrong class.
194    *              Use the new method {@link #newFactory(java.lang.String,
195    *              java.lang.ClassLoader)} instead.
196    */
197   public static XMLInputFactory newInstance(String factoryId,
198           ClassLoader classLoader)
199           throws FactoryConfigurationError {
200       //do not fallback if given classloader can't find the class, throw exception
201       return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
202   }
203 
204   /**
205    * Create a new instance of the factory.
206    * If the classLoader argument is null, then the ContextClassLoader is used.
207    * <p>
208    * This method uses the following ordered lookup procedure to determine
209    * the XMLOutputFactory implementation class to load:
210    * </p>
211    * <ul>
212    * <li>
213    *   Use the value of the system property identified by {@code factoryId}.
214    * </li>
215    * <li>
216    *   Use the properties file "lib/stax.properties" in the JRE directory.
217    *     This configuration file is in standard java.util.Properties format
218    *     and contains the fully qualified name of the implementation class
219    *     with the key being the given {@code factoryId}.
220    * </li>
221    * <li>
222    *   If {@code factoryId} is "javax.xml.stream.XMLOutputFactory",
223    *   use the service-provider loading facilities, defined by the
224    *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
225    *   implementation of the service using the specified {@code ClassLoader}.
226    *   If {@code classLoader} is null, the {@linkplain
227    *   java.util.ServiceLoader#load(java.lang.Class) default loading mechanism} will apply:
228    *   That is, the service-provider loading facility will use the {@linkplain
229    *   java.lang.Thread#getContextClassLoader() current thread's context class loader}
230    *   to attempt to load the service. If the context class
231    *   loader is null, the {@linkplain
232    *   ClassLoader#getSystemClassLoader() system class loader} will be used.
233    * </li>
234    * <li>
235    *   Otherwise, throws a {@link FactoryConfigurationError}.
236    * </li>
237    * </ul>
238    *
239    * @apiNote The parameter factoryId defined here is inconsistent with that
240    * of other JAXP factories where the first parameter is fully qualified
241    * factory class name that provides implementation of the factory.
242    *
243    * <p>
244    *   Note that this is a new method that replaces the deprecated
245    *   {@link #newInstance(java.lang.String, java.lang.ClassLoader)
246    *   newInstance(String factoryId, ClassLoader classLoader)} method.
247    *   The original method was incorrectly defined to return XMLInputFactory.
248    * </p>
249    *
250    * @param factoryId             Name of the factory to find, same as
251    *                              a property name
252    * @param classLoader           classLoader to use
253    * @return the factory implementation
254    * @throws FactoryConfigurationError in case of {@linkplain
255    *   java.util.ServiceConfigurationError service configuration error} or if
256    *   the implementation is not available or cannot be instantiated.
257    */
258   public static XMLOutputFactory newFactory(String factoryId,
259           ClassLoader classLoader)
260           throws FactoryConfigurationError {
261       //do not fallback if given classloader can't find the class, throw exception
262       return FactoryFinder.find(XMLOutputFactory.class, factoryId, classLoader, null);
263   }
264 
265   /**
266    * Create a new XMLStreamWriter that writes to a writer
267    * @param stream the writer to write to
268    * @throws XMLStreamException
269    */
270   public abstract XMLStreamWriter createXMLStreamWriter(java.io.Writer stream) throws XMLStreamException;
271 
272   /**
273    * Create a new XMLStreamWriter that writes to a stream
274    * @param stream the stream to write to
275    * @throws XMLStreamException
276    */
277   public abstract XMLStreamWriter createXMLStreamWriter(java.io.OutputStream stream) throws XMLStreamException;
278 
279   /**
280    * Create a new XMLStreamWriter that writes to a stream
281    * @param stream the stream to write to
282    * @param encoding the encoding to use
283    * @throws XMLStreamException
284    */
285   public abstract XMLStreamWriter createXMLStreamWriter(java.io.OutputStream stream,
286                                          String encoding) throws XMLStreamException;
287 
288   /**
289    * Create a new XMLStreamWriter that writes to a JAXP result.  This method is optional.
290    * @param result the result to write to
291    * @throws UnsupportedOperationException if this method is not
292    * supported by this XMLOutputFactory
293    * @throws XMLStreamException
294    */
295   public abstract XMLStreamWriter createXMLStreamWriter(Result result) throws XMLStreamException;
296 
297 
298   /**
299    * Create a new XMLEventWriter that writes to a JAXP result.  This method is optional.
300    * @param result the result to write to
301    * @throws UnsupportedOperationException if this method is not
302    * supported by this XMLOutputFactory
303    * @throws XMLStreamException
304    */
305   public abstract XMLEventWriter createXMLEventWriter(Result result) throws XMLStreamException;
306 
307   /**
308    * Create a new XMLEventWriter that writes to a stream
309    * @param stream the stream to write to
310    * @throws XMLStreamException
311    */
312   public abstract XMLEventWriter createXMLEventWriter(java.io.OutputStream stream) throws XMLStreamException;
313 
314 
315 
316   /**
317    * Create a new XMLEventWriter that writes to a stream
318    * @param stream the stream to write to
319    * @param encoding the encoding to use
320    * @throws XMLStreamException
321    */
322   public abstract XMLEventWriter createXMLEventWriter(java.io.OutputStream stream,
323                                                      String encoding) throws XMLStreamException;
324 
325   /**
326    * Create a new XMLEventWriter that writes to a writer
327    * @param stream the stream to write to
328    * @throws XMLStreamException
329    */
330   public abstract XMLEventWriter createXMLEventWriter(java.io.Writer stream) throws XMLStreamException;
331 
332   /**
333    * Allows the user to set specific features/properties on the underlying implementation.
334    * @param name The name of the property
335    * @param value The value of the property
336    * @throws java.lang.IllegalArgumentException if the property is not supported
337    */
338   public abstract void setProperty(java.lang.String name,
339                                     Object value)
340     throws IllegalArgumentException;
341 
342   /**
343    * Get a feature/property on the underlying implementation
344    * @param name The name of the property
345    * @return The value of the property
346    * @throws java.lang.IllegalArgumentException if the property is not supported
347    */
348   public abstract Object getProperty(java.lang.String name)
349     throws IllegalArgumentException;
350 
351   /**
352    * Query the set of properties that this factory supports.
353    *
354    * @param name The name of the property (may not be null)
355    * @return true if the property is supported and false otherwise
356    */
357   public abstract boolean isPropertySupported(String name);
358 }