1 /* 2 * Copyright 2009-2021 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.apache.ibatis.io; 17 18 import java.io.InputStream; 19 import java.net.URL; 20 21 /** 22 * A class to wrap access to multiple class loaders making them work as one 23 * 24 * @author Clinton Begin 25 */ 26 public class ClassLoaderWrapper { 27 28 ClassLoader defaultClassLoader; 29 ClassLoader systemClassLoader; 30 31 ClassLoaderWrapper() { 32 try { 33 systemClassLoader = ClassLoader.getSystemClassLoader(); 34 } catch (SecurityException ignored) { 35 // AccessControlException on Google App Engine 36 } 37 } 38 39 /** 40 * Get a resource as a URL using the current class path 41 * 42 * @param resource - the resource to locate 43 * @return the resource or null 44 */ 45 public URL getResourceAsURL(String resource) { 46 return getResourceAsURL(resource, getClassLoaders(null)); 47 } 48 49 /** 50 * Get a resource from the classpath, starting with a specific class loader 51 * 52 * @param resource - the resource to find 53 * @param classLoader - the first classloader to try 54 * @return the stream or null 55 */ 56 public URL getResourceAsURL(String resource, ClassLoader classLoader) { 57 return getResourceAsURL(resource, getClassLoaders(classLoader)); 58 } 59 60 /** 61 * Get a resource from the classpath 62 * 63 * @param resource - the resource to find 64 * @return the stream or null 65 */ 66 public InputStream getResourceAsStream(String resource) { 67 return getResourceAsStream(resource, getClassLoaders(null)); 68 } 69 70 /** 71 * Get a resource from the classpath, starting with a specific class loader 72 * 73 * @param resource - the resource to find 74 * @param classLoader - the first class loader to try 75 * @return the stream or null 76 */ 77 public InputStream getResourceAsStream(String resource, ClassLoader classLoader) { 78 return getResourceAsStream(resource, getClassLoaders(classLoader)); 79 } 80 81 /** 82 * Find a class on the classpath (or die trying) 83 * 84 * @param name - the class to look for 85 * @return - the class 86 * @throws ClassNotFoundException Duh. 87 */ 88 public Class<?> classForName(String name) throws ClassNotFoundException { 89 return classForName(name, getClassLoaders(null)); 90 } 91 92 /** 93 * Find a class on the classpath, starting with a specific classloader (or die trying) 94 * 95 * @param name - the class to look for 96 * @param classLoader - the first classloader to try 97 * @return - the class 98 * @throws ClassNotFoundException Duh. 99 */ 100 public Class<?> classForName(String name, ClassLoader classLoader) throws ClassNotFoundException { 101 return classForName(name, getClassLoaders(classLoader)); 102 } 103 104 /** 105 * Try to get a resource from a group of classloaders 106 * 107 * @param resource - the resource to get 108 * @param classLoader - the classloaders to examine 109 * @return the resource or null 110 */ 111 InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) { 112 for (ClassLoader cl : classLoader) { 113 if (null != cl) { 114 115 // try to find the resource as passed 116 InputStream returnValue = cl.getResourceAsStream(resource); 117 118 // now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource 119 if (null == returnValue) { 120 returnValue = cl.getResourceAsStream("/" + resource); 121 } 122 123 if (null != returnValue) { 124 return returnValue; 125 } 126 } 127 } 128 return null; 129 } 130 131 /** 132 * Get a resource as a URL using the current class path 133 * 134 * @param resource - the resource to locate 135 * @param classLoader - the class loaders to examine 136 * @return the resource or null 137 */ 138 URL getResourceAsURL(String resource, ClassLoader[] classLoader) { 139 140 URL url; 141 142 for (ClassLoader cl : classLoader) { 143 144 if (null != cl) { 145 146 // look for the resource as passed in... 147 url = cl.getResource(resource); 148 149 // ...but some class loaders want this leading "/", so we'll add it 150 // and try again if we didn't find the resource 151 if (null == url) { 152 url = cl.getResource("/" + resource); 153 } 154 155 // "It's always in the last place I look for it!" 156 // ... because only an idiot would keep looking for it after finding it, so stop looking already. 157 if (null != url) { 158 return url; 159 } 160 161 } 162 163 } 164 165 // didn't find it anywhere. 166 return null; 167 168 } 169 170 /** 171 * Attempt to load a class from a group of classloaders 172 * 173 * @param name - the class to load 174 * @param classLoader - the group of classloaders to examine 175 * @return the class 176 * @throws ClassNotFoundException - Remember the wisdom of Judge Smails: Well, the world needs ditch diggers, too. 177 */ 178 Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException { 179 180 for (ClassLoader cl : classLoader) { 181 182 if (null != cl) { 183 184 try { 185 186 return Class.forName(name, true, cl); 187 188 } catch (ClassNotFoundException e) { 189 // we'll ignore this until all classloaders fail to locate the class 190 } 191 192 } 193 194 } 195 196 throw new ClassNotFoundException("Cannot find class: " + name); 197 198 } 199 200 ClassLoader[] getClassLoaders(ClassLoader classLoader) { 201 return new ClassLoader[]{ 202 classLoader, 203 defaultClassLoader, 204 Thread.currentThread().getContextClassLoader(), 205 getClass().getClassLoader(), 206 systemClassLoader}; 207 } 208 209 }