Path: blob/jdk8u272-b10-aarch32-20201026/jaxp/src/javax/xml/stream/FactoryFinder.java
48792 views
/*1* Copyright (c) 2005, 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.stream;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 streams.</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*/43class FactoryFinder {44// Check we have access to package.45private static final String DEFAULT_PACKAGE = "com.sun.xml.internal.";4647/**48* Internal debug flag.49*/50private static boolean debug = false;5152/**53* Cache for properties in java.home/lib/jaxp.properties54*/55final private static Properties cacheProps = new Properties();5657/**58* Flag indicating if properties from java.home/lib/jaxp.properties59* have been cached.60*/61private static volatile boolean firstTime = true;6263/**64* Security support class use to check access control before65* getting certain system resources.66*/67final private static SecuritySupport ss = new SecuritySupport();6869// Define system property "jaxp.debug" to get output70static {71// Use try/catch block to support applets, which throws72// SecurityException out of this code.73try {74String val = ss.getSystemProperty("jaxp.debug");75// Allow simply setting the prop to turn on debug76debug = val != null && !"false".equals(val);77}78catch (SecurityException se) {79debug = false;80}81}8283private static void dPrint(String msg) {84if (debug) {85System.err.println("JAXP: " + msg);86}87}8889/**90* Attempt to load a class using the class loader supplied. If that fails91* and fall back is enabled, the current (i.e. bootstrap) class loader is92* tried.93*94* If the class loader supplied is <code>null</code>, first try using the95* context class loader followed by the current (i.e. bootstrap) class96* loader.97*98* Use bootstrap classLoader if cl = null and useBSClsLoader is true99*/100static private Class getProviderClass(String className, ClassLoader cl,101boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException102{103try {104if (cl == null) {105if (useBSClsLoader) {106return Class.forName(className, false, FactoryFinder.class.getClassLoader());107} else {108cl = ss.getContextClassLoader();109if (cl == null) {110throw new ClassNotFoundException();111}112else {113return Class.forName(className, false, cl);114}115}116}117else {118return Class.forName(className, false, cl);119}120}121catch (ClassNotFoundException e1) {122if (doFallback) {123// Use current class loader - should always be bootstrap CL124return Class.forName(className, false, FactoryFinder.class.getClassLoader());125}126else {127throw e1;128}129}130}131132/**133* Create an instance of a class. Delegates to method134* <code>getProviderClass()</code> in order to load the class.135*136* @param type Base class / Service interface of the factory to137* instantiate.138*139* @param className Name of the concrete class corresponding to the140* service provider141*142* @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>143* current <code>Thread</code>'s context classLoader is used to load the factory class.144*145* @param doFallback True if the current ClassLoader should be tried as146* a fallback if the class is not found using cl147*/148static <T> T newInstance(Class<T> type, String className, ClassLoader cl, boolean 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;178179// make sure we have access to restricted packages180if (System.getSecurityManager() != null) {181if (className != null && className.startsWith(DEFAULT_PACKAGE)) {182cl = null;183useBSClsLoader = true;184}185}186187try {188Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);189if (!type.isAssignableFrom(providerClass)) {190throw new ClassCastException(className + " cannot be cast to " + type.getName());191}192Object instance = providerClass.newInstance();193if (debug) { // Extra check to avoid computing cl strings194dPrint("created new instance of " + providerClass +195" using ClassLoader: " + cl);196}197return type.cast(instance);198}199catch (ClassNotFoundException x) {200throw new FactoryConfigurationError(201"Provider " + className + " not found", x);202}203catch (Exception x) {204throw new FactoryConfigurationError(205"Provider " + className + " could not be instantiated: " + x,206x);207}208}209210/**211* Finds the implementation Class object in the specified order.212*213* @return Class object of factory, never null214*215* @param type Base class / Service interface of the216* factory to find.217*218* @param fallbackClassName Implementation class name, if nothing else219* is found. Use null to mean no fallback.220*221* Package private so this code can be shared.222*/223static <T> T find(Class<T> type, String fallbackClassName)224throws FactoryConfigurationError225{226return find(type, type.getName(), null, fallbackClassName);227}228229/**230* Finds the implementation Class object in the specified order. Main231* entry point.232* @return Class object of factory, never null233*234* @param type Base class / Service interface of the235* factory to find.236*237* @param factoryId Name of the factory to find, same as238* a property name239*240* @param cl ClassLoader to be used to load the class, null means to use241* the bootstrap ClassLoader242*243* @param fallbackClassName Implementation class name, if nothing else244* is found. Use null to mean no fallback.245*246* Package private so this code can be shared.247*/248static <T> T find(Class<T> type, String factoryId, ClassLoader cl, String fallbackClassName)249throws FactoryConfigurationError250{251dPrint("find factoryId =" + factoryId);252253// Use the system property first254try {255256final String systemProp;257if (type.getName().equals(factoryId)) {258systemProp = ss.getSystemProperty(factoryId);259} else {260systemProp = System.getProperty(factoryId);261}262if (systemProp != null) {263dPrint("found system property, value=" + systemProp);264return newInstance(type, systemProp, cl, true);265}266}267catch (SecurityException se) {268throw new FactoryConfigurationError(269"Failed to read factoryId '" + factoryId + "'", se);270}271272// Try read $java.home/lib/stax.properties followed by273// $java.home/lib/jaxp.properties if former not present274String configFile = null;275try {276if (firstTime) {277synchronized (cacheProps) {278if (firstTime) {279configFile = ss.getSystemProperty("java.home") + File.separator +280"lib" + File.separator + "stax.properties";281File f = new File(configFile);282firstTime = false;283if (ss.doesFileExist(f)) {284dPrint("Read properties file "+f);285cacheProps.load(ss.getFileInputStream(f));286}287else {288configFile = ss.getSystemProperty("java.home") + File.separator +289"lib" + File.separator + "jaxp.properties";290f = new File(configFile);291if (ss.doesFileExist(f)) {292dPrint("Read properties file "+f);293cacheProps.load(ss.getFileInputStream(f));294}295}296}297}298}299final String factoryClassName = cacheProps.getProperty(factoryId);300301if (factoryClassName != null) {302dPrint("found in " + configFile + " value=" + factoryClassName);303return newInstance(type, factoryClassName, cl, true);304}305}306catch (Exception ex) {307if (debug) ex.printStackTrace();308}309310if (type.getName().equals(factoryId)) {311// Try Jar Service Provider Mechanism312final T provider = findServiceProvider(type, cl);313if (provider != null) {314return provider;315}316} else {317// We're in the case where a 'custom' factoryId was provided,318// and in every case where that happens, we expect that319// fallbackClassName will be null.320assert fallbackClassName == null;321}322if (fallbackClassName == null) {323throw new FactoryConfigurationError(324"Provider for " + factoryId + " cannot be found", null);325}326327dPrint("loaded from fallback value: " + fallbackClassName);328return newInstance(type, fallbackClassName, cl, true);329}330331/*332* Try to find provider using the ServiceLoader API333*334* @param type Base class / Service interface of the factory to find.335*336* @return instance of provider class if found or null337*/338private static <T> T findServiceProvider(final Class<T> type, final ClassLoader cl) {339try {340return AccessController.doPrivileged(new PrivilegedAction<T>() {341@Override342public T run() {343final ServiceLoader<T> serviceLoader;344if (cl == null) {345//the current thread's context class loader346serviceLoader = ServiceLoader.load(type);347} else {348serviceLoader = ServiceLoader.load(type, cl);349}350final Iterator<T> iterator = serviceLoader.iterator();351if (iterator.hasNext()) {352return iterator.next();353} else {354return null;355}356}357});358} catch(ServiceConfigurationError e) {359// It is not possible to wrap an error directly in360// FactoryConfigurationError - so we need to wrap the361// ServiceConfigurationError in a RuntimeException.362// The alternative would be to modify the logic in363// FactoryConfigurationError to allow setting a364// Throwable as the cause, but that could cause365// compatibility issues down the road.366final RuntimeException x = new RuntimeException(367"Provider for " + type + " cannot be created", e);368final FactoryConfigurationError error =369new FactoryConfigurationError(x, x.getMessage());370throw error;371}372}373374}375376377