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