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