You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-cvs@xml.apache.org by il...@apache.org on 2003/01/02 18:25:14 UTC
cvs commit: xml-commons/java/external/src/javax/xml/transform SecuritySupport12.java SecuritySupport.java FactoryFinder.java TransformerFactory.java
ilene 2003/01/02 09:25:14
Modified: java/external/src/javax/xml/transform Tag: tck-jaxp-1_2_0
FactoryFinder.java TransformerFactory.java
Added: java/external/src/javax/xml/transform Tag: tck-jaxp-1_2_0
SecuritySupport12.java SecuritySupport.java
Log:
Updating javax.xml.transform package with code from RIVERCOURT1 branch.
Revision Changes Path
No revision
No revision
1.7.6.1 +213 -130 xml-commons/java/external/src/javax/xml/transform/FactoryFinder.java
Index: FactoryFinder.java
===================================================================
RCS file: /home/cvs/xml-commons/java/external/src/javax/xml/transform/FactoryFinder.java,v
retrieving revision 1.7
retrieving revision 1.7.6.1
diff -u -r1.7 -r1.7.6.1
--- FactoryFinder.java 26 Oct 2001 00:23:47 -0000 1.7
+++ FactoryFinder.java 2 Jan 2003 17:25:13 -0000 1.7.6.1
@@ -55,17 +55,15 @@
package javax.xml.transform;
-import java.io.InputStream;
-import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.IOException;
-import java.util.Properties;
import java.io.BufferedReader;
import java.io.InputStreamReader;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
+import java.util.Properties;
/**
* This class is duplicated for each JAXP subpackage so keep it in sync.
@@ -73,65 +71,170 @@
* API.
*
* This code is designed to implement the JAXP 1.1 spec pluggability
- * feature and is designed to both compile and run on JDK version 1.1 and
- * later. The code also runs both as part of an unbundled jar file and
- * when bundled as part of the JDK.
+ * feature. The code runs both as part of an unbundled jar file and also
+ * when bundled as part of the JDK. Ideally the code should both compile
+ * and run on JDK version 1.1 and later. However, due to the complexities
+ * of invoking Java 2 security methods via reflection, this code will only
+ * compile on Java 2 although it will run under JDK 1.1 VMs. As of 1may02
+ * this file is on a "java2-branch".
+ *
+ * @author Edwin Goei
*/
class FactoryFinder {
- /** Set to true for debugging */
- private static final boolean debug = false;
+ /** Controls debugging output to stderr */
+ private static boolean debug;
- private static void debugPrintln(String msg) {
- if (debug) {
- System.err.println("JAXP: " + msg);
+ // Define system property "jaxp.debug" to get output
+ static {
+ try {
+ String val =
+ SecuritySupport.getInstance().getSystemProperty("jaxp.debug");
+ // Allow simply setting the prop to turn on debug
+ debug = val != null && (! "false".equals(val));
+ } catch (SecurityException se) {
+ debug = false;
}
}
/**
- * Figure out which ClassLoader to use. For JDK 1.2 and later use
- * the context ClassLoader.
- */
- private static ClassLoader findClassLoader()
+ * Main entry point. Finds and creates a new instance of a concrete
+ * factory implementation in the specified order as stated in the JAXP
+ * spec. This code attempts to find a factory implementation in
+ * serveral locations. If one fails, the next one is tried. To be
+ * more robust, this occurs even if a SecurityException is thrown, but
+ * perhaps it may be better to propogate the SecurityException instead,
+ * so SecurityException-s are not masked.
+ *
+ * @return A new instance of the concrete factory class, never null
+ *
+ * @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 not to use a fallback.
+ *
+ * @throws FactoryFinder.ConfigurationError
+ * If a factory instance cannot be returned
+ *
+ * Package private so this code can be shared.
+ */
+ static Object find(String factoryId, String fallbackClassName)
throws ConfigurationError
{
- Method m = null;
+ SecuritySupport ss = SecuritySupport.getInstance();
+ // Figure out which ClassLoader to use for loading the provider
+ // class. If there is a Context ClassLoader then use it.
+ ClassLoader cl = ss.getContextClassLoader();
+ if (cl == null) {
+ // Assert: we are on JDK 1.1 or we have no Context ClassLoader
+ // so use the current ClassLoader
+ cl = FactoryFinder.class.getClassLoader();
+ }
+
+ dPrint("find factoryId=" + factoryId);
+
+ // Use the system property first
try {
- m = Thread.class.getMethod("getContextClassLoader", null);
- } catch (NoSuchMethodException e) {
- // Assume that we are running JDK 1.1, use the current ClassLoader
- debugPrintln("assuming JDK 1.1");
- return FactoryFinder.class.getClassLoader();
+ String systemProp = ss.getSystemProperty(factoryId);
+ if (systemProp != null) {
+ dPrint("found system property, value=" + systemProp);
+ return newInstance(systemProp, cl, true);
+ }
+ } catch (SecurityException se) {
+ // Ignore and continue w/ next location
}
+ // Try to read from $java.home/lib/jaxp.properties
try {
- return (ClassLoader) m.invoke(Thread.currentThread(), null);
- } catch (IllegalAccessException e) {
- // assert(false)
- throw new ConfigurationError("Unexpected IllegalAccessException",
- e);
- } catch (InvocationTargetException e) {
- // assert(e.getTargetException() instanceof SecurityException)
- throw new ConfigurationError("Unexpected InvocationTargetException",
- e);
+ String javah = ss.getSystemProperty("java.home");
+ String configFile = javah + File.separator +
+ "lib" + File.separator + "jaxp.properties";
+ FileInputStream fis = ss.getFileInputStream(new File(configFile));
+ Properties props = new Properties();
+ props.load(fis);
+ String factoryClassName = props.getProperty(factoryId);
+ if (factoryClassName != null) {
+ dPrint("found in jaxp.properties, value=" + factoryClassName);
+ return newInstance(factoryClassName, cl, true);
+ }
+ } catch (Exception x) {
+ // assert(x instanceof FileNotFoundException
+ // || x instanceof SecurityException)
+ // In both cases, ignore and continue w/ next location
+ }
+
+ // 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("using fallback, value=" + fallbackClassName);
+ return newInstance(fallbackClassName, cl, true);
+ }
+
+ private static void dPrint(String msg) {
+ if (debug) {
+ System.err.println("JAXP: " + msg);
}
}
/**
- * Create an instance of a class using the specified ClassLoader
+ * Create an instance of a class using the specified ClassLoader and
+ * optionally fall back to the current ClassLoader if not found.
+ *
+ * @param className Name of the concrete class corresponding to the
+ * service provider
+ *
+ * @param cl ClassLoader to use to load the class, null means to use
+ * the bootstrap ClassLoader
+ *
+ * @param doFallback true if the current ClassLoader should be tried as
+ * a fallback if the class is not found using cl
*/
- private static Object newInstance(String className,
- ClassLoader classLoader)
+ private static Object newInstance(String className, ClassLoader cl,
+ boolean doFallback)
throws ConfigurationError
{
+ // assert(className != null);
+
try {
- Class spiClass;
- if (classLoader == null) {
- spiClass = Class.forName(className);
+ Class providerClass;
+ if (cl == null) {
+ // XXX Use the bootstrap ClassLoader. There is no way to
+ // load a class using the bootstrap ClassLoader that works
+ // in both JDK 1.1 and Java 2. However, this should still
+ // work b/c the following should be true:
+ //
+ // (cl == null) iff current ClassLoader == null
+ //
+ // Thus Class.forName(String) will use the current
+ // ClassLoader which will be the bootstrap ClassLoader.
+ providerClass = Class.forName(className);
} else {
- spiClass = classLoader.loadClass(className);
+ try {
+ providerClass = cl.loadClass(className);
+ } catch (ClassNotFoundException x) {
+ if (doFallback) {
+ // Fall back to current classloader
+ cl = FactoryFinder.class.getClassLoader();
+ providerClass = cl.loadClass(className);
+ } else {
+ throw x;
+ }
+ }
}
- return spiClass.newInstance();
+ Object instance = providerClass.newInstance();
+ dPrint("created new instance of " + providerClass +
+ " using ClassLoader: " + cl);
+ return instance;
} catch (ClassNotFoundException x) {
throw new ConfigurationError(
"Provider " + className + " not found", x);
@@ -142,111 +245,91 @@
}
}
- /**
- * Finds the implementation Class object in the specified order. Main
- * entry point.
- * @return Class object of factory, never null
- *
- * @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.
- *
- * @exception FactoryFinder.ConfigurationError
+ /*
+ * Try to find provider using Jar Service Provider Mechanism
*
- * Package private so this code can be shared.
+ * @return instance of provider class if found or null
*/
- static Object find(String factoryId, String fallbackClassName)
+ private static Object findJarServiceProvider(String factoryId)
throws ConfigurationError
{
- debugPrintln("debug is on");
-
- ClassLoader classLoader = findClassLoader();
+ SecuritySupport ss = SecuritySupport.getInstance();
+ String serviceId = "META-INF/services/" + factoryId;
+ InputStream is = null;
- // Use the system property first
- try {
- String systemProp =
- System.getProperty( factoryId );
- if( systemProp!=null) {
- debugPrintln("found system property " + systemProp);
- return newInstance(systemProp, classLoader);
+ // 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);
}
- } catch (SecurityException se) {
+ } else {
+ // No Context ClassLoader or JDK 1.1 so try the current
+ // ClassLoader
+ cl = FactoryFinder.class.getClassLoader();
+ is = ss.getResourceAsStream(cl, serviceId);
}
- // try to read from $java.home/lib/xml.properties
- try {
- String javah=System.getProperty( "java.home" );
- String configFile = javah + File.separator +
- "lib" + File.separator + "jaxp.properties";
- File f=new File( configFile );
- if( f.exists()) {
- Properties props=new Properties();
- props.load( new FileInputStream(f));
- String factoryClassName = props.getProperty(factoryId);
- debugPrintln("found java.home property " + factoryClassName);
- return newInstance(factoryClassName, classLoader);
- }
- } catch(Exception ex ) {
- if( debug ) ex.printStackTrace();
+ if (is == null) {
+ // No provider found
+ return null;
}
- String serviceId = "META-INF/services/" + factoryId;
- // try to find services in CLASSPATH
- try {
- InputStream is=null;
- if (classLoader == null) {
- is=ClassLoader.getSystemResourceAsStream( serviceId );
- } else {
- is=classLoader.getResourceAsStream( serviceId );
- }
-
- if( is!=null ) {
- debugPrintln("found " + serviceId);
+ dPrint("found jar resource=" + serviceId +
+ " using ClassLoader: " + cl);
- // Read the service provider name in UTF-8 as specified in
- // the jar spec. Unfortunately this fails in Microsoft
- // VJ++, which does not implement the UTF-8
- // encoding. Theoretically, we should simply let it fail in
- // that case, since the JVM is obviously broken if it
- // doesn't support such a basic standard. But since there
- // are still some users attempting to use VJ++ for
- // development, we have dropped in a fallback which makes a
- // second attempt using the platform's default encoding. In
- // VJ++ this is apparently ASCII, which is a subset of
- // UTF-8... and since the strings we'll be reading here are
- // also primarily limited to the 7-bit ASCII range (at
- // least, in English versions), this should work well
- // enough to keep us on the air until we're ready to
- // officially decommit from VJ++. [Edited comment from
- // jkesselm]
- BufferedReader rd;
- try {
- rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
- } catch (java.io.UnsupportedEncodingException e) {
- rd = new BufferedReader(new InputStreamReader(is));
- }
+ // Read the service provider name in UTF-8 as specified in
+ // the jar spec. Unfortunately this fails in Microsoft
+ // VJ++, which does not implement the UTF-8
+ // encoding. Theoretically, we should simply let it fail in
+ // that case, since the JVM is obviously broken if it
+ // doesn't support such a basic standard. But since there
+ // are still some users attempting to use VJ++ for
+ // development, we have dropped in a fallback which makes a
+ // second attempt using the platform's default encoding. In
+ // VJ++ this is apparently ASCII, which is a subset of
+ // UTF-8... and since the strings we'll be reading here are
+ // also primarily limited to the 7-bit ASCII range (at
+ // least, in English versions), this should work well
+ // enough to keep us on the air until we're ready to
+ // officially decommit from VJ++. [Edited comment from
+ // jkesselm]
+ BufferedReader rd;
+ try {
+ rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ } catch (java.io.UnsupportedEncodingException e) {
+ rd = new BufferedReader(new InputStreamReader(is));
+ }
- String factoryClassName = rd.readLine();
- rd.close();
-
- if (factoryClassName != null &&
- ! "".equals(factoryClassName)) {
- debugPrintln("loaded from services: " + factoryClassName);
- return newInstance(factoryClassName, classLoader);
- }
- }
- } catch( Exception ex ) {
- if( debug ) ex.printStackTrace();
+ 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 (fallbackClassName == null) {
- throw new ConfigurationError(
- "Provider for " + factoryId + " cannot be found", 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);
}
- debugPrintln("loaded from fallback value: " + fallbackClassName);
- return newInstance(fallbackClassName, classLoader);
+ // No provider found
+ return null;
}
static class ConfigurationError extends Error {
1.4.6.1 +1 -1 xml-commons/java/external/src/javax/xml/transform/TransformerFactory.java
Index: TransformerFactory.java
===================================================================
RCS file: /home/cvs/xml-commons/java/external/src/javax/xml/transform/TransformerFactory.java,v
retrieving revision 1.4
retrieving revision 1.4.6.1
diff -u -r1.4 -r1.4.6.1
--- TransformerFactory.java 22 Jan 2002 20:45:17 -0000 1.4
+++ TransformerFactory.java 2 Jan 2003 17:25:13 -0000 1.4.6.1
@@ -142,7 +142,7 @@
/* The default property name according to the JAXP spec */
"javax.xml.transform.TransformerFactory",
/* The fallback implementation class name */
- null);
+ "org.apache.xalan.processor.TransformerFactoryImpl");
} catch (FactoryFinder.ConfigurationError e) {
throw new TransformerFactoryConfigurationError(e.getException(),
e.getMessage());
No revision
No revision
1.1.6.1 +125 -0 xml-commons/java/external/src/javax/xml/transform/Attic/SecuritySupport12.java
1.1.6.1 +140 -0 xml-commons/java/external/src/javax/xml/transform/Attic/SecuritySupport.java