001 /* XMLOutputFactory.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.OutputStream;
047 import java.io.Writer;
048 import java.util.Properties;
049 import javax.xml.transform.Result;
050
051 /**
052 * Factory for obtaining XML stream and event writers for various kinds of
053 * output sink.
054 * <h3>Configuration</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.isRepairingNamespaces</td>
065 * <td>default namespace prefixes</td>
066 * <td>Boolean</td>
067 * <td>Boolean.FALSE</td>
068 * <td>yes</td>
069 * </tr>
070 * </table>
071 */
072 public abstract class XMLOutputFactory
073 {
074
075 /**
076 * Property used to control whether to default namespace prefixes.
077 * If true, the writer will create a namespace declaration for any
078 * attribute that doesn't have a namespace declaration in scope.
079 */
080 public static final java.lang.String IS_REPAIRING_NAMESPACES =
081 "javax.xml.stream.isRepairingNamespaces";
082
083 protected XMLOutputFactory()
084 {
085 }
086
087 /**
088 * Creates a new <b>output</b> factory.
089 * @see #newInstance(String,ClassLoader)
090 */
091 public static XMLOutputFactory newInstance()
092 throws FactoryConfigurationError
093 {
094 return newInstance(null, null);
095 }
096
097 /**
098 * Creates a new <b>output</b> factory.
099 * 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 */
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
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 */
209 public abstract XMLStreamWriter createXMLStreamWriter(Writer stream)
210 throws XMLStreamException;
211
212 /**
213 * Creates a new stream writer.
214 */
215 public abstract XMLStreamWriter createXMLStreamWriter(OutputStream stream)
216 throws XMLStreamException;
217
218 /**
219 * Creates a new stream writer.
220 */
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 */
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 */
238 public abstract XMLEventWriter createXMLEventWriter(Result result)
239 throws XMLStreamException;
240
241 /**
242 * Creates a new event writer.
243 */
244 public abstract XMLEventWriter createXMLEventWriter(OutputStream stream)
245 throws XMLStreamException;
246
247 /**
248 * Creates a new event writer.
249 */
250 public abstract XMLEventWriter createXMLEventWriter(OutputStream stream,
251 String encoding)
252 throws XMLStreamException;
253
254 /**
255 * Creates a new event writer.
256 */
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 */
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 */
271 public abstract Object getProperty(String name)
272 throws IllegalArgumentException;
273
274 /**
275 * Indicates whether the specified property is supported.
276 */
277 public abstract boolean isPropertySupported(String name);
278
279 }