1 /* XMLOutputFactory.java --
2    Copyright (C) 2005,2006,2009  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 package javax.xml.stream;
39 
40 import java.io.BufferedReader;
41 import java.io.File;
42 import java.io.FileInputStream;
43 import java.io.InputStream;
44 import java.io.InputStreamReader;
45 import java.io.IOException;
46 import java.io.OutputStream;
47 import java.io.Writer;
48 import java.util.Properties;
49 import javax.xml.transform.Result;
50 
51 /**
52  * Factory for obtaining XML stream and event writers for various kinds of
53  * output sink.
54  * <h3>Configuration</h3>
55  * <table>
56  * <tr>
57  * <th>Name</th>
58  * <th>Description</th>
59  * <th>Type</th>
60  * <th>Default</th>
61  * <th>Required</th>
62  * </tr>
63  * <tr>
64  * <td>javax.xml.stream.isRepairingNamespaces</td>
65  * <td>default namespace prefixes</td>
66  * <td>Boolean</td>
67  * <td>Boolean.FALSE</td>
68  * <td>yes</td>
69  * </tr>
70  * </table>
71  */
72 public abstract class XMLOutputFactory
73 {
74 
75   /**
76    * Property used to control whether to default namespace prefixes.
77    * If true, the writer will create a namespace declaration for any
78    * attribute that doesn't have a namespace declaration in scope.
79    */
80   public static final java.lang.String IS_REPAIRING_NAMESPACES =
81     "javax.xml.stream.isRepairingNamespaces";
82 
XMLOutputFactory()83   protected XMLOutputFactory()
84   {
85   }
86 
87   /**
88    * Creates a new <b>output</b> factory.
89    * @see #newInstance(String,ClassLoader)
90    */
newInstance()91   public static XMLOutputFactory newInstance()
92     throws FactoryConfigurationError
93   {
94     return newInstance(null, null);
95   }
96 
97   /**
98    * Creates a new <b>output</b> factory.
99    * The implementation class to load is the first found in the following
100    * locations:
101    * <ol>
102    * <li>the <code>javax.xml.stream.XMLOutputFactory</code> system
103    * property</li>
104    * <li>the above named property value in the
105    * <code><i>$JAVA_HOME</i>/lib/stax.properties</code> file</li>
106    * <li>the class name specified in the
107    * <code>META-INF/services/javax.xml.stream.XMLOutputFactory</code>
108    * system resource</li>
109    * <li>the default factory class</li>
110    * </ol>
111    * @param factoryId the name of the factory, same as the property
112    * @param classLoader the class loader to use
113    * @return a new factory instance
114    * @exception FactoryConfigurationError if an instance of this factory
115    * could not be loaded
116    */
newInstance(String factoryId, ClassLoader classLoader)117   public static XMLOutputFactory newInstance(String factoryId,
118                                              ClassLoader classLoader)
119     throws FactoryConfigurationError
120   {
121     if (classLoader == null)
122       {
123         classLoader = Thread.currentThread().getContextClassLoader();
124       }
125     if (classLoader == null)
126       {
127         classLoader = XMLOutputFactory.class.getClassLoader();
128       }
129     String className = null;
130     int count = 0;
131     do
132       {
133         className = getFactoryClassName(classLoader, count++);
134         if (className != null)
135           {
136             try
137               {
138                 Class<?> t = (classLoader != null) ?
139                   classLoader.loadClass(className) :
140                   Class.forName(className);
141                 return (XMLOutputFactory) t.newInstance();
142               }
143             catch (ClassNotFoundException e)
144               {
145                 className = null;
146               }
147             catch (Exception e)
148               {
149                 throw new FactoryConfigurationError(e,
150                      "error instantiating class " + className);
151               }
152           }
153       }
154     while (className == null && count < 3);
155     return new gnu.xml.stream.XMLOutputFactoryImpl();
156   }
157 
getFactoryClassName(ClassLoader loader, int attempt)158   private static String getFactoryClassName(ClassLoader loader, int attempt)
159   {
160     final String propertyName = "javax.xml.stream.XMLOutputFactory";
161     switch (attempt)
162       {
163         case 0:
164           return System.getProperty(propertyName);
165         case 1:
166           try
167             {
168               File file = new File(System.getProperty("java.home"));
169               file = new File(file, "lib");
170               file = new File(file, "stax.properties");
171               InputStream in = new FileInputStream(file);
172               Properties props = new Properties();
173               props.load(in);
174               in.close();
175               return props.getProperty(propertyName);
176             }
177           catch (IOException e)
178             {
179               return null;
180             }
181         case 2:
182           try
183             {
184               String serviceKey = "/META-INF/services/" + propertyName;
185               InputStream in = (loader != null) ?
186                  loader.getResourceAsStream(serviceKey) :
187                 XMLOutputFactory.class.getResourceAsStream(serviceKey);
188               if (in != null)
189                 {
190                   BufferedReader r =
191                      new BufferedReader(new InputStreamReader(in));
192                   String ret = r.readLine();
193                   r.close();
194                   return ret;
195                 }
196             }
197           catch (IOException e)
198             {
199             }
200           return null;
201         default:
202           return null;
203       }
204   }
205 
206   /**
207    * Creates a new stream writer.
208    */
createXMLStreamWriter(Writer stream)209   public abstract XMLStreamWriter createXMLStreamWriter(Writer stream)
210     throws XMLStreamException;
211 
212   /**
213    * Creates a new stream writer.
214    */
createXMLStreamWriter(OutputStream stream)215   public abstract XMLStreamWriter createXMLStreamWriter(OutputStream stream)
216     throws XMLStreamException;
217 
218   /**
219    * Creates a new stream writer.
220    */
createXMLStreamWriter(OutputStream stream, String encoding)221   public abstract XMLStreamWriter createXMLStreamWriter(OutputStream stream,
222                                                         String encoding)
223     throws XMLStreamException;
224 
225   /**
226    * Creates a new stream writer.
227    * @exception UnsupportedOperationException if this method is not
228    * supported
229    */
createXMLStreamWriter(Result result)230   public abstract XMLStreamWriter createXMLStreamWriter(Result result)
231     throws XMLStreamException;
232 
233   /**
234    * Creates a new event writer.
235    * @exception UnsupportedOperationException if this method is not
236    * supported
237    */
createXMLEventWriter(Result result)238   public abstract XMLEventWriter createXMLEventWriter(Result result)
239     throws XMLStreamException;
240 
241   /**
242    * Creates a new event writer.
243    */
createXMLEventWriter(OutputStream stream)244   public abstract XMLEventWriter createXMLEventWriter(OutputStream stream)
245     throws XMLStreamException;
246 
247   /**
248    * Creates a new event writer.
249    */
createXMLEventWriter(OutputStream stream, String encoding)250   public abstract XMLEventWriter createXMLEventWriter(OutputStream stream,
251                                                       String encoding)
252     throws XMLStreamException;
253 
254   /**
255    * Creates a new event writer.
256    */
createXMLEventWriter(Writer stream)257   public abstract XMLEventWriter createXMLEventWriter(Writer stream)
258     throws XMLStreamException;
259 
260   /**
261    * Sets the implementation-specific property of the given name.
262    * @exception IllegalArgumentException if the property is not supported
263    */
setProperty(String name, Object value)264   public abstract void setProperty(String name, Object value)
265     throws IllegalArgumentException;
266 
267   /**
268    * Returns the implementation-specific property of the given name.
269    * @exception IllegalArgumentException if the property is not supported
270    */
getProperty(String name)271   public abstract Object getProperty(String name)
272     throws IllegalArgumentException;
273 
274   /**
275    * Indicates whether the specified property is supported.
276    */
isPropertySupported(String name)277   public abstract boolean isPropertySupported(String name);
278 
279 }
280