FactoryFinderpublic class FactoryFinder extends Object Implements pluggable Datatypes.
This class is duplicated for each JAXP subpackage so keep it in
sync. It is package private for secure class loading. |
Fields Summary |
---|
private static boolean | debugInternal debug flag. | static Properties | cachePropsCache for properties in java.home/lib/jaxp.properties | static boolean | firstTimeFlag indicating if properties from java.home/lib/jaxp.properties
have been cached. | static SecuritySupport | ssSecurity support class use to check access control before
getting certain system resources. |
Methods Summary |
---|
private static void | dPrint(java.lang.String msg)
// Define system property "jaxp.debug" to get output
// Use try/catch block to support applets, which throws
// SecurityException out of this code.
try {
String val = ss.getSystemProperty("jaxp.debug");
// Allow simply setting the prop to turn on debug
debug = val != null && !"false".equals(val);
}
catch (SecurityException se) {
debug = false;
}
if (debug) {
System.err.println("JAXP: " + msg);
}
| static java.lang.Object | find(java.lang.String factoryId, java.lang.String fallbackClassName)Finds the implementation Class object in the specified order. Main
entry point.
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);
}
}
catch (SecurityException se) {
if (debug) se.printStackTrace();
}
// try to read from $java.home/lib/jaxp.properties
try {
String factoryClassName = null;
if (firstTime) {
synchronized (cacheProps) {
if (firstTime) {
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);
cacheProps.load(ss.getFileInputStream(f));
}
}
}
}
factoryClassName = cacheProps.getProperty(factoryId);
if (factoryClassName != null) {
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
return newInstance(factoryClassName, null, true);
}
}
catch (Exception ex) {
if (debug) ex.printStackTrace();
}
// Try Jar Service Provider Mechanism
Object provider = findJarServiceProvider(factoryId);
if (provider != null) {
return provider;
}
if (fallbackClassName == null) {
throw new ConfigurationError(
"Provider for " + factoryId + " cannot be found", null);
}
dPrint("loaded from fallback value: " + fallbackClassName);
return newInstance(fallbackClassName, null, true);
| private static java.lang.Object | findJarServiceProvider(java.lang.String factoryId)
String serviceId = "META-INF/services/" + factoryId;
InputStream is = null;
// First try the Context ClassLoader
ClassLoader cl = ss.getContextClassLoader();
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);
}
} else {
// No Context ClassLoader, try the current ClassLoader
cl = FactoryFinder.class.getClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
}
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;
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);
}
// No provider found
return null;
| private static java.lang.Class | getProviderClass(java.lang.String className, java.lang.ClassLoader cl, boolean doFallback)Attempt to load a class using the class loader supplied. If that fails
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.
try {
if (cl == null) {
cl = ss.getContextClassLoader();
if (cl == null) {
throw new ClassNotFoundException();
}
else {
return cl.loadClass(className);
}
}
else {
return cl.loadClass(className);
}
}
catch (ClassNotFoundException e1) {
if (doFallback) {
// Use current class loader - should always be bootstrap CL
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
}
else {
throw e1;
}
}
| static java.lang.Object | newInstance(java.lang.String className, java.lang.ClassLoader cl, boolean doFallback)Create an instance of a class. Delegates to method
getProviderClass() in order to load the class.
try {
Class providerClass = getProviderClass(className, cl, doFallback);
Object instance = providerClass.newInstance();
if (debug) { // Extra check to avoid computing cl strings
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);
}
|
|