View Javadoc
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 }