src/javax/xml/validation/SchemaFactoryFinder.java

Print this page

        

*** 23,66 **** * questions. */ 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.net.URL; ! import java.util.ArrayList; ! import java.util.Enumeration; ! import java.util.Iterator; ! import java.util.NoSuchElementException; import java.util.Properties; /** * Implementation of {@link SchemaFactory#newInstance(String)}. * * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> * @version $Revision: 1.8 $, $Date: 2010-11-01 04:36:13 $ * @since 1.5 */ class SchemaFactoryFinder { ! /** debug support code. */ private static boolean debug = false; /** ! *<p> Take care of restrictions imposed by java security model </p> */ private static SecuritySupport ss = new SecuritySupport(); /** * <p>Cache properties for performance.</p> */ private static Properties cacheProps = new Properties(); - /** * <p>First time requires initialization overhead.</p> */ private static volatile boolean firstTime = true; --- 23,64 ---- * questions. */ package javax.xml.validation; import java.io.File; import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; import java.net.URL; ! 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)}. * * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> * @version $Revision: 1.8 $, $Date: 2010-11-01 04:36:13 $ * @since 1.5 */ class SchemaFactoryFinder { ! private static final String DEFAULT_IMPL_NAME = "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory"; ! /** ! * debug support code. ! */ private static boolean debug = false; /** ! * <p> Take care of restrictions imposed by java security model </p> */ private static SecuritySupport ss = new SecuritySupport(); /** * <p>Cache properties for performance.</p> */ private static Properties cacheProps = new Properties(); /** * <p>First time requires initialization overhead.</p> */ private static volatile boolean firstTime = true;
*** 81,199 **** private static void debugPrintln(String msg) { if (debug) { System.err.println("JAXP: " + msg); } } - /** ! * <p><code>ClassLoader</code> to use to find <code>SchemaFactory</code>.</p> */ private final ClassLoader classLoader; /** ! * <p>Constructor that specifies <code>ClassLoader</code> to use ! * to find <code>SchemaFactory</code>.</p> ! * ! * @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 ) { debugDisplayClassLoader(); } } private void debugDisplayClassLoader() { try { ! if( classLoader == ss.getContextClassLoader() ) { ! debugPrintln("using thread context class loader ("+classLoader+") for search"); return; } ! } catch( Throwable _ ) { ; // getContextClassLoader() undefined in JDK1.1 } ! if( classLoader==ClassLoader.getSystemClassLoader() ) { ! debugPrintln("using system class loader ("+classLoader+") for search"); return; } ! debugPrintln("using class loader ("+classLoader+") for search"); } /** ! * <p>Creates a new {@link SchemaFactory} object for the specified ! * schema language.</p> * ! * @param schemaLanguage ! * See {@link SchemaFactory Schema Language} table in <code>SchemaFactory</code> ! * for the list of available schema languages. * * @return <code>null</code> if the callee fails to create one. * ! * @throws NullPointerException ! * If the <code>schemaLanguage</code> parameter is null. */ ! public SchemaFactory newFactory(String schemaLanguage) { ! if(schemaLanguage==null) throw new NullPointerException(); SchemaFactory f = _newFactory(schemaLanguage); if (f != null) { debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage); } else { debugPrintln("unable to find a factory for " + schemaLanguage); } return f; } /** ! * <p>Lookup a <code>SchemaFactory</code> for the given <code>schemaLanguage</code>.</p> * ! * @param schemaLanguage Schema language to lookup <code>SchemaFactory</code> for. * ! * @return <code>SchemaFactory</code> for the given <code>schemaLanguage</code>. */ ! private SchemaFactory _newFactory(String schemaLanguage) { SchemaFactory sf; String propertyName = SERVICE_CLASS.getName() + ":" + schemaLanguage; // system property look up try { ! debugPrintln("Looking up system property '"+propertyName+"'" ); String r = ss.getSystemProperty(propertyName); ! if(r!=null) { ! debugPrintln("The value is '"+r+"'"); sf = createInstance(r, true); ! if(sf!=null) return sf; ! } else debugPrintln("The property is undefined."); ! } 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 factoryClassName = null ; // try to read from $java.home/lib/jaxp.properties try { ! 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)); } } } --- 79,206 ---- private static void debugPrintln(String msg) { if (debug) { System.err.println("JAXP: " + msg); } } /** ! * <p><code>ClassLoader</code> to use to find ! * <code>SchemaFactory</code>.</p> */ private final ClassLoader classLoader; /** ! * <p>Constructor that specifies ! * <code>ClassLoader</code> to use to find ! * <code>SchemaFactory</code>.</p> ! * ! * @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) { debugDisplayClassLoader(); } } private void debugDisplayClassLoader() { try { ! if (classLoader == ss.getContextClassLoader()) { ! debugPrintln("using thread context class loader (" + classLoader + ") for search"); return; } ! } catch (Throwable _) { ; // getContextClassLoader() undefined in JDK1.1 } ! if (classLoader == ClassLoader.getSystemClassLoader()) { ! debugPrintln("using system class loader (" + classLoader + ") for search"); return; } ! debugPrintln("using class loader (" + classLoader + ") for search"); } /** ! * <p>Creates a new {@link SchemaFactory} object for the specified schema ! * language.</p> * ! * @param schemaLanguage See {@link SchemaFactory Schema Language} table ! * in <code>SchemaFactory</code> for the list of available schema languages. * * @return <code>null</code> if the callee fails to create one. * ! * @throws NullPointerException If the <code>schemaLanguage</code> parameter ! * is null. */ ! 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); } else { debugPrintln("unable to find a factory for " + schemaLanguage); } return f; } /** ! * <p>Lookup a ! * <code>SchemaFactory</code> for the given ! * <code>schemaLanguage</code>.</p> * ! * @param schemaLanguage Schema language to ! * lookup <code>SchemaFactory</code> for. * ! * @return <code>SchemaFactory</code> for the ! * given <code>schemaLanguage</code>. */ ! 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 + "'"); String r = ss.getSystemProperty(propertyName); ! if (r != null) { ! debugPrintln("The value is '" + r + "'"); sf = createInstance(r, true); ! if (sf != null) { ! return sf; ! } ! } else { debugPrintln("The property is undefined."); ! } ! } 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 factoryClassName = null; // try to read from $java.home/lib/jaxp.properties try { ! 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)); } } }
*** 201,270 **** factoryClassName = cacheProps.getProperty(propertyName); debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); if (factoryClassName != null) { sf = createInstance(factoryClassName, true); ! if(sf != null){ return sf; } } } catch (Exception ex) { if (debug) { ex.printStackTrace(); } } - /** - // 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(); ! } ! } } // platform default ! 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); } debugPrintln("all things were tried, but none was found. bailing out."); return null; } ! /** <p>Create class using appropriate ClassLoader.</p> * * @param className Name of class to create. * @return Created class or <code>null</code>. */ private Class createClass(String className) { --- 208,246 ---- factoryClassName = cacheProps.getProperty(propertyName); debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); if (factoryClassName != null) { sf = createInstance(factoryClassName, true); ! if (sf != null) { return sf; } } } catch (Exception ex) { if (debug) { ex.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")) { debugPrintln("attempting to use the platform default XML Schema validator"); ! return createInstance(DEFAULT_IMPL_NAME, true); } debugPrintln("all things were tried, but none was found. bailing out."); return null; } ! /** ! * <p>Create class using appropriate ClassLoader.</p> * * @param className Name of class to create. * @return Created class or <code>null</code>. */ private Class createClass(String className) {
*** 276,306 **** clazz = classLoader.loadClass(className); } else { clazz = Class.forName(className); } } catch (Throwable t) { ! if(debug) t.printStackTrace(); return null; } return clazz; } /** * <p>Creates an instance of the specified and returns it.</p> * ! * @param className ! * fully qualified class name to be instanciated. * ! * @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, boolean useServicesMechanism ) { SchemaFactory schemaFactory = null; debugPrintln("createInstance(" + className + ")"); // get Class from className --- 252,282 ---- clazz = classLoader.loadClass(className); } else { clazz = Class.forName(className); } } catch (Throwable t) { ! if (debug) { ! t.printStackTrace(); ! } return null; } return clazz; } /** * <p>Creates an instance of the specified and returns it.</p> * ! * @param className fully qualified class name to be instanciated. * ! * @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, boolean useServicesMechanism) { SchemaFactory schemaFactory = null; debugPrintln("createInstance(" + className + ")"); // get Class from className
*** 339,551 **** return null; } return schemaFactory; } /** ! * 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( ! "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. * ! * @return null ! * if there was an error. */ ! 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; } } /** ! * <p>Look up a value in a property file.</p> ! * ! * <p>Set <code>debug</code> to <code>true</code> to trace property evaluation.</p> * * @param schemaLanguage Schema Language to support. - * @param inputName Name of <code>InputStream</code>. - * @param in <code>InputStream</code> of properties. - * - * @return <code>SchemaFactory</code> as determined by <code>keyName</code> value or <code>null</code> if there was an error. * ! * @throws IOException If IO error reading from <code>in</code>. */ ! 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. ! */ ! 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(); - } - - 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 - } - } - } - 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() ); } /** * <p>Search the specified classloader for the given classname.</p> * --- 315,411 ---- return null; } return schemaFactory; } + /** ! * 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( ! "newXMLSchemaFactoryNoServiceLoader"); return creationMethod.invoke(null, null); } catch (NoSuchMethodException exc) { return null; } catch (Exception exc) { return null; } } ! /* ! * Try to find a provider using Service Loader * ! * @return instance of provider class if found or 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()); + } } /** ! * <p>Test if the specified schemas are supported by the provider.</p> * + * @param schemaFactory a Schema factory provider. * @param schemaLanguage Schema Language to support. * ! * @return <code>true</code> if the Schema Language is supported by the ! * provider. */ ! private static boolean isSchemaSupported(SchemaFactory schemaFactory, String schemaLanguage) { final Class[] stringClassArray = {"".getClass()}; final Object[] schemaLanguageObjectArray = {schemaLanguage}; final String isSchemaLanguageSupportedMethod = "isSchemaLanguageSupported"; // 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 String which(Class clazz) { ! return which(clazz.getName(), clazz.getClassLoader()); } /** * <p>Search the specified classloader for the given classname.</p> *
*** 556,566 **** */ private static String which(String classname, ClassLoader loader) { String classnameAsResource = classname.replace('.', '/') + ".class"; ! if( loader==null ) loader = ClassLoader.getSystemClassLoader(); //URL it = loader.getResource(classnameAsResource); URL it = ss.getResourceAsURL(loader, classnameAsResource); if (it != null) { return it.toString(); --- 416,428 ---- */ private static String which(String classname, ClassLoader loader) { String classnameAsResource = classname.replace('.', '/') + ".class"; ! if (loader == null) { ! loader = ClassLoader.getSystemClassLoader(); ! } //URL it = loader.getResource(classnameAsResource); URL it = ss.getResourceAsURL(loader, classnameAsResource); if (it != null) { return it.toString();