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