neilg       2002/08/26 16:55:45

  Modified:    java/src/org/xml/sax/helpers NewInstance.java
                        ParserAdapter.java ParserFactory.java
                        XMLReaderFactory.java
  Added:       java/src/org/xml/sax/helpers SecuritySupport.java
                        SecuritySupport12.java
  Log:
  porting changes by Edwin Goei that address problems in environments with Security 
managers into
  our SAX interfaces.  This code is now thoroughly nonstandard, but
  no test-suite compatibility problems should result from this change.
  
  Revision  Changes    Path
  1.2       +51 -27    xml-xerces/java/src/org/xml/sax/helpers/NewInstance.java
  
  Index: NewInstance.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/xml/sax/helpers/NewInstance.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- NewInstance.java  28 Nov 2001 15:26:48 -0000      1.1
  +++ NewInstance.java  26 Aug 2002 23:55:45 -0000      1.2
  @@ -23,32 +23,61 @@
    * <p>This class contains a static method for creating an instance of a
    * class from an explicit class name.  It tries to use the thread's context
    * ClassLoader if possible and falls back to using
  - * Class.forName(String).</p>
  + * Class.forName(String).  It also takes into account JDK 1.2+'s
  + * AccessController mechanism for performing its actions.  </p>
    *
  - * <p>This code is designed to compile and run on JDK version 1.1 and later
  - * including versions of Java 2.</p>
  + * <p>This code is designed to run on JDK version 1.1 and later and compile
  + * on versions of Java 2 and later.</p>
    *
  - * @author Edwin Goei, David Brownell
  - * @version 2.0r2pre3
  + * @author Edwin Goei, David Brownell, Neil Graham
  + * @version $Id$
    */
   class NewInstance {
   
  +    // constants
  +
  +    // governs whether, if we fail in finding a class even
  +    // when given a classloader, we'll make a last-ditch attempt
  +    // to use the current classloader.  
  +    private static final boolean DO_FALLBACK = true;
  +
       /**
        * Creates a new instance of the specified class name
        *
        * Package private so this code is not exposed at the API level.
        */
  -    static Object newInstance (ClassLoader classLoader, String className)
  +    static Object newInstance (ClassLoader cl, String className)
           throws ClassNotFoundException, IllegalAccessException,
               InstantiationException
       {
  -        Class driverClass;
  -        if (classLoader == null) {
  -            driverClass = 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 {
  -            driverClass = classLoader.loadClass(className);
  +            try {
  +                providerClass = cl.loadClass(className);
  +            } catch (ClassNotFoundException x) {
  +                if (DO_FALLBACK) {
  +                    // Fall back to current classloader
  +                    cl = NewInstance.class.getClassLoader();
  +                    providerClass = cl.loadClass(className);
  +                } else {
  +                    throw x;
  +                }
  +            }
           }
  -        return driverClass.newInstance();
  +        Object instance = providerClass.newInstance();
  +        return instance;
       }
   
       /**
  @@ -57,23 +86,18 @@
        */           
       static ClassLoader getClassLoader ()
       {
  -        Method m = null;
   
  -        try {
  -            m = Thread.class.getMethod("getContextClassLoader", null);
  -        } catch (NoSuchMethodException e) {
  -            // Assume that we are running JDK 1.1, use the current ClassLoader
  -            return NewInstance.class.getClassLoader();
  -        }
  +        SecuritySupport ss = SecuritySupport.getInstance();
   
  -        try {
  -            return (ClassLoader) m.invoke(Thread.currentThread(), null);
  -        } catch (IllegalAccessException e) {
  -            // assert(false)
  -            throw new UnknownError(e.getMessage());
  -        } catch (InvocationTargetException e) {
  -            // assert(e.getTargetException() instanceof SecurityException)
  -            throw new UnknownError(e.getMessage());
  +        // 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 = NewInstance.class.getClassLoader();
           }
  +        return cl;
  +
       }
   }
  
  
  
  1.4       +2 -1      xml-xerces/java/src/org/xml/sax/helpers/ParserAdapter.java
  
  Index: ParserAdapter.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/xml/sax/helpers/ParserAdapter.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ParserAdapter.java        8 May 2000 23:08:39 -0000       1.3
  +++ ParserAdapter.java        26 Aug 2002 23:55:45 -0000      1.4
  @@ -76,7 +76,8 @@
       {
        super();
   
  -     String driver = System.getProperty("org.xml.sax.parser");
  +    SecuritySupport ss = SecuritySupport.getInstance();
  +     String driver = ss.getSystemProperty("org.xml.sax.parser");
   
        try {
            setup(ParserFactory.makeParser());
  
  
  
  1.6       +2 -1      xml-xerces/java/src/org/xml/sax/helpers/ParserFactory.java
  
  Index: ParserFactory.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/xml/sax/helpers/ParserFactory.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ParserFactory.java        28 Nov 2001 15:26:48 -0000      1.5
  +++ ParserFactory.java        26 Aug 2002 23:55:45 -0000      1.6
  @@ -85,7 +85,8 @@
        NullPointerException,
        ClassCastException
       {
  -     String className = System.getProperty("org.xml.sax.parser");
  +    SecuritySupport ss = SecuritySupport.getInstance();
  +     String className = ss.getSystemProperty("org.xml.sax.parser");
        if (className == null) {
            throw new NullPointerException("No value for sax.parser property");
        } else {
  
  
  
  1.4       +70 -23    xml-xerces/java/src/org/xml/sax/helpers/XMLReaderFactory.java
  
  Index: XMLReaderFactory.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/xml/sax/helpers/XMLReaderFactory.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XMLReaderFactory.java     12 Dec 2001 18:21:27 -0000      1.3
  +++ XMLReaderFactory.java     26 Aug 2002 23:55:45 -0000      1.4
  @@ -104,34 +104,81 @@
       public static XMLReader createXMLReader ()
        throws SAXException
       {
  -     String          className = null;
  -     ClassLoader     loader = NewInstance.getClassLoader ();
  +         String              className = null;
  +        SecuritySupport ss = SecuritySupport.getInstance();
  +         ClassLoader loader = NewInstance.getClassLoader ();
        
  -     // 1. try the JVM-instance-wide system property
  -     try { className = System.getProperty (property); }
  -     catch (Exception e) { /* normally fails for applets */ }
  +         // 1. try the JVM-instance-wide system property 
  +        try {
  +            className = ss.getSystemProperty(property);
  +         } catch (Exception e) { /* normally fails for applets */ }
   
        // 2. if that fails, try META-INF/services/
        if (className == null) {
  -         try {
  -             String          service = "META-INF/services/" + property;
  -             InputStream     in;
  -             BufferedReader  reader;
  -
  -             if (loader == null)
  -                 in = ClassLoader.getSystemResourceAsStream (service);
  -             else
  -                 in = loader.getResourceAsStream (service);
  -
  -             if (in != null) {
  -                 reader = new BufferedReader (
  -                         new InputStreamReader (in, "UTF8"));
  -                 className = reader.readLine ();
  -                 in.close ();
  -             }
  -         } catch (Exception e) {
  -         }
  +        String               service = "META-INF/services/" + property;
  +
  +        InputStream is = null;
  +
  +        // First try the Context ClassLoader
  +        ClassLoader cl = ss.getContextClassLoader();
  +        if (cl != null) {
  +            is = ss.getResourceAsStream(cl, service);
  +
  +            // If no provider found then try the current ClassLoader
  +            if (is == null) {
  +                cl = XMLReaderFactory.class.getClassLoader();
  +                is = ss.getResourceAsStream(cl, service);
  +            }
  +        } else {
  +            // No Context ClassLoader or JDK 1.1 so try the current
  +            // ClassLoader
  +            cl = XMLReaderFactory.class.getClassLoader();
  +            is = ss.getResourceAsStream(cl, service);
  +        }
  +
  +        if (is != null) {
  +
  +            // 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));
  +            }
  +        
  +            try {
  +                // XXX Does not handle all possible input as specified by the
  +                // Jar Service Provider specification
  +                className = rd.readLine();
  +                rd.close();
  +            } catch (Exception x) {
  +                // No provider found
  +            } 
  +        }
        }
  +    // REVISIT:  there is a comment in the original FactoryFinder codde to the 
effect:
  +    //
  +    // 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.
  +    //
  +    // But it's not clear how the class loader "cl" (now out of scope!)
  +    // that loaded the inputStream would matter here...
   
        // 3. Distro-specific fallback
        if (className == null) {
  
  
  
  1.1                  xml-xerces/java/src/org/xml/sax/helpers/SecuritySupport.java
  
  Index: SecuritySupport.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The name "Apache Software Foundation" must not be used to endorse or
   *    promote products derived from this software without prior written
   *    permission. For written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2002, Sun Microsystems,
   * Inc., http://www.sun.com.  For more information on the Apache Software
   * Foundation, please see <http://www.apache.org/>.
   */
  
  package org.xml.sax.helpers;
  
  import java.lang.reflect.*;
  import java.net.*;
  import java.io.*;
  
  /**
   * This class is duplicated for each JAXP subpackage so keep it in sync.
   * It is package private and therefore is not exposed as part of the JAXP
   * API.
   *
   * Base class with security related methods that work on JDK 1.1.
   */
  class SecuritySupport {
  
      /*
       * Make this of type Object so that the verifier won't try to
       * prove its type, thus possibly trying to load the SecuritySupport12
       * class.
       */
      private static final Object securitySupport;
  
      static {
        SecuritySupport ss = null;
        try {
            Class c = Class.forName("java.security.AccessController");
            // if that worked, we're on 1.2.
            /*
             * Unfortunately, we can't load the class using reflection
             * because the class is package private.  And the class has
             * to be package private so the APIs aren't exposed to other
             * code that could use them to circumvent security.  Thus,
             * we accept the risk that the direct reference might fail
             * on some JDK 1.1 JVMs, even though we would never execute
             * this code in such a case.  Sigh...
             */
            ss = new SecuritySupport12();
        } catch (Exception ex) {
            // ignore it
        } finally {
            if (ss == null)
                ss = new SecuritySupport();
            securitySupport = ss;
        }
      }
  
      /**
       * Return an appropriate instance of this class, depending on whether
       * we're on a JDK 1.1 or J2SE 1.2 (or later) system.
       */
      public static SecuritySupport getInstance() {
        return (SecuritySupport)securitySupport;
      }
  
      public ClassLoader getContextClassLoader() {
        return null;
      }
  
      public String getSystemProperty(String propName) {
          return System.getProperty(propName);
      }
  
      public FileInputStream getFileInputStream(File file)
          throws FileNotFoundException
      {
          return new FileInputStream(file);
      }
  
      public InputStream getResourceAsStream(ClassLoader cl, String name) {
          InputStream ris;
          if (cl == null) {
              ris = ClassLoader.getSystemResourceAsStream(name);
          } else {
              ris = cl.getResourceAsStream(name);
          }
          return ris;
      }
  }
  
  
  
  1.1                  xml-xerces/java/src/org/xml/sax/helpers/SecuritySupport12.java
  
  Index: SecuritySupport12.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The name "Apache Software Foundation" must not be used to endorse or
   *    promote products derived from this software without prior written
   *    permission. For written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999-2002, Sun Microsystems,
   * Inc., http://www.sun.com.  For more information on the Apache Software
   * Foundation, please see <http://www.apache.org/>.
   */
  
  package org.xml.sax.helpers;
  
  import java.security.*;
  import java.net.*;
  import java.io.*;
  import java.util.*;
  
  /**
   * This class is duplicated for each JAXP subpackage so keep it in sync.
   * It is package private and therefore is not exposed as part of the JAXP
   * API.
   *
   * Security related methods that only work on J2SE 1.2 and newer.
   */
  class SecuritySupport12 extends SecuritySupport {
  
      public ClassLoader getContextClassLoader() {
        return (ClassLoader)
                AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                ClassLoader cl = null;
                try {
                    cl = Thread.currentThread().getContextClassLoader();
                } catch (SecurityException ex) { }
                return cl;
            }
        });
      }
  
      public String getSystemProperty(final String propName) {
        return (String)
              AccessController.doPrivileged(new PrivilegedAction() {
                  public Object run() {
                      return System.getProperty(propName);
                  }
              });
      }
  
      public FileInputStream getFileInputStream(final File file)
          throws FileNotFoundException
      {
        try {
              return (FileInputStream)
                  AccessController.doPrivileged(new PrivilegedExceptionAction() {
                      public Object run() throws FileNotFoundException {
                          return new FileInputStream(file);
                      }
                  });
        } catch (PrivilegedActionException e) {
            throw (FileNotFoundException)e.getException();
        }
      }
  
      public InputStream getResourceAsStream(final ClassLoader cl,
                                             final String name)
      {
          return (InputStream)
              AccessController.doPrivileged(new PrivilegedAction() {
                  public Object run() {
                      InputStream ris;
                      if (cl == null) {
                          ris = ClassLoader.getSystemResourceAsStream(name);
                      } else {
                          ris = cl.getResourceAsStream(name);
                      }
                      return ris;
                  }
              });
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to