ClassLoaderWrapper.java

  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. 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
  38.    *          - the resource to locate
  39.    *
  40.    * @return the resource or null
  41.    */
  42.   public URL getResourceAsURL(String resource) {
  43.     return getResourceAsURL(resource, getClassLoaders(null));
  44.   }

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

  58.   /**
  59.    * Get a resource from the classpath
  60.    *
  61.    * @param resource
  62.    *          - the resource to find
  63.    *
  64.    * @return the stream or null
  65.    */
  66.   public InputStream getResourceAsStream(String resource) {
  67.     return getResourceAsStream(resource, getClassLoaders(null));
  68.   }

  69.   /**
  70.    * Get a resource from the classpath, starting with a specific class loader
  71.    *
  72.    * @param resource
  73.    *          - the resource to find
  74.    * @param classLoader
  75.    *          - the first class loader to try
  76.    *
  77.    * @return the stream or null
  78.    */
  79.   public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
  80.     return getResourceAsStream(resource, getClassLoaders(classLoader));
  81.   }

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

  96.   /**
  97.    * Find a class on the classpath, starting with a specific classloader (or die trying)
  98.    *
  99.    * @param name
  100.    *          - the class to look for
  101.    * @param classLoader
  102.    *          - the first classloader to try
  103.    *
  104.    * @return - the class
  105.    *
  106.    * @throws ClassNotFoundException
  107.    *           Duh.
  108.    */
  109.   public Class<?> classForName(String name, ClassLoader classLoader) throws ClassNotFoundException {
  110.     return classForName(name, getClassLoaders(classLoader));
  111.   }

  112.   /**
  113.    * Try to get a resource from a group of classloaders
  114.    *
  115.    * @param resource
  116.    *          - the resource to get
  117.    * @param classLoader
  118.    *          - the classloaders to examine
  119.    *
  120.    * @return the resource or null
  121.    */
  122.   InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
  123.     for (ClassLoader cl : classLoader) {
  124.       if (null != cl) {

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

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

  131.         if (null != returnValue) {
  132.           return returnValue;
  133.         }
  134.       }
  135.     }
  136.     return null;
  137.   }

  138.   /**
  139.    * Get a resource as a URL using the current class path
  140.    *
  141.    * @param resource
  142.    *          - the resource to locate
  143.    * @param classLoader
  144.    *          - the class loaders to examine
  145.    *
  146.    * @return the resource or null
  147.    */
  148.   URL getResourceAsURL(String resource, ClassLoader[] classLoader) {

  149.     URL url;

  150.     for (ClassLoader cl : classLoader) {

  151.       if (null != cl) {

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

  154.         // ...but some class loaders want this leading "/", so we'll add it
  155.         // and try again if we didn't find the resource
  156.         if (null == url) {
  157.           url = cl.getResource("/" + resource);
  158.         }

  159.         // "It's always in the last place I look for it!"
  160.         // ... because only an idiot would keep looking for it after finding it, so stop looking already.
  161.         if (null != url) {
  162.           return url;
  163.         }

  164.       }

  165.     }

  166.     // didn't find it anywhere.
  167.     return null;

  168.   }

  169.   /**
  170.    * Attempt to load a class from a group of classloaders
  171.    *
  172.    * @param name
  173.    *          - the class to load
  174.    * @param classLoader
  175.    *          - the group of classloaders to examine
  176.    *
  177.    * @return the class
  178.    *
  179.    * @throws ClassNotFoundException
  180.    *           - Remember the wisdom of Judge Smails: Well, the world needs ditch diggers, too.
  181.    */
  182.   Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {

  183.     for (ClassLoader cl : classLoader) {

  184.       if (null != cl) {

  185.         try {

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

  187.         } catch (ClassNotFoundException e) {
  188.           // we'll ignore this until all classloaders fail to locate the class
  189.         }

  190.       }

  191.     }

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

  193.   }

  194.   ClassLoader[] getClassLoaders(ClassLoader classLoader) {
  195.     return new ClassLoader[] { classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(),
  196.         getClass().getClassLoader(), systemClassLoader };
  197.   }

  198. }