EmbedderClassLoader.java

  1. package org.jbehave.core.embedder;

  2. import java.io.File;
  3. import java.lang.reflect.Modifier;
  4. import java.net.URL;
  5. import java.net.URLClassLoader;
  6. import java.util.ArrayList;
  7. import java.util.Arrays;
  8. import java.util.List;

  9. import org.apache.commons.lang3.builder.ToStringBuilder;
  10. import org.apache.commons.lang3.builder.ToStringStyle;

  11. /**
  12.  * EmbedderClassLoader is a URLClassLoader with a specified list of classpath
  13.  * elements. It also provides a utility method
  14.  * {@link #newInstance(Class, String)} to instantiate generic types.
  15.  */
  16. public class EmbedderClassLoader extends URLClassLoader {

  17.     public EmbedderClassLoader(ClassLoader parent) {
  18.         this(Arrays.<String>asList(), parent);
  19.     }

  20.     public EmbedderClassLoader(List<String> classpathElements) {
  21.         this(classpathElements, Embedder.class.getClassLoader());
  22.     }

  23.     public EmbedderClassLoader(List<String> classpathElements, ClassLoader parent) {
  24.         super(classpathURLs(classpathElements), parent);
  25.     }

  26.     @SuppressWarnings("unchecked")
  27.     public <T> T newInstance(Class<T> type, String className) {
  28.         try {
  29.             Thread.currentThread().setContextClassLoader(this);
  30.             return (T) loadClass(className, true).newInstance();
  31.         } catch (Exception e) {
  32.             throw new InstantiationFailed(className, type, this, e);
  33.         }
  34.     }

  35.     public boolean isAbstract(String className) {
  36.         try {
  37.             return Modifier.isAbstract(loadClass(className, true).getModifiers());
  38.         } catch (ClassNotFoundException e) {
  39.             return false;
  40.         }
  41.     }

  42.     List<String> asShortPaths(URL... urls) {
  43.         List<String> names = new ArrayList<>();
  44.         for (URL url : urls) {
  45.             String path = url.getPath();
  46.             if (isJar(path)) {
  47.                 names.add(shortPath(path));
  48.             } else {
  49.                 names.add(path);
  50.             }
  51.         }
  52.         return names;
  53.     }

  54.     private static String shortPath(String path) {
  55.         return path.substring(path.lastIndexOf("/") + 1);
  56.     }

  57.     private static boolean isJar(String path) {
  58.         return path.endsWith(".jar");
  59.     }

  60.     private static URL[] classpathURLs(List<String> elements) {
  61.         List<URL> urls = new ArrayList<>();
  62.         if (elements != null) {
  63.             for (String element : elements) {
  64.                 urls.add(toURL(element));
  65.             }
  66.         }
  67.         return urls.toArray(new URL[urls.size()]);
  68.     }

  69.     private static URL toURL(String element) {
  70.         try {
  71.             return new File(element).toURI().toURL();
  72.         } catch (Exception e) {
  73.             throw new InvalidClasspathElement(element, e);
  74.         }
  75.     }

  76.     @Override
  77.     public String toString() {
  78.         return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("urls", asShortPaths(getURLs()))
  79.                 .append("parent", getParent()).toString();
  80.     }

  81.     @SuppressWarnings("serial")
  82.     public static class InstantiationFailed extends RuntimeException {

  83.         public InstantiationFailed(String className, Class<?> type, ClassLoader classLoader, Throwable cause) {
  84.             super("Instantiation failed for" + className + " of type " + type + " using class loader " + classLoader,
  85.                     cause);
  86.         }

  87.     }

  88.     @SuppressWarnings("serial")
  89.     public static class InvalidClasspathElement extends RuntimeException {

  90.         public InvalidClasspathElement(String element, Throwable cause) {
  91.             super("Invalid classpath element " + element, cause);
  92.         }

  93.     }
  94. }