--- old/src/javax/xml/transform/FactoryFinder.java 2012-08-27 21:27:24.468348100 -0700 +++ new/src/javax/xml/transform/FactoryFinder.java 2012-08-27 21:27:23.681709800 -0700 @@ -25,19 +25,19 @@ package javax.xml.transform; -import java.io.BufferedReader; import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Properties; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; /** *

Implements pluggable Datatypes.

* - *

This class is duplicated for each JAXP subpackage so keep it in - * sync. It is package private for secure class loading.

+ *

This class is duplicated for each JAXP subpackage so keep it in sync. It + * is package private for secure class loading.

* * @author Santiago.PericasGeertsen@sun.com * @author Huizhe.Wang@oracle.com @@ -48,21 +48,18 @@ * Internal debug flag. */ private static boolean debug = false; - /** * Cache for properties in java.home/lib/jaxp.properties */ static Properties cacheProps = new Properties(); - /** - * Flag indicating if properties from java.home/lib/jaxp.properties - * have been cached. + * Flag indicating if properties from java.home/lib/jaxp.properties have + * been cached. */ static volatile boolean firstTime = true; - /** - * Security support class use to check access control before - * getting certain system resources. + * Security support class use to check access control before getting certain + * system resources. */ static SecuritySupport ss = new SecuritySupport(); @@ -74,8 +71,7 @@ String val = ss.getSystemProperty("jaxp.debug"); // Allow simply setting the prop to turn on debug debug = val != null && !"false".equals(val); - } - catch (SecurityException se) { + } catch (SecurityException se) { debug = false; } } @@ -91,15 +87,14 @@ * and fall back is enabled, the current (i.e. bootstrap) class loader is * tried. * - * If the class loader supplied is null, first try using the - * context class loader followed by the current (i.e. bootstrap) class - * loader. + * If the class loader supplied is + * null, first try using the context class loader followed by + * the current (i.e. bootstrap) class loader. * * Use bootstrap classLoader if cl = null and useBSClsLoader is true */ static private Class getProviderClass(String className, ClassLoader cl, - boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException - { + boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException { try { if (cl == null) { if (useBSClsLoader) { @@ -108,22 +103,18 @@ cl = ss.getContextClassLoader(); if (cl == null) { throw new ClassNotFoundException(); - } - else { + } else { return cl.loadClass(className); } } - } - else { + } else { return cl.loadClass(className); } - } - catch (ClassNotFoundException e1) { + } catch (ClassNotFoundException e1) { if (doFallback) { // Use current class loader - should always be bootstrap CL return Class.forName(className, true, FactoryFinder.class.getClassLoader()); - } - else { + } else { throw e1; } } @@ -133,18 +124,18 @@ * Create an instance of a class. Delegates to method * getProviderClass() in order to load the class. * - * @param className Name of the concrete class corresponding to the - * service provider + * @param className Name of the concrete class corresponding to the service + * provider * - * @param cl ClassLoader used to load the factory class. If null - * current Thread's context classLoader is used to load the factory class. + * @param cl ClassLoader used to load the factory class. + * If null current Thread's context classLoader is + * used to load the factory class. * - * @param doFallback True if the current ClassLoader should be tried as - * a fallback if the class is not found using cl + * @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 - { + throws TransformerFactoryConfigurationError { return newInstance(className, cl, doFallback, false, false); } @@ -152,23 +143,25 @@ * Create an instance of a class. Delegates to method * getProviderClass() in order to load the class. * - * @param className Name of the concrete class corresponding to the - * service provider - * - * @param cl ClassLoader used to load the factory class. If null - * current Thread's context classLoader is used to load the factory class. + * @param className Name of the concrete class corresponding to the service + * provider * - * @param doFallback True if the current ClassLoader should be tried as - * a fallback if the class is not found using cl - * - * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter - * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader. + * @param cl ClassLoader used to load the factory class. + * If null current Thread's context classLoader is + * used to load the factory class. + * + * @param doFallback True if the current ClassLoader should be tried as a + * fallback if the class is not found using cl + * + * @param useBSClsLoader True if cl=null actually meant bootstrap + * classLoader. This parameter is needed since + * DocumentBuilderFactory/SAXParserFactory defined null as context + * classLoader. * * @param useServicesMechanism True use services mechanism */ static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader, boolean useServicesMechanism) - throws ConfigurationError - { + throws TransformerFactoryConfigurationError { try { Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader); Object instance = null; @@ -179,59 +172,55 @@ instance = providerClass.newInstance(); } if (debug) { // Extra check to avoid computing cl strings - dPrint("created new instance of " + providerClass + - " using ClassLoader: " + cl); + 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); + } catch (ClassNotFoundException x) { + throw new TransformerFactoryConfigurationError(x, + "Provider " + className + " not found"); + } catch (Exception x) { + throw new TransformerFactoryConfigurationError(x, + "Provider " + className + " could not be instantiated: " + x); } } + /** - * Try to construct using newTransformerFactoryNoServiceLoader - * method if available. + * Try to construct using newTransformerFactoryNoServiceLoader method if + * available. */ private static Object newInstanceNoServiceLoader( - Class providerClass - ) { + Class providerClass) { // Retain maximum compatibility if no security manager. if (System.getSecurityManager() == null) { return null; } try { Method creationMethod = - providerClass.getDeclaredMethod( - "newTransformerFactoryNoServiceLoader" - ); - return creationMethod.invoke(null, null); - } catch (NoSuchMethodException exc) { - return null; - } catch (Exception exc) { - return null; + providerClass.getDeclaredMethod( + "newTransformerFactoryNoServiceLoader"); + return creationMethod.invoke(null, null); + } catch (NoSuchMethodException exc) { + return null; + } catch (Exception exc) { + return null; } } + /** - * Finds the implementation Class object in the specified order. Main - * entry point. + * 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. + * @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 - { + static Object find(Class factoryClass, String factoryId, String fallbackClassName) + throws TransformerFactoryConfigurationError { dPrint("find factoryId =" + factoryId); // Use the system property first try { @@ -240,9 +229,10 @@ dPrint("found system property, value=" + systemProp); return newInstance(systemProp, null, true, false, true); } - } - catch (SecurityException se) { - if (debug) se.printStackTrace(); + } catch (SecurityException se) { + if (debug) { + se.printStackTrace(); + } } // try to read from $java.home/lib/jaxp.properties @@ -251,12 +241,12 @@ if (firstTime) { synchronized (cacheProps) { if (firstTime) { - String configFile = ss.getSystemProperty("java.home") + File.separator + - "lib" + File.separator + "jaxp.properties"; + String configFile = ss.getSystemProperty("java.home") + File.separator + + "lib" + File.separator + "jaxp.properties"; File f = new File(configFile); firstTime = false; if (ss.doesFileExist(f)) { - dPrint("Read properties file "+f); + dPrint("Read properties file " + f); cacheProps.load(ss.getFileInputStream(f)); } } @@ -268,19 +258,20 @@ dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName); return newInstance(factoryClassName, null, true, false, true); } - } - catch (Exception ex) { - if (debug) ex.printStackTrace(); + } catch (Exception ex) { + if (debug) { + ex.printStackTrace(); + } } // Try Jar Service Provider Mechanism - Object provider = findJarServiceProvider(factoryId); + Object provider = findServiceProvider(factoryClass, fallbackClassName); if (provider != null) { return provider; } if (fallbackClassName == null) { - throw new ConfigurationError( - "Provider for " + factoryId + " cannot be found", null); + throw new TransformerFactoryConfigurationError(null, + "Provider for " + factoryId + " cannot be found"); } dPrint("loaded from fallback value: " + fallbackClassName); @@ -288,99 +279,31 @@ } /* - * Try to find provider using Jar Service Provider Mechanism + * Try to find a provider using Service Loader * * @return instance of provider class if found or null */ - private static Object findJarServiceProvider(String factoryId) - throws ConfigurationError - { - String serviceId = "META-INF/services/" + factoryId; - InputStream is = null; - - // First try the Context ClassLoader - ClassLoader cl = ss.getContextClassLoader(); - boolean useBSClsLoader = false; - if (cl != null) { - is = ss.getResourceAsStream(cl, serviceId); - - // If no provider found then try the current ClassLoader - if (is == null) { - cl = FactoryFinder.class.getClassLoader(); - is = ss.getResourceAsStream(cl, serviceId); - useBSClsLoader = true; - } - } else { - // No Context ClassLoader, try the current ClassLoader - cl = FactoryFinder.class.getClassLoader(); - is = ss.getResourceAsStream(cl, serviceId); - useBSClsLoader = true; - } - - if (is == null) { - // No provider found - return null; - } - - if (debug) { // Extra check to avoid computing cl strings - dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); - } - - BufferedReader rd; + private static Object findServiceProvider(final Class factoryClass, final String fallbackClassName) + throws TransformerFactoryConfigurationError { 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 newInstance(factoryClassName, cl, false, useBSClsLoader, true); - } - - // 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; - } - /** - * use the exception chaining mechanism of JDK1.4 - */ - @Override - public Throwable getCause() { - return exception; + return AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + Object defaultProvider = null; + for (Object factory : ServiceLoader.load(factoryClass)) { + if (factory.getClass().getName().equals(fallbackClassName)) { + defaultProvider = factory; + } else { + return factory; + } + } + if (defaultProvider != null) { + return defaultProvider; + } + return null; + } + }); + } catch (ServiceConfigurationError e) { + throw new TransformerFactoryConfigurationError((Exception) e.getCause(), e.getMessage()); } } - }