##### Coverage Report - org.jbehave.core.configuration.groovy.BytecodeGroovyClassLoader

Classes in this File | Line Coverage | Branch Coverage | Complexity
BytecodeGroovyClassLoader |
87% | 7/8
50% | 1/2
| 1.4;1.4
BytecodeGroovyClassLoader$1 |
100% | 2/2
N/A | N/A
| 1.4;1.4
BytecodeGroovyClassLoader$BytecodeClassCollector |
100% | 5/5
N/A | N/A
| 1.4;1.4

1 |  |
     package org.jbehave.core.configuration.groovy;
2 |  |
3 |  |
     import groovy.lang.GroovyClassLoader;
4 |  |
     import groovyjarjarasm.asm.ClassWriter;
5 |  |
     import org.codehaus.groovy.ast.ClassNode;
6 |  |
     import org.codehaus.groovy.control.CompilationUnit;
7 |  |
     import org.codehaus.groovy.control.SourceUnit;
8 |  |
9 |  |
     import java.io.ByteArrayInputStream;
10 |  |
     import java.io.InputStream;
11 |  |
     import java.security.AccessController;
12 |  |
     import java.security.PrivilegedAction;
13 |  |
     import java.util.HashMap;
14 |  |
     import java.util.Map;
15 |  |
16 |  |
     /**
17 |  |
      * Groovy does not cache the bytecode sequences for generated classes.
18 |  |
      * BytecodeReadingParanamer needs these to get paramater names from classes The
19 |  |
      * Groovy compiler does create the debug tables, and they are the same as the
20 |  |
      * ones made for a native Java class, so this derived GroovyClassLoader fills in
21 |  |
      * for the missing functionality from the base GroovyClassLoader.
22 |  |
      *
23 |  |
      * Groovy allows a mechanism via a system property to force the dump of bytecode
24 |  |
      * to a (temp) directory, but caching the bytecode avoids having to clean up
25 |  |
      * temp directories after the run.
26 |  |
      */
27 | 5 |
     public class BytecodeGroovyClassLoader extends GroovyClassLoader {
28 |  |
29 | 5 |
         private Map<String, byte[]> classBytes = new HashMap<String, byte[]>();
30 |  |
31 |  |
         @Override
32 |  |
         public InputStream getResourceAsStream(String name) {
33 | 1 |
             if (classBytes.containsKey(name)) {
34 | 1 |
                 return new ByteArrayInputStream(classBytes.get(name));
35 |  |
             }
36 | 0 |
             return super.getResourceAsStream(name);
37 |  |
         }
38 |  |
39 |  |
         @Override
40 |  |
         protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
41 |  |
             // These six lines copied from Groovy itself, with the intention to
42 |  |
             // return a subclass
43 | 12 |
             InnerLoader loader = AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() {
44 |  |
                 public InnerLoader run() {
45 | 6 |
                     return new InnerLoader(BytecodeGroovyClassLoader.this);
46 |  |
                 }
47 |  |
             });
48 | 6 |
             return new BytecodeClassCollector(classBytes, loader, unit, su);
49 |  |
         }
50 |  |
51 | 5 |
         public static class BytecodeClassCollector extends ClassCollector {
52 |  |
             private final Map<String, byte[]> classBytes;
53 |  |
54 |  |
             public BytecodeClassCollector(Map<String, byte[]> classBytes, InnerLoader loader, CompilationUnit unit,
55 |  |
                     SourceUnit su) {
56 | 6 |
                 super(loader, unit, su);
57 | 6 |
                 this.classBytes = classBytes;
58 | 6 |
             }
59 |  |
60 |  |
             @Override
61 |  |
             protected Class<?> onClassNode(ClassWriter classWriter, ClassNode classNode) {
62 | 6 |
                 classBytes.put(classNode.getName() + ".class", classWriter.toByteArray());
63 | 6 |
                 return super.onClassNode(classWriter, classNode);
64 |  |
             }
65 |  |
         }
66 |  |
67 |  |
     }