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