1 2 package org.quilt.cover.stmt; 3 4 import java.util.List ; 5 import java.util.Vector ; 6 7 import org.apache.bcel.classfile.Field; 8 import org.apache.bcel.classfile.Method; 9 import org.apache.bcel.generic.*; 10 import org.quilt.cl.ClassTransformer; 11 import org.quilt.cl.CodeVertex; 12 import org.apache.bcel.Constants; 13 14 30 31 public class ClassAction implements org.quilt.cl.ClassXformer { 32 33 35 private static String name_ = null; 36 37 38 private ClassTransformer classTrans; 39 40 41 private ClassGen clazz_; 42 43 44 private String className; 45 46 47 private String prefixedClassName; 48 49 50 private ConstantPoolGen cpGen_; 51 52 53 private InstructionFactory factory; 54 55 56 boolean clinitExists = false; 57 58 59 int clinitIndex = -1; 60 61 63 private static StmtRegistry stmtReg = null; 64 65 66 private Ephemera eph; 67 68 public ClassAction() { 70 } 71 public ClassAction (StmtRegistry reg) { 72 stmtReg = reg; 73 setName(this.getClass().getName()); } 75 76 80 public void setClassTransformer (ClassTransformer ct) { 81 classTrans = ct; 82 } 83 96 public void preMethods( ClassGen clazz ) { 97 clazz_ = clazz; 98 cpGen_ = clazz.getConstantPool(); 99 className = clazz_.getClassName(); 100 prefixedClassName = "class$QIC"; 102 eph = new Ephemera(className); 103 if (!stmtReg.putEphemera(className, eph)) { 104 System.out.println("ClassAction.preMethods INTERNAL ERRROR - " 106 + " couldn't register ephemeral data"); 107 } 108 FieldGen field; 109 if (clazz.containsField("q$$q") != null) { 110 System.out.println("ClassAction.preMethods WARNING - " 111 + className + " already has q$$q field, aborting"); 112 classTrans.abort(); 113 } else { 114 field = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 116 new ArrayType(Type.INT, 1), "q$$q", cpGen_); 117 clazz.addField(field.getField()); 118 field = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 120 Type.INT, "q$$qID", cpGen_); 121 clazz.addField(field.getField()); 122 field = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC 124 | Constants.ACC_FINAL, 125 new ObjectType("org.quilt.cover.stmt.StmtRegistry"), 126 "q$$qStmtReg", cpGen_); 127 clazz.addField(field.getField()); 128 129 field = new FieldGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 131 Type.INT, "q$$qVer", cpGen_); 132 clazz.addField(field.getField()); 133 134 field = new FieldGen(Constants.ACC_PUBLIC |Constants.ACC_STATIC, 136 new ObjectType("java.lang.Class"), 137 "class$QIC", cpGen_); 138 clazz.addField(field.getField()); 139 140 Method[] m = clazz.getMethods(); 142 for (int i = 0; i < m.length; i++) { 143 if (m[i].getName().equals("<clinit>")) { 144 clinitExists = true; 145 clinitIndex = i; 146 break; 147 } 148 } 149 } 150 } 151 152 private void dumpIList(InstructionList ilist, String where) { 153 if (ilist != null) { 154 System.out.println(where + ": instruction list"); 155 int i=0; 156 for (InstructionHandle ih = ilist.getStart(); ih != null; 157 ih = ih.getNext()) { 158 System.out.println(" " + (i++) + " " + ih); 159 } 160 } 161 } 162 163 private void addClass$Method() { 167 InstructionList il = new InstructionList(); 168 MethodGen method = new MethodGen(Constants.ACC_STATIC, 169 new ObjectType("java.lang.Class"), new Type[] { Type.STRING }, 170 new String [] { "arg0" }, "class$", className, il, cpGen_); 171 172 InstructionHandle ih_0 = il.append(factory.createLoad(Type.OBJECT, 0)); 174 InstructionHandle ih_1 = il.append(factory 175 .createInvoke("java.lang.Class", "forName", 176 new ObjectType("java.lang.Class"), new Type[] { Type.STRING }, 177 Constants.INVOKESTATIC)); 178 il.append(factory.createReturn(Type.OBJECT)); 179 180 InstructionHandle ih_5 = il.append(factory 182 .createStore(Type.OBJECT, 1)); 183 InstructionHandle ih_6 = il.append(factory 184 .createNew("java.lang.NoClassDefFoundError")); 185 il.append(InstructionConstants.DUP); 186 il.append(factory.createLoad(Type.OBJECT, 1)); 187 il.append(factory 188 .createInvoke("java.lang.ClassNotFoundException", "getMessage", 189 Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 190 il.append(factory 191 .createInvoke("java.lang.NoClassDefFoundError", "<init>", 192 Type.VOID, new Type[] { Type.STRING }, 193 Constants.INVOKESPECIAL)); 194 InstructionHandle ih_17 = il.append(InstructionConstants.ATHROW); 195 196 method.addExceptionHandler(ih_0, ih_1, ih_5, 198 new ObjectType("java.lang.ClassNotFoundException")); 199 method.setMaxStack(); 200 method.setMaxLocals(); 201 clazz_.addMethod(method.getMethod()); 202 il.dispose(); 203 } 209 public void postMethods (ClassGen clazz ) { 210 int counterCount = eph.getCounterCount(); 211 List methodNames = eph.getMethodNames(); 212 List methodEnds = eph.getMethodEnds(); 213 if (clazz != clazz_) { 214 System.out.println("ClassAction.postMethods: INTERNAL ERROR:" 216 + " preMethods class different from postMethods"); 217 } 218 factory = new InstructionFactory (clazz_, cpGen_); 219 addClass$Method(); 221 MethodGen mg; 222 InstructionList ilist; 223 InstructionHandle ih; 224 if (clinitExists) { 225 mg = new MethodGen (clazz_.getMethodAt(clinitIndex), 226 className, clazz_.getConstantPool() ); 227 ilist = mg.getInstructionList(); 228 } else { 229 ilist = new InstructionList(); 230 mg = new MethodGen ( Constants.ACC_STATIC, Type.VOID, Type.NO_ARGS, 231 new String [] {}, "<clinit>", className, 232 ilist, clazz_.getConstantPool() ); 233 } 234 238 ih = ilist.insert(new PUSH (cpGen_, counterCount)); 240 241 247 ih = ilist.append(ih, new NEWARRAY(Type.INT)); 248 249 ih = ilist.append(ih, factory.createFieldAccess ( 250 className, "q$$q", 251 new ArrayType (Type.INT, 1), Constants.PUTSTATIC)); 252 253 ih = ilist.append(ih, new PUSH(cpGen_, 0)); 257 ih = ilist.append(ih, factory.createFieldAccess( 258 className, "q$$qVer", Type.INT, 259 Constants.PUTSTATIC)); 260 261 268 ih = ilist.append(ih, new PUSH(cpGen_, "org.quilt.QIC")); 270 ih = ilist.append(ih, factory.createInvoke(className, "class$", 271 new ObjectType("java.lang.Class"), new Type[] { Type.STRING }, 272 Constants.INVOKESTATIC)); 273 ih = ilist.append(ih, InstructionConstants.DUP); 275 ih = ilist.append(ih, factory.createFieldAccess(className, 276 "class$QIC", new ObjectType("java.lang.Class"), 277 Constants.PUTSTATIC)); 278 279 ih = ilist.append(ih, factory 281 .createInvoke("java.lang.Class", "getClassLoader", 282 new ObjectType("java.lang.ClassLoader"), Type.NO_ARGS, 283 Constants.INVOKEVIRTUAL)); 284 ih = ilist.append(ih, factory 286 .createCheckCast(new ObjectType("org.quilt.cl.QuiltClassLoader"))); 287 ih = ilist.append(ih, 289 new PUSH(cpGen_, "org.quilt.cover.stmt.StmtRegistry")); 290 ih = ilist.append(ih, factory 292 .createInvoke("org.quilt.cl.QuiltClassLoader", "getRegistry", 293 new ObjectType("org.quilt.reg.QuiltRegistry"), 294 new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); 295 ih = ilist.append(ih, factory 297 .createCheckCast( 298 new ObjectType("org.quilt.cover.stmt.StmtRegistry"))); 299 ih = ilist.append(ih, factory 301 .createFieldAccess(className, "q$$qStmtReg", 302 new ObjectType("org.quilt.cover.stmt.StmtRegistry"), 303 Constants.PUTSTATIC)); 304 305 309 ih = ilist.append(ih, factory.createFieldAccess( 310 className, "q$$qStmtReg", 311 new ObjectType("org.quilt.cover.stmt.StmtRegistry"), 312 Constants.GETSTATIC)); 313 ih = ilist.append(ih, new PUSH(cpGen_, className)); 314 ih = ilist.append(ih, factory.createFieldAccess ( 315 className, "q$$q", 316 new ArrayType (Type.INT, 1), Constants.GETSTATIC)); 317 ih = ilist.append(ih, factory.createInvoke( 318 "org.quilt.cover.stmt.StmtRegistry", "registerCounts", 319 Type.INT, 320 new Type[] { Type.STRING, new ArrayType(Type.INT,1) }, 321 Constants.INVOKEVIRTUAL)); 322 ih = ilist.append(ih, factory.createFieldAccess ( 323 className, "q$$qID", Type.INT, 324 Constants.PUTSTATIC)); 325 326 if (!clinitExists) { 330 ih = ilist.append(ih, factory.createReturn (Type.VOID)); 331 } 332 ilist.setPositions(); 333 mg.setMaxStack(); 334 mg.setMaxLocals(); 335 336 boolean aborting = false; 337 if (clinitExists) { 338 clazz_.setMethodAt(mg.getMethod(), clinitIndex); 345 } else { 346 clazz_.addMethod(mg.getMethod()); 347 } 348 350 if (!aborting) { 352 int len = methodNames.size(); 353 String [] myNames = new String [len]; 354 int [] myEndCounts = new int[len]; 355 356 for (int k = 0; k < len; k++) { 357 myNames[k] = (String ) methodNames.get(k); 358 myEndCounts[k] = ((Integer )methodEnds. get(k)).intValue(); 359 } 360 stmtReg.registerMethods(className, myNames, myEndCounts); 361 } stmtReg.removeEphemera(className); 363 } 364 366 public String getName() { 367 return name_; 368 } 369 370 371 public void setName(String name) { 372 name_ = name; 373 } 374 } 375 | Popular Tags |