ClassLoaderWrapper.java

  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. import java.io.InputStream;
  18. import java.net.URL;

  19. /**
  20.  * A class to wrap access to multiple class loaders making them work as one
  21.  *
  22.  * @author Clinton Begin
  23.  */
  24. public class ClassLoaderWrapper {

  25.   ClassLoader defaultClassLoader;
  26.   ClassLoader systemClassLoader;

  27.   ClassLoaderWrapper() {
  28.     try {
  29.       systemClassLoader = ClassLoader.getSystemClassLoader();
  30.     } catch (SecurityException ignored) {
  31.       // AccessControlException on Google App Engine
  32.     }
  33.   }

  34.   /**
  35.    * Get a resource as a URL using the current class path
  36.    *
  37.    * @param resource - the resource to locate
  38.    * @return the resource or null
  39.    */
  40.   public URL getResourceAsURL(String resource) {
  41.     return getResourceAsURL(resource, getClassLoaders(null));
  42.   }

  43.   /**
  44.    * Get a resource from the classpath, starting with a specific class loader
  45.    *
  46.    * @param resource    - the resource to find
  47.    * @param classLoader - the first classloader to try
  48.    * @return the stream or null
  49.    */
  50.   public URL getResourceAsURL(String resource, ClassLoader classLoader) {
  51.     return getResourceAsURL(resource, getClassLoaders(classLoader));
  52.   }

  53.   /**
  54.    * Get a resource from the classpath
  55.    *
  56.    * @param resource - the resource to find
  57.    * @return the stream or null
  58.    */
  59.   public InputStream getResourceAsStream(String resource) {
  60.     return getResourceAsStream(resource, getClassLoaders(null));
  61.   }

  62.   /**
  63.    * Get a resource from the classpath, starting with a specific class loader
  64.    *
  65.    * @param resource    - the resource to find
  66.    * @param classLoader - the first class loader to try
  67.    * @return the stream or null
  68.    */
  69.   public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
  70.     return getResourceAsStream(resource, getClassLoaders(classLoader));
  71.   }

  72.   /**
  73.    * Find a class on the classpath (or die trying)
  74.    *
  75.    * @param name - the class to look for
  76.    * @return - the class
  77.    * @throws ClassNotFoundException Duh.
  78.    */
  79.   public Class<?> classForName(String name) throws ClassNotFoundException {
  80.     return classForName(name, getClassLoaders(null));
  81.   }

  82.   /**
  83.    * Find a class on the classpath, starting with a specific classloader (or die trying)
  84.    *
  85.    * @param name        - the class to look for
  86.    * @param classLoader - the first classloader to try
  87.    * @return - the class
  88.    * @throws ClassNotFoundException Duh.
  89.    */
  90.   public Class<?> classForName(String name, ClassLoader classLoader) throws ClassNotFoundException {
  91.     return classForName(name, getClassLoaders(classLoader));
  92.   }

  93.   /**
  94.    * Try to get a resource from a group of classloaders
  95.    *
  96.    * @param resource    - the resource to get
  97.    * @param classLoader - the classloaders to examine
  98.    * @return the resource or null
  99.    */
  100.   InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
  101.     for (ClassLoader cl : classLoader) {
  102.       if (null != cl) {

  103.         // try to find the resource as passed
  104.         InputStream returnValue = cl.getResourceAsStream(resource);

  105.         // now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource
  106.         if (null == returnValue) {
  107.           returnValue = cl.getResourceAsStream("/" + resource);
  108.         }

  109.         if (null != returnValue) {
  110.           return returnValue;
  111.         }
  112.       }
  113.     }
  114.     return null;
  115.   }

  116.   /**
  117.    * Get a resource as a URL using the current class path
  118.    *
  119.    * @param resource    - the resource to locate
  120.    * @param classLoader - the class loaders to examine
  121.    * @return the resource or null
  122.    */
  123.   URL getResourceAsURL(String resource, ClassLoader[] classLoader) {

  124.     URL url;

  125.     for (ClassLoader cl : classLoader) {

  126.       if (null != cl) {

  127.         // look for the resource as passed in...
  128.         url = cl.getResource(resource);

  129.         // ...but some class loaders want this leading "/", so we'll add it
  130.         // and try again if we didn't find the resource
  131.         if (null == url) {
  132.           url = cl.getResource("/" + resource);
  133.         }

  134.         // "It's always in the last place I look for it!"
  135.         // ... because only an idiot would keep looking for it after finding it, so stop looking already.
  136.         if (null != url) {
  137.           return url;
  138.         }

  139.       }

  140.     }

  141.     // didn't find it anywhere.
  142.     return null;

  143.   }

  144.   /**
  145.    * Attempt to load a class from a group of classloaders
  146.    *
  147.    * @param name        - the class to load
  148.    * @param classLoader - the group of classloaders to examine
  149.    * @return the class
  150.    * @throws ClassNotFoundException - Remember the wisdom of Judge Smails: Well, the world needs ditch diggers, too.
  151.    */
  152.   Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {

  153.     for (ClassLoader cl : classLoader) {

  154.       if (null != cl) {

  155.         try {

  156.           return Class.forName(name, true, cl);

  157.         } catch (ClassNotFoundException e) {
  158.           // we'll ignore this until all classloaders fail to locate the class
  159.         }

  160.       }

  161.     }

  162.     throw new ClassNotFoundException("Cannot find class: " + name);

  163.   }

  164.   ClassLoader[] getClassLoaders(ClassLoader classLoader) {
  165.     return new ClassLoader[]{
  166.         classLoader,
  167.         defaultClassLoader,
  168.         Thread.currentThread().getContextClassLoader(),
  169.         getClass().getClassLoader(),
  170.         systemClassLoader};
  171.   }

  172. }