BytecodeGroovyClassLoader.java
- package org.jbehave.core.configuration.groovy;
- import java.io.ByteArrayInputStream;
- import java.io.InputStream;
- import java.security.AccessController;
- import java.security.PrivilegedAction;
- import java.util.HashMap;
- import java.util.Map;
- import org.codehaus.groovy.ast.ClassNode;
- import org.codehaus.groovy.control.CompilationUnit;
- import org.codehaus.groovy.control.SourceUnit;
- import groovy.lang.GroovyClassLoader;
- import groovyjarjarasm.asm.ClassWriter;
- /**
- * Groovy does not cache the bytecode sequences for generated classes. BytecodeReadingParanamer needs these to get
- * paramater names from classes The Groovy compiler does create the debug tables, and they are the same as the ones made
- * for a native Java class, so this derived GroovyClassLoader fills in for the missing functionality from the base
- * GroovyClassLoader.
- *
- * <p>Groovy allows a mechanism via a system property to force the dump of bytecode to a (temp) directory, but caching
- * the bytecode avoids having to clean up temp directories after the run.</p>
- */
- public class BytecodeGroovyClassLoader extends GroovyClassLoader {
- private Map<String, byte[]> classBytes = new HashMap<>();
- @Override
- public InputStream getResourceAsStream(String name) {
- if (classBytes.containsKey(name)) {
- return new ByteArrayInputStream(classBytes.get(name));
- }
- return super.getResourceAsStream(name);
- }
- @Override
- protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
- // These six lines copied from Groovy itself, with the intention to
- // return a subclass
- InnerLoader loader = AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() {
- @Override
- public InnerLoader run() {
- return new InnerLoader(BytecodeGroovyClassLoader.this);
- }
- });
- return new BytecodeClassCollector(classBytes, loader, unit, su);
- }
- public static class BytecodeClassCollector extends ClassCollector {
- private final Map<String, byte[]> classBytes;
- public BytecodeClassCollector(Map<String, byte[]> classBytes, InnerLoader loader, CompilationUnit unit,
- SourceUnit su) {
- super(loader, unit, su);
- this.classBytes = classBytes;
- }
- @Override
- protected Class<?> onClassNode(ClassWriter classWriter, ClassNode classNode) {
- classBytes.put(classNode.getName() + ".class", classWriter.toByteArray());
- return super.onClassNode(classWriter, classNode);
- }
- }
- }