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