View Javadoc

1   /*
2    * $Id: ClassLoaderUtils.java 418521 2006-07-01 23:36:50Z mrdon $
3    *
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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 }