diff --git a/java/external/src/javax/xml/parsers/DocumentBuilder.java b/java/external/src/javax/xml/parsers/DocumentBuilder.java index 5143053..1858b3d 100644 --- a/java/external/src/javax/xml/parsers/DocumentBuilder.java +++ b/java/external/src/javax/xml/parsers/DocumentBuilder.java @@ -100,6 +100,7 @@ public abstract class DocumentBuilder { protected DocumentBuilder () { } + private static final boolean DEBUG = false ; /** * Parse the content of the given InputStream as an XML * document and return a new DOM {@link org.w3c.dom.Document} object. @@ -189,11 +190,12 @@ public abstract class DocumentBuilder { throw new IllegalArgumentException("File cannot be null"); } - String uri = "file:" + f.getAbsolutePath(); - if (File.separatorChar == '\\') { - uri = uri.replace('\\', '/'); - } - InputSource in = new InputSource(uri); + String escapedURI = FilePathToURI.filepath2URI(f.getAbsolutePath()) ; + + if(DEBUG) + System.out.println("Escaped URI = " + escapedURI) ; + + InputSource in = new InputSource(escapedURI); return parse(in); } diff --git a/java/external/src/javax/xml/parsers/DocumentBuilderFactory.java b/java/external/src/javax/xml/parsers/DocumentBuilderFactory.java index e4064da..7568198 100644 --- a/java/external/src/javax/xml/parsers/DocumentBuilderFactory.java +++ b/java/external/src/javax/xml/parsers/DocumentBuilderFactory.java @@ -140,7 +140,7 @@ public abstract class DocumentBuilderFactory { /* The default property name according to the JAXP spec */ "javax.xml.parsers.DocumentBuilderFactory", /* The fallback implementation class name */ - null); + "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); } catch (FactoryFinder.ConfigurationError e) { throw new FactoryConfigurationError(e.getException(), e.getMessage()); diff --git a/java/external/src/javax/xml/parsers/FactoryFinder.java b/java/external/src/javax/xml/parsers/FactoryFinder.java index 0157924..c9500ee 100644 --- a/java/external/src/javax/xml/parsers/FactoryFinder.java +++ b/java/external/src/javax/xml/parsers/FactoryFinder.java @@ -55,17 +55,15 @@ package javax.xml.parsers; -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 @@ import java.lang.reflect.InvocationTargetException; * 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) { + // 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; + } + } + + /** + * 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 + { + 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 { + 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 { + 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); } } /** - * Figure out which ClassLoader to use. For JDK 1.2 and later use - * the context ClassLoader. - */ - private static ClassLoader findClassLoader() - throws ConfigurationError - { - 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 - debugPrintln("assuming JDK 1.1"); - return FactoryFinder.class.getClassLoader(); - } - - 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); - } - } - - /** - * 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 @@ class FactoryFinder { } } - /** - * Finds the implementation Class object in the specified order. Main - * entry point. - * @return Class object of factory, never null + /* + * Try to find provider using Jar Service Provider Mechanism * - * @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 - * - * 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(); - - // Use the system property first - try { - String systemProp = - System.getProperty( factoryId ); - if( systemProp!=null) { - debugPrintln("found system property " + systemProp); - return newInstance(systemProp, classLoader); - } - } catch (SecurityException se) { - } - - // 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(); - } - + SecuritySupport ss = SecuritySupport.getInstance(); String serviceId = "META-INF/services/" + factoryId; - // try to find services in CLASSPATH + InputStream is = null; + + // 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); + } + } else { + // No Context ClassLoader or JDK 1.1 so try the current + // ClassLoader + cl = FactoryFinder.class.getClassLoader(); + is = ss.getResourceAsStream(cl, serviceId); + } + + if (is == null) { + // No provider found + return null; + } + + 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 { - InputStream is=null; - if (classLoader == null) { - is=ClassLoader.getSystemResourceAsStream( serviceId ); - } else { - is=classLoader.getResourceAsStream( serviceId ); - } + rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); + } catch (java.io.UnsupportedEncodingException e) { + rd = new BufferedReader(new InputStreamReader(is)); + } - if( is!=null ) { - debugPrintln("found " + serviceId); - - // 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 { diff --git a/java/external/src/javax/xml/parsers/FilePathToURI.java b/java/external/src/javax/xml/parsers/FilePathToURI.java new file mode 100644 index 0000000..977d4ae --- /dev/null +++ b/java/external/src/javax/xml/parsers/FilePathToURI.java @@ -0,0 +1,169 @@ +/* + * 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 names "Xerces" and "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 apache@apache.org. + * + * 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, International + * Business Machines, Inc., http://www.apache.org. For more + * information on the Apache Software Foundation, please see + * . + */ + +package javax.xml.parsers; + +class FilePathToURI { + + // which ASCII characters need to be escaped + private static boolean gNeedEscaping[] = new boolean[128]; + // the first hex character if a character needs to be escaped + private static char gAfterEscaping1[] = new char[128]; + // the second hex character if a character needs to be escaped + private static char gAfterEscaping2[] = new char[128]; + private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + // initialize the above 3 arrays + static { + for (int i = 0; i <= 0x1f; i++) { + gNeedEscaping[i] = true; + gAfterEscaping1[i] = gHexChs[i >> 4]; + gAfterEscaping2[i] = gHexChs[i & 0xf]; + } + gNeedEscaping[0x7f] = true; + gAfterEscaping1[0x7f] = '7'; + gAfterEscaping2[0x7f] = 'F'; + char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', + '|', '\\', '^', '~', '[', ']', '`'}; + int len = escChs.length; + char ch; + for (int i = 0; i < len; i++) { + ch = escChs[i]; + gNeedEscaping[ch] = true; + gAfterEscaping1[ch] = gHexChs[ch >> 4]; + gAfterEscaping2[ch] = gHexChs[ch & 0xf]; + } + } + + // To escape a file path to a URI, by using %HH to represent + // special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', '#', '%' + // and '"' and non-ASCII characters (whose value >= 128). + public static String filepath2URI(String path){ + // return null if path is null. + if (path == null) + return null; + + char separator = java.io.File.separatorChar; + path = path.replace(separator, '/'); + + int len = path.length(), ch; + StringBuffer buffer = new StringBuffer(len*3); + buffer.append("file://"); + // change C:/blah to /C:/blah + if (len >= 2 && path.charAt(1) == ':') { + ch = Character.toUpperCase(path.charAt(0)); + if (ch >= 'A' && ch <= 'Z') { + buffer.append('/'); + } + } + + // for each character in the path + int i = 0; + for (; i < len; i++) { + ch = path.charAt(i); + // if it's not an ASCII character, break here, and use UTF-8 encoding + if (ch >= 128) + break; + if (gNeedEscaping[ch]) { + buffer.append('%'); + buffer.append(gAfterEscaping1[ch]); + buffer.append(gAfterEscaping2[ch]); + // record the fact that it's escaped + } + else { + buffer.append((char)ch); + } + } + + // we saw some non-ascii character + if (i < len) { + // get UTF-8 bytes for the remaining sub-string + byte[] bytes = null; + byte b; + try { + bytes = path.substring(i).getBytes("UTF-8"); + } catch (java.io.UnsupportedEncodingException e) { + // should never happen + return path; + } + len = bytes.length; + + // for each byte + for (i = 0; i < len; i++) { + b = bytes[i]; + // for non-ascii character: make it positive, then escape + if (b < 0) { + ch = b + 256; + buffer.append('%'); + buffer.append(gHexChs[ch >> 4]); + buffer.append(gHexChs[ch & 0xf]); + } + else if (gNeedEscaping[b]) { + buffer.append('%'); + buffer.append(gAfterEscaping1[b]); + buffer.append(gAfterEscaping2[b]); + } + else { + buffer.append((char)b); + } + } + } + + return buffer.toString(); + } + +}//FilePathToURI diff --git a/java/external/src/javax/xml/parsers/SAXParser.java b/java/external/src/javax/xml/parsers/SAXParser.java index 67da490..fbf3b33 100644 --- a/java/external/src/javax/xml/parsers/SAXParser.java +++ b/java/external/src/javax/xml/parsers/SAXParser.java @@ -107,6 +107,7 @@ import org.xml.sax.SAXNotSupportedException; public abstract class SAXParser { + private static final boolean DEBUG = false ; protected SAXParser () { } @@ -293,14 +294,16 @@ public abstract class SAXParser { throw new IllegalArgumentException("File cannot be null"); } - String uri = "file:" + f.getAbsolutePath(); - if (File.separatorChar == '\\') { - uri = uri.replace('\\', '/'); - } - InputSource input = new InputSource(uri); + String escapedURI = FilePathToURI.filepath2URI(f.getAbsolutePath()) ; + + if(DEBUG) + System.out.println("Escaped URI = " + escapedURI) ; + + InputSource input = new InputSource(escapedURI); this.parse(input, hb); } + /** * Parse the content of the file specified as XML using the * specified {@link org.xml.sax.helpers.DefaultHandler}. @@ -321,11 +324,12 @@ public abstract class SAXParser { throw new IllegalArgumentException("File cannot be null"); } - String uri = "file:" + f.getAbsolutePath(); - if (File.separatorChar == '\\') { - uri = uri.replace('\\', '/'); - } - InputSource input = new InputSource(uri); + String escapedURI = FilePathToURI.filepath2URI(f.getAbsolutePath()) ; + + if(DEBUG) + System.out.println("Escaped URI = " + escapedURI) ; + + InputSource input = new InputSource(escapedURI); this.parse(input, dh); } @@ -353,6 +357,7 @@ public abstract class SAXParser { } Parser parser = this.getParser(); + if (hb != null) { parser.setDocumentHandler(hb); parser.setEntityResolver(hb); diff --git a/java/external/src/javax/xml/parsers/SAXParserFactory.java b/java/external/src/javax/xml/parsers/SAXParserFactory.java index 4be02c8..29fb8f0 100644 --- a/java/external/src/javax/xml/parsers/SAXParserFactory.java +++ b/java/external/src/javax/xml/parsers/SAXParserFactory.java @@ -136,7 +136,7 @@ public abstract class SAXParserFactory { /* The default property name according to the JAXP spec */ "javax.xml.parsers.SAXParserFactory", /* The fallback implementation class name */ - null); + "org.apache.xerces.jaxp.SAXParserFactoryImpl"); } catch (FactoryFinder.ConfigurationError e) { throw new FactoryConfigurationError(e.getException(), e.getMessage()); diff --git a/java/external/src/javax/xml/parsers/SecuritySupport.java b/java/external/src/javax/xml/parsers/SecuritySupport.java new file mode 100644 index 0000000..7299d48 --- /dev/null +++ b/java/external/src/javax/xml/parsers/SecuritySupport.java @@ -0,0 +1,140 @@ +/* + * 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 apache@apache.org. + * + * 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 . + */ + +package javax.xml.parsers; + +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. + /* + // don't reference the class explicitly so it doesn't + // get dragged in accidentally. + c = Class.forName("javax.mail.SecuritySupport12"); + Constructor cons = c.getConstructor(new Class[] { }); + ss = (SecuritySupport)cons.newInstance(new Object[] { }); + */ + /* + * 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/javax/xml/parsers/SecuritySupport12.java b/java/external/src/javax/xml/parsers/SecuritySupport12.java new file mode 100644 index 0000000..77b93a0 --- /dev/null +++ b/java/external/src/javax/xml/parsers/SecuritySupport12.java @@ -0,0 +1,125 @@ +/* + * 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 apache@apache.org. + * + * 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 . + */ + +package javax.xml.parsers; + +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; + } + }); + } +} diff --git a/java/external/src/org/xml/sax/SAXException.java b/java/external/src/org/xml/sax/SAXException.java index 0ffd56e..1597e8b 100644 --- a/java/external/src/org/xml/sax/SAXException.java +++ b/java/external/src/org/xml/sax/SAXException.java @@ -40,11 +40,14 @@ public class SAXException extends Exception { /** * Create a new SAXException. */ + /**** + * commented out by neilg for JAXP 1.2 compatibiliby. public SAXException () { super(); this.exception = null; } + ****/ /** diff --git a/java/external/src/org/xml/sax/SAXNotRecognizedException.java b/java/external/src/org/xml/sax/SAXNotRecognizedException.java index f5afae1..fb72a03 100644 --- a/java/external/src/org/xml/sax/SAXNotRecognizedException.java +++ b/java/external/src/org/xml/sax/SAXNotRecognizedException.java @@ -34,10 +34,13 @@ public class SAXNotRecognizedException extends SAXException /** * Default constructor. */ + /**** + * commented out by neilg for JAXP 1.2 compatibiliby. public SAXNotRecognizedException () { super(); } + *****/ /** diff --git a/java/external/src/org/xml/sax/SAXNotSupportedException.java b/java/external/src/org/xml/sax/SAXNotSupportedException.java index 3e1654f..fcf3a81 100644 --- a/java/external/src/org/xml/sax/SAXNotSupportedException.java +++ b/java/external/src/org/xml/sax/SAXNotSupportedException.java @@ -34,10 +34,13 @@ public class SAXNotSupportedException extends SAXException /** * Construct a new exception with no message. */ + /**** + * commented out by neilg for JAXP 1.2 compatibiliby. public SAXNotSupportedException () { super(); } + *****/ /** diff --git a/java/external/src/org/xml/sax/helpers/NamespaceSupport.java b/java/external/src/org/xml/sax/helpers/NamespaceSupport.java index cff88dd..9a26ef3 100644 --- a/java/external/src/org/xml/sax/helpers/NamespaceSupport.java +++ b/java/external/src/org/xml/sax/helpers/NamespaceSupport.java @@ -1,6 +1,5 @@ // NamespaceSupport.java - generic Namespace support for SAX. -// http://www.saxproject.org -// Written by David Megginson +// Written by David Megginson, sax@megginson.com // This class is in the Public Domain. NO WARRANTY! // $Id$ @@ -14,14 +13,11 @@ import java.util.Vector; /** - * Encapsulate Namespace logic for use by applications using SAX, - * or internally by SAX drivers. + * Encapsulate Namespace logic for use by SAX drivers. * *
* This module, both source code and documentation, is in the * Public Domain, and comes with NO WARRANTY. - * See http://www.saxproject.org - * for further information. *
* *

