1 /* 2 * Atlassian Source Code Template. 3 * User: sfarquhar 4 * Date: 8/03/2002 5 * Time: 17:37:41 6 * CVS Revision: $Revision: 1.6 $ 7 * Last CVS Commit: $Date: 2006/08/31 20:55:22 $ 8 * Author of last CVS Commit: $Author: jnolen $ 9 */ 10 package com.atlassian.core.util; 11 12 import java.io.IOException; 13 import java.io.InputStream; 14 import java.net.URL; 15 import java.util.Enumeration; 16 import java.util.ResourceBundle; 17 import java.util.Locale; 18 19 ///CLOVER:OFF 20 21 /** 22 * This class is extremely useful for loading resources and classes in a fault tolerant manner 23 * that works across different applications servers. 24 * <p> 25 * It has come out of many months of frustrating use of multiple application servers at Atlassian, 26 * please don't change things unless you're sure they're not going to break in one server or another! 27 * 28 * @author $Author: jnolen $ 29 * @version $Revision: 1.6 $ 30 */ 31 public class ClassLoaderUtils 32 { 33 /** 34 * Load a class with a given name. 35 * <p> 36 * It will try to load the class in the following order: 37 * <ul> 38 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()} 39 * <li>Using the basic {@link Class#forName(java.lang.String) } 40 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()} 41 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() } 42 * </ul> 43 * 44 * @param className The name of the class to load 45 * @param callingClass The Class object of the calling object 46 * @throws ClassNotFoundException If the class cannot be found anywhere. 47 */ 48 public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException 49 { 50 return loadClass(className, callingClass.getClassLoader()); 51 } 52 53 /** 54 * Load a class with a given name. 55 * <p> 56 * It will try to load the class in the following order: 57 * <ul> 58 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()} 59 * <li>Using the basic {@link Class#forName(java.lang.String) } 60 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()} 61 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() } 62 * </ul> 63 * 64 * @param className The name of the class to load 65 * @param callingClassLoader The ClassLoader the calling object which will be used to look up className 66 * @throws ClassNotFoundException If the class cannot be found anywhere. 67 */ 68 public static Class loadClass(String className, ClassLoader callingClassLoader) throws ClassNotFoundException 69 { 70 try 71 { 72 return Thread.currentThread().getContextClassLoader().loadClass(className); 73 } 74 catch (ClassNotFoundException e) 75 { 76 try 77 { 78 return Class.forName(className); 79 } 80 catch (ClassNotFoundException ex) 81 { 82 try 83 { 84 return ClassLoaderUtils.class.getClassLoader().loadClass(className); 85 } 86 catch (ClassNotFoundException exc) 87 { 88 return callingClassLoader.loadClass(className); 89 } 90 91 } 92 } 93 } 94 95 96 /** 97 * Load a given resource. 98 * <p> 99 * This method will try to load the resource using the following methods (in order): 100 * <ul> 101 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()} 102 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()} 103 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() } 104 * </ul> 105 * 106 * @param resourceName The name of the resource to load 107 * @param callingClass The Class object of the calling object 108 */ 109 public static URL getResource(String resourceName, Class callingClass) 110 { 111 URL url = null; 112 113 url = Thread.currentThread().getContextClassLoader().getResource(resourceName); 114 115 if (url == null) 116 { 117 url = ClassLoaderUtils.class.getClassLoader().getResource(resourceName); 118 } 119 120 if (url == null) 121 { 122 url = callingClass.getClassLoader().getResource(resourceName); 123 } 124 return url; 125 } 126 127 /** 128 * getBundle() version of getResource() (that checks against the same list of class loaders) 129 * @param resourceName 130 * @param locale 131 * @param callingClass 132 */ 133 public static ResourceBundle getBundle(String resourceName, Locale locale, Class callingClass) 134 { 135 ResourceBundle bundle = null; 136 137 bundle = ResourceBundle.getBundle(resourceName, locale, Thread.currentThread().getContextClassLoader()); 138 139 if (bundle == null) 140 { 141 bundle = ResourceBundle.getBundle(resourceName, locale, ClassLoaderUtils.class.getClassLoader()); 142 } 143 144 if (bundle == null) 145 { 146 bundle = ResourceBundle.getBundle(resourceName, locale, callingClass.getClassLoader()); 147 } 148 return bundle; 149 } 150 151 /** 152 * returns all found resources as java.net.URLs. 153 * <p> 154 * This method will try to load the resource using the following methods (in order): 155 * <ul> 156 * <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()} 157 * <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()} 158 * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() } 159 * </ul> 160 * 161 * @param resourceName The name of the resource to load 162 * @param callingClass The Class object of the calling object 163 */ 164 public static Enumeration getResources(String resourceName, Class callingClass) throws IOException 165 { 166 Enumeration urls = Thread.currentThread().getContextClassLoader().getResources(resourceName); 167 if (urls == null) 168 { 169 urls = ClassLoaderUtils.class.getClassLoader().getResources(resourceName); 170 if (urls == null) 171 { 172 urls = callingClass.getClassLoader().getResources(resourceName); 173 } 174 } 175 176 return urls; 177 } 178 179 /** 180 * This is a convenience method to load a resource as a stream. 181 * 182 * The algorithm used to find the resource is given in getResource() 183 * 184 * @param resourceName The name of the resource to load 185 * @param callingClass The Class object of the calling object 186 */ 187 public static InputStream getResourceAsStream(String resourceName, Class callingClass) 188 { 189 URL url = getResource(resourceName, callingClass); 190 try 191 { 192 return url != null ? url.openStream() : null; 193 } 194 catch (IOException e) 195 { 196 return null; 197 } 198 } 199 200 /** 201 * Prints the current classloader hierarchy - useful for debugging. 202 */ 203 public static void printClassLoader() 204 { 205 System.out.println("ClassLoaderUtils.printClassLoader"); 206 printClassLoader(Thread.currentThread().getContextClassLoader()); 207 } 208 209 /** 210 * Prints the classloader hierarchy from a given classloader - useful for debugging. 211 */ 212 public static void printClassLoader(ClassLoader cl) 213 { 214 System.out.println("ClassLoaderUtils.printClassLoader(cl = " + cl + ")"); 215 if (cl != null) 216 { 217 printClassLoader(cl.getParent()); 218 } 219 } 220 }