| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // $Id: FactoryFinder.java 670431 2008-06-23 01:40:03Z mrglavas $ |
| |
| package javax.xml.transform; |
| |
| |
| /** |
| * This class is duplicated for each JAXP subpackage so keep it in |
| * sync. It is package private. |
| * |
| * This code is designed to implement the JAXP 1.1 spec pluggability |
| * feature and is designed to run on JDK version 1.1 and later including |
| * JVMs that perform early linking like the Microsoft JVM in IE 5. Note |
| * however that it must be compiled on a JDK version 1.2 or later system |
| * since it calls Thread#getContextClassLoader(). The code also runs both |
| * as part of an unbundled jar file and when bundled as part of the JDK. |
| */ |
| final class FactoryFinder { |
| |
| /** |
| * <p>Debug flag to trace loading process.</p> |
| */ |
| private static boolean debug = false; |
| |
| // Define system property "jaxp.debug" to get output |
| static { |
| // Use try/catch block to support applets, which throws |
| // SecurityException out of this code. |
| try { |
| String val = System.getProperty("jaxp.debug"); |
| // Allow simply setting the prop to turn on debug |
| debug = val != null && (! "false".equals(val)); |
| } catch (SecurityException se) { |
| debug = false; |
| } |
| } |
| |
| private FactoryFinder() {} |
| |
| private static void dPrint(String msg) { |
| if (debug) { |
| System.err.println("JAXP: " + msg); |
| } |
| } |
| |
| /** |
| * Create an instance of a class using the specified ClassLoader and |
| * optionally fall back to the current ClassLoader if not found. |
| * |
| * @param className Name of the concrete class corresponding to the |
| * service provider |
| * |
| * @param cl ClassLoader to use to load the class, null means to use |
| * the bootstrap ClassLoader |
| * |
| * @param doFallback true if the current ClassLoader should be tried as |
| * a fallback if the class is not found using cl |
| */ |
| static Object newInstance(String className, ClassLoader cl, |
| boolean doFallback) |
| throws ConfigurationError |
| { |
| // assert(className != null); |
| |
| try { |
| Class providerClass; |
| if (cl == null) { |
| // If classloader is null Use the bootstrap ClassLoader. |
| // Thus Class.forName(String) will use the current |
| // ClassLoader which will be the bootstrap ClassLoader. |
| providerClass = Class.forName(className); |
| } else { |
| try { |
| providerClass = cl.loadClass(className); |
| } catch (ClassNotFoundException x) { |
| if (doFallback) { |
| // Fall back to current classloader |
| cl = FactoryFinder.class.getClassLoader(); |
| if (cl != null) { |
| providerClass = cl.loadClass(className); |
| } |
| else { |
| providerClass = Class.forName(className); |
| } |
| } else { |
| throw x; |
| } |
| } |
| } |
| |
| Object instance = providerClass.newInstance(); |
| if (debug) dPrint("created new instance of " + providerClass + |
| " using ClassLoader: " + cl); |
| return instance; |
| } 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. |
| * |
| * Package private so this code can be shared. |
| */ |
| static Object find(String factoryId, String fallbackClassName) |
| throws ConfigurationError |
| { |
| |
| // Figure out which ClassLoader to use for loading the provider |
| // class. If there is a Context ClassLoader then use it. |
| |
| ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); |
| |
| if (classLoader == null) { |
| // if we have no Context ClassLoader |
| // so use the current ClassLoader |
| classLoader = FactoryFinder.class.getClassLoader(); |
| } |
| |
| if (debug) dPrint("loaded from fallback value: " + fallbackClassName); |
| return newInstance(fallbackClassName, classLoader, true); |
| } |
| |
| 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; |
| } |
| } |
| |
| } |