Repository: groovy Updated Branches: refs/heads/master 54f00a236 -> 3d7e2cae3
GROOVY-7443: traits classloaders support Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/03d37205 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/03d37205 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/03d37205 Branch: refs/heads/master Commit: 03d372054cf2713a22ca41fa1211874cc872fed4 Parents: 54f00a2 Author: Dariusz Kobylarz <[email protected]> Authored: Sat Jun 20 00:08:02 2015 +0200 Committer: paulk <[email protected]> Committed: Wed Aug 3 08:34:43 2016 +1000 ---------------------------------------------------------------------- .../groovy/runtime/ProxyGeneratorAdapter.java | 84 ++++++++++++++++++-- 1 file changed, 78 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/03d37205/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java ---------------------------------------------------------------------- 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.GroovyClassLoader; 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 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes { 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 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes { } } - 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 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes { 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;
