--- old/src/javax/xml/validation/SchemaFactory.java 2013-01-09 12:44:07.000000000 +0100 +++ new/src/javax/xml/validation/SchemaFactory.java 2013-01-09 12:44:06.000000000 +0100 @@ -27,15 +27,14 @@ import java.io.File; import java.net.URL; - import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; - import org.w3c.dom.ls.LSResourceResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.SAXParseException; /** * Factory that creates {@link Schema} objects. Entry-point to @@ -79,7 +78,7 @@ * and has a significant effect on the parsing process, it is impossible * to define the DTD validation as a process independent from parsing. * For this reason, this specification does not define the semantics for - * the XML DTD. This doesn't prohibit implentors from implementing it + * the XML DTD. This doesn't prohibit implementors from implementing it * in a way they see fit, but users are warned that any DTD * validation implemented on this interface necessarily deviate from * the XML DTD semantics as defined in the XML 1.0. @@ -147,14 +146,17 @@ * is looked for. If present, the value is processed just like above. * *
The class loader is asked for service provider provider-configuration files matching
- * javax.xml.validation.SchemaFactory
in the resource directory META-INF/services.
- * See the JAR File Specification for file format and parsing rules.
- * Each potential service provider is required to implement the method:
- * {@link #isSchemaLanguageSupported(String schemaLanguage)} - *- * The first service provider found in class loader order that supports the specified schema language is returned. + * Use the service-provider loading facilities, defined by the + * {@link java.util.ServiceLoader} class, to attempt to locate and load an + * implementation of the service.
SchemaFactory
is located
@@ -186,10 +188,12 @@
* If no implementation of the schema language is available.
* @throws NullPointerException
* If the schemaLanguage
parameter is null.
+ * @throws SchemaFactoryConfigurationError
+ * If a configuration error is encountered.
*
* @see #newInstance(String schemaLanguage, String factoryClassName, ClassLoader classLoader)
*/
- public static final SchemaFactory newInstance(String schemaLanguage) {
+ public static SchemaFactory newInstance(String schemaLanguage) {
ClassLoader cl;
cl = ss.getContextClassLoader();
@@ -275,19 +279,19 @@
}
- /**
- * Is specified schema supported by this SchemaFactory
?
SchemaFactory
will understand.
+ /**
+ * Is specified schema supported by this SchemaFactory
?
SchemaFactory
will understand.
* schemaLanguage
must specify a valid schema language.
- *
- * @return true
if SchemaFactory
supports schemaLanguage
, else false
.
- *
- * @throws NullPointerException If schemaLanguage
is null
.
- * @throws IllegalArgumentException If schemaLanguage.length() == 0
- * or schemaLanguage
does not specify a valid schema language.
- */
- public abstract boolean isSchemaLanguageSupported(String schemaLanguage);
+ *
+ * @return true
if SchemaFactory
supports schemaLanguage
, else false
.
+ *
+ * @throws NullPointerException If schemaLanguage
is null
.
+ * @throws IllegalArgumentException If schemaLanguage.length() == 0
+ * or schemaLanguage
does not specify a valid schema language.
+ */
+ public abstract boolean isSchemaLanguageSupported(String schemaLanguage);
/**
* Look up the value of a feature flag.
--- old/src/javax/xml/validation/SchemaFactoryFinder.java 2013-01-09 12:44:09.000000000 +0100
+++ new/src/javax/xml/validation/SchemaFactoryFinder.java 2013-01-09 12:44:08.000000000 +0100
@@ -25,19 +25,16 @@
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.Modifier;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
+import java.security.AccessControlContext;
+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)}.
@@ -53,16 +50,15 @@
/**
*Take care of restrictions imposed by java security model
*/ - private static SecuritySupport ss = new SecuritySupport(); + private static final 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 final Properties cacheProps = new Properties(); + /** + *First time requires initialization overhead.
+ */ + private static volatile boolean firstTime = true; static { // Use try/catch block to support applets @@ -114,7 +110,7 @@ return; } } catch( Throwable _ ) { - ; // getContextClassLoader() undefined in JDK1.1 + // getContextClassLoader() undefined in JDK1.1 } if( classLoader==ClassLoader.getSystemClassLoader() ) { @@ -137,9 +133,13 @@ * * @throws NullPointerException * If theschemaLanguage
parameter is null.
+ * @throws SchemaFactoryConfigurationError
+ * If a configuration error is encountered.
*/
public SchemaFactory newFactory(String schemaLanguage) {
- if(schemaLanguage==null) throw new NullPointerException();
+ if(schemaLanguage==null) {
+ throw new NullPointerException();
+ }
SchemaFactory f = _newFactory(schemaLanguage);
if (f != null) {
debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage);
@@ -182,7 +182,7 @@
String configFile = javah + File.separator +
"lib" + File.separator + "jaxp.properties";
- String factoryClassName = null ;
+ String factoryClassName;
// try to read from $java.home/lib/jaxp.properties
try {
@@ -213,43 +213,11 @@
}
}
- /**
- // 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 with ServiceLoader
+ final SchemaFactory factoryImpl = findServiceProvider(schemaLanguage);
+ assert factoryImpl == null || factoryImpl.isSchemaLanguageSupported(schemaLanguage);
+ if (factoryImpl != null) {
+ return factoryImpl;
}
// platform default
@@ -267,29 +235,31 @@
* @param className Name of class to create.
* @return Created class or null
.
*/
- private Class createClass(String className) {
- Class clazz;
+ private Class> createClass(String className) {
+ 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 = Class.forName(className, false, classLoader);
+ } 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. + * fully qualified class name to be instantiated. * * @return null * if it fails. Error messages will be printed by this method. @@ -304,7 +274,7 @@ debugPrintln("createInstance(" + className + ")"); // get Class from className - Class clazz = createClass(className); + Class> clazz = createClass(className); if (clazz == null) { debugPrintln("failed to getClass(" + className + ")"); return null; @@ -313,9 +283,13 @@ // instantiate Class as a SchemaFactory try { - if (!useServicesMechanism) { - schemaFactory = (SchemaFactory) newInstanceNoServiceLoader(clazz); - } + if (!SchemaFactory.class.isAssignableFrom(clazz)) { + throw new ClassCastException(clazz.getName() + + " cannot be cast to " + SchemaFactory.class); + } + if (!useServicesMechanism) { + schemaFactory = newInstanceNoServiceLoader(clazz); + } if (schemaFactory == null) { schemaFactory = (SchemaFactory) clazz.newInstance(); } @@ -341,11 +315,12 @@ return schemaFactory; } + /** - * Try to construct using newTransformerFactoryNoServiceLoader + * Try to construct using newXMLSchemaFactoryNoServiceLoader * method if available. */ - private static Object newInstanceNoServiceLoader( + private static SchemaFactory newInstanceNoServiceLoader( Class> providerClass ) { // Retain maximum compatibility if no security manager. @@ -353,196 +328,87 @@ return null; } try { - Method creationMethod = + final Method creationMethod = providerClass.getDeclaredMethod( "newXMLSchemaFactoryNoServiceLoader" ); - return creationMethod.invoke(null, (Object[])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(); - } + final int modifiers = creationMethod.getModifiers(); - 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"); + // Do not call the method if it's not public static. + if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) { + return null; + } + + // Only calls "newXMLSchemaFactoryNoServiceLoader" if it's + // declared to return an instance of SchemaFactory. + final Class> returnType = creationMethod.getReturnType(); + if (SERVICE_CLASS.isAssignableFrom(returnType)) { + return SERVICE_CLASS.cast(creationMethod.invoke(null, (Object[])null)); + } else { + // Should not happen since + // XMLSchemaFactory.newXMLSchemaFactoryNoServiceLoader is + // declared to return XMLSchemaFactory. + throw new ClassCastException(returnType + + " cannot be cast to " + SERVICE_CLASS); + } + } catch(ClassCastException e) { + throw new SchemaFactoryConfigurationError(e.getMessage(), e); + } catch (NoSuchMethodException exc) { + return null; + } catch (Exception exc) { return null; } } - /** - *Look up a value in a property file.
- * - *Set debug
to true
to trace property evaluation.
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;
+ // Call isSchemaLanguageSupported with initial context.
+ private boolean isSchemaLanguageSupportedBy(final SchemaFactory factory,
+ final String schemaLanguage,
+ AccessControlContext acc) {
+ return AccessController.doPrivileged(new PrivilegedActionSchemaFactoryConfigurationError
with no
+ * detail message.
+ */
+ public SchemaFactoryConfigurationError() {
+ }
+
+
+ /**
+ * Create a new SchemaFactoryConfigurationError
with
+ * the String
specified as an error message.
+ *
+ * @param message The error message for the exception.
+ */
+ public SchemaFactoryConfigurationError(String message) {
+ super(message);
+ }
+
+ /**
+ * Create a new SchemaFactoryConfigurationError
with the
+ * given Throwable
base cause.
+ *
+ * @param cause The exception or error to be encapsulated in a
+ * SchemaFactoryConfigurationError.
+ */
+ public SchemaFactoryConfigurationError(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Create a new SchemaFactoryConfigurationError
with the
+ * given Throwable
base cause and detail message.
+ *
+ * @param cause The exception or error to be encapsulated in a
+ * SchemaFactoryConfigurationError.
+ * @param message The detail message.
+ */
+ public SchemaFactoryConfigurationError(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}