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