001: // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
002:
003: package jodd.util;
004:
005: import java.net.URL;
006: import java.net.URLClassLoader;
007: import java.io.InputStream;
008: import java.io.IOException;
009: import java.io.File;
010: import java.util.ArrayList;
011: import java.util.List;
012:
013: public class ClassLoaderUtil {
014:
015: // ---------------------------------------------------------------- add class path
016:
017: /**
018: * Adds additional path to system class loader CLASSPATH during runtime.
019: * @see #addClassPath(String, java.net.URLClassLoader)
020: */
021: public static void addClassPath(String path) {
022: addClassPath(path, (URLClassLoader) ClassLoader
023: .getSystemClassLoader());
024: }
025:
026: /**
027: * Adds additional path to system class loader CLASSPATH during runtime.
028: * This is done by using reflection since <code>addURL</code> method of <code>URLClassLoader</code>
029: * is protected.
030: */
031: public static void addClassPath(String path,
032: URLClassLoader classLoader) {
033: try {
034: ReflectUtil.invokeDeclared(URLClassLoader.class,
035: classLoader, "addURL", new Class[] { URL.class },
036: new Object[] { new File(path).toURL() });
037: } catch (Throwable th) {
038: throw new RuntimeException("Unable to add class path'"
039: + path + "'.", th);
040: }
041: }
042:
043: // ---------------------------------------------------------------- define class
044:
045: /**
046: * Defines a class from byte array into the system class loader.
047: * @see #defineClass(String, byte[], ClassLoader)
048: */
049: public static Class defineClass(byte[] classData) {
050: return defineClass(null, classData, ClassLoader
051: .getSystemClassLoader());
052: }
053:
054: /**
055: * Defines a class from byte array into the system class loader.
056: * @see #defineClass(String, byte[], ClassLoader)
057: */
058: public static Class defineClass(String className, byte[] classData) {
059: return defineClass(className, classData, ClassLoader
060: .getSystemClassLoader());
061: }
062:
063: /**
064: * Defines a class from byte array into the specified class loader.
065: * @see #defineClass(String, byte[], ClassLoader)
066: */
067: public static Class defineClass(byte[] classData,
068: ClassLoader classLoader) {
069: return defineClass(null, classData, classLoader);
070: }
071:
072: /**
073: * Defines a class from byte array into the specified class loader.
074: * @see #defineClass(String, byte[], ClassLoader)
075: */
076: public static Class defineClass(String className, byte[] classData,
077: ClassLoader classLoader) {
078: try {
079: return (Class) ReflectUtil.invokeDeclared(
080: ClassLoader.class, classLoader, "defineClass",
081: new Class[] { String.class, byte[].class,
082: int.class, int.class }, new Object[] {
083: className, classData, new Integer(0),
084: new Integer(classData.length) });
085:
086: } catch (Throwable th) {
087: throw new RuntimeException("Unable to define class '"
088: + className + "'.", th);
089: }
090: }
091:
092: // ---------------------------------------------------------------- classpath
093:
094: /**
095: * Returns complete class path from all availiable <code>URLClassLoaders</code>
096: * starting from class loader that has loaded the specified class.
097: */
098: public static URL[] getFullClassPath(Class clazz) {
099: return getFullClassPath(clazz.getClassLoader());
100: }
101:
102: /**
103: * Returns complete class path from all availiable <code>URLClassLoader</code>s.
104: */
105: public static URL[] getFullClassPath(ClassLoader classLoader) {
106: List<URL> list = new ArrayList<URL>();
107: while (classLoader != null) {
108: if (classLoader instanceof URLClassLoader) {
109: URL[] urls = ((URLClassLoader) classLoader).getURLs();
110: for (URL url : urls) {
111: list.add(url);
112: }
113: }
114: classLoader = classLoader.getParent();
115: }
116:
117: URL[] result = new URL[list.size()];
118: return list.toArray(result);
119: }
120:
121: // ---------------------------------------------------------------- get resource
122:
123: public static URL getResource(String resourceName) {
124: return getResource(resourceName, ClassLoaderUtil.class);
125: }
126:
127: public static URL getResource(String resourceName,
128: Class callingClass) {
129: URL url = Thread.currentThread().getContextClassLoader()
130: .getResource(resourceName);
131: if (url == null) {
132: url = (jodd.util.ClassLoaderUtil.class).getClassLoader()
133: .getResource(resourceName);
134: }
135: if ((url == null) && (callingClass != null)) {
136: ClassLoader cl = callingClass.getClassLoader();
137: if (cl != null) {
138: url = cl.getResource(resourceName);
139: }
140: }
141: if ((url == null) && (resourceName != null)
142: && (resourceName.charAt(0) != '/')) {
143: return getResource('/' + resourceName, callingClass);
144: }
145: return url;
146: }
147:
148: // ---------------------------------------------------------------- get resource stream
149:
150: public static InputStream getResourceAsStream(String resourceName)
151: throws IOException {
152: return getResourceAsStream(resourceName, ClassLoaderUtil.class);
153: }
154:
155: public static InputStream getResourceAsStream(String resourceName,
156: Class callingClass) throws IOException {
157: URL url = getResource(resourceName, callingClass);
158: if (url != null) {
159: return url.openStream();
160: }
161: return null;
162: }
163:
164: // ---------------------------------------------------------------- load class
165:
166: /**
167: * Loads class dynamically.
168: * @see #loadClass(String, Class)
169: */
170: public static Class loadClass(String className)
171: throws ClassNotFoundException {
172: return loadClass(className, ClassLoaderUtil.class);
173: }
174:
175: /**
176: * Loads class dynamically, more reliable then <code>Class.forName</code>.
177: * Uses current thread classloader, then <code>Class.forName</code> and, finally,
178: * class loader of the calling class, if class is provided.
179: */
180: public static Class loadClass(String className, Class callingClass)
181: throws ClassNotFoundException {
182: try {
183: return Thread.currentThread().getContextClassLoader()
184: .loadClass(className);
185: } catch (ClassNotFoundException cnfex1) {
186: try {
187: return Class.forName(className);
188: } catch (ClassNotFoundException cnfex2) {
189: try {
190: return (jodd.util.ClassLoaderUtil.class)
191: .getClassLoader().loadClass(className);
192: } catch (ClassNotFoundException cnfex3) {
193: if (callingClass == null) {
194: throw cnfex3;
195: }
196: return callingClass.getClassLoader().loadClass(
197: className);
198: }
199: }
200: }
201: }
202:
203: }
|