1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.util;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.URL;
27
28
29 /***
30 * This class is extremely useful for loading resources and classes in a fault tolerant manner
31 * that works across different applications servers.
32 * <p/>
33 * It has come out of many months of frustrating use of multiple application servers at Atlassian,
34 * please don't change things unless you're sure they're not going to break in one server or another!
35 *
36 */
37 public class ClassLoaderUtils {
38
39 /***
40 * Load a given resource.
41 * <p/>
42 * This method will try to load the resource using the following methods (in order):
43 * <ul>
44 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
45 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
46 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
47 * </ul>
48 *
49 * @param resourceName The name of the resource to load
50 * @param callingClass The Class object of the calling object
51 */
52 public static URL getResource(String resourceName, Class callingClass) {
53 URL url = null;
54
55 url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
56
57 if (url == null) {
58 url = ClassLoaderUtils.class.getClassLoader().getResource(resourceName);
59 }
60
61 if (url == null) {
62 url = callingClass.getClassLoader().getResource(resourceName);
63 }
64
65 return url;
66 }
67
68 /***
69 * This is a convenience method to load a resource as a stream.
70 * <p/>
71 * The algorithm used to find the resource is given in getResource()
72 *
73 * @param resourceName The name of the resource to load
74 * @param callingClass The Class object of the calling object
75 */
76 public static InputStream getResourceAsStream(String resourceName, Class callingClass) {
77 URL url = getResource(resourceName, callingClass);
78
79 try {
80 return (url != null) ? url.openStream() : null;
81 } catch (IOException e) {
82 return null;
83 }
84 }
85
86 /***
87 * Load a class with a given name.
88 * <p/>
89 * It will try to load the class in the following order:
90 * <ul>
91 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
92 * <li>Using the basic {@link Class#forName(java.lang.String) }
93 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
94 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
95 * </ul>
96 *
97 * @param className The name of the class to load
98 * @param callingClass The Class object of the calling object
99 * @throws ClassNotFoundException If the class cannot be found anywhere.
100 */
101 public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {
102 try {
103 return Thread.currentThread().getContextClassLoader().loadClass(className);
104 } catch (ClassNotFoundException e) {
105 try {
106 return Class.forName(className);
107 } catch (ClassNotFoundException ex) {
108 try {
109 return ClassLoaderUtils.class.getClassLoader().loadClass(className);
110 } catch (ClassNotFoundException exc) {
111 return callingClass.getClassLoader().loadClass(className);
112 }
113 }
114 }
115 }
116
117 /***
118 * Prints the current classloader hierarchy - useful for debugging.
119 */
120 public static void printClassLoader() {
121 System.out.println("ClassLoaderUtils.printClassLoader");
122 printClassLoader(Thread.currentThread().getContextClassLoader());
123 }
124
125 /***
126 * Prints the classloader hierarchy from a given classloader - useful for debugging.
127 */
128 public static void printClassLoader(ClassLoader cl) {
129 System.out.println("ClassLoaderUtils.printClassLoader(cl = " + cl + ")");
130
131 if (cl != null) {
132 printClassLoader(cl.getParent());
133 }
134 }
135 }