1 /**
2 * Copyright 2009-2019 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 Class<?> c = Class.forName(name, true, cl);
187
188 if (null != c) {
189 return c;
190 }
191
192 } catch (ClassNotFoundException e) {
193 // we'll ignore this until all classloaders fail to locate the class
194 }
195
196 }
197
198 }
199
200 throw new ClassNotFoundException("Cannot find class: " + name);
201
202 }
203
204 ClassLoader[] getClassLoaders(ClassLoader classLoader) {
205 return new ClassLoader[]{
206 classLoader,
207 defaultClassLoader,
208 Thread.currentThread().getContextClassLoader(),
209 getClass().getClassLoader(),
210 systemClassLoader};
211 }
212
213 }