FileDocCategorySizeDatePackage
FactoryFinder.javaAPI DocJava SE 5 API11633Fri Aug 26 14:58:22 BST 2005javax.xml.datatype

FactoryFinder

public class FactoryFinder extends Object

Implement pluggabile Datatypes.

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

author
Jeff Suttor
version
$Revision: 1.1.10.2 $, $Date: 2004/09/21 12:59:26 $
since
1.5

Fields Summary
private static final String
CLASS_NAME

Name of class to display in output messages.

private static boolean
debug

Debug flag to trace loading process.

private static Properties
cacheProps

Cache properties for performance.

private static boolean
firstTime

First time requires initialization overhead.

private static SecuritySupport
ss

Take care of restrictions imposed by java security model

Constructors Summary
Methods Summary
private static voiddebugPrintln(java.lang.String msg)

Output debugging messages.

param
msg String to print to stderr.

	
	                       	 
     
        try {
            debug = ss.getSystemProperty("jaxp.debug") != null;
        } catch (Exception x) {
        	; // NOP, ignore exception
        }
    
        if (debug) {
            System.err.println(
            	CLASS_NAME
            	+ ":"
            	+ msg);
        }
    
static java.lang.Objectfind(java.lang.String factoryId, java.lang.String fallbackClassName)
Finds the implementation Class object in the specified order. Main entry point. Package private so this code can be shared.

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.
return
Class Object of factory, never null
throws
ConfigurationError If Class cannot be found.

        	
        ClassLoader classLoader = findClassLoader();

        // Use the system property first
        try {
            String systemProp = ss.getSystemProperty(factoryId);
            if (systemProp != null) {
                debugPrintln("found " + systemProp + " in the system property " + factoryId);
                return newInstance(systemProp, classLoader);
            }
        } catch (SecurityException se) {
        	; // NOP, explicitly ignore SecurityException
        }

        // try to read from $java.home/lib/jaxp.properties
        try {
            String javah = ss.getSystemProperty("java.home");
            String configFile = javah + File.separator + "lib" + File.separator + "jaxp.properties";
			String factoryClassName = null;
			if (firstTime) {
				synchronized (cacheProps) {
					if (firstTime) {
						File f = new File(configFile);
						firstTime = false;
						if (ss.doesFileExist(f)) {
							debugPrintln("Read properties file " + f);
							cacheProps.load(ss.getFileInputStream(f));
						}
					}
				}
			}
			factoryClassName = cacheProps.getProperty(factoryId);
            debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); 
			
			if (factoryClassName != null) {
				return newInstance(factoryClassName, classLoader);
			}
        } 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);
        }

        debugPrintln("loaded from fallback value: " + fallbackClassName);
        return newInstance(fallbackClassName, classLoader);
    
private static java.lang.ClassLoaderfindClassLoader()

Find the appropriate ClassLoader to use.

The context ClassLoader is prefered.

return
ClassLoader to use.
throws
ConfigurationError If a valid ClassLoader cannot be identified.

        ClassLoader classLoader;

        // Figure out which ClassLoader to use for loading the provider
        // class.  If there is a Context ClassLoader then use it.

        classLoader = ss.getContextClassLoader();            

        debugPrintln(
            "Using context class loader: "
            + classLoader);

        if (classLoader == null) {
            // if we have no Context ClassLoader
            // so use the current ClassLoader
            classLoader = FactoryFinder.class.getClassLoader();
            debugPrintln(
                "Using the class loader of FactoryFinder: "
                + classLoader);                
        }
                    
        return classLoader;
    
private static java.lang.ObjectfindJarServiceProvider(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;
        }

        debugPrintln("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)) {
            debugPrintln("found in resource, value="
                   + factoryClassName);

            return newInstance(factoryClassName, cl);
        }

        // No provider found
        return null;
    
private static java.lang.ObjectnewInstance(java.lang.String className, java.lang.ClassLoader classLoader)

Create an instance of a class using the specified ClassLoader.

param
className Name of class to create.
param
classLoader ClassLoader to use to create named class.
return
New instance of specified class created using the specified ClassLoader.
throws
ConfigurationError If class could not be created.

        	
        try {
            Class spiClass;
            if (classLoader == null) {
                spiClass = Class.forName(className);
            } else {
                spiClass = classLoader.loadClass(className);
            }
            
            if (debug) {
            	debugPrintln("Loaded " + className + " from " + which(spiClass));
            }
             
            return spiClass.newInstance();
        } 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);
        }
    
private static java.lang.Stringwhich(java.lang.Class clazz)
Returns the location where the given Class is loaded from.

param
clazz Class to find load location.
return
Location where class would be loaded from.

        try {
            String classnameAsResource = clazz.getName().replace('.", '/") + ".class";
    
            ClassLoader loader = clazz.getClassLoader();
            
            URL it;
    
            if (loader != null) {
            	it = loader.getResource(classnameAsResource);
            } else {
            	it = ClassLoader.getSystemResource(classnameAsResource);
            } 
    
            if (it != null) {
            	return it.toString();
            } 
        } catch (Throwable t) {
            // work defensively.
            if (debug) {
            	t.printStackTrace();
            } 
        }
        return "unknown location";