1 /*
2 * Copyright 2009-2023 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 * https://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
43 * - the resource to locate
44 *
45 * @return the resource or null
46 */
47 public URL getResourceAsURL(String resource) {
48 return getResourceAsURL(resource, getClassLoaders(null));
49 }
50
51 /**
52 * Get a resource from the classpath, starting with a specific class loader
53 *
54 * @param resource
55 * - the resource to find
56 * @param classLoader
57 * - the first classloader to try
58 *
59 * @return the stream or null
60 */
61 public URL getResourceAsURL(String resource, ClassLoader classLoader) {
62 return getResourceAsURL(resource, getClassLoaders(classLoader));
63 }
64
65 /**
66 * Get a resource from the classpath
67 *
68 * @param resource
69 * - the resource to find
70 *
71 * @return the stream or null
72 */
73 public InputStream getResourceAsStream(String resource) {
74 return getResourceAsStream(resource, getClassLoaders(null));
75 }
76
77 /**
78 * Get a resource from the classpath, starting with a specific class loader
79 *
80 * @param resource
81 * - the resource to find
82 * @param classLoader
83 * - the first class loader to try
84 *
85 * @return the stream or null
86 */
87 public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
88 return getResourceAsStream(resource, getClassLoaders(classLoader));
89 }
90
91 /**
92 * Find a class on the classpath (or die trying)
93 *
94 * @param name
95 * - the class to look for
96 *
97 * @return - the class
98 *
99 * @throws ClassNotFoundException
100 * Duh.
101 */
102 public Class<?> classForName(String name) throws ClassNotFoundException {
103 return classForName(name, getClassLoaders(null));
104 }
105
106 /**
107 * Find a class on the classpath, starting with a specific classloader (or die trying)
108 *
109 * @param name
110 * - the class to look for
111 * @param classLoader
112 * - the first classloader to try
113 *
114 * @return - the class
115 *
116 * @throws ClassNotFoundException
117 * Duh.
118 */
119 public Class<?> classForName(String name, ClassLoader classLoader) throws ClassNotFoundException {
120 return classForName(name, getClassLoaders(classLoader));
121 }
122
123 /**
124 * Try to get a resource from a group of classloaders
125 *
126 * @param resource
127 * - the resource to get
128 * @param classLoader
129 * - the classloaders to examine
130 *
131 * @return the resource or null
132 */
133 InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
134 for (ClassLoader cl : classLoader) {
135 if (null != cl) {
136
137 // try to find the resource as passed
138 InputStream returnValue = cl.getResourceAsStream(resource);
139
140 // now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource
141 if (null == returnValue) {
142 returnValue = cl.getResourceAsStream("/" + resource);
143 }
144
145 if (null != returnValue) {
146 return returnValue;
147 }
148 }
149 }
150 return null;
151 }
152
153 /**
154 * Get a resource as a URL using the current class path
155 *
156 * @param resource
157 * - the resource to locate
158 * @param classLoader
159 * - the class loaders to examine
160 *
161 * @return the resource or null
162 */
163 URL getResourceAsURL(String resource, ClassLoader[] classLoader) {
164
165 URL url;
166
167 for (ClassLoader cl : classLoader) {
168
169 if (null != cl) {
170
171 // look for the resource as passed in...
172 url = cl.getResource(resource);
173
174 // ...but some class loaders want this leading "/", so we'll add it
175 // and try again if we didn't find the resource
176 if (null == url) {
177 url = cl.getResource("/" + resource);
178 }
179
180 // "It's always in the last place I look for it!"
181 // ... because only an idiot would keep looking for it after finding it, so stop looking already.
182 if (null != url) {
183 return url;
184 }
185
186 }
187
188 }
189
190 // didn't find it anywhere.
191 return null;
192
193 }
194
195 /**
196 * Attempt to load a class from a group of classloaders
197 *
198 * @param name
199 * - the class to load
200 * @param classLoader
201 * - the group of classloaders to examine
202 *
203 * @return the class
204 *
205 * @throws ClassNotFoundException
206 * - Remember the wisdom of Judge Smails: Well, the world needs ditch diggers, too.
207 */
208 Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {
209
210 for (ClassLoader cl : classLoader) {
211
212 if (null != cl) {
213
214 try {
215
216 return Class.forName(name, true, cl);
217
218 } catch (ClassNotFoundException e) {
219 // we'll ignore this until all classloaders fail to locate the class
220 }
221
222 }
223
224 }
225
226 throw new ClassNotFoundException("Cannot find class: " + name);
227
228 }
229
230 ClassLoader[] getClassLoaders(ClassLoader classLoader) {
231 return new ClassLoader[] { classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(),
232 getClass().getClassLoader(), systemClassLoader };
233 }
234
235 }