/* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The name "Apache Software Foundation" must not be used to endorse or * promote products derived from this software without prior written * permission. For written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999-2001, Sun Microsystems, * Inc., http://www.sun.com. For more information on the Apache Software * Foundation, please see . */ package javax.xml.transform; import java.io.InputStream; import java.io.IOException; import java.io.File; import java.io.FileInputStream; import java.util.Properties; import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; /** * This class is duplicated for each JAXP subpackage so keep it in sync. * It is package private and therefore is not exposed as part of the JAXP * API. * * This code is designed to implement the JAXP 1.1 spec pluggability * feature and is designed to both compile and run on JDK version 1.1 and * later. The code also runs both as part of an unbundled jar file and * when bundled as part of the JDK. */ class FactoryFinder { /** Temp debug code - this will be removed after we test everything */ private static boolean debug = false; static { // Use try/catch block to support applets try { debug = System.getProperty("jaxp.debug") != null; } catch (Exception x) { } } private static void debugPrintln(String msg) { if (debug) { System.err.println("JAXP: " + msg); } } /** * Figure out which ClassLoader to use. For JDK 1.2 and later use * the context ClassLoader. */ private static ClassLoader findClassLoader() throws ConfigurationError { ClassLoader classLoader; Method m = null; try { m = Thread.class.getMethod("getContextClassLoader", null); } catch (NoSuchMethodException e) { // Assume that we are running JDK 1.1, use the current ClassLoader if (debug) { debugPrintln("assuming JDK 1.1"); } classLoader = FactoryFinder.class.getClassLoader(); } try { classLoader = (ClassLoader) m.invoke(Thread.currentThread(), null); } catch (IllegalAccessException e) { // assert(false) throw new ConfigurationError("Unexpected IllegalAccessException", e); } catch (InvocationTargetException e) { // assert(e.getTargetException() instanceof SecurityException) throw new ConfigurationError("Unexpected InvocationTargetException", e); } return classLoader; } /** * Create an instance of a class using the specified ClassLoader */ private static Object newInstance(String className, ClassLoader classLoader) throws ConfigurationError { try { Class spiClass; if (classLoader == null) { spiClass = Class.forName(className); } else { spiClass = classLoader.loadClass(className); } return spiClass.newInstance(); } catch (ClassNotFoundException x) { throw new ConfigurationError( "Provider " + className + " not found", x); } catch (Exception x) { throw new ConfigurationError( "Provider " + className + " could not be instantiated: " + x, x); } } /** * Finds the implementation Class object in the specified order. Main * entry point. * @return Class object of factory, never null * * @param factoryId Name of the factory to find, same as * a property name * @param fallbackClassName Implementation class name, if nothing else * is found. Use null to mean no fallback. * * @exception FactoryFinder.ConfigurationError * * Package private so this code can be shared. */ static Object find(String factoryId, String fallbackClassName) throws ConfigurationError { ClassLoader classLoader = findClassLoader(); // Use the system property first try { String systemProp = System.getProperty( factoryId ); if( systemProp!=null) { debugPrintln("found system property " + systemProp); return newInstance(systemProp, classLoader); } } catch (SecurityException se) { } // try to read from $java.home/lib/xml.properties try { String javah=System.getProperty( "java.home" ); String configFile = javah + File.separator + "lib" + File.separator + "jaxp.properties"; File f=new File( configFile ); if( f.exists()) { Properties props=new Properties(); props.load( new FileInputStream(f)); String factoryClassName = props.getProperty(factoryId); debugPrintln("found java.home property " + factoryClassName); return newInstance(factoryClassName, classLoader); } } catch(Exception ex ) { if( debug ) ex.printStackTrace(); } String serviceId = "META-INF/services/" + factoryId; // try to find services in CLASSPATH try { InputStream is=null; if (classLoader == null) { is=ClassLoader.getSystemResourceAsStream( serviceId ); } else { is=classLoader.getResourceAsStream( serviceId ); } if( is!=null ) { debugPrintln("found " + serviceId); BufferedReader rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); String factoryClassName = rd.readLine(); rd.close(); if (factoryClassName != null && ! "".equals(factoryClassName)) { debugPrintln("loaded from services: " + factoryClassName); return newInstance(factoryClassName, classLoader); } } } catch( Exception ex ) { if( debug ) ex.printStackTrace(); } if (fallbackClassName == null) { throw new ConfigurationError( "Provider for " + factoryId + " cannot be found", null); } debugPrintln("loaded from fallback value: " + fallbackClassName); return newInstance(fallbackClassName, classLoader); } static class ConfigurationError extends Error { private Exception exception; /** * Construct a new instance with the specified detail string and * exception. */ ConfigurationError(String msg, Exception x) { super(msg); this.exception = x; } Exception getException() { return exception; } } }