--- old/src/javax/xml/validation/SchemaFactoryFinder.java 2012-08-27 21:27:32.344800400 -0700 +++ new/src/javax/xml/validation/SchemaFactoryFinder.java 2012-08-27 21:27:31.585413400 -0700 @@ -25,19 +25,15 @@ package javax.xml.validation; -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.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.NoSuchElementException; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Properties; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; /** * Implementation of {@link SchemaFactory#newInstance(String)}. @@ -46,23 +42,25 @@ * @version $Revision: 1.8 $, $Date: 2010-11-01 04:36:13 $ * @since 1.5 */ -class SchemaFactoryFinder { +class SchemaFactoryFinder { - /** debug support code. */ + private static final String DEFAULT_IMPL_NAME = "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory"; + /** + * debug support code. + */ private static boolean debug = false; /** - *

Take care of restrictions imposed by java security model

+ *

Take care of restrictions imposed by java security model

*/ private static SecuritySupport ss = new SecuritySupport(); /** *

Cache properties for performance.

*/ - private static Properties cacheProps = new Properties(); - - /** - *

First time requires initialization overhead.

- */ - private static volatile boolean firstTime = true; + private static Properties cacheProps = new Properties(); + /** + *

First time requires initialization overhead.

+ */ + private static volatile boolean firstTime = true; static { // Use try/catch block to support applets @@ -83,63 +81,64 @@ System.err.println("JAXP: " + msg); } } - /** - *

ClassLoader to use to find SchemaFactory.

+ *

ClassLoader to use to find + * SchemaFactory.

*/ private final ClassLoader classLoader; /** - *

Constructor that specifies ClassLoader to use - * to find SchemaFactory.

- * - * @param loader - * to be used to load resource, {@link SchemaFactory}, and - * {@link SchemaFactoryLoader} implementations during - * the resolution process. - * If this parameter is null, the default system class loader - * will be used. + *

Constructor that specifies + * ClassLoader to use to find + * SchemaFactory.

+ * + * @param loader to be used to load resource, {@link SchemaFactory}, and + * {@link SchemaFactoryLoader} implementations during the resolution + * process. If this parameter is null, the default system class loader will + * be used. */ public SchemaFactoryFinder(ClassLoader loader) { this.classLoader = loader; - if( debug ) { + if (debug) { debugDisplayClassLoader(); } } private void debugDisplayClassLoader() { try { - if( classLoader == ss.getContextClassLoader() ) { - debugPrintln("using thread context class loader ("+classLoader+") for search"); + if (classLoader == ss.getContextClassLoader()) { + debugPrintln("using thread context class loader (" + classLoader + ") for search"); return; } - } catch( Throwable _ ) { + } catch (Throwable _) { ; // getContextClassLoader() undefined in JDK1.1 } - if( classLoader==ClassLoader.getSystemClassLoader() ) { - debugPrintln("using system class loader ("+classLoader+") for search"); + if (classLoader == ClassLoader.getSystemClassLoader()) { + debugPrintln("using system class loader (" + classLoader + ") for search"); return; } - debugPrintln("using class loader ("+classLoader+") for search"); + debugPrintln("using class loader (" + classLoader + ") for search"); } /** - *

Creates a new {@link SchemaFactory} object for the specified - * schema language.

+ *

Creates a new {@link SchemaFactory} object for the specified schema + * language.

* - * @param schemaLanguage - * See {@link SchemaFactory Schema Language} table in SchemaFactory - * for the list of available schema languages. + * @param schemaLanguage See {@link SchemaFactory Schema Language} table + * in SchemaFactory for the list of available schema languages. * * @return null if the callee fails to create one. * - * @throws NullPointerException - * If the schemaLanguage parameter is null. + * @throws NullPointerException If the schemaLanguage parameter + * is null. */ - public SchemaFactory newFactory(String schemaLanguage) { - if(schemaLanguage==null) throw new NullPointerException(); + public SchemaFactory newFactory(String schemaLanguage) + throws FactoryConfigurationError { + if (schemaLanguage == null) { + throw new NullPointerException(); + } SchemaFactory f = _newFactory(schemaLanguage); if (f != null) { debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage); @@ -150,48 +149,56 @@ } /** - *

Lookup a SchemaFactory for the given schemaLanguage.

+ *

Lookup a + * SchemaFactory for the given + * schemaLanguage.

* - * @param schemaLanguage Schema language to lookup SchemaFactory for. + * @param schemaLanguage Schema language to + * lookup SchemaFactory for. * - * @return SchemaFactory for the given schemaLanguage. + * @return SchemaFactory for the + * given schemaLanguage. */ - private SchemaFactory _newFactory(String schemaLanguage) { + private SchemaFactory _newFactory(String schemaLanguage) + throws FactoryConfigurationError { SchemaFactory sf; String propertyName = SERVICE_CLASS.getName() + ":" + schemaLanguage; // system property look up try { - debugPrintln("Looking up system property '"+propertyName+"'" ); + debugPrintln("Looking up system property '" + propertyName + "'"); String r = ss.getSystemProperty(propertyName); - if(r!=null) { - debugPrintln("The value is '"+r+"'"); + if (r != null) { + debugPrintln("The value is '" + r + "'"); sf = createInstance(r, true); - if(sf!=null) return sf; - } else + if (sf != null) { + return sf; + } + } else { debugPrintln("The property is undefined."); - } catch( Throwable t ) { - if( debug ) { - debugPrintln("failed to look up system property '"+propertyName+"'" ); + } + } catch (Throwable t) { + if (debug) { + debugPrintln("failed to look up system property '" + propertyName + "'"); t.printStackTrace(); } } - String javah = ss.getSystemProperty( "java.home" ); - String configFile = javah + File.separator + - "lib" + File.separator + "jaxp.properties"; + String javah = ss.getSystemProperty("java.home"); + String configFile = javah + File.separator + + "lib" + File.separator + "jaxp.properties"; - String factoryClassName = null ; + String factoryClassName = null; // try to read from $java.home/lib/jaxp.properties try { - if(firstTime){ - synchronized(cacheProps){ - if(firstTime){ - File f=new File( configFile ); + if (firstTime) { + synchronized (cacheProps) { + if (firstTime) { + File f = new File(configFile); firstTime = false; - if(ss.doesFileExist(f)){ + if (ss.doesFileExist(f)) { debugPrintln("Read properties file " + f); cacheProps.load(ss.getFileInputStream(f)); } @@ -203,7 +210,7 @@ if (factoryClassName != null) { sf = createInstance(factoryClassName, true); - if(sf != null){ + if (sf != null) { return sf; } } @@ -213,92 +220,61 @@ } } - /** - // 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"; - File f = new File( configFile ); - if( ss.doesFileExist(f)) { - sf = loadFromProperty( - propertyName,f.getAbsolutePath(), new FileInputStream(f)); - if(sf!=null) return sf; - } else { - debugPrintln("Tried to read "+ f.getAbsolutePath()+", but it doesn't exist."); - } - } catch(Throwable e) { - if( debug ) { - debugPrintln("failed to read $java.home/lib/jaxp.properties"); - e.printStackTrace(); - } - } - */ - - // try META-INF/services files - Iterator sitr = createServiceFileIterator(); - while(sitr.hasNext()) { - URL resource = (URL)sitr.next(); - debugPrintln("looking into " + resource); - try { - sf = loadFromService(schemaLanguage,resource.toExternalForm(), - ss.getURLInputStream(resource)); - if(sf!=null) return sf; - } catch(IOException e) { - if( debug ) { - debugPrintln("failed to read "+resource); - e.printStackTrace(); - } - } + + // try finding a service provider + sf = findServiceProvider(schemaLanguage, DEFAULT_IMPL_NAME); + if (sf != null) { + return sf; } // platform default - if(schemaLanguage.equals("http://www.w3.org/2001/XMLSchema")) { + if (schemaLanguage.equals("http://www.w3.org/2001/XMLSchema")) { debugPrintln("attempting to use the platform default XML Schema validator"); - return createInstance("com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", true); + return createInstance(DEFAULT_IMPL_NAME, true); } debugPrintln("all things were tried, but none was found. bailing out."); return null; } - /**

Create class using appropriate ClassLoader.

+ /** + *

Create class using appropriate ClassLoader.

* * @param className Name of class to create. * @return Created class or null. */ private Class createClass(String className) { - Class clazz; + Class clazz; - // use approprite ClassLoader - try { - if (classLoader != null) { - clazz = classLoader.loadClass(className); - } else { - clazz = Class.forName(className); - } - } catch (Throwable t) { - if(debug) t.printStackTrace(); - return null; + // use approprite ClassLoader + try { + if (classLoader != null) { + clazz = classLoader.loadClass(className); + } else { + clazz = Class.forName(className); } + } catch (Throwable t) { + if (debug) { + t.printStackTrace(); + } + return null; + } - return clazz; + return clazz; } /** *

Creates an instance of the specified and returns it.

* - * @param className - * fully qualified class name to be instanciated. + * @param className fully qualified class name to be instanciated. * - * @return null - * if it fails. Error messages will be printed by this method. + * @return null if it fails. Error messages will be printed by this method. */ - SchemaFactory createInstance( String className ) { - return createInstance( className, false ); + SchemaFactory createInstance(String className) { + return createInstance(className, false); } - SchemaFactory createInstance( String className, boolean useServicesMechanism ) { + SchemaFactory createInstance(String className, boolean useServicesMechanism) { SchemaFactory schemaFactory = null; debugPrintln("createInstance(" + className + ")"); @@ -306,8 +282,8 @@ // get Class from className Class clazz = createClass(className); if (clazz == null) { - debugPrintln("failed to getClass(" + className + ")"); - return null; + debugPrintln("failed to getClass(" + className + ")"); + return null; } debugPrintln("loaded " + className + " from " + which(clazz)); @@ -316,234 +292,118 @@ if (!useServicesMechanism) { schemaFactory = (SchemaFactory) newInstanceNoServiceLoader(clazz); } - if (schemaFactory == null) { - schemaFactory = (SchemaFactory) clazz.newInstance(); - } + if (schemaFactory == null) { + schemaFactory = (SchemaFactory) clazz.newInstance(); + } } catch (ClassCastException classCastException) { - debugPrintln("could not instantiate " + clazz.getName()); - if (debug) { - classCastException.printStackTrace(); - } - return null; + debugPrintln("could not instantiate " + clazz.getName()); + if (debug) { + classCastException.printStackTrace(); + } + return null; } catch (IllegalAccessException illegalAccessException) { - debugPrintln("could not instantiate " + clazz.getName()); - if (debug) { - illegalAccessException.printStackTrace(); - } - return null; + debugPrintln("could not instantiate " + clazz.getName()); + if (debug) { + illegalAccessException.printStackTrace(); + } + return null; } catch (InstantiationException instantiationException) { - debugPrintln("could not instantiate " + clazz.getName()); - if (debug) { - instantiationException.printStackTrace(); - } - return null; + debugPrintln("could not instantiate " + clazz.getName()); + if (debug) { + instantiationException.printStackTrace(); + } + return null; } return schemaFactory; } + /** - * 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( - "newXMLSchemaFactoryNoServiceLoader" - ); - return creationMethod.invoke(null, null); - } catch (NoSuchMethodException exc) { - return null; - } catch (Exception exc) { - return null; + providerClass.getDeclaredMethod( + "newXMLSchemaFactoryNoServiceLoader"); + return creationMethod.invoke(null, null); + } catch (NoSuchMethodException exc) { + return null; + } catch (Exception exc) { + return null; } } - /** Iterator that lazily computes one value and returns it. */ - private static abstract class SingleIterator implements Iterator { - private boolean seen = false; - - public final void remove() { throw new UnsupportedOperationException(); } - public final boolean hasNext() { return !seen; } - public final Object next() { - if(seen) throw new NoSuchElementException(); - seen = true; - return value(); - } - - protected abstract Object value(); - } - /** - * Looks up a value in a property file - * while producing all sorts of debug messages. + /* + * Try to find a provider using Service Loader * - * @return null - * if there was an error. + * @return instance of provider class if found or null */ - private SchemaFactory loadFromProperty( String keyName, String resourceName, InputStream in ) - throws IOException { - debugPrintln("Reading "+resourceName ); - - Properties props=new Properties(); - props.load(in); - in.close(); - String factoryClassName = props.getProperty(keyName); - if(factoryClassName != null){ - debugPrintln("found "+keyName+" = " + factoryClassName); - return createInstance(factoryClassName); - } else { - debugPrintln(keyName+" is not in the property file"); - return null; + private SchemaFactory findServiceProvider(final String schemaLanguage, final String fallbackClassName) + throws FactoryConfigurationError { + try { + return (SchemaFactory) AccessController.doPrivileged(new PrivilegedAction() { + public SchemaFactory run() { + SchemaFactory defaultProvider = null; + for (SchemaFactory schemaFactory : ServiceLoader.load(SchemaFactory.class, classLoader)) { + if (schemaFactory.getClass().getName().equals(fallbackClassName)) { + defaultProvider = schemaFactory; + } else { + if (isSchemaSupported(schemaFactory, schemaLanguage)) { + return schemaFactory; + } + } + } + if (defaultProvider != null) { + return defaultProvider; + } + return null; + } + }); + } catch (ServiceConfigurationError e) { + throw new FactoryConfigurationError(e.getMessage(), (Exception) e.getCause()); } } /** - *

Look up a value in a property file.

- * - *

Set debug to true to trace property evaluation.

+ *

Test if the specified schemas are supported by the provider.

* + * @param schemaFactory a Schema factory provider. * @param schemaLanguage Schema Language to support. - * @param inputName Name of InputStream. - * @param in InputStream of properties. * - * @return SchemaFactory as determined by keyName value or null if there was an error. - * - * @throws IOException If IO error reading from in. - */ - private SchemaFactory loadFromService( - String schemaLanguage, - String inputName, - InputStream in) - throws IOException { - - SchemaFactory schemaFactory = null; - final Class[] stringClassArray = {"".getClass()}; - final Object[] schemaLanguageObjectArray = {schemaLanguage}; - final String isSchemaLanguageSupportedMethod = "isSchemaLanguageSupported"; - - debugPrintln("Reading " + inputName); - - // read from InputStream until a match is found - BufferedReader configFile = new BufferedReader(new InputStreamReader(in)); - String line = null; - while ((line = configFile.readLine()) != null) { - // '#' is comment char - int comment = line.indexOf("#"); - switch (comment) { - case -1: break; // no comment - case 0: line = ""; break; // entire line is a comment - default: line = line.substring(0, comment); break; // trim comment - } - - // trim whitespace - line = line.trim(); - - // any content left on line? - if (line.length() == 0) { - continue; - } - - // line content is now the name of the class - Class clazz = createClass(line); - if (clazz == null) { - continue; - } - - // create an instance of the Class - try { - schemaFactory = (SchemaFactory) clazz.newInstance(); - } catch (ClassCastException classCastExcpetion) { - schemaFactory = null; - continue; - } catch (InstantiationException instantiationException) { - schemaFactory = null; - continue; - } catch (IllegalAccessException illegalAccessException) { - schemaFactory = null; - continue; - } - - // does this Class support desired Schema? - try { - Method isSchemaLanguageSupported = clazz.getMethod(isSchemaLanguageSupportedMethod, stringClassArray); - Boolean supported = (Boolean) isSchemaLanguageSupported.invoke(schemaFactory, schemaLanguageObjectArray); - if (supported.booleanValue()) { - break; - } - } catch (NoSuchMethodException noSuchMethodException) { - - } catch (IllegalAccessException illegalAccessException) { - - } catch (InvocationTargetException invocationTargetException) { - - } - schemaFactory = null; - } - - // clean up - configFile.close(); - - // return new instance of SchemaFactory or null - return schemaFactory; - } - - /** - * Returns an {@link Iterator} that enumerates all - * the META-INF/services files that we care. + * @return true if the Schema Language is supported by the + * provider. */ - private Iterator createServiceFileIterator() { - if (classLoader == null) { - return new SingleIterator() { - protected Object value() { - ClassLoader classLoader = SchemaFactoryFinder.class.getClassLoader(); - //return (ClassLoader.getSystemResource( SERVICE_ID )); - return ss.getResourceAsURL(classLoader, SERVICE_ID); - } - }; - } else { - try { - //final Enumeration e = classLoader.getResources(SERVICE_ID); - final Enumeration e = ss.getResources(classLoader, SERVICE_ID); - if(!e.hasMoreElements()) { - debugPrintln("no "+SERVICE_ID+" file was found"); - } - - // wrap it into an Iterator. - return new Iterator() { - public void remove() { - throw new UnsupportedOperationException(); - } + private static boolean isSchemaSupported(SchemaFactory schemaFactory, String schemaLanguage) { + final Class[] stringClassArray = {"".getClass()}; + final Object[] schemaLanguageObjectArray = {schemaLanguage}; + final String isSchemaLanguageSupportedMethod = "isSchemaLanguageSupported"; - public boolean hasNext() { - return e.hasMoreElements(); - } - - public Object next() { - return e.nextElement(); - } - }; - } catch (IOException e) { - debugPrintln("failed to enumerate resources "+SERVICE_ID); - if(debug) e.printStackTrace(); - return new ArrayList().iterator(); // empty iterator + // does this Class support desired Schema? + try { + Method isSchemaLanguageSupported = schemaFactory.getClass().getMethod(isSchemaLanguageSupportedMethod, stringClassArray); + Boolean supported = (Boolean) isSchemaLanguageSupported.invoke(schemaFactory, schemaLanguageObjectArray); + if (supported.booleanValue()) { + return true; } + } catch (NoSuchMethodException noSuchMethodException) { + } catch (IllegalAccessException illegalAccessException) { + } catch (InvocationTargetException invocationTargetException) { } - } + return false; + } private static final Class SERVICE_CLASS = SchemaFactory.class; - private static final String SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName(); - - - private static String which( Class clazz ) { - return which( clazz.getName(), clazz.getClassLoader() ); + private static String which(Class clazz) { + return which(clazz.getName(), clazz.getClassLoader()); } /** @@ -558,7 +418,9 @@ String classnameAsResource = classname.replace('.', '/') + ".class"; - if( loader==null ) loader = ClassLoader.getSystemClassLoader(); + if (loader == null) { + loader = ClassLoader.getSystemClassLoader(); + } //URL it = loader.getResource(classnameAsResource); URL it = ss.getResourceAsURL(loader, classnameAsResource);