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-04 22:07:43 -0500 (Thu, 04 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 }