Path: blob/aarch64-shenandoah-jdk8u272-b10/jaxp/src/javax/xml/transform/FactoryFinder.java
32285 views
/*1* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.xml.transform;2627import java.io.File;28import java.lang.reflect.Method;29import java.lang.reflect.Modifier;30import java.security.AccessController;31import java.security.PrivilegedAction;32import java.util.Iterator;33import java.util.Properties;34import java.util.ServiceConfigurationError;35import java.util.ServiceLoader;3637/**38* <p>Implements pluggable Datatypes.</p>39*40* <p>This class is duplicated for each JAXP subpackage so keep it in41* sync. It is package private for secure class loading.</p>42*43* @author [email protected]44* @author [email protected]45*/46class FactoryFinder {47private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xalan.internal.";4849/**50* Internal debug flag.51*/52private static boolean debug = false;5354/**55* Cache for properties in java.home/lib/jaxp.properties56*/57private final static Properties cacheProps = new Properties();5859/**60* Flag indicating if properties from java.home/lib/jaxp.properties61* have been cached.62*/63static volatile boolean firstTime = true;6465/**66* Security support class use to check access control before67* getting certain system resources.68*/69private final static SecuritySupport ss = new SecuritySupport();7071// Define system property "jaxp.debug" to get output72static {73// Use try/catch block to support applets, which throws74// SecurityException out of this code.75try {76String val = ss.getSystemProperty("jaxp.debug");77// Allow simply setting the prop to turn on debug78debug = val != null && !"false".equals(val);79}80catch (SecurityException se) {81debug = false;82}83}8485private static void dPrint(String msg) {86if (debug) {87System.err.println("JAXP: " + msg);88}89}9091/**92* Attempt to load a class using the class loader supplied. If that fails93* and fall back is enabled, the current (i.e. bootstrap) class loader is94* tried.95*96* If the class loader supplied is <code>null</code>, first try using the97* context class loader followed by the current (i.e. bootstrap) class98* loader.99*100* Use bootstrap classLoader if cl = null and useBSClsLoader is true101*/102static private Class<?> getProviderClass(String className, ClassLoader cl,103boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException104{105try {106if (cl == null) {107if (useBSClsLoader) {108return Class.forName(className, false, FactoryFinder.class.getClassLoader());109} else {110cl = ss.getContextClassLoader();111if (cl == null) {112throw new ClassNotFoundException();113}114else {115return Class.forName(className, false, cl);116}117}118}119else {120return Class.forName(className, false, cl);121}122}123catch (ClassNotFoundException e1) {124if (doFallback) {125// Use current class loader - should always be bootstrap CL126return Class.forName(className, false, FactoryFinder.class.getClassLoader());127}128else {129throw e1;130}131}132}133134/**135* Create an instance of a class. Delegates to method136* <code>getProviderClass()</code> in order to load the class.137*138* @param type Base class / Service interface of the factory to139* instantiate.140*141* @param className Name of the concrete class corresponding to the142* service provider143*144* @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>145* current <code>Thread</code>'s context classLoader is used to load the factory class.146*147* @param doFallback True if the current ClassLoader should be tried as148* a fallback if the class is not found using cl149*150*/151static <T> T newInstance(Class<T> type, String className, ClassLoader cl,152boolean doFallback)153throws TransformerFactoryConfigurationError154{155assert type != null;156157boolean useBSClsLoader = false;158// make sure we have access to restricted packages159if (System.getSecurityManager() != null) {160if (className != null && className.startsWith(DEFAULT_PACKAGE)) {161cl = null;162useBSClsLoader = true;163}164}165166try {167Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);168if (!type.isAssignableFrom(providerClass)) {169throw new ClassCastException(className + " cannot be cast to " + type.getName());170}171Object instance = providerClass.newInstance();172173if (debug) { // Extra check to avoid computing cl strings174dPrint("created new instance of " + providerClass +175" using ClassLoader: " + cl);176}177return type.cast(instance);178}179catch (ClassNotFoundException x) {180throw new TransformerFactoryConfigurationError(x,181"Provider " + className + " not found");182}183catch (Exception x) {184throw new TransformerFactoryConfigurationError(x,185"Provider " + className + " could not be instantiated: " + x);186}187}188189/**190* Finds the implementation Class object in the specified order. Main191* entry point.192* @return Class object of factory, never null193*194* @param type Base class / Service interface of the195* factory to find.196*197* @param fallbackClassName Implementation class name, if nothing else198* is found. Use null to mean no fallback.199*200* Package private so this code can be shared.201*/202static <T> T find(Class<T> type, String fallbackClassName)203throws TransformerFactoryConfigurationError204{205assert type != null;206207final String factoryId = type.getName();208209dPrint("find factoryId =" + factoryId);210// Use the system property first211try {212String systemProp = ss.getSystemProperty(factoryId);213if (systemProp != null) {214dPrint("found system property, value=" + systemProp);215return newInstance(type, systemProp, null, true);216}217}218catch (SecurityException se) {219if (debug) se.printStackTrace();220}221222// try to read from $java.home/lib/jaxp.properties223try {224if (firstTime) {225synchronized (cacheProps) {226if (firstTime) {227String configFile = ss.getSystemProperty("java.home") + File.separator +228"lib" + File.separator + "jaxp.properties";229File f = new File(configFile);230firstTime = false;231if (ss.doesFileExist(f)) {232dPrint("Read properties file "+f);233cacheProps.load(ss.getFileInputStream(f));234}235}236}237}238final String factoryClassName = cacheProps.getProperty(factoryId);239240if (factoryClassName != null) {241dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);242return newInstance(type, factoryClassName, null, true);243}244}245catch (Exception ex) {246if (debug) ex.printStackTrace();247}248249// Try Jar Service Provider Mechanism250T provider = findServiceProvider(type);251if (provider != null) {252return provider;253}254if (fallbackClassName == null) {255throw new TransformerFactoryConfigurationError(null,256"Provider for " + factoryId + " cannot be found");257}258259dPrint("loaded from fallback value: " + fallbackClassName);260return newInstance(type, fallbackClassName, null, true);261}262263/*264* Try to find provider using the ServiceLoader.265*266* @param type Base class / Service interface of the factory to find.267*268* @return instance of provider class if found or null269*/270private static <T> T findServiceProvider(final Class<T> type)271throws TransformerFactoryConfigurationError272{273try {274return AccessController.doPrivileged(new PrivilegedAction<T>() {275public T run() {276final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);277final Iterator<T> iterator = serviceLoader.iterator();278if (iterator.hasNext()) {279return iterator.next();280} else {281return null;282}283}284});285} catch(ServiceConfigurationError e) {286// It is not possible to wrap an error directly in287// FactoryConfigurationError - so we need to wrap the288// ServiceConfigurationError in a RuntimeException.289// The alternative would be to modify the logic in290// FactoryConfigurationError to allow setting a291// Throwable as the cause, but that could cause292// compatibility issues down the road.293final RuntimeException x = new RuntimeException(294"Provider for " + type + " cannot be created", e);295final TransformerFactoryConfigurationError error =296new TransformerFactoryConfigurationError(x, x.getMessage());297throw error;298}299}300}301302303