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