factoryfinder.java
来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 358 行
JAVA
358 行
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001-2003 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 <http://www.apache.org/>. */package com.sun.org.apache.xml.internal.dtm;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.Properties;/** * This class is based on the FactoryFinder classes in the JAXP subpackages * in the xml-commons project (xml-apis.jar) * * This copy of FactoryFinder is for the DTMManager. It caches the class * name after it is found the first time, if the System.property is not set. * If the System.property is set, then it is always used. * * It does not use context class loaders, but we will probably need to add * this support in the future. Question: If we use context class loaders, can * we still cache the class (do we need to also cache the class loader for * comparison purposes)? * * @author Edwin Goei, Ilene Seelemann */class FactoryFinder { /** Controls debugging output to stderr */ private static boolean debug; /** * Avoid reading all the files when the findFactory * method is called the second time (cache the result of * finding the default impl). */ private static String foundFactory = null; // Define system property "jaxp.debug" to get output static { try { String val = SecuritySupport.getInstance().getSystemProperty("jaxp.debug"); // Allow simply setting the prop to turn on debug debug = val != null && (! "false".equals(val)); } catch (SecurityException se) { debug = false; } } /** * Main entry point. Finds and creates a new instance of a concrete * factory implementation in the specified order as stated in the JAXP * spec. This code attempts to find a factory implementation in * serveral locations. If one fails, the next one is tried. To be * more robust, this occurs even if a SecurityException is thrown, but * perhaps it may be better to propogate the SecurityException instead, * so SecurityException-s are not masked. * * @return A new instance of the concrete factory class, 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 not to use a fallback. * * @throws FactoryFinder.ConfigurationError * If a factory instance cannot be returned * * Package private so this code can be shared. */ static Object find(String factoryId, String fallbackClassName) throws ConfigurationError { SecuritySupport ss = SecuritySupport.getInstance(); ClassLoader cl = FactoryFinder.class.getClassLoader(); dPrint("find factoryId=" + factoryId); // Use the system property first try { String systemProp = ss.getSystemProperty(factoryId); if (systemProp != null) { dPrint("found system property, value=" + systemProp); return newInstance(systemProp, cl, true); } } catch (SecurityException se) { // Ignore and continue w/ next location } synchronized (FactoryFinder.class) { // This block will only run once, and then foundFactory will // be set and immutable. Currently there is no support in this // class for context class loaders. If the contents of the // xalan.properties file changes, or the class loader changes, // this will *not* affect the cached class. if (foundFactory == null) { // Try to read from $java.home/lib/xalan.properties Properties xalanProperties = null; try { String javah = ss.getSystemProperty("java.home"); String configFile = javah + File.separator + "lib" + File.separator + "xalan.properties"; File f = new File(configFile); FileInputStream fis = ss.getFileInputStream(f); xalanProperties = new Properties(); xalanProperties.load(fis); fis.close(); } catch (Exception x) { // assert(x instanceof FileNotFoundException // || x instanceof SecurityException) // In both cases, ignore and continue w/ next location } if (xalanProperties != null) { foundFactory = xalanProperties.getProperty(factoryId); if (foundFactory != null) { dPrint("found in xalan.properties, value=" + foundFactory); } } else { // Try Jar Service Provider Mechanism // (foundFactory gets set in findJarServiceProvider method) findJarServiceProvider(factoryId); if (foundFactory == null) { if (fallbackClassName == null) { throw new ConfigurationError( "Provider for " + factoryId + " cannot be found", null); } dPrint("using fallback, value=" + fallbackClassName); foundFactory = fallbackClassName; } } } } return newInstance(foundFactory, cl, true); } 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 */ private static Object newInstance(String className, ClassLoader cl, boolean doFallback) throws ConfigurationError { // assert(className != null); try { Class providerClass; if (cl == null) { // XXX Use the bootstrap ClassLoader. There is no way to // load a class using the bootstrap ClassLoader that works // in both JDK 1.1 and Java 2. However, this should still // work b/c the following should be true: // // (cl == null) iff current ClassLoader == null // // 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(); providerClass = cl.loadClass(className); } else { throw x; } } } Object instance = providerClass.newInstance(); 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); } } /* * Try to find provider using Jar Service Provider Mechanism * * @return instance of provider class if found or null */ private static String findJarServiceProvider(String factoryId) throws ConfigurationError { SecuritySupport ss = SecuritySupport.getInstance(); String serviceId = "META-INF/services/" + factoryId; InputStream is = null; // No support yet for context class loader ClassLoader cl = FactoryFinder.class.getClassLoader(); is = ss.getResourceAsStream(cl, serviceId); if (is == null) { // No provider found return null; } dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); // Read the service provider name in UTF-8 as specified in // the jar spec. Unfortunately this fails in Microsoft // VJ++, which does not implement the UTF-8 // encoding. Theoretically, we should simply let it fail in // that case, since the JVM is obviously broken if it // doesn't support such a basic standard. But since there // are still some users attempting to use VJ++ for // development, we have dropped in a fallback which makes a // second attempt using the platform's default encoding. In // VJ++ this is apparently ASCII, which is a subset of // UTF-8... and since the strings we'll be reading here are // also primarily limited to the 7-bit ASCII range (at // least, in English versions), this should work well // enough to keep us on the air until we're ready to // officially decommit from VJ++. [Edited comment from // jkesselm] BufferedReader rd; try { rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); } catch (java.io.UnsupportedEncodingException e) { rd = new BufferedReader(new InputStreamReader(is)); } String factoryClassName = null; try { // XXX Does not handle all possible input as specified by the // Jar Service Provider specification factoryClassName = rd.readLine(); rd.close(); } catch (IOException x) { // No provider found return null; } if (factoryClassName != null && ! "".equals(factoryClassName)) { dPrint("found in resource, value=" + factoryClassName); // Note: here we do not want to fall back to the current // ClassLoader because we want to avoid the case where the // resource file was found using one ClassLoader and the // provider class was instantiated using a different one. return factoryClassName; } // No provider found return null; } 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; } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?