01: package dalma.helpers;
02:
03: import org.apache.commons.io.IOUtils;
04: import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
05: import org.apache.commons.javaflow.bytecode.transformation.bcel.BcelClassTransformer;
06:
07: import java.io.IOException;
08: import java.io.InputStream;
09:
10: /**
11: * {@link ClassLoader} that loads the same classes as its parent
12: * {@code ClassLoader} but with necessary bytecode enhancement for
13: * running conversations.
14: *
15: * <p>
16: * This {@code ClassLoader} is useful when all the application classes
17: * are available in a single {@code ClassLoader} (which is typically
18: * the application classloader), but yet you still want to selectively
19: * instrument classes at runtime.
20: *
21: * @author Kohsuke Kawaguchi
22: */
23: public class ParallelInstrumentingClassLoader extends ClassLoader {
24: private ResourceTransformer transformer = new BcelClassTransformer();
25:
26: private final String prefix;
27:
28: /**
29: * Creates a new instance.
30: *
31: * @param parent
32: * parent class loader. Can be null, in which case it delegates
33: * to the application class loader.
34: * @param prefix
35: * prefix of the classes that will be instrumented by this class loader.
36: * for example, if this parameter is "org.acme.foo.", then classes like
37: * "org.acme.foo.Abc" or "org.acme.foo.bar.Zot" will be instrumented,
38: * but not "org.acme.Joe" or "org.acme.foobar.Zot".
39: */
40: public ParallelInstrumentingClassLoader(ClassLoader parent,
41: String prefix) {
42: super (parent);
43: this .prefix = prefix;
44: if (prefix == null)
45: throw new IllegalArgumentException();
46: }
47:
48: private boolean shouldBeRewritten(String s) {
49: return s.startsWith(prefix);
50: }
51:
52: protected synchronized Class loadClass(String name, boolean resolve)
53: throws ClassNotFoundException {
54:
55: Class c = findLoadedClass(name);
56:
57: if (c == null && shouldBeRewritten(name)) {
58: InputStream is = super .getResourceAsStream(name.replace(
59: '.', '/')
60: + ".class");
61: if (is != null) {
62: try {
63: byte[] buf = IOUtils.toByteArray(is);
64: buf = transformer.transform(buf);
65: c = defineClass(name, buf, 0, buf.length);
66: } catch (IOException e) {
67: throw new ClassNotFoundException(
68: "failed to read the class file", e);
69: }
70: }
71: }
72:
73: if (c == null) {
74: // delegate
75: final ClassLoader parent = getParent();
76: if (parent != null)
77: c = parent.loadClass(name);
78: else
79: throw new ClassNotFoundException(name);
80: }
81:
82: if (resolve)
83: resolveClass(c);
84: return c;
85: }
86: }
|