1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23 24package com.sun.org.apache.xml.internal.security.utils; 25 26import java.io.IOException; 27import java.io.InputStream; 28import java.net.URL; 29import java.util.ArrayList; 30import java.util.Enumeration; 31import java.util.List; 32 33/** 34 * This class is extremely useful for loading resources and classes in a fault 35 * tolerant manner that works across different applications servers. Do not 36 * touch this unless you're a grizzled classloading guru veteran who is going to 37 * verify any change on 6 different application servers. 38 */ 39final class ClassLoaderUtils { 40 41 /** {@link org.apache.commons.logging} logging facility */ 42 private static final java.util.logging.Logger log = 43 java.util.logging.Logger.getLogger(ClassLoaderUtils.class.getName()); 44 45 private ClassLoaderUtils() { 46 } 47 48 /** 49 * Load a given resource. <p/> This method will try to load the resource 50 * using the following methods (in order): 51 * <ul> 52 * <li>From Thread.currentThread().getContextClassLoader() 53 * <li>From ClassLoaderUtil.class.getClassLoader() 54 * <li>callingClass.getClassLoader() 55 * </ul> 56 * 57 * @param resourceName The name of the resource to load 58 * @param callingClass The Class object of the calling object 59 */ 60 static URL getResource(String resourceName, Class<?> callingClass) { 61 URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName); 62 if (url == null && resourceName.startsWith("/")) { 63 //certain classloaders need it without the leading / 64 url = 65 Thread.currentThread().getContextClassLoader().getResource( 66 resourceName.substring(1) 67 ); 68 } 69 70 ClassLoader cluClassloader = ClassLoaderUtils.class.getClassLoader(); 71 if (cluClassloader == null) { 72 cluClassloader = ClassLoader.getSystemClassLoader(); 73 } 74 if (url == null) { 75 url = cluClassloader.getResource(resourceName); 76 } 77 if (url == null && resourceName.startsWith("/")) { 78 //certain classloaders need it without the leading / 79 url = cluClassloader.getResource(resourceName.substring(1)); 80 } 81 82 if (url == null) { 83 ClassLoader cl = callingClass.getClassLoader(); 84 85 if (cl != null) { 86 url = cl.getResource(resourceName); 87 } 88 } 89 90 if (url == null) { 91 url = callingClass.getResource(resourceName); 92 } 93 94 if ((url == null) && (resourceName != null) && (resourceName.charAt(0) != '/')) { 95 return getResource('/' + resourceName, callingClass); 96 } 97 98 return url; 99 } 100 101 /** 102 * Load a given resources. <p/> This method will try to load the resources 103 * using the following methods (in order): 104 * <ul> 105 * <li>From Thread.currentThread().getContextClassLoader() 106 * <li>From ClassLoaderUtil.class.getClassLoader() 107 * <li>callingClass.getClassLoader() 108 * </ul> 109 * 110 * @param resourceName The name of the resource to load 111 * @param callingClass The Class object of the calling object 112 */ 113 static List<URL> getResources(String resourceName, Class<?> callingClass) { 114 List<URL> ret = new ArrayList<URL>(); 115 Enumeration<URL> urls = new Enumeration<URL>() { 116 public boolean hasMoreElements() { 117 return false; 118 } 119 public URL nextElement() { 120 return null; 121 } 122 123 }; 124 try { 125 urls = Thread.currentThread().getContextClassLoader().getResources(resourceName); 126 } catch (IOException e) { 127 if (log.isLoggable(java.util.logging.Level.FINE)) { 128 log.log(java.util.logging.Level.FINE, e.getMessage(), e); 129 } 130 //ignore 131 } 132 if (!urls.hasMoreElements() && resourceName.startsWith("/")) { 133 //certain classloaders need it without the leading / 134 try { 135 urls = 136 Thread.currentThread().getContextClassLoader().getResources( 137 resourceName.substring(1) 138 ); 139 } catch (IOException e) { 140 if (log.isLoggable(java.util.logging.Level.FINE)) { 141 log.log(java.util.logging.Level.FINE, e.getMessage(), e); 142 } 143 // ignore 144 } 145 } 146 147 ClassLoader cluClassloader = ClassLoaderUtils.class.getClassLoader(); 148 if (cluClassloader == null) { 149 cluClassloader = ClassLoader.getSystemClassLoader(); 150 } 151 if (!urls.hasMoreElements()) { 152 try { 153 urls = cluClassloader.getResources(resourceName); 154 } catch (IOException e) { 155 if (log.isLoggable(java.util.logging.Level.FINE)) { 156 log.log(java.util.logging.Level.FINE, e.getMessage(), e); 157 } 158 // ignore 159 } 160 } 161 if (!urls.hasMoreElements() && resourceName.startsWith("/")) { 162 //certain classloaders need it without the leading / 163 try { 164 urls = cluClassloader.getResources(resourceName.substring(1)); 165 } catch (IOException e) { 166 if (log.isLoggable(java.util.logging.Level.FINE)) { 167 log.log(java.util.logging.Level.FINE, e.getMessage(), e); 168 } 169 // ignore 170 } 171 } 172 173 if (!urls.hasMoreElements()) { 174 ClassLoader cl = callingClass.getClassLoader(); 175 176 if (cl != null) { 177 try { 178 urls = cl.getResources(resourceName); 179 } catch (IOException e) { 180 if (log.isLoggable(java.util.logging.Level.FINE)) { 181 log.log(java.util.logging.Level.FINE, e.getMessage(), e); 182 } 183 // ignore 184 } 185 } 186 } 187 188 if (!urls.hasMoreElements()) { 189 URL url = callingClass.getResource(resourceName); 190 if (url != null) { 191 ret.add(url); 192 } 193 } 194 while (urls.hasMoreElements()) { 195 ret.add(urls.nextElement()); 196 } 197 198 199 if (ret.isEmpty() && (resourceName != null) && (resourceName.charAt(0) != '/')) { 200 return getResources('/' + resourceName, callingClass); 201 } 202 return ret; 203 } 204 205 206 /** 207 * This is a convenience method to load a resource as a stream. <p/> The 208 * algorithm used to find the resource is given in getResource() 209 * 210 * @param resourceName The name of the resource to load 211 * @param callingClass The Class object of the calling object 212 */ 213 static InputStream getResourceAsStream(String resourceName, Class<?> callingClass) { 214 URL url = getResource(resourceName, callingClass); 215 216 try { 217 return (url != null) ? url.openStream() : null; 218 } catch (IOException e) { 219 if (log.isLoggable(java.util.logging.Level.FINE)) { 220 log.log(java.util.logging.Level.FINE, e.getMessage(), e); 221 } 222 return null; 223 } 224 } 225 226 /** 227 * Load a class with a given name. <p/> It will try to load the class in the 228 * following order: 229 * <ul> 230 * <li>From Thread.currentThread().getContextClassLoader() 231 * <li>Using the basic Class.forName() 232 * <li>From ClassLoaderUtil.class.getClassLoader() 233 * <li>From the callingClass.getClassLoader() 234 * </ul> 235 * 236 * @param className The name of the class to load 237 * @param callingClass The Class object of the calling object 238 * @throws ClassNotFoundException If the class cannot be found anywhere. 239 */ 240 static Class<?> loadClass(String className, Class<?> callingClass) 241 throws ClassNotFoundException { 242 try { 243 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 244 245 if (cl != null) { 246 return cl.loadClass(className); 247 } 248 } catch (ClassNotFoundException e) { 249 if (log.isLoggable(java.util.logging.Level.FINE)) { 250 log.log(java.util.logging.Level.FINE, e.getMessage(), e); 251 } 252 //ignore 253 } 254 return loadClass2(className, callingClass); 255 } 256 257 private static Class<?> loadClass2(String className, Class<?> callingClass) 258 throws ClassNotFoundException { 259 try { 260 return Class.forName(className); 261 } catch (ClassNotFoundException ex) { 262 try { 263 if (ClassLoaderUtils.class.getClassLoader() != null) { 264 return ClassLoaderUtils.class.getClassLoader().loadClass(className); 265 } 266 } catch (ClassNotFoundException exc) { 267 if (callingClass != null && callingClass.getClassLoader() != null) { 268 return callingClass.getClassLoader().loadClass(className); 269 } 270 } 271 if (log.isLoggable(java.util.logging.Level.FINE)) { 272 log.log(java.util.logging.Level.FINE, ex.getMessage(), ex); 273 } 274 throw ex; 275 } 276 } 277} 278