Path: blob/aarch64-shenandoah-jdk8u272-b10/jaxp/src/javax/xml/parsers/FactoryFinder.java
48482 views
/*1* Copyright (c) 2003, 2013, 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.parsers;2627import java.io.File;28import java.security.AccessController;29import java.security.PrivilegedAction;30import java.util.Iterator;31import java.util.Properties;32import java.util.ServiceConfigurationError;33import java.util.ServiceLoader;3435/**36* <p>Implements pluggable Parsers.</p>37*38* <p>This class is duplicated for each JAXP subpackage so keep it in39* sync. It is package private for secure class loading.</p>40*41* @author [email protected]42* @author [email protected]43*/44class FactoryFinder {45private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";46/**47* Internal debug flag.48*/49private static boolean debug = false;5051/**52* Cache for properties in java.home/lib/jaxp.properties53*/54private static final Properties cacheProps = new Properties();5556/**57* Flag indicating if properties from java.home/lib/jaxp.properties58* have been cached.59*/60static volatile boolean firstTime = true;6162/**63* Security support class use to check access control before64* getting certain system resources.65*/66private static final SecuritySupport ss = new SecuritySupport();6768// Define system property "jaxp.debug" to get output69static {70// Use try/catch block to support applets, which throws71// SecurityException out of this code.72try {73String val = ss.getSystemProperty("jaxp.debug");74// Allow simply setting the prop to turn on debug75debug = val != null && !"false".equals(val);76}77catch (SecurityException se) {78debug = false;79}80}8182private static void dPrint(String msg) {83if (debug) {84System.err.println("JAXP: " + msg);85}86}8788/**89* Attempt to load a class using the class loader supplied. If that fails90* and fall back is enabled, the current (i.e. bootstrap) class loader is91* tried.92*93* If the class loader supplied is <code>null</code>, first try using the94* context class loader followed by the current (i.e. bootstrap) class95* loader.96*97* Use bootstrap classLoader if cl = null and useBSClsLoader is true98*/99static private Class<?> getProviderClass(String className, ClassLoader cl,100boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException101{102try {103if (cl == null) {104if (useBSClsLoader) {105return Class.forName(className, false, FactoryFinder.class.getClassLoader());106} else {107cl = ss.getContextClassLoader();108if (cl == null) {109throw new ClassNotFoundException();110}111else {112return Class.forName(className, false, cl);113}114}115}116else {117return Class.forName(className, false, cl);118}119}120catch (ClassNotFoundException e1) {121if (doFallback) {122// Use current class loader - should always be bootstrap CL123return Class.forName(className, false, FactoryFinder.class.getClassLoader());124}125else {126throw e1;127}128}129}130131/**132* Create an instance of a class. Delegates to method133* <code>getProviderClass()</code> in order to load the class.134*135* @param type Base class / Service interface of the factory to136* instantiate.137*138* @param className Name of the concrete class corresponding to the139* service provider140*141* @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>142* current <code>Thread</code>'s context classLoader is used to load the factory class.143*144* @param doFallback True if the current ClassLoader should be tried as145* a fallback if the class is not found using cl146*/147static <T> T newInstance(Class<T> type, String className, ClassLoader cl,148boolean doFallback)149throws FactoryConfigurationError150{151return newInstance(type, className, cl, doFallback, false);152}153154/**155* Create an instance of a class. Delegates to method156* <code>getProviderClass()</code> in order to load the class.157*158* @param type Base class / Service interface of the factory to159* instantiate.160*161* @param className Name of the concrete class corresponding to the162* service provider163*164* @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>165* current <code>Thread</code>'s context classLoader is used to load the factory class.166*167* @param doFallback True if the current ClassLoader should be tried as168* a fallback if the class is not found using cl169*170* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter171* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.172*/173static <T> T newInstance(Class<T> type, String className, ClassLoader cl,174boolean doFallback, boolean useBSClsLoader)175throws FactoryConfigurationError176{177assert type != null;178// make sure we have access to restricted packages179if (System.getSecurityManager() != null) {180if (className != null && className.startsWith(DEFAULT_PACKAGE)) {181cl = null;182useBSClsLoader = true;183}184}185186try {187Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);188if (!type.isAssignableFrom(providerClass)) {189throw new ClassCastException(className + " cannot be cast to " + type.getName());190}191Object instance = providerClass.newInstance();192if (debug) { // Extra check to avoid computing cl strings193dPrint("created new instance of " + providerClass +194" using ClassLoader: " + cl);195}196return type.cast(instance);197}198catch (ClassNotFoundException x) {199throw new FactoryConfigurationError(x,200"Provider " + className + " not found");201}202catch (Exception x) {203throw new FactoryConfigurationError(x,204"Provider " + className + " could not be instantiated: " + x);205}206}207208/**209* Finds the implementation Class object in the specified order. Main210* entry point.211* @return Class object of factory, never null212*213* @param type Base class / Service interface of the214* factory to find.215* @param fallbackClassName Implementation class name, if nothing else216* is found. Use null to mean no fallback.217*218* Package private so this code can be shared.219*/220static <T> T find(Class<T> type, String fallbackClassName)221throws FactoryConfigurationError222{223final String factoryId = type.getName();224dPrint("find factoryId =" + factoryId);225226// Use the system property first227try {228String systemProp = ss.getSystemProperty(factoryId);229if (systemProp != null) {230dPrint("found system property, value=" + systemProp);231return newInstance(type, systemProp, null, true);232}233}234catch (SecurityException se) {235if (debug) se.printStackTrace();236}237238// try to read from $java.home/lib/jaxp.properties239try {240if (firstTime) {241synchronized (cacheProps) {242if (firstTime) {243String configFile = ss.getSystemProperty("java.home") + File.separator +244"lib" + File.separator + "jaxp.properties";245File f = new File(configFile);246firstTime = false;247if (ss.doesFileExist(f)) {248dPrint("Read properties file "+f);249cacheProps.load(ss.getFileInputStream(f));250}251}252}253}254final String factoryClassName = cacheProps.getProperty(factoryId);255256if (factoryClassName != null) {257dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);258return newInstance(type, factoryClassName, null, true);259}260}261catch (Exception ex) {262if (debug) ex.printStackTrace();263}264265// Try Jar Service Provider Mechanism266T provider = findServiceProvider(type);267if (provider != null) {268return provider;269}270if (fallbackClassName == null) {271throw new FactoryConfigurationError(272"Provider for " + factoryId + " cannot be found");273}274275dPrint("loaded from fallback value: " + fallbackClassName);276return newInstance(type, fallbackClassName, null, true);277}278279/*280* Try to find provider using the ServiceLoader API281*282* @param type Base class / Service interface of the factory to find.283*284* @return instance of provider class if found or null285*/286private static <T> T findServiceProvider(final Class<T> type) {287try {288return AccessController.doPrivileged(new PrivilegedAction<T>() {289public T run() {290final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);291final Iterator<T> iterator = serviceLoader.iterator();292if (iterator.hasNext()) {293return iterator.next();294} else {295return null;296}297}298});299} catch(ServiceConfigurationError e) {300// It is not possible to wrap an error directly in301// FactoryConfigurationError - so we need to wrap the302// ServiceConfigurationError in a RuntimeException.303// The alternative would be to modify the logic in304// FactoryConfigurationError to allow setting a305// Throwable as the cause, but that could cause306// compatibility issues down the road.307final RuntimeException x = new RuntimeException(308"Provider for " + type + " cannot be created", e);309final FactoryConfigurationError error =310new FactoryConfigurationError(x, x.getMessage());311throw error;312}313}314315}316317318