1 | |
package org.jbehave.core.embedder; |
2 | |
|
3 | |
import java.io.File; |
4 | |
import java.lang.reflect.Modifier; |
5 | |
import java.net.URL; |
6 | |
import java.net.URLClassLoader; |
7 | |
import java.util.ArrayList; |
8 | |
import java.util.Arrays; |
9 | |
import java.util.List; |
10 | |
|
11 | |
import org.apache.commons.lang.builder.ToStringBuilder; |
12 | |
import org.apache.commons.lang.builder.ToStringStyle; |
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
public class EmbedderClassLoader extends URLClassLoader { |
20 | |
|
21 | |
public EmbedderClassLoader(ClassLoader parent) { |
22 | 80 | this(Arrays.<String>asList(), parent); |
23 | 80 | } |
24 | |
|
25 | |
public EmbedderClassLoader(List<String> classpathElements) { |
26 | 7 | this(classpathElements, Embedder.class.getClassLoader()); |
27 | 6 | } |
28 | |
|
29 | |
public EmbedderClassLoader(List<String> classpathElements, ClassLoader parent) { |
30 | 87 | super(classpathURLs(classpathElements), parent); |
31 | 86 | } |
32 | |
|
33 | |
@SuppressWarnings("unchecked") |
34 | |
public <T> T newInstance(Class<T> type, String className) { |
35 | |
try { |
36 | 4 | Thread.currentThread().setContextClassLoader(this); |
37 | 4 | return (T) loadClass(className, true).newInstance(); |
38 | 1 | } catch (Exception e) { |
39 | 1 | throw new InstantiationFailed(className, type, this, e); |
40 | |
} |
41 | |
} |
42 | |
|
43 | |
public boolean isAbstract(String className) { |
44 | |
try { |
45 | 3 | return Modifier.isAbstract(loadClass(className, true).getModifiers()); |
46 | 1 | } catch (ClassNotFoundException e) { |
47 | 1 | return false; |
48 | |
} |
49 | |
} |
50 | |
|
51 | |
List<String> asShortPaths(URL... urls) { |
52 | 6 | List<String> names = new ArrayList<String>(); |
53 | 10 | for (URL url : urls) { |
54 | 4 | String path = url.getPath(); |
55 | 4 | if (isJar(path)) { |
56 | 2 | names.add(shortPath(path)); |
57 | |
} else { |
58 | 2 | names.add(path); |
59 | |
} |
60 | |
} |
61 | 6 | return names; |
62 | |
} |
63 | |
|
64 | |
private static String shortPath(String path) { |
65 | 2 | return path.substring(path.lastIndexOf("/") + 1); |
66 | |
} |
67 | |
|
68 | |
private static boolean isJar(String path) { |
69 | 4 | return path.endsWith(".jar"); |
70 | |
} |
71 | |
|
72 | |
private static URL[] classpathURLs(List<String> elements) { |
73 | 87 | List<URL> urls = new ArrayList<URL>(); |
74 | 87 | if (elements != null) { |
75 | 86 | for (String element : elements) { |
76 | 4 | urls.add(toURL(element)); |
77 | |
} |
78 | |
} |
79 | 86 | return urls.toArray(new URL[urls.size()]); |
80 | |
} |
81 | |
|
82 | |
private static URL toURL(String element) { |
83 | |
try { |
84 | 4 | return new File(element).toURI().toURL(); |
85 | 1 | } catch ( Exception e ){ |
86 | 1 | throw new InvalidClasspathElement(element, e); |
87 | |
} |
88 | |
} |
89 | |
|
90 | |
@Override |
91 | |
public String toString() { |
92 | 5 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("urls", asShortPaths(getURLs())) |
93 | |
.append("parent", getParent()).toString(); |
94 | |
} |
95 | |
|
96 | |
@SuppressWarnings("serial") |
97 | |
public static class InstantiationFailed extends RuntimeException { |
98 | |
|
99 | |
public InstantiationFailed(String className, Class<?> type, ClassLoader classLoader, Throwable cause) { |
100 | 1 | super("Instantiation failed for" + className + " of type " + type + " using class loader "+classLoader, cause); |
101 | 1 | } |
102 | |
|
103 | |
} |
104 | |
|
105 | |
@SuppressWarnings("serial") |
106 | |
public static class InvalidClasspathElement extends RuntimeException { |
107 | |
|
108 | |
public InvalidClasspathElement(String element, Throwable cause) { |
109 | 1 | super("Invalid classpath element " + element, cause); |
110 | 1 | } |
111 | |
|
112 | |
} |
113 | |
} |