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
+ *
* 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* 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 toorg.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?