From 80124b43a842a1a5fc0522db2cef5875a8e0821e Mon Sep 17 00:00:00 2001 From: mrglavas Date: Tue, 21 Jun 2005 19:03:16 +0000 Subject: [PATCH] Merging in SecuritySupport code from the tck-jaxp-1_2_0 branch. git-svn-id: https://svn.apache.org/repos/asf/xml/commons/trunk@226249 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/xml/sax/helpers/SecuritySupport.java | 95 +++++++++ .../xml/sax/helpers/SecuritySupport12.java | 90 +++++++++ .../org/xml/sax/helpers/XMLReaderFactory.java | 188 +++++++++++------- 3 files changed, 298 insertions(+), 75 deletions(-) create mode 100644 java/external/src/org/xml/sax/helpers/SecuritySupport.java create mode 100644 java/external/src/org/xml/sax/helpers/SecuritySupport12.java diff --git a/java/external/src/org/xml/sax/helpers/SecuritySupport.java b/java/external/src/org/xml/sax/helpers/SecuritySupport.java new file mode 100644 index 0000000..7b91e9a --- /dev/null +++ b/java/external/src/org/xml/sax/helpers/SecuritySupport.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.xml.sax.helpers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +/** + * 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; + } +} diff --git a/java/external/src/org/xml/sax/helpers/SecuritySupport12.java b/java/external/src/org/xml/sax/helpers/SecuritySupport12.java new file mode 100644 index 0000000..6cc7826 --- /dev/null +++ b/java/external/src/org/xml/sax/helpers/SecuritySupport12.java @@ -0,0 +1,90 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.xml.sax.helpers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +/** + * 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; + } + }); + } +} diff --git a/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java b/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java index c3a669f..116f499 100644 --- a/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java +++ b/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java @@ -56,9 +56,9 @@ final public class XMLReaderFactory private XMLReaderFactory () { } - + private static final String property = "org.xml.sax.driver"; - + /** * Attempt to create an XMLReader from system defaults. * In environments which can support it, the name of the XMLReader @@ -102,63 +102,101 @@ final public class XMLReaderFactory * @see #createXMLReader(java.lang.String) */ public static XMLReader createXMLReader () - throws SAXException + throws SAXException { - String className = null; - ClassLoader loader = NewInstance.getClassLoader (); - - // 1. try the JVM-instance-wide system property - try { className = System.getProperty (property); } - catch (RuntimeException 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) { - } - } - - // 3. Distro-specific fallback - if (className == null) { -// BEGIN DISTRIBUTION-SPECIFIC - - // EXAMPLE: - // className = "com.example.sax.XmlReader"; - // or a $JAVA_HOME/jre/lib/*properties setting... + 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 (RuntimeException e) { /* normally fails for applets */ } + + // 2. if that fails, try META-INF/services/ + if (className == null) { + 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 + } + } + } + + // 3. Distro-specific fallback + if (className == null) { + // BEGIN DISTRIBUTION-SPECIFIC + + // EXAMPLE: + // className = "com.example.sax.XmlReader"; + // or a $JAVA_HOME/jre/lib/*properties setting... className = "org.apache.xerces.parsers.SAXParser"; - -// END DISTRIBUTION-SPECIFIC - } - - // do we know the XMLReader implementation class yet? - if (className != null) - return loadClass (loader, className); - - // 4. panic -- adapt any SAX1 parser - try { - return new ParserAdapter (ParserFactory.makeParser ()); - } catch (Exception e) { - throw new SAXException ("Can't create default XMLReader; " - + "is system property org.xml.sax.driver set?"); - } + + // END DISTRIBUTION-SPECIFIC + } + + // do we know the XMLReader implementation class yet? + if (className != null) + return loadClass (loader, className); + + // 4. panic -- adapt any SAX1 parser + try { + return new ParserAdapter (ParserFactory.makeParser ()); + } catch (Exception e) { + throw new SAXException ("Can't create default XMLReader; " + + "is system property org.xml.sax.driver set?"); + } } - - + + /** * Attempt to create an XML reader from a class name. * @@ -175,29 +213,29 @@ final public class XMLReaderFactory * @see #createXMLReader() */ public static XMLReader createXMLReader (String className) - throws SAXException + throws SAXException { - return loadClass (NewInstance.getClassLoader (), className); + return loadClass (NewInstance.getClassLoader (), className); } - + private static XMLReader loadClass (ClassLoader loader, String className) throws SAXException { - try { - return (XMLReader) NewInstance.newInstance (loader, className); - } catch (ClassNotFoundException e1) { - throw new SAXException("SAX2 driver class " + className + - " not found", e1); - } catch (IllegalAccessException e2) { - throw new SAXException("SAX2 driver class " + className + - " found but cannot be loaded", e2); - } catch (InstantiationException e3) { - throw new SAXException("SAX2 driver class " + className + - " loaded but cannot be instantiated (no empty public constructor?)", - e3); - } catch (ClassCastException e4) { - throw new SAXException("SAX2 driver class " + className + - " does not implement XMLReader", e4); - } + try { + return (XMLReader) NewInstance.newInstance (loader, className); + } catch (ClassNotFoundException e1) { + throw new SAXException("SAX2 driver class " + className + + " not found", e1); + } catch (IllegalAccessException e2) { + throw new SAXException("SAX2 driver class " + className + + " found but cannot be loaded", e2); + } catch (InstantiationException e3) { + throw new SAXException("SAX2 driver class " + className + + " loaded but cannot be instantiated (no empty public constructor?)", + e3); + } catch (ClassCastException e4) { + throw new SAXException("SAX2 driver class " + className + + " does not implement XMLReader", e4); + } } }