View Javadoc
1 /*** 2 * MethInstClassLoader 3 * 4 * This is a superclass for all class loaders at 5 * the Method Instrumentation level. If you 6 * want to have more information at any one time 7 * than just the method, then use ClassLoader. 8 */ 9 10 package junit.quilt.cover.generic; 11 12 import junit.quilt.exception.*; 13 14 import org.apache.commons.graph.*; 15 16 import org.apache.bcel.*; 17 import org.apache.bcel.generic.*; 18 import org.apache.bcel.classfile.*; 19 20 import java.util.Iterator; 21 import java.util.Map; 22 import java.util.HashMap; 23 import java.util.SortedMap; 24 import java.util.TreeMap; 25 import java.util.List; 26 import java.util.ArrayList; 27 28 import java.net.URL; 29 30 public abstract class MethInstClassLoader 31 extends QuiltClassLoader 32 { 33 private EdgeFactory edgeFactory = new EdgeFactoryImpl(); 34 35 publicMethInstClassLoader( String packages[],/index.html"> MethInstClassLoader( String packages[], 36 URL path[]) { 37 super( packages, path ); 38 } 39 40 publicMethInstClassLoader( String packages[],/index.html"> MethInstClassLoader( String packages[], 41 URL path[], 42 ClassLoader parent) { 43 super( packages, path, parent ); 44 } 45 46 /*** 47 * modifyClass 48 * 49 * This is a generic version. It basically cleans some 50 * things in the class (i.e. make it public.) Pass 51 * each Method and a Graph representing the method 52 * to the super class. 53 */ 54 55 protected JavaClass modifyClass( JavaClass jClass ) { 56 if (jClass == null) { 57 System.err.println("Warning: modifyClass called with null JavaClass"); 58 } 59 60 if (!jClass.isClass()) return jClass; 61 62 InstContext context = new InstContext(); 63 64 ConstantPoolGen pool = new ConstantPoolGen( jClass.getConstantPool() ); 65 66 context.setConstantPoolGen( pool ); 67 68 ClassGen clazz = new ClassGen( jClass ); 69 context.setClassGen( clazz ); 70 71 int accFlags = clazz.getAccessFlags(); 72 73 if ((accFlags & org.apache.bcel.Constants.ACC_PRIVATE) > 0) { 74 System.err.println("Warning: Changing class " + 75 clazz.getClassName() + 76 " to public."); 77 accFlags = (accFlags & (~org.apache.bcel.Constants.ACC_PRIVATE)) 78 | org.apache.bcel.Constants.ACC_PUBLIC; 79 clazz.setAccessFlags( accFlags ); 80 } 81 82 if ((accFlags & org.apache.bcel.Constants.ACC_PROTECTED) > 0) { 83 System.err.println("Warning: Changing class " + 84 clazz.getClassName() + 85 " to public."); 86 accFlags = (accFlags & (~org.apache.bcel.Constants.ACC_PROTECTED)) 87 | org.apache.bcel.Constants.ACC_PUBLIC; 88 clazz.setAccessFlags( accFlags ); 89 } 90 91 if ((accFlags & org.apache.bcel.Constants.ACC_PUBLIC) == 0) { 92 System.err.println("Warning: Changing class " + 93 clazz.getClassName() + 94 " to public."); 95 accFlags = accFlags | org.apache.bcel.Constants.ACC_PUBLIC; 96 clazz.setAccessFlags( accFlags ); 97 } 98 99 if (!clazz.isPublic()) { 100 System.err.println("Warning: " + clazz.getClassName() + 101 " is not public."); 102 } 103 104 /* 105 * Allow the subclass to modify the pool if they want. 106 */ 107 instrumentPool( context ); 108 109 Method [] methods = clazz.getMethods(); 110 111 for (int i = 0; i < methods.length; i++) { 112 if (isMethodOK( methods[i] )) { 113 MethodGen method = new MethodGen( methods[i], 114 clazz.getClassName(), 115 pool ); 116 try { 117 ControlFlowGraph cfg = 118 new ControlFlowGraph( context, method ); 119 cfg.initialize( getEdgeFactory() ); 120 instrumentMethod( context, cfg ); 121 clazz.replaceMethod( methods[i], 122 cfg.getMethod() ); 123 } catch (QuiltException e) { 124 System.err.println("Warning: Unable to instrument method " + 125 method.getName() + " / " + e.toString() ); 126 } 127 } 128 } 129 130 clazz.setConstantPool( pool ); 131 JavaClass RC = clazz.getJavaClass(); 132 133 if (!RC.isPublic()) 134 System.err.println("Warning: Class isn't public."); 135 return RC; 136 } 137 138 /*** 139 * instrumentMethod 140 * 141 * Override this abstract method to instrument a method. 142 */ 143 public abstract void instrumentMethod( InstContext context, 144 ControlFlowGraph graph ) 145 throws QuiltException; 146 147 /*** 148 * instrumentEdge 149 * 150 * Call this to add a Vertex in place of an edge. 151 */ 152 public void instrumentEdge( InstContext context, 153 ControlFlowGraph graph, 154 FlowControlEdge edge, 155 BlockVertex vertex ) { 156 157 if (edge.getTarget() != null) { 158 159 // 160 // *-------* 161 // 162 graph.addVertex( vertex ); 163 164 // 165 // * 166 // 167 // *-------* 168 // 169 170 FlowControlEdge outEdge = 171 getEdgeFactory().makeNormalEdge( vertex, edge.getTarget() ); 172 graph.addEdge( outEdge ); 173 174 // 175 // *---+ 176 // | 177 // *-------* 178 // 179 180 edge.setTarget( vertex ); 181 graph.updateEdge( edge ); 182 183 // 184 // +---*---+ 185 // | | 186 // * * 187 // 188 } 189 } 190 191 /*** 192 * instrumentPool 193 * 194 * Gives the subclass a chance to add things into the Constant Pool. 195 * If you need to pass information from here to the instrumentMethod 196 * make sure you drop it in the context. 197 */ 198 public void instrumentPool( InstContext context ) 199 {} 200 201 /*** 202 * getEdgeFactory() 203 * 204 * Override this method to provide your own edges. . . 205 */ 206 public EdgeFactory getEdgeFactory() { 207 return edgeFactory; 208 } 209 210 private boolean isMethodOK( Method method ) { 211 // Don't instrument the Class Initializer. Its bad luck. 212 if (method.getName().equals("<clinit>")) return false; 213 214 // Don't instrument any abstract methods. 215 if (method.getCode() == null) return false; 216 217 return true; 218 } 219 220 221 } 222 223 224 225 226

This page was automatically generated by Maven