diff --git a/java/external/src/org/xml/sax/helpers/NewInstance.java b/java/external/src/org/xml/sax/helpers/NewInstance.java index 25dd345..b12d372 100644 --- a/java/external/src/org/xml/sax/helpers/NewInstance.java +++ b/java/external/src/org/xml/sax/helpers/NewInstance.java @@ -7,9 +7,6 @@ package org.xml.sax.helpers; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; - /** * Create a new instance of a class by name. * @@ -23,15 +20,26 @@ 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 is not the NewInstance accompanying SAX 2.0.2; it + * represents many fixes to that code. + * * @author Edwin Goei, David Brownell * @version 2.0.1 (sax2r2) */ 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 @@ -44,11 +52,36 @@ class NewInstance { { Class driverClass; if (classLoader == 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. driverClass = Class.forName(className); } else { - driverClass = classLoader.loadClass(className); + try { + driverClass = classLoader.loadClass(className); + } catch (ClassNotFoundException x) { + if (DO_FALLBACK) { + // Fall back to current classloader + classLoader = NewInstance.class.getClassLoader(); + if (classLoader != null) { + driverClass = classLoader.loadClass(className); + } + else { + driverClass = Class.forName(className); + } + } else { + throw x; + } + } } - return driverClass.newInstance(); + Object instance = driverClass.newInstance(); + return instance; } /** @@ -57,23 +90,16 @@ class NewInstance { */ static ClassLoader getClassLoader () { - Method m = null; + SecuritySupport ss = SecuritySupport.getInstance(); - try { - m = Thread.class.getMethod("getContextClassLoader", (Class[]) null); - } catch (NoSuchMethodException e) { - // Assume that we are running JDK 1.1, use the current ClassLoader - return NewInstance.class.getClassLoader(); - } - - try { - return (ClassLoader) m.invoke(Thread.currentThread(), (Object[]) 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; } }