View Javadoc
1 /*** 2 * ClassLoader 3 * 4 * This is a superclass for all instrumenting class loaders. 5 */ 6 7 package junit.quilt.cover.generic; 8 9 import org.apache.commons.graph.Graph; 10 11 import org.apache.bcel.Constants; 12 13 import org.apache.bcel.generic.*; 14 import org.apache.bcel.classfile.*; 15 16 import java.lang.reflect.Field; 17 18 import java.net.URL; 19 import java.net.URLClassLoader; 20 21 import java.io.File; 22 import java.io.InputStream; 23 24 import java.util.Enumeration; 25 import java.util.Iterator; 26 import java.util.Map; 27 import java.util.HashMap; 28 import java.util.List; 29 import java.util.ArrayList; 30 31 public class QuiltClassLoader 32 extends URLClassLoader 33 { 34 private String packages[] = null; 35 36 publicQuiltClassLoader( String packages[],/index.html"> QuiltClassLoader( String packages[], 37 URL path[] ) { 38 super( path ); 39 this.packages = packages; 40 } 41 42 publicQuiltClassLoader( String packages[],/index.html"> QuiltClassLoader( String packages[], 43 URL path[], 44 ClassLoader parent ) { 45 super( path, parent ); 46 this.packages = packages; 47 } 48 49 private Map addedStaticFields = new HashMap(); 50 // CLASS X LIST( AddedStaticField ) 51 52 private Map loadedClasses = new HashMap(); 53 // CLASS_NAME X JAVA_CLASS 54 55 private static int lastField = 0; 56 57 /*** 58 * AddedStaticField 59 * 60 * This class just keeps the field name that was generated, 61 * and the data that is supposed to go in there together. 62 */ 63 private class AddedStaticField 64 { 65 public String fieldName = null; 66 public Object initData = null; 67 68 public AddedStaticField( String fieldName, 69 Object initData ) 70 { 71 this.fieldName = fieldName; 72 this.initData = initData; 73 } 74 } 75 76 /*** 77 * makeUniqueFieldName 78 * 79 * This method will create a unique field name for adding 80 * data to a class. 81 */ 82 private String makeUniqueFieldName() { 83 String RC = "junit_quilt_Field_" + lastField; 84 lastField++; 85 return RC; 86 } 87 88 /*** 89 * addStaticField 90 * 91 * This creates a unique static field on the class, and returns 92 * a field reference which is valid in the current ConstantPool. 93 * 94 * The name is autogenerated. 95 */ 96 protected int addStaticField( InstContext context, 97 Type type, 98 Object initData) 99 { 100 ClassGen clazz = context.getClassGen(); 101 ConstantPoolGen pool = context.getConstantPoolGen(); 102 103 String fieldName = makeUniqueFieldName(); 104 List fields = (List) addedStaticFields.get( clazz.getClassName() ); 105 if (fields == null) { 106 fields = new ArrayList(); 107 addedStaticFields.put( clazz.getClassName(), fields ); 108 } 109 110 fields.add( new AddedStaticField( fieldName, 111 initData )); 112 FieldGen field = 113 new FieldGen( Constants.ACC_PUBLIC | 114 Constants.ACC_STATIC, 115 type, 116 fieldName, 117 pool ); 118 clazz.addField( field.getField() ); 119 return pool.addFieldref( clazz.getClassName(), 120 fieldName, 121 type.getSignature()); 122 123 } 124 125 private boolean skip( String className ) { 126 for (int i = 0; i < packages.length; i++) { 127 if (className.startsWith( packages[i] )) 128 return false; 129 } 130 131 System.err.println("Skipping: " + className ); 132 return true; 133 } 134 135 protected JavaClass modifyClass( JavaClass clazz ) { 136 return clazz; 137 } 138 139 private JavaClass makeJavaClass( String className ) 140 throws ClassNotFoundException 141 { 142 try { 143 String classFile = className.replace('.', File.pathSeparatorChar) 144 + ".class"; 145 URL bytecodeURL = getResource( classFile ); 146 InputStream bytecodeIS = bytecodeURL.openStream(); 147 148 return new ClassParser( bytecodeIS, className ).parse(); 149 } catch (Exception e) { 150 e.printStackTrace(); 151 throw new ClassNotFoundException( e.toString() ); 152 } 153 } 154 155 public Class findClass( String className ) 156 throws ClassNotFoundException 157 { 158 if (skip( className )) 159 return super.findClass( className ) ; 160 161 JavaClass clazz = null; 162 163 if (loadedClasses.containsKey( className )) { 164 clazz = (JavaClass) loadedClasses.get( className ); 165 } else { 166 clazz = makeJavaClass( className ); 167 clazz = modifyClass( clazz ); 168 } 169 170 byte bytecode[] = clazz.getBytes(); 171 Class RC = defineClass( className, 172 bytecode, 0, 173 bytecode.length); 174 175 if (addedStaticFields.containsKey( className )) { 176 Iterator addedFields = 177 ((List) addedStaticFields.get( className )).iterator(); 178 while (addedFields.hasNext()) { 179 AddedStaticField af = (AddedStaticField) addedFields.next(); 180 try { 181 java.lang.reflect.Field field = 182 RC.getField( af.fieldName ); 183 field.set( null, af.initData ); 184 } catch (Exception e) { 185 System.err.println("Warning: Field " + af.fieldName + 186 " not initialized."); 187 } 188 } 189 } 190 return RC; 191 } 192 // /*** 193 // * This loads the class specified by the Class Name. 194 // * 195 // * After it is loaded, it will initialize all of the static 196 // * values which have been added to the system by the instrumentors. 197 // */ 198 // public synchronized Class loadClass( String className ) 199 // throws ClassNotFoundException 200 // { 201 // addedStaticFields.put( className, new ArrayList() ); 202 203 // Class RC = super.loadClass( className ); 204 205 // try { 206 // List fields = (List) addedStaticFields.get( className ); 207 // if (fields != null) { 208 // Iterator f = fields.iterator(); 209 210 // while (f.hasNext()) { 211 // AddedStaticField asf = (AddedStaticField) f.next(); 212 // java.lang.reflect.Field field 213 // = RC.getField( asf.fieldName ); 214 // field.set( null, asf.initData ); 215 // } 216 // } 217 // } catch (Exception e) { 218 // System.err.println("Warning: Coverage fields not initialized."); 219 // System.err.println("Class: " + className ); 220 // e.printStackTrace(); 221 // } 222 223 // return RC; 224 // } 225 } 226 227 228 229 230

This page was automatically generated by Maven