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