1 /*
2 * Atlassian Source Code Template.
3 * User: sfarquhar
4 * Date: 8/03/2002
5 * Time: 17:37:41
6 * CVS Revision: $Revision: 2420 $
7 * Last CVS Commit: $Date: 2005-08-05 13:07:43 +1000 (Fri, 05 Aug 2005) $
8 * Author of last CVS Commit: $Author: nfaiz $
9 */
10 package com.atlassian.user.util;
11
12 import java.io.IOException;
13 import java.io.InputStream;
14 import java.net.URL;
15 import java.util.Enumeration;
16
17
18 ///CLOVER:OFF
19
20 /**
21 * This class is extremely useful for loading resources and classes in a fault tolerant manner
22 * that works across different applications servers.
23 * <p>
24 * It has come out of many months of frustrating use of multiple application servers at Atlassian,
25 * please don't change things unless you're sure they're not going to break in one server or another!
26 *
27 * @author $Author: nfaiz $
28 * @version $Revision: 2420 $
29 */
30 public class ClassLoaderUtils
31 {
32 /**
33 * Load a class with a given name.
34 * <p>
35 * It will try to load the class in the following order:
36 * <ul>
37 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
38 * <li>Using the basic {@link Class#forName(java.lang.String) }
39 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
40 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
41 * </ul>
42 *
43 * @param className The name of the class to load
44 * @param callingClass The Class object of the calling object
45 * @throws ClassNotFoundException If the class cannot be found anywhere.
46 */
47 public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException
48 {
49 try
50 {
51 return Thread.currentThread().getContextClassLoader().loadClass(className);
52 }
53 catch (ClassNotFoundException e)
54 {
55 try
56 {
57 return Class.forName(className);
58 }
59 catch (ClassNotFoundException ex)
60 {
61 try
62 {
63 return ClassLoaderUtils.class.getClassLoader().loadClass(className);
64 }
65 catch (ClassNotFoundException exc)
66 {
67 return callingClass.getClassLoader().loadClass(className);
68 }
69
70 }
71 }
72 }
73
74 /**
75 * Load a given resource.
76 * <p>
77 * This method will try to load the resource using the following methods (in order):
78 * <ul>
79 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
80 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
81 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
82 * </ul>
83 *
84 * @param resourceName The name of the resource to load
85 * @param callingClass The Class object of the calling object
86 */
87 public static URL getResource(String resourceName, Class callingClass)
88 {
89 URL url = null;
90
91 url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
92
93 if (url == null)
94 {
95 url = ClassLoaderUtils.class.getClassLoader().getResource(resourceName);
96 }
97
98 if (url == null)
99 {
100 url = callingClass.getClassLoader().getResource(resourceName);
101 }
102 return url;
103 }
104
105 /**
106 * returns all found resources as java.net.URLs.
107 * <p>
108 * This method will try to load the resource using the following methods (in order):
109 * <ul>
110 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
111 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
112 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
113 * </ul>
114 *
115 * @param resourceName The name of the resource to load
116 * @param callingClass The Class object of the calling object
117 */
118 public static Enumeration getResources(String resourceName, Class callingClass) throws IOException
119 {
120 Enumeration urls = Thread.currentThread().getContextClassLoader().getResources(resourceName);
121 if (urls == null)
122 {
123 urls = ClassLoaderUtils.class.getClassLoader().getResources(resourceName);
124 if (urls == null)
125 {
126 urls = callingClass.getClassLoader().getResources(resourceName);
127 }
128 }
129
130 return urls;
131 }
132
133 /**
134 * This is a convenience method to load a resource as a stream.
135 *
136 * The algorithm used to find the resource is given in getResource()
137 *
138 * @param resourceName The name of the resource to load
139 * @param callingClass The Class object of the calling object
140 */
141 public static InputStream getResourceAsStream(String resourceName, Class callingClass)
142 {
143 URL url = getResource(resourceName, callingClass);
144 try
145 {
146 return url != null ? url.openStream() : null;
147 }
148 catch (IOException e)
149 {
150 return null;
151 }
152 }
153
154 /**
155 * Prints the current classloader hierarchy - useful for debugging.
156 */
157 public static void printClassLoader()
158 {
159 System.out.println("ClassLoaderUtils.printClassLoader");
160 printClassLoader(Thread.currentThread().getContextClassLoader());
161 }
162
163 /**
164 * Prints the classloader hierarchy from a given classloader - useful for debugging.
165 */
166 public static void printClassLoader(ClassLoader cl)
167 {
168 System.out.println("ClassLoaderUtils.printClassLoader(cl = " + cl + ")");
169 if (cl != null)
170 {
171 printClassLoader(cl.getParent());
172 }
173 }
174 }