GROOVY-7443: traits classloaders support
diff --git a/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java b/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
index 9b7deb9..2b09bdb 100644
--- a/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
+++ b/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
@@ -24,6 +24,7 @@
import groovy.lang.GroovyObject;
import groovy.lang.GroovyRuntimeException;
import groovy.transform.Trait;
+
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
@@ -145,7 +146,7 @@
final boolean emptyBody,
final Class delegateClass) {
super(Opcodes.ASM4, new ClassWriter(0));
- this.loader = proxyLoader!=null?createInnerLoader(proxyLoader):findClassLoader(superClass);
+ this.loader = proxyLoader!=null?createInnerLoader(proxyLoader, interfaces):findClassLoader(superClass, interfaces);
this.visitedMethods = new LinkedHashSet<Object>();
this.delegatedClosures = closureMap.isEmpty()? EMPTY_DELEGATECLOSURE_MAP :new HashMap<String, Boolean>();
boolean wildcard = false;
@@ -250,18 +251,18 @@
}
}
- private static InnerLoader createInnerLoader(final ClassLoader parent) {
+ private static InnerLoader createInnerLoader(final ClassLoader parent, final Class[] interfaces) {
return AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() {
public InnerLoader run() {
- return new InnerLoader(parent);
+ return new InnerLoader(parent, interfaces);
}
});
}
- private InnerLoader findClassLoader(Class clazz) {
+ private InnerLoader findClassLoader(Class clazz, Class[] interfaces) {
ClassLoader cl = clazz.getClassLoader();
if (cl==null) cl = this.getClass().getClassLoader();
- return createInnerLoader(cl);
+ return createInnerLoader(cl, interfaces);
}
private static Set<String> createDelegateMethodList(Class superClass, Class delegateClass, Class[] interfaces) {
@@ -917,16 +918,87 @@
throw new IllegalArgumentException("Unexpected type class [" + type + "]");
}
+
private static class InnerLoader extends GroovyClassLoader {
- protected InnerLoader(final ClassLoader parent) {
+
+ List<ClassLoader> internalClassLoaders = null;
+
+ protected InnerLoader(final ClassLoader parent, final Class[] interfaces) {
super(parent);
+ if(interfaces != null) {
+ for(Class c : interfaces) {
+ if(c.getClassLoader() != parent) {
+ if(internalClassLoaders == null) internalClassLoaders = new ArrayList<ClassLoader>(interfaces.length);
+ if( ! internalClassLoaders.contains(c.getClassLoader()) ) {
+ internalClassLoaders.add(c.getClassLoader());
+ }
+ }
+ }
+ }
}
public Class defineClass(String name, byte[] data) {
return super.defineClass(name, data, 0, data.length);
}
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ // First check whether it's already been loaded, if so use it
+ Class loadedClass = findLoadedClass(name);
+
+ if (loadedClass != null) return loadedClass;
+
+
+ //check this class loader
+ try {
+
+ loadedClass = findClass(name);
+
+ } catch (ClassNotFoundException e) { }
+
+ if(loadedClass != null) return loadedClass;
+
+
+ //check parent classloader, keep the exception for future use
+ ClassNotFoundException ex = null;
+ try {
+ loadedClass = super.loadClass(name);
+ } catch(ClassNotFoundException e) {
+ ex = e;
+ }
+
+ if (loadedClass != null) return loadedClass;
+
+
+ // Not loaded, try to load it
+ if(internalClassLoaders != null) {
+
+ for(ClassLoader i : internalClassLoaders) {
+ try {
+ // Ignore parent delegation and just try to load locally
+
+ loadedClass = i.loadClass(name);
+
+ if(loadedClass != null) return loadedClass;
+
+ } catch (ClassNotFoundException e) {
+ // Swallow exception - does not exist locally
+ }
+
+ }
+
+ }
+
+
+ //throw parent exception if exists, otherwise create a new exception
+ if(ex != null) throw ex;
+
+ throw new ClassNotFoundException(name);
+
+ }
+
}
+
+
private static class ReturnValueWrappingClosure<V> extends Closure<V>{
private final V value;