View Javadoc

1   /*
2    * $Id: ClassLoaderUtils.java 651946 2008-04-27 13:41:38Z apetrelli $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.util;
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.URL;
27  
28  
29  /***
30   * This class is extremely useful for loading resources and classes in a fault tolerant manner
31   * that works across different applications servers.
32   * <p/>
33   * It has come out of many months of frustrating use of multiple application servers at Atlassian,
34   * please don't change things unless you're sure they're not going to break in one server or another!
35   *
36   */
37  public class ClassLoaderUtils {
38  
39      /***
40       * Load a given resource.
41       * <p/>
42       * This method will try to load the resource using the following methods (in order):
43       * <ul>
44       * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
45       * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
46       * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
47       * </ul>
48       *
49       * @param resourceName The name of the resource to load
50       * @param callingClass The Class object of the calling object
51       */
52      public static URL getResource(String resourceName, Class callingClass) {
53          URL url = null;
54  
55          url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
56  
57          if (url == null) {
58              url = ClassLoaderUtils.class.getClassLoader().getResource(resourceName);
59          }
60  
61          if (url == null) {
62              url = callingClass.getClassLoader().getResource(resourceName);
63          }
64  
65          return url;
66      }
67  
68      /***
69       * This is a convenience method to load a resource as a stream.
70       * <p/>
71       * The algorithm used to find the resource is given in getResource()
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 InputStream getResourceAsStream(String resourceName, Class callingClass) {
77          URL url = getResource(resourceName, callingClass);
78  
79          try {
80              return (url != null) ? url.openStream() : null;
81          } catch (IOException e) {
82              return null;
83          }
84      }
85  
86      /***
87       * Load a class with a given name.
88       * <p/>
89       * It will try to load the class in the following order:
90       * <ul>
91       * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
92       * <li>Using the basic {@link Class#forName(java.lang.String) }
93       * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
94       * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
95       * </ul>
96       *
97       * @param className    The name of the class to load
98       * @param callingClass The Class object of the calling object
99       * @throws ClassNotFoundException If the class cannot be found anywhere.
100      */
101     public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {
102         try {
103             return Thread.currentThread().getContextClassLoader().loadClass(className);
104         } catch (ClassNotFoundException e) {
105             try {
106                 return Class.forName(className);
107             } catch (ClassNotFoundException ex) {
108                 try {
109                     return ClassLoaderUtils.class.getClassLoader().loadClass(className);
110                 } catch (ClassNotFoundException exc) {
111                     return callingClass.getClassLoader().loadClass(className);
112                 }
113             }
114         }
115     }
116 
117     /***
118      * Prints the current classloader hierarchy - useful for debugging.
119      */
120     public static void printClassLoader() {
121         System.out.println("ClassLoaderUtils.printClassLoader");
122         printClassLoader(Thread.currentThread().getContextClassLoader());
123     }
124 
125     /***
126      * Prints the classloader hierarchy from a given classloader - useful for debugging.
127      */
128     public static void printClassLoader(ClassLoader cl) {
129         System.out.println("ClassLoaderUtils.printClassLoader(cl = " + cl + ")");
130 
131         if (cl != null) {
132             printClassLoader(cl.getParent());
133         }
134     }
135 }