View Javadoc

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