1 // NewInstance.java - create a new instance of a class by name.
2 // http://www.saxproject.org
3 // Written by Edwin Goei, edwingo@apache.org
4 // and by David Brownell, dbrownell@users.sourceforge.net
5 // NO WARRANTY! This class is in the Public Domain.
6 // $Id: NewInstance.java 670295 2008-06-22 01:46:43Z mrglavas $
7
8 package org.xml.sax.helpers;
9
10 /**
11 * Create a new instance of a class by name.
12 *
13 * <blockquote>
14 * <em>This module, both source code and documentation, is in the
15 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
16 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
17 * for further information.
18 * </blockquote>
19 *
20 * <p>This class contains a static method for creating an instance of a
21 * class from an explicit class name. It tries to use the thread's context
22 * ClassLoader if possible and falls back to using
23 * Class.forName(String). It also takes into account JDK 1.2+'s
24 * AccessController mechanism for performing its actions. </p>
25 *
26 * <p>This code is designed to compile and run on JDK version 1.1 and later
27 * including versions of Java 2.</p>
28 *
29 * <p>This is <strong>not</strong> the NewInstance accompanying SAX 2.0.2; it
30 * represents many fixes to that code.
31 *
32 * @author Edwin Goei, David Brownell
33 * @version 2.0.1 (sax2r2)
34 */
35 class NewInstance {
36
37 // constants
38
39 // governs whether, if we fail in finding a class even
40 // when given a classloader, we'll make a last-ditch attempt
41 // to use the current classloader.
42 private static final boolean DO_FALLBACK = true;
43
44 /**
45 * Creates a new instance of the specified class name
46 *
47 * Package private so this code is not exposed at the API level.
48 */
49 static Object newInstance (ClassLoader classLoader, String className)
50 throws ClassNotFoundException, IllegalAccessException,
51 InstantiationException
52 {
53 Class driverClass;
54 if (classLoader == null) {
55 // XXX Use the bootstrap ClassLoader. There is no way to
56 // load a class using the bootstrap ClassLoader that works
57 // in both JDK 1.1 and Java 2. However, this should still
58 // work b/c the following should be true:
59 //
60 // (cl == null) iff current ClassLoader == null
61 //
62 // Thus Class.forName(String) will use the current
63 // ClassLoader which will be the bootstrap ClassLoader.
64 driverClass = Class.forName(className);
65 } else {
66 try {
67 driverClass = classLoader.loadClass(className);
68 } catch (ClassNotFoundException x) {
69 if (DO_FALLBACK) {
70 // Fall back to current classloader
71 classLoader = NewInstance.class.getClassLoader();
72 if (classLoader != null) {
73 driverClass = classLoader.loadClass(className);
74 }
75 else {
76 driverClass = Class.forName(className);
77 }
78 } else {
79 throw x;
80 }
81 }
82 }
83 Object instance = driverClass.newInstance();
84 return instance;
85 }
86
87 /**
88 * Figure out which ClassLoader to use. For JDK 1.2 and later use
89 * the context ClassLoader.
90 */
91 static ClassLoader getClassLoader ()
92 {
93 // Figure out which ClassLoader to use for loading the provider
94 // class. If there is a Context ClassLoader then use it.
95 ClassLoader cl = SecuritySupport.getContextClassLoader();
96 if (cl == null) {
97 // Assert: we are on JDK 1.1 or we have no Context ClassLoader
98 // so use the current ClassLoader
99 cl = NewInstance.class.getClassLoader();
100 }
101 return cl;
102 }
103 }