This class encapsulates the logic of Namespace processing: @@ -43,16 +39,16 @@ import java.util.Vector; * support.declarePrefix("", "http://www.w3.org/1999/xhtml"); * support.declarePrefix("dc", "http://www.purl.org/dc#"); * - * parts = support.processName("p", parts, false); + * String parts[] = support.processName("p", parts, false); * System.out.println("Namespace URI: " + parts[0]); * System.out.println("Local name: " + parts[1]); * System.out.println("Raw name: " + parts[2]); - * - * parts = support.processName("dc:title", parts, false); + + * String parts[] = support.processName("dc:title", parts, false); * System.out.println("Namespace URI: " + parts[0]); * System.out.println("Local name: " + parts[1]); * System.out.println("Raw name: " + parts[2]); - * + * support.popContext(); * * @@ -61,14 +57,15 @@ import java.util.Vector; * prefix/URI mapping is repeated for each context (for example), this * class will be somewhat less efficient.

* - *

Although SAX drivers (parsers) may choose to use this class to - * implement namespace handling, they are not required to do so. - * Applications must track namespace information themselves if they - * want to use namespace information. + * This class is not the 2.0.1 version; this was taken from Xerces + * to ensure JAXP 1.2 compatibility. It is unlikely the code changes + * between this class and the 2.0.1 version are significant, but + * it is best to be safe. * * @since SAX 2.0 - * @author David Megginson - * @version 2.0.1 (sax2r2) + * @author David Megginson, + * sax@megginson.com + * @version 2.0 */ public class NamespaceSupport { @@ -80,9 +77,7 @@ public class NamespaceSupport /** - * The XML Namespace URI as a constant. - * The value is http://www.w3.org/XML/1998/namespace - * as defined in the XML Namespaces specification. + * The XML Namespace as a constant. * *

This is the Namespace URI that is automatically mapped * to the "xml" prefix.

@@ -135,45 +130,21 @@ public class NamespaceSupport /** * Start a new Namespace context. - * The new context will automatically inherit + * + *

Normally, you should push a new context at the beginning + * of each XML element: the new context will automatically inherit * the declarations of its parent context, but it will also keep - * track of which declarations were made within this context. - * - *

Event callback code should start a new context once per element. - * This means being ready to call this in either of two places. - * For elements that don't include namespace declarations, the - * ContentHandler.startElement() callback is the right place. - * For elements with such a declaration, it'd done in the first - * ContentHandler.startPrefixMapping() callback. - * A boolean flag can be used to - * track whether a context has been started yet. When either of - * those methods is called, it checks the flag to see if a new context - * needs to be started. If so, it starts the context and sets the - * flag. After ContentHandler.startElement() - * does that, it always clears the flag. - * - *

Normally, SAX drivers would push a new context at the beginning - * of each XML element. Then they perform a first pass over the - * attributes to process all namespace declarations, making - * ContentHandler.startPrefixMapping() callbacks. - * Then a second pass is made, to determine the namespace-qualified - * names for all attributes and for the element name. - * Finally all the information for the - * ContentHandler.startElement() callback is available, - * so it can then be made. + * track of which declarations were made within this context.

* *

The Namespace support object always starts with a base context * already in force: in this context, only the "xml" prefix is * declared.

* - * @see org.xml.sax.ContentHandler * @see #popContext */ public void pushContext () { int max = contexts.length; - - contexts [contextPos].declsOK = false; contextPos++; // Extend the array if necessary @@ -212,7 +183,6 @@ public class NamespaceSupport */ public void popContext () { - contexts[contextPos].clear(); contextPos--; if (contextPos < 0) { throw new EmptyStackException(); @@ -228,42 +198,29 @@ public class NamespaceSupport /** - * Declare a Namespace prefix. All prefixes must be declared - * before they are referenced. For example, a SAX driver (parser) - * would scan an element's attributes - * in two passes: first for namespace declarations, - * then a second pass using {@link #processName processName()} to - * interpret prefixes against (potentially redefined) prefixes. + * Declare a Namespace prefix. * *

This method declares a prefix in the current Namespace * context; the prefix will remain in force until this context * is popped, unless it is shadowed in a descendant context.

* - *

To declare the default element Namespace, use the empty string as - * the prefix.

+ *

To declare a default Namespace, use the empty string. The + * prefix must not be "xml" or "xmlns".

* *

Note that you must not declare a prefix after - * you've pushed and popped another Namespace context, or - * treated the declarations phase as complete by processing - * a prefixed name.

+ * you've pushed and popped another Namespace.

* - *

Note that there is an asymmetry in this library: {@link - * #getPrefix getPrefix} will not return the "" prefix, - * even if you have declared a default element namespace. - * To check for a default namespace, + *

Note that there is an asymmetry in this library: while {@link + * #getPrefix getPrefix} will not return the default "" prefix, + * even if you have declared one; to check for a default prefix, * you have to look it up explicitly using {@link #getURI getURI}. * This asymmetry exists to make it easier to look up prefixes * for attribute names, where the default prefix is not allowed.

* - * @param prefix The prefix to declare, or the empty string to - * indicate the default element namespace. This may never have - * the value "xml" or "xmlns". + * @param prefix The prefix to declare, or null for the empty + * string. * @param uri The Namespace URI to associate with the prefix. * @return true if the prefix was legal, false otherwise - * @exception IllegalStateException when a prefix is declared - * after looking up a name in the context, or after pushing - * another context on top of it. - * * @see #processName * @see #getURI * @see #getPrefix @@ -280,8 +237,7 @@ public class NamespaceSupport /** - * Process a raw XML 1.0 name, after all declarations in the current - * context have been handled by {@link #declarePrefix declarePrefix()}. + * Process a raw XML 1.0 name. * *

This method processes a raw XML 1.0 name in the current * context by removing the prefix and looking it up among the @@ -304,7 +260,7 @@ public class NamespaceSupport * *

Note that attribute names are processed differently than * element names: an unprefixed element name will received the - * default Namespace (if any), while an unprefixed attribute name + * default Namespace (if any), while an unprefixed element name * will not.

* * @param qName The raw XML 1.0 name to be processed. @@ -468,14 +424,9 @@ public class NamespaceSupport /** * Internal class for a single Namespace context. * - *

This module caches and reuses Namespace contexts, - * so the number allocated + *

This module caches and reuses Namespace contexts, so the number allocated * will be equal to the element depth of the document, not to the total - * number of elements (i.e. 5-10 rather than tens of thousands). - * Also, data structures used to represent contexts are shared when - * possible (child contexts without declarations) to further reduce - * the amount of memory that's consumed. - *

+ * number of elements (i.e. 5-10 rather than tens of thousands).

*/ final class Context { @@ -490,8 +441,6 @@ public class NamespaceSupport /** * (Re)set the parent of this Namespace context. - * The context must either have been freshly constructed, - * or must have been cleared. * * @param context The parent Namespace context object. */ @@ -504,24 +453,7 @@ public class NamespaceSupport elementNameTable = parent.elementNameTable; attributeNameTable = parent.attributeNameTable; defaultNS = parent.defaultNS; - declSeen = false; - declsOK = true; - } - - /** - * Makes associated state become collectible, - * invalidating this context. - * {@link #setParent} must be called before - * this context may be used again. - */ - void clear () - { - parent = null; - prefixTable = null; - uriTable = null; - elementNameTable = null; - attributeNameTable = null; - defaultNS = null; + tablesDirty = false; } @@ -535,10 +467,7 @@ public class NamespaceSupport void declarePrefix (String prefix, String uri) { // Lazy processing... - if (!declsOK) - throw new IllegalStateException ( - "can't declare any more prefixes in this context"); - if (!declSeen) { + if (!tablesDirty) { copyTables(); } if (declarations == null) { @@ -577,14 +506,11 @@ public class NamespaceSupport String name[]; Hashtable table; - // detect errors in call sequence - declsOK = false; - // Select the appropriate table. if (isAttribute) { - table = attributeNameTable; - } else { table = elementNameTable; + } else { + table = attributeNameTable; } // Start by looking in the cache, and @@ -596,11 +522,8 @@ public class NamespaceSupport } // We haven't seen this name in this - // context before. Maybe in the parent - // context, but we can't assume prefix - // bindings are the same. + // context before. name = new String[3]; - name[2] = qName.intern(); int index = qName.indexOf(':'); @@ -611,7 +534,8 @@ public class NamespaceSupport } else { name[0] = defaultNS; } - name[1] = name[2]; + name[1] = qName.intern(); + name[2] = name[1]; } // Prefix @@ -629,11 +553,12 @@ public class NamespaceSupport } name[0] = uri; name[1] = local.intern(); + name[2] = qName.intern(); } // Save in the cache for future use. - // (Could be shared with parent context...) table.put(name[2], name); + tablesDirty = true; return name; } @@ -739,7 +664,7 @@ public class NamespaceSupport } elementNameTable = new Hashtable(); attributeNameTable = new Hashtable(); - declSeen = true; + tablesDirty = true; } @@ -753,7 +678,6 @@ public class NamespaceSupport Hashtable elementNameTable; Hashtable attributeNameTable; String defaultNS = null; - boolean declsOK = true; @@ -762,7 +686,7 @@ public class NamespaceSupport //////////////////////////////////////////////////////////////// private Vector declarations = null; - private boolean declSeen = false; + private boolean tablesDirty = false; private Context parent = null; } } diff --git a/java/external/src/org/xml/sax/helpers/NewInstance.java b/java/external/src/org/xml/sax/helpers/NewInstance.java index a5a124b..532f090 100644 --- a/java/external/src/org/xml/sax/helpers/NewInstance.java +++ b/java/external/src/org/xml/sax/helpers/NewInstance.java @@ -3,7 +3,6 @@ // Written by Edwin Goei, edwingo@apache.org // and by David Brownell, dbrownell@users.sourceforge.net // NO WARRANTY! This class is in the Public Domain. - // $Id$ package org.xml.sax.helpers; @@ -24,32 +23,64 @@ import java.lang.reflect.InvocationTargetException; *

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).

+ * Class.forName(String). It also takes into account JDK 1.2+'s + * AccessController mechanism for performing its actions.

* - *

This code is designed to compile and run on JDK version 1.1 and later - * including versions of Java 2.

+ *

This code is designed to run on JDK version 1.1 and later and compile + * on versions of Java 2 and later.

* - * @author Edwin Goei, David Brownell - * @version 2.0.1 (sax2r2) + *

This is not the NewInstance accompanying SAX 2.0.1; it + * represents some fixes to that code. + * + * @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; } /** @@ -58,23 +89,18 @@ class NewInstance { */ 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; + } } diff --git a/java/external/src/org/xml/sax/helpers/ParserAdapter.java b/java/external/src/org/xml/sax/helpers/ParserAdapter.java index 2a45663..e4d78f4 100644 --- a/java/external/src/org/xml/sax/helpers/ParserAdapter.java +++ b/java/external/src/org/xml/sax/helpers/ParserAdapter.java @@ -1,6 +1,5 @@ // ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader. -// http://www.saxproject.org -// Written by David Megginson +// Written by David Megginson, sax@megginson.com // NO WARRANTY! This class is in the public domain. // $Id$ @@ -9,7 +8,6 @@ package org.xml.sax.helpers; import java.io.IOException; import java.util.Enumeration; -import java.util.Vector; import org.xml.sax.Parser; // deprecated import org.xml.sax.InputSource; @@ -35,8 +33,6 @@ import org.xml.sax.SAXNotSupportedException; *

* This module, both source code and documentation, is in the * Public Domain, and comes with NO WARRANTY. - * See http://www.saxproject.org - * for further information. *
* *

This class wraps a SAX1 {@link org.xml.sax.Parser Parser} @@ -48,9 +44,15 @@ import org.xml.sax.SAXNotSupportedException; *

This adapter does not test for duplicate Namespace-qualified * attribute names.

* + *

Note that this is not the class shipped with + * SAX 2.0.1; this class takes into account the presence of AccessControllers + * in J2EE 1.4. It also throws NullPointerExceptions when setters are + * called with null parameters; the 2.0.1 version does not exhibit this behaviour.

+ * * @since SAX 2.0 - * @author David Megginson - * @version 2.0.1 (sax2r2) + * @author David Megginson, + * sax@megginson.com + * @version 2.0 * @see org.xml.sax.helpers.XMLReaderAdapter * @see org.xml.sax.XMLReader * @see org.xml.sax.Parser @@ -70,7 +72,7 @@ public class ParserAdapter implements XMLReader, DocumentHandler *

Use the "org.xml.sax.parser" property to locate the * embedded SAX1 driver.

* - * @exception SAXException If the embedded driver + * @exception org.xml.sax.SAXException If the embedded driver * cannot be instantiated or if the * org.xml.sax.parser property is not specified. */ @@ -79,7 +81,8 @@ public class ParserAdapter implements XMLReader, DocumentHandler { 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()); @@ -159,37 +162,46 @@ public class ParserAdapter implements XMLReader, DocumentHandler private final static String FEATURES = "http://xml.org/sax/features/"; private final static String NAMESPACES = FEATURES + "namespaces"; private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes"; + private final static String VALIDATION = FEATURES + "validation"; + private final static String EXTERNAL_GENERAL = + FEATURES + "external-general-entities"; + private final static String EXTERNAL_PARAMETER = + FEATURES + "external-parameter-entities"; /** - * Set a feature flag for the parser. + * Set a feature for the parser. * - *

The only features recognized are namespaces and + *

The only features supported are namespaces and * namespace-prefixes.

* * @param name The feature name, as a complete URI. - * @param value The requested feature value. - * @exception SAXNotRecognizedException If the feature - * can't be assigned or retrieved. - * @exception SAXNotSupportedException If the feature - * can't be assigned that value. + * @param state The requested feature state. + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * name is not known. + * @exception org.xml.sax.SAXNotSupportedException If the feature + * state is not supported. * @see org.xml.sax.XMLReader#setFeature */ - public void setFeature (String name, boolean value) + public void setFeature (String name, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException { if (name.equals(NAMESPACES)) { checkNotParsing("feature", name); - namespaces = value; + namespaces = state; if (!namespaces && !prefixes) { prefixes = true; } } else if (name.equals(NAMESPACE_PREFIXES)) { checkNotParsing("feature", name); - prefixes = value; + prefixes = state; if (!prefixes && !namespaces) { namespaces = true; } + } else if (name.equals(VALIDATION) || + name.equals(EXTERNAL_GENERAL) || + name.equals(EXTERNAL_PARAMETER)) { + throw new SAXNotSupportedException("Feature: " + name); } else { throw new SAXNotRecognizedException("Feature: " + name); } @@ -197,17 +209,17 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Check a parser feature flag. + * Check a parser feature. * - *

The only features recognized are namespaces and + *

The only features supported are namespaces and * namespace-prefixes.

* * @param name The feature name, as a complete URI. - * @return The current feature value. - * @exception SAXNotRecognizedException If the feature - * value can't be assigned or retrieved. - * @exception SAXNotSupportedException If the - * feature is not currently readable. + * @return The current feature state. + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * name is not known. + * @exception org.xml.sax.SAXNotSupportedException If querying the + * feature state is not supported. * @see org.xml.sax.XMLReader#setFeature */ public boolean getFeature (String name) @@ -217,6 +229,10 @@ public class ParserAdapter implements XMLReader, DocumentHandler return namespaces; } else if (name.equals(NAMESPACE_PREFIXES)) { return prefixes; + } else if (name.equals(VALIDATION) || + name.equals(EXTERNAL_GENERAL) || + name.equals(EXTERNAL_PARAMETER)) { + throw new SAXNotSupportedException("Feature: " + name); } else { throw new SAXNotRecognizedException("Feature: " + name); } @@ -226,14 +242,14 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** * Set a parser property. * - *

No properties are currently recognized.

+ *

No special properties are currently supported.

* * @param name The property name. * @param value The property value. - * @exception SAXNotRecognizedException If the property - * value can't be assigned or retrieved. - * @exception SAXNotSupportedException If the property - * can't be assigned that value. + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * name is not known. + * @exception org.xml.sax.SAXNotSupportedException If the feature + * state is not supported. * @see org.xml.sax.XMLReader#setProperty */ public void setProperty (String name, Object value) @@ -246,14 +262,14 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** * Get a parser property. * - *

No properties are currently recognized.

+ *

No special properties are currently supported.

* * @param name The property name. * @return The property value. - * @exception SAXNotRecognizedException If the property - * value can't be assigned or retrieved. - * @exception SAXNotSupportedException If the property - * value is not currently readable. + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * name is not known. + * @exception org.xml.sax.SAXNotSupportedException If the feature + * state is not supported. * @see org.xml.sax.XMLReader#getProperty */ public Object getProperty (String name) @@ -267,10 +283,15 @@ public class ParserAdapter implements XMLReader, DocumentHandler * Set the entity resolver. * * @param resolver The new entity resolver. + * @exception java.lang.NullPointerException If the entity resolver + * parameter is null. * @see org.xml.sax.XMLReader#setEntityResolver */ public void setEntityResolver (EntityResolver resolver) { + if (resolver == null) { + throw new NullPointerException("Null entity resolver"); + } entityResolver = resolver; } @@ -291,10 +312,15 @@ public class ParserAdapter implements XMLReader, DocumentHandler * Set the DTD handler. * * @param resolver The new DTD handler. + * @exception java.lang.NullPointerException If the DTD handler + * parameter is null. * @see org.xml.sax.XMLReader#setEntityResolver */ public void setDTDHandler (DTDHandler handler) { + if (handler == null) { + throw new NullPointerException("Null DTD handler"); + } dtdHandler = handler; } @@ -315,10 +341,15 @@ public class ParserAdapter implements XMLReader, DocumentHandler * Set the content handler. * * @param resolver The new content handler. + * @exception java.lang.NullPointerException If the content handler + * parameter is null. * @see org.xml.sax.XMLReader#setEntityResolver */ public void setContentHandler (ContentHandler handler) { + if (handler == null) { + throw new NullPointerException("Null content handler"); + } contentHandler = handler; } @@ -339,10 +370,15 @@ public class ParserAdapter implements XMLReader, DocumentHandler * Set the error handler. * * @param resolver The new error handler. + * @exception java.lang.NullPointerException If the error handler + * parameter is null. * @see org.xml.sax.XMLReader#setEntityResolver */ public void setErrorHandler (ErrorHandler handler) { + if (handler == null) { + throw new NullPointerException("Null error handler"); + } errorHandler = handler; } @@ -365,7 +401,7 @@ public class ParserAdapter implements XMLReader, DocumentHandler * @param systemId The absolute URL of the document. * @exception java.io.IOException If there is a problem reading * the raw content of the document. - * @exception SAXException If there is a problem + * @exception org.xml.sax.SAXException If there is a problem * processing the document. * @see #parse(org.xml.sax.InputSource) * @see org.xml.sax.Parser#parse(java.lang.String) @@ -383,7 +419,7 @@ public class ParserAdapter implements XMLReader, DocumentHandler * @param input An input source for the document. * @exception java.io.IOException If there is a problem reading * the raw content of the document. - * @exception SAXException If there is a problem + * @exception org.xml.sax.SAXException If there is a problem * processing the document. * @see #parse(java.lang.String) * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource) @@ -412,7 +448,6 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Adapter implementation method; do not call. * Adapt a SAX1 document locator event. * * @param locator A document locator. @@ -428,10 +463,9 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Adapter implementation method; do not call. * Adapt a SAX1 start document event. * - * @exception SAXException The client may raise a + * @exception org.xml.sax.SAXException The client may raise a * processing exception. * @see org.xml.sax.DocumentHandler#startDocument */ @@ -445,10 +479,9 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Adapter implementation method; do not call. * Adapt a SAX1 end document event. * - * @exception SAXException The client may raise a + * @exception org.xml.sax.SAXException The client may raise a * processing exception. * @see org.xml.sax.DocumentHandler#endDocument */ @@ -462,25 +495,16 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Adapter implementation method; do not call. * Adapt a SAX1 startElement event. * *

If necessary, perform Namespace processing.

* * @param qName The qualified (prefixed) name. * @param qAtts The XML 1.0 attribute list (with qnames). - * @exception SAXException The client may raise a - * processing exception. */ public void startElement (String qName, AttributeList qAtts) throws SAXException { - // These are exceptions from the - // first pass; they should be - // ignored if there's a second pass, - // but reported otherwise. - Vector exceptions = null; - // If we're not doing Namespace // processing, dispatch this quickly. if (!namespaces) { @@ -495,103 +519,80 @@ public class ParserAdapter implements XMLReader, DocumentHandler // OK, we're doing Namespace processing. nsSupport.pushContext(); - int length = qAtts.getLength(); - - // First pass: handle NS decls - for (int i = 0; i < length; i++) { - String attQName = qAtts.getName(i); - - if (!attQName.startsWith("xmlns")) - continue; - // Could be a declaration... - String prefix; - int n = attQName.indexOf(':'); - - // xmlns=... - if (n == -1 && attQName.length () == 5) { - prefix = ""; - } else if (n != 5) { - // XML namespaces spec doesn't discuss "xmlnsf:oo" - // (and similarly named) attributes ... at most, warn - continue; - } else // xmlns:foo=... - prefix = attQName.substring(n+1); - - String value = qAtts.getValue(i); - if (!nsSupport.declarePrefix(prefix, value)) { - reportError("Illegal Namespace prefix: " + prefix); - continue; - } - if (contentHandler != null) - contentHandler.startPrefixMapping(prefix, value); - } - - // Second pass: copy all relevant - // attributes into the SAX2 AttributeList - // using updated prefix bindings + boolean seenDecl = false; atts.clear(); + + // Take a first pass and copy all + // attributes into the SAX2 attribute + // list, noting any Namespace + // declarations. + int length = qAtts.getLength(); for (int i = 0; i < length; i++) { String attQName = qAtts.getName(i); String type = qAtts.getType(i); String value = qAtts.getValue(i); - // Declaration? + // Found a declaration... if (attQName.startsWith("xmlns")) { String prefix; int n = attQName.indexOf(':'); - - if (n == -1 && attQName.length () == 5) { + if (n == -1) { prefix = ""; - } else if (n != 5) { - // XML namespaces spec doesn't discuss "xmlnsf:oo" - // (and similarly named) attributes ... ignore - prefix = null; } else { prefix = attQName.substring(n+1); } - // Yes, decl: report or prune - if (prefix != null) { - if (prefixes) - atts.addAttribute("", "", attQName.intern(), - type, value); - continue; + if (!nsSupport.declarePrefix(prefix, value)) { + reportError("Illegal Namespace prefix: " + prefix); } - } + if (contentHandler != null) { + contentHandler.startPrefixMapping(prefix, value); + } + // We may still have to add this to + // the list. + if (prefixes) { + atts.addAttribute("", "", attQName.intern(), + type, value); + } + seenDecl = true; - // Not a declaration -- report - try { - String attName[] = processName(attQName, true, true); + // This isn't a declaration. + } else { + String attName[] = processName(attQName, true); atts.addAttribute(attName[0], attName[1], attName[2], type, value); - } catch (SAXException e) { - if (exceptions == null) - exceptions = new Vector(); - exceptions.addElement(e); - atts.addAttribute("", attQName, attQName, type, value); } } - // now handle the deferred exception reports - if (exceptions != null && errorHandler != null) { - for (int i = 0; i < exceptions.size(); i++) - errorHandler.error((SAXParseException) - (exceptions.elementAt(i))); + // If there was a Namespace declaration, + // we have to make a second pass just + // to be safe -- this will happen very + // rarely, possibly only once for each + // document. + if (seenDecl) { + length = atts.getLength(); + for (int i = 0; i < length; i++) { + String attQName = atts.getQName(i); + if (!attQName.startsWith("xmlns")) { + String attName[] = processName(attQName, true); + atts.setURI(i, attName[0]); + atts.setLocalName(i, attName[1]); + } + } } // OK, finally report the event. if (contentHandler != null) { - String name[] = processName(qName, false, false); + String name[] = processName(qName, false); contentHandler.startElement(name[0], name[1], name[2], atts); } } /** - * Adapter implementation method; do not call. * Adapt a SAX1 end element event. * * @param qName The qualified (prefixed) name. - * @exception SAXException The client may raise a + * @exception org.xml.sax.SAXException The client may raise a * processing exception. * @see org.xml.sax.DocumentHandler#endElement */ @@ -608,7 +609,7 @@ public class ParserAdapter implements XMLReader, DocumentHandler } // Split the name. - String names[] = processName(qName, false, false); + String names[] = processName(qName, false); if (contentHandler != null) { contentHandler.endElement(names[0], names[1], names[2]); Enumeration prefixes = nsSupport.getDeclaredPrefixes(); @@ -622,13 +623,12 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Adapter implementation method; do not call. * Adapt a SAX1 characters event. * * @param ch An array of characters. * @param start The starting position in the array. * @param length The number of characters to use. - * @exception SAXException The client may raise a + * @exception org.xml.sax.SAXException The client may raise a * processing exception. * @see org.xml.sax.DocumentHandler#characters */ @@ -642,13 +642,12 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Adapter implementation method; do not call. * Adapt a SAX1 ignorable whitespace event. * * @param ch An array of characters. * @param start The starting position in the array. * @param length The number of characters to use. - * @exception SAXException The client may raise a + * @exception org.xml.sax.SAXException The client may raise a * processing exception. * @see org.xml.sax.DocumentHandler#ignorableWhitespace */ @@ -662,12 +661,11 @@ public class ParserAdapter implements XMLReader, DocumentHandler /** - * Adapter implementation method; do not call. * Adapt a SAX1 processing instruction event. * * @param target The processing instruction target. * @param data The remainder of the processing instruction - * @exception SAXException The client may raise a + * @exception org.xml.sax.SAXException The client may raise a * processing exception. * @see org.xml.sax.DocumentHandler#processingInstruction */ @@ -717,22 +715,18 @@ public class ParserAdapter implements XMLReader, DocumentHandler * @param qName The qualified (prefixed) name. * @param isAttribute true if this is an attribute name. * @return The name split into three parts. - * @exception SAXException The client may throw + * @exception org.xml.sax.SAXException The client may throw * an exception if there is an error callback. */ - private String [] processName (String qName, boolean isAttribute, - boolean useException) + private String [] processName (String qName, boolean isAttribute) throws SAXException { String parts[] = nsSupport.processName(qName, nameParts, isAttribute); if (parts == null) { - if (useException) - throw makeException("Undeclared prefix: " + qName); - reportError("Undeclared prefix: " + qName); parts = new String[3]; - parts[0] = parts[1] = ""; parts[2] = qName.intern(); + reportError("Undeclared prefix: " + qName); } return parts; } @@ -742,29 +736,23 @@ public class ParserAdapter implements XMLReader, DocumentHandler * Report a non-fatal error. * * @param message The error message. - * @exception SAXException The client may throw + * @exception org.xml.sax.SAXException The client may throw * an exception. */ void reportError (String message) throws SAXException { - if (errorHandler != null) - errorHandler.error(makeException(message)); - } - - - /** - * Construct an exception for the current context. - * - * @param message The error message. - */ - private SAXParseException makeException (String message) - { - if (locator != null) { - return new SAXParseException(message, locator); - } else { - return new SAXParseException(message, null, null, -1, -1); + if (errorHandler == null) { + return; } + + SAXParseException e; + if (locator != null) { + e = new SAXParseException(message, locator); + } else { + e = new SAXParseException(message, null, null, -1, -1); + } + errorHandler.error(e); } @@ -776,7 +764,7 @@ public class ParserAdapter implements XMLReader, DocumentHandler * * @param type The type of thing (feature or property). * @param name The feature or property name. - * @exception SAXNotSupportedException If a + * @exception org.xml.sax.SAXNotSupportedException If a * document is currently being parsed. */ private void checkNotParsing (String type, String name) diff --git a/java/external/src/org/xml/sax/helpers/ParserFactory.java b/java/external/src/org/xml/sax/helpers/ParserFactory.java index de726dd..0509ea2 100644 --- a/java/external/src/org/xml/sax/helpers/ParserFactory.java +++ b/java/external/src/org/xml/sax/helpers/ParserFactory.java @@ -39,12 +39,15 @@ import org.xml.sax.Parser; *

Note that the application still requires an XML parser that * implements SAX1.

* + *

Note that this is not the ParserFactory shipped with SAX 2.0.1; + * this class takes into account the needs of J2EE 1.4 AccessControllers.

+ * * @deprecated This class works with the deprecated * {@link org.xml.sax.Parser Parser} * interface. * @since SAX 1.0 * @author David Megginson - * @version 2.0.1 (sax2r2) + * @version 2.0r2pre3 */ public class ParserFactory { @@ -85,7 +88,8 @@ public class ParserFactory { 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 { 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..6c4100e --- /dev/null +++ b/java/external/src/org/xml/sax/helpers/SecuritySupport.java @@ -0,0 +1,133 @@ +/* + * 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 apache@apache.org. + * + * 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 . + */ + +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; + } +} 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..e71f16c --- /dev/null +++ b/java/external/src/org/xml/sax/helpers/SecuritySupport12.java @@ -0,0 +1,125 @@ +/* + * 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 apache@apache.org. + * + * 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 . + */ + +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; + } + }); + } +} diff --git a/java/external/src/org/xml/sax/helpers/XMLFilterImpl.java b/java/external/src/org/xml/sax/helpers/XMLFilterImpl.java index 4ebf552..2e967b3 100644 --- a/java/external/src/org/xml/sax/helpers/XMLFilterImpl.java +++ b/java/external/src/org/xml/sax/helpers/XMLFilterImpl.java @@ -1,6 +1,5 @@ // XMLFilterImpl.java - base SAX2 filter implementation. -// http://www.saxproject.org -// Written by David Megginson +// Written by David Megginson, sax@megginson.com // NO WARRANTY! This class is in the Public Domain. // $Id$ @@ -30,8 +29,6 @@ import org.xml.sax.SAXNotRecognizedException; *
* This module, both source code and documentation, is in the * Public Domain, and comes with NO WARRANTY. - * See http://www.saxproject.org - * for further information. *
* *

This class is designed to sit between an {@link org.xml.sax.XMLReader @@ -41,9 +38,14 @@ import org.xml.sax.SAXNotRecognizedException; * specific methods to modify the event stream or the configuration * requests as they pass through.

* + *

Note that this is not the version shipped with SAX 2.0.1; this class + * throws NullPointerExceptions when setter methods are called with null parameters; + * the 2.0.1 version does not exhibit this behaviour.

+ * * @since SAX 2.0 - * @author David Megginson - * @version 2.0.1 (sax2r2) + * @author David Megginson, + * sax@megginson.com + * @version 2.0 * @see org.xml.sax.XMLFilter * @see org.xml.sax.XMLReader * @see org.xml.sax.EntityResolver @@ -66,12 +68,10 @@ public class XMLFilterImpl * *

This filter will have no parent: you must assign a parent * before you start a parse or do any configuration with - * setFeature or setProperty, unless you use this as a pure event - * consumer rather than as an {@link XMLReader}.

+ * setFeature or setProperty.

* * @see org.xml.sax.XMLReader#setFeature * @see org.xml.sax.XMLReader#setProperty - * @see #setParent */ public XMLFilterImpl () { @@ -109,10 +109,14 @@ public class XMLFilterImpl * or to set or get a feature or property will fail.

* * @param parent The parent XML reader. + * @exception java.lang.NullPointerException If the parent is null. * @see #getParent */ public void setParent (XMLReader parent) { + if (parent == null) { + throw new NullPointerException("Null parent"); + } this.parent = parent; } @@ -136,23 +140,24 @@ public class XMLFilterImpl /** - * Set the value of a feature. + * Set the state of a feature. * *

This will always fail if the parent is null.

* * @param name The feature name. - * @param value The requested feature value. - * @exception org.xml.sax.SAXNotRecognizedException If the feature - * value can't be assigned or retrieved from the parent. + * @param state The requested feature state. + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the feature name. * @exception org.xml.sax.SAXNotSupportedException When the - * parent recognizes the feature name but + * XMLReader recognizes the feature name but * cannot set the requested value. + * @see org.xml.sax.XMLReader#setFeature */ - public void setFeature (String name, boolean value) + public void setFeature (String name, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException { if (parent != null) { - parent.setFeature(name, value); + parent.setFeature(name, state); } else { throw new SAXNotRecognizedException("Feature: " + name); } @@ -160,17 +165,18 @@ public class XMLFilterImpl /** - * Look up the value of a feature. + * Look up the state of a feature. * *

This will always fail if the parent is null.

* * @param name The feature name. - * @return The current value of the feature. - * @exception org.xml.sax.SAXNotRecognizedException If the feature - * value can't be assigned or retrieved from the parent. + * @return The current state of the feature. + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the feature name. * @exception org.xml.sax.SAXNotSupportedException When the - * parent recognizes the feature name but - * cannot determine its value at this time. + * XMLReader recognizes the feature name but + * cannot determine its state at this time. + * @see org.xml.sax.XMLReader#getFeature */ public boolean getFeature (String name) throws SAXNotRecognizedException, SAXNotSupportedException @@ -189,12 +195,13 @@ public class XMLFilterImpl *

This will always fail if the parent is null.

* * @param name The property name. - * @param value The requested property value. - * @exception org.xml.sax.SAXNotRecognizedException If the property - * value can't be assigned or retrieved from the parent. + * @param state The requested property value. + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the property name. * @exception org.xml.sax.SAXNotSupportedException When the - * parent recognizes the property name but + * XMLReader recognizes the property name but * cannot set the requested value. + * @see org.xml.sax.XMLReader#setProperty */ public void setProperty (String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException @@ -212,11 +219,12 @@ public class XMLFilterImpl * * @param name The property name. * @return The current value of the property. - * @exception org.xml.sax.SAXNotRecognizedException If the property - * value can't be assigned or retrieved from the parent. + * @exception org.xml.sax.SAXNotRecognizedException When the + * XMLReader does not recognize the feature name. * @exception org.xml.sax.SAXNotSupportedException When the - * parent recognizes the property name but + * XMLReader recognizes the property name but * cannot determine its value at this time. + * @see org.xml.sax.XMLReader#setFeature */ public Object getProperty (String name) throws SAXNotRecognizedException, SAXNotSupportedException @@ -233,10 +241,17 @@ public class XMLFilterImpl * Set the entity resolver. * * @param resolver The new entity resolver. + * @exception java.lang.NullPointerException If the resolver + * is null. + * @see org.xml.sax.XMLReader#setEntityResolver */ public void setEntityResolver (EntityResolver resolver) { - entityResolver = resolver; + if (resolver == null) { + throw new NullPointerException("Null entity resolver"); + } else { + entityResolver = resolver; + } } @@ -244,6 +259,7 @@ public class XMLFilterImpl * Get the current entity resolver. * * @return The current entity resolver, or null if none was set. + * @see org.xml.sax.XMLReader#getEntityResolver */ public EntityResolver getEntityResolver () { @@ -255,10 +271,17 @@ public class XMLFilterImpl * Set the DTD event handler. * * @param resolver The new DTD handler. + * @exception java.lang.NullPointerException If the handler + * is null. + * @see org.xml.sax.XMLReader#setDTDHandler */ public void setDTDHandler (DTDHandler handler) { - dtdHandler = handler; + if (handler == null) { + throw new NullPointerException("Null DTD handler"); + } else { + dtdHandler = handler; + } } @@ -266,6 +289,7 @@ public class XMLFilterImpl * Get the current DTD event handler. * * @return The current DTD handler, or null if none was set. + * @see org.xml.sax.XMLReader#getDTDHandler */ public DTDHandler getDTDHandler () { @@ -277,10 +301,17 @@ public class XMLFilterImpl * Set the content event handler. * * @param resolver The new content handler. + * @exception java.lang.NullPointerException If the handler + * is null. + * @see org.xml.sax.XMLReader#setContentHandler */ public void setContentHandler (ContentHandler handler) { - contentHandler = handler; + if (handler == null) { + throw new NullPointerException("Null content handler"); + } else { + contentHandler = handler; + } } @@ -288,6 +319,7 @@ public class XMLFilterImpl * Get the content event handler. * * @return The current content handler, or null if none was set. + * @see org.xml.sax.XMLReader#getContentHandler */ public ContentHandler getContentHandler () { @@ -299,10 +331,17 @@ public class XMLFilterImpl * Set the error event handler. * * @param handle The new error handler. + * @exception java.lang.NullPointerException If the handler + * is null. + * @see org.xml.sax.XMLReader#setErrorHandler */ public void setErrorHandler (ErrorHandler handler) { - errorHandler = handler; + if (handler == null) { + throw new NullPointerException("Null error handler"); + } else { + errorHandler = handler; + } } @@ -310,6 +349,7 @@ public class XMLFilterImpl * Get the current error event handler. * * @return The current error handler, or null if none was set. + * @see org.xml.sax.XMLReader#getErrorHandler */ public ErrorHandler getErrorHandler () { @@ -326,6 +366,7 @@ public class XMLFilterImpl * @exception java.io.IOException An IO exception from the parser, * possibly from a byte stream or character stream * supplied by the application. + * @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource) */ public void parse (InputSource input) throws SAXException, IOException @@ -344,6 +385,7 @@ public class XMLFilterImpl * @exception java.io.IOException An IO exception from the parser, * possibly from a byte stream or character stream * supplied by the application. + * @see org.xml.sax.XMLReader#parse(java.lang.String) */ public void parse (String systemId) throws SAXException, IOException @@ -369,6 +411,7 @@ public class XMLFilterImpl * @exception java.io.IOException The client may throw an * I/O-related exception while obtaining the * new InputSource. + * @see org.xml.sax.EntityResolver#resolveEntity */ public InputSource resolveEntity (String publicId, String systemId) throws SAXException, IOException @@ -395,6 +438,7 @@ public class XMLFilterImpl * @param systemId The notation's system identifier, or null. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.DTDHandler#notationDecl */ public void notationDecl (String name, String publicId, String systemId) throws SAXException @@ -414,6 +458,7 @@ public class XMLFilterImpl * @param notationName The name of the associated notation. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.DTDHandler#unparsedEntityDecl */ public void unparsedEntityDecl (String name, String publicId, String systemId, String notationName) @@ -436,6 +481,7 @@ public class XMLFilterImpl * Filter a new document locator event. * * @param locator The document locator. + * @see org.xml.sax.ContentHandler#setDocumentLocator */ public void setDocumentLocator (Locator locator) { @@ -451,6 +497,7 @@ public class XMLFilterImpl * * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#startDocument */ public void startDocument () throws SAXException @@ -466,6 +513,7 @@ public class XMLFilterImpl * * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#endDocument */ public void endDocument () throws SAXException @@ -483,6 +531,7 @@ public class XMLFilterImpl * @param uri The Namespace URI. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#startPrefixMapping */ public void startPrefixMapping (String prefix, String uri) throws SAXException @@ -499,6 +548,7 @@ public class XMLFilterImpl * @param prefix The Namespace prefix. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#endPrefixMapping */ public void endPrefixMapping (String prefix) throws SAXException @@ -519,6 +569,7 @@ public class XMLFilterImpl * @param atts The element's attributes. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#startElement */ public void startElement (String uri, String localName, String qName, Attributes atts) @@ -539,6 +590,7 @@ public class XMLFilterImpl * string. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#endElement */ public void endElement (String uri, String localName, String qName) throws SAXException @@ -557,6 +609,7 @@ public class XMLFilterImpl * @param length The number of characters to use from the array. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#characters */ public void characters (char ch[], int start, int length) throws SAXException @@ -575,6 +628,7 @@ public class XMLFilterImpl * @param length The number of characters to use from the array. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#ignorableWhitespace */ public void ignorableWhitespace (char ch[], int start, int length) throws SAXException @@ -592,6 +646,7 @@ public class XMLFilterImpl * @param data The text following the target. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#processingInstruction */ public void processingInstruction (String target, String data) throws SAXException @@ -608,6 +663,7 @@ public class XMLFilterImpl * @param name The name of the skipped entity. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ContentHandler#skippedEntity */ public void skippedEntity (String name) throws SAXException @@ -627,9 +683,10 @@ public class XMLFilterImpl /** * Filter a warning event. * - * @param e The warning as an exception. + * @param e The nwarning as an exception. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ErrorHandler#warning */ public void warning (SAXParseException e) throws SAXException @@ -646,6 +703,7 @@ public class XMLFilterImpl * @param e The error as an exception. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ErrorHandler#error */ public void error (SAXParseException e) throws SAXException @@ -662,6 +720,7 @@ public class XMLFilterImpl * @param e The error as an exception. * @exception org.xml.sax.SAXException The client may throw * an exception during processing. + * @see org.xml.sax.ErrorHandler#fatalError */ public void fatalError (SAXParseException e) throws SAXException diff --git a/java/external/src/org/xml/sax/helpers/XMLReaderAdapter.java b/java/external/src/org/xml/sax/helpers/XMLReaderAdapter.java index 44f3c8c..8d62f60 100644 --- a/java/external/src/org/xml/sax/helpers/XMLReaderAdapter.java +++ b/java/external/src/org/xml/sax/helpers/XMLReaderAdapter.java @@ -1,6 +1,5 @@ // XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser -// http://www.saxproject.org -// Written by David Megginson +// Written by David Megginson, sax@megginson.com // NO WARRANTY! This class is in the public domain. // $Id$ @@ -32,8 +31,6 @@ import org.xml.sax.SAXNotSupportedException; *
* This module, both source code and documentation, is in the * Public Domain, and comes with NO WARRANTY. - * See http://www.saxproject.org - * for further information. *
* *

This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader} @@ -44,9 +41,14 @@ import org.xml.sax.SAXNotSupportedException; * supports a false value for the http://xml.org/sax/features/namespaces * property, that will also be used to improve efficiency.

* + *

Note that this is not the version shipped with SAX 2.0.1; this class + * throws NullPointerExceptions when setter methods are called with null parameters; + * the 2.0.1 version does not exhibit this behaviour.

+ * * @since SAX 2.0 - * @author David Megginson - * @version 2.0.1 (sax2r2) + * @author David Megginson, + * sax@megginson.com + * @version 2.0 * @see org.xml.sax.Parser * @see org.xml.sax.XMLReader */ @@ -122,7 +124,6 @@ public class XMLReaderAdapter implements Parser, ContentHandler * * @param The locale for error reporting. * @see org.xml.sax.Parser#setLocale - * @exception org.xml.sax.SAXException Thrown unless overridden. */ public void setLocale (Locale locale) throws SAXException @@ -258,8 +259,7 @@ public class XMLReaderAdapter implements Parser, ContentHandler */ public void setDocumentLocator (Locator locator) { - if (documentHandler != null) - documentHandler.setDocumentLocator(locator); + documentHandler.setDocumentLocator(locator); } @@ -273,8 +273,7 @@ public class XMLReaderAdapter implements Parser, ContentHandler public void startDocument () throws SAXException { - if (documentHandler != null) - documentHandler.startDocument(); + documentHandler.startDocument(); } @@ -288,8 +287,7 @@ public class XMLReaderAdapter implements Parser, ContentHandler public void endDocument () throws SAXException { - if (documentHandler != null) - documentHandler.endDocument(); + documentHandler.endDocument(); } @@ -331,10 +329,8 @@ public class XMLReaderAdapter implements Parser, ContentHandler String qName, Attributes atts) throws SAXException { - if (documentHandler != null) { - qAtts.setAttributes(atts); - documentHandler.startElement(qName, qAtts); - } + qAtts.setAttributes(atts); + documentHandler.startElement(qName, qAtts); } @@ -352,8 +348,7 @@ public class XMLReaderAdapter implements Parser, ContentHandler String qName) throws SAXException { - if (documentHandler != null) - documentHandler.endElement(qName); + documentHandler.endElement(qName); } @@ -370,8 +365,7 @@ public class XMLReaderAdapter implements Parser, ContentHandler public void characters (char ch[], int start, int length) throws SAXException { - if (documentHandler != null) - documentHandler.characters(ch, start, length); + documentHandler.characters(ch, start, length); } @@ -388,8 +382,7 @@ public class XMLReaderAdapter implements Parser, ContentHandler public void ignorableWhitespace (char ch[], int start, int length) throws SAXException { - if (documentHandler != null) - documentHandler.ignorableWhitespace(ch, start, length); + documentHandler.ignorableWhitespace(ch, start, length); } @@ -405,8 +398,7 @@ public class XMLReaderAdapter implements Parser, ContentHandler public void processingInstruction (String target, String data) throws SAXException { - if (documentHandler != null) - documentHandler.processingInstruction(target, data); + documentHandler.processingInstruction(target, data); } @@ -415,7 +407,6 @@ public class XMLReaderAdapter implements Parser, ContentHandler * * @param name The name of the skipped entity. * @see org.xml.sax.ContentHandler#skippedEntity - * @exception org.xml.sax.SAXException Throwable by subclasses. */ public void skippedEntity (String name) throws SAXException diff --git a/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java b/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java index 2983df4..66cacdc 100644 --- a/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java +++ b/java/external/src/org/xml/sax/helpers/XMLReaderFactory.java @@ -3,7 +3,6 @@ // Written by David Megginson // and by David Brownell // NO WARRANTY! This class is in the Public Domain. - // $Id$ package org.xml.sax.helpers; @@ -43,9 +42,12 @@ import org.xml.sax.SAXException; * nothing bound its class name to org.xml.sax.driver so * those configuration mechanisms would see it.

* + *

Note that this is not the XMLReaderFactory shipped with SAX 2.0.1; + * this class takes into account the needs of J2EE 1.4 AccessControllers.

+ * * @since SAX 2.0 * @author David Megginson, David Brownell - * @version 2.0.1 (sax2r2) + * @version 2.0r2pre3 */ final public class XMLReaderFactory { @@ -105,44 +107,89 @@ final public class XMLReaderFactory 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; + String service = "META-INF/services/" + property; - if (loader == null) - in = ClassLoader.getSystemResourceAsStream (service); - else - in = loader.getResourceAsStream (service); + InputStream is = null; - if (in != null) { - reader = new BufferedReader ( - new InputStreamReader (in, "UTF8")); - className = reader.readLine (); - in.close (); - } - } catch (Exception e) { - } + // 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) { -// BEGIN DISTRIBUTION-SPECIFIC + // modified by neilg in accordance with the "strong encouragement" + // provided to distributions which include parsers. - // 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?