001 /* TransformerFactory.java --
002 Copyright (C) 2004, 2005 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.transform;
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.util.Properties;
047
048 /**
049 * Factory for obtaining transformation contexts.
050 *
051 * @author (a href='mailto:dog@gnu.org'>Chris Burdess</a)
052 */
053 public abstract class TransformerFactory
054 {
055
056 protected TransformerFactory()
057 {
058 }
059
060 /**
061 * Creates a new factory instance.
062 * The implementation class to load is the first found in the following
063 * locations:
064 * <ol>
065 * <li>the <code>javax.xml.transform.TransformerFactory</code> system
066 * property</li>
067 * <li>the above named property value in the
068 * <code><i>$JAVA_HOME</i>/lib/jaxp.properties</code> file</li>
069 * <li>the class name specified in the
070 * <code>META-INF/services/javax.xml.parsers.DocumentBuilderFactory</code>
071 * system resource</li>
072 * <li>the default factory class</li>
073 * </ol>
074 */
075 public static TransformerFactory newInstance()
076 throws TransformerFactoryConfigurationError
077 {
078 ClassLoader loader = Thread.currentThread().getContextClassLoader();
079 if (loader == null)
080 {
081 loader = TransformerFactory.class.getClassLoader();
082 }
083 String className = null;
084 int count = 0;
085 do
086 {
087 className = getFactoryClassName(loader, count++);
088 if (className != null)
089 {
090 try
091 {
092 Class<?> t = (loader != null) ? loader.loadClass(className) :
093 Class.forName(className);
094 return (TransformerFactory) t.newInstance();
095 }
096 catch (ClassNotFoundException e)
097 {
098 className = null;
099 }
100 catch (Exception e)
101 {
102 throw new TransformerFactoryConfigurationError(e,
103 "error instantiating class " + className);
104 }
105 }
106 }
107 while (className == null && count < 3);
108 try
109 {
110 Class<?> t =
111 Class.forName("gnu.xml.transform.TransformerFactoryImpl");
112 return (TransformerFactory) t.newInstance();
113 }
114 catch (Exception e)
115 {
116 throw new TransformerFactoryConfigurationError(e);
117 }
118 }
119
120 private static String getFactoryClassName(ClassLoader loader, int attempt)
121 {
122 final String propertyName = "javax.xml.transform.TransformerFactory";
123 switch (attempt)
124 {
125 case 0:
126 return System.getProperty(propertyName);
127 case 1:
128 try
129 {
130 File file = new File(System.getProperty("java.home"));
131 file = new File(file, "lib");
132 file = new File(file, "jaxp.properties");
133 InputStream in = new FileInputStream(file);
134 Properties props = new Properties();
135 props.load(in);
136 in.close();
137 return props.getProperty(propertyName);
138 }
139 catch (IOException e)
140 {
141 return null;
142 }
143 case 2:
144 try
145 {
146 String serviceKey = "/META-INF/services/" + propertyName;
147 InputStream in = (loader != null) ?
148 loader.getResourceAsStream(serviceKey) :
149 TransformerFactory.class.getResourceAsStream(serviceKey);
150 if (in != null)
151 {
152 BufferedReader r =
153 new BufferedReader(new InputStreamReader(in));
154 String ret = r.readLine();
155 r.close();
156 return ret;
157 }
158 }
159 catch (IOException e)
160 {
161 }
162 return null;
163 default:
164 return null;
165 }
166 }
167
168 /**
169 * Creates a new transformer using the specified stylesheet.
170 * @param source the source of an <a href='http://www.w3.org/TR/xslt'>XSLT
171 * stylesheet</a> specifying the transformation to apply
172 */
173 public abstract Transformer newTransformer(Source source)
174 throws TransformerConfigurationException;
175
176 /**
177 * Creates a new transformer that applies the identity transform.
178 */
179 public abstract Transformer newTransformer()
180 throws TransformerConfigurationException;
181
182 /**
183 * Creates a new compiled transformation using the specified stylesheet.
184 * @param source the source of an <a href='http://www.w3.org/TR/xslt'>XSLT
185 * stylesheet</a> specifying the transformation to apply
186 */
187 public abstract Templates newTemplates(Source source)
188 throws TransformerConfigurationException;
189
190 /**
191 * Returns a source object representing the XML resource specified by the
192 * <a href='http://www.w3.org/TR/xml-stylesheet/'>xml-stylesheet</a>
193 * processing instruction and matching the given criteria.
194 * Note that if multiple stylesheets are selected, the source represents a
195 * stylesheet composed of a list of imports.
196 * @param source the source XML document
197 * @param media the media attribute to match, or <code>null</code> to match
198 * the preferred templates
199 * @param title the title attribute to match, or <code>null</code> to match
200 * any
201 * @param charset the charset attribute to match, or <code>null</code> to
202 * match any
203 */
204 public abstract Source getAssociatedStylesheet(Source source,
205 String media,
206 String title,
207 String charset)
208 throws TransformerConfigurationException;
209
210 /**
211 * Set the resolver callback to be used by transformers obtained from
212 * this factory.
213 */
214 public abstract void setURIResolver(URIResolver resolver);
215
216 /**
217 * Returns the resolver callback to be used by transformers obtained from
218 * this factory.
219 */
220 public abstract URIResolver getURIResolver();
221
222 /**
223 * Sets a feature of transformers and templates obtained from this
224 * factory.
225 * Feature names are fully qualified URIs, and may depend on the factory
226 * implementation.
227 * @param name the name of the feature
228 * @param value the feature state
229 * @exception TransformerConfigurationException if the feature is
230 * unsupported
231 */
232 public abstract void setFeature(String name, boolean value)
233 throws TransformerConfigurationException;
234
235 /**
236 * Returns the state of a feature in the factory implementation.
237 * Feature names are fully qualified URIs, and may depend on the factory
238 * implementation. JAXP also predefines several features, including the
239 * constants in {@link javax.xml.XMLConstants} and
240 * <ul>
241 * <li>{@link javax.xml.transform.dom.DOMSource#FEATURE}</li>
242 * <li>{@link javax.xml.transform.dom.DOMResult#FEATURE}</li>
243 * <li>{@link javax.xml.transform.sax.SAXSource#FEATURE}</li>
244 * <li>{@link javax.xml.transform.sax.SAXResult#FEATURE}</li>
245 * <li>{@link javax.xml.transform.sax.SAXTransformerFactory#FEATURE}</li>
246 * <li>{@link javax.xml.transform.sax.SAXTransformerFactory#FEATURE_XMLFILTER}</li>
247 * <li>{@link javax.xml.transform.stream.StreamSource#FEATURE}</li>
248 * <li>{@link javax.xml.transform.stream.StreamResult#FEATURE}</li>
249 * </ul>
250 * The latter expose various capabilities of the factory implementation.
251 */
252 public abstract boolean getFeature(String name);
253
254 /**
255 * Set a named attribute on the underlying implementation.
256 * @param name the attribute name
257 * @param value the value to assign
258 * @exception IllegalArgumentException if the attribute is not supported
259 */
260 public abstract void setAttribute(String name, Object value)
261 throws IllegalArgumentException;
262
263 /**
264 * Retrieve the specified named attribute value.
265 * @param name the attribute name
266 * @exception IllegalArgumentException if the attribute is not supported
267 */
268 public abstract Object getAttribute(String name)
269 throws IllegalArgumentException;
270
271 /**
272 * Sets the callback to be used by transformers obtained from this factory
273 * to report transformation errors.
274 */
275 public abstract void setErrorListener(ErrorListener listener)
276 throws IllegalArgumentException;
277
278 /**
279 * Returns the callback to be used by transformers obtained from this
280 * factory to report transformation errors.
281 */
282 public abstract ErrorListener getErrorListener();
283
284 }