--- a/jaxp/src/javax/xml/transform/FactoryFinder.java Thu Apr 12 08:38:26 2012 -0700
+++ b/jaxp/src/javax/xml/transform/FactoryFinder.java Tue Apr 17 11:17:59 2012 -0700
@@ -25,15 +25,13 @@
package javax.xml.transform;
+import java.io.BufferedReader;
import java.io.File;
-import java.io.FileInputStream;
-
-import java.util.Properties;
-import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.net.URL;
+import java.lang.reflect.Method;
+import java.util.Properties;
/**
* <p>Implements pluggable Datatypes.</p>
@@ -42,6 +40,7 @@
* sync. It is package private for secure class loading.</p>
*
* @author Santiago.PericasGeertsen@sun.com
+ * @author Huizhe.Wang@oracle.com
*/
class FactoryFinder {
@@ -59,7 +58,7 @@
* Flag indicating if properties from java.home/lib/jaxp.properties
* have been cached.
*/
- static boolean firstTime = true;
+ static volatile boolean firstTime = true;
/**
* Security support class use to check access control before
@@ -95,18 +94,24 @@
* If the class loader supplied is <code>null</code>, 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) throws ClassNotFoundException
+ boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
{
try {
if (cl == null) {
- cl = ss.getContextClassLoader();
- if (cl == null) {
- throw new ClassNotFoundException();
- }
- else {
- return cl.loadClass(className);
+ if (useBSClsLoader) {
+ return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+ } else {
+ cl = ss.getContextClassLoader();
+ if (cl == null) {
+ throw new ClassNotFoundException();
+ }
+ else {
+ return cl.loadClass(className);
+ }
}
}
else {
@@ -131,8 +136,8 @@
* @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 cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>
+ * current <code>Thread</code>'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
@@ -140,9 +145,39 @@
static Object newInstance(String className, ClassLoader cl, boolean doFallback)
throws ConfigurationError
{
+ return newInstance(className, cl, doFallback, false, false);
+ }
+
+ /**
+ * Create an instance of a class. Delegates to method
+ * <code>getProviderClass()</code> in order to load the class.
+ *
+ * @param className Name of the concrete class corresponding to the
+ * service provider
+ *
+ * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>
+ * current <code>Thread</code>'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
+ {
try {
- Class providerClass = getProviderClass(className, cl, doFallback);
- Object instance = providerClass.newInstance();
+ Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+ Object instance = null;
+ if (!useServicesMechanism) {
+ instance = newInstanceNoServiceLoader(providerClass);
+ }
+ if (instance == null) {
+ instance = providerClass.newInstance();
+ }
if (debug) { // Extra check to avoid computing cl strings
dPrint("created new instance of " + providerClass +
" using ClassLoader: " + cl);
@@ -159,7 +194,29 @@
x);
}
}
-
+ /**
+ * Try to construct using newTransformerFactoryNoServiceLoader
+ * method if available.
+ */
+ private static Object newInstanceNoServiceLoader(
+ 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;
+ }
+ }
/**
* Finds the implementation Class object in the specified order. Main
* entry point.
@@ -176,13 +233,12 @@
throws ConfigurationError
{
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, null, true);
+ return newInstance(systemProp, null, true, false, true);
}
}
catch (SecurityException se) {
@@ -210,7 +266,7 @@
if (factoryClassName != null) {
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
- return newInstance(factoryClassName, null, true);
+ return newInstance(factoryClassName, null, true, false, true);
}
}
catch (Exception ex) {
@@ -228,7 +284,7 @@
}
dPrint("loaded from fallback value: " + fallbackClassName);
- return newInstance(fallbackClassName, null, true);
+ return newInstance(fallbackClassName, null, true, false, true);
}
/*
@@ -244,6 +300,7 @@
// First try the Context ClassLoader
ClassLoader cl = ss.getContextClassLoader();
+ boolean useBSClsLoader = false;
if (cl != null) {
is = ss.getResourceAsStream(cl, serviceId);
@@ -251,11 +308,13 @@
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) {
@@ -293,7 +352,7 @@
// 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);
+ return newInstance(factoryClassName, cl, false, useBSClsLoader, true);
}
// No provider found