1 /***
2 * SMClassLoader -
3 *
4 * This class extends the ClassLoader provided
5 * by the BCEL project.
6 *
7 * It instruments the code loaded with the implementation
8 * of the StateMachine provided here.
9 */
10
11 package junit.quilt.cover.state;
12
13 import java.io.*;
14
15 import java.net.URL;
16
17 import java.util.Set;
18 import java.util.List;
19 import java.util.ArrayList;
20 import java.util.Map;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Collection;
24
25 // import java.lang.reflect.Constructor;
26
27 import junit.quilt.cover.generic.*;
28
29 import org.apache.bcel.generic.*;
30 import org.apache.bcel.classfile.*;
31 import org.apache.bcel.Constants;
32
33 import org.apache.commons.graph.*;
34
35 public class SMClassLoader
36 extends MethInstClassLoader
37 {
38 private StateMachineRegistry registry = null;
39
40 protectedSMClassLoader( String packages[],/index.html"> SMClassLoader( String packages[],
41 URL path[],
42 ClassLoader parent,
43 StateMachineRegistry registry ) {
44 super( packages, path, parent );
45 this.registry = registry;
46 }
47
48 public void instrumentPool(InstContext context)
49 {
50 ConstantPoolGen pool = context.getConstantPoolGen();
51
52 int visitRef
53 = pool.addMethodref(
54 "junit/quilt/cover/state/SimpleStateMachine",
55 "visit",
56 "(I)V");
57
58 int startRef
59 = pool.addMethodref(
60 "junit/quilt/cover/state/SimpleStateMachine",
61 "start",
62 "()V" );
63
64 context.put( "visitRef", new Integer( visitRef ));
65 context.put( "startRef", new Integer( startRef ));
66 }
67
68 public void instrumentMethod( InstContext context,
69 ControlFlowGraph cfg ) {
70 ClassGen clazz = context.getClassGen();
71
72 // Initialize some variables. . .
73 int startRef = ((Integer) context.get("startRef")).intValue();
74 int visitRef = ((Integer) context.get("visitRef")).intValue();
75 int fieldVar = cfg.makeNewLocal("MSM",
76 new ObjectType("junit.quilt.cover.state.SimpleStateMachine"));
77
78 int numVertices = cfg.getVertices().size() + 4;
79 SimpleStateMachine ssm = new SimpleStateMachine( clazz.getFileName(),
80 numVertices);
81 int fieldRef = addStaticField( context,
82 new ObjectType("junit.quilt.cover.state.SimpleStateMachine"),
83 ssm);
84
85 // Add Initialization Code
86 junit.quilt.cover.state.InitVertex init =
87 new junit.quilt.cover.state.InitVertex(fieldVar,
88 fieldRef,
89 startRef);
90
91 BlockVertex start = cfg.getStartVertex();
92 cfg.setStartVertex( init );
93
94 FlowControlEdge initEdge =
95 getEdgeFactory().makeNormalEdge( init, start );
96 cfg.addEdge( initEdge );
97
98 // Add the Visit code
99 Set blockSet = cfg.getVertices();
100 Vertex blocks[] = (Vertex []) blockSet.toArray( new Vertex[ blockSet.size() ]);
101
102 Map labels = new HashMap(); // BLOCK X INDEX
103 for (short i = 0; i < blocks.length; i++) {
104 BlockVertex bv = (BlockVertex) blocks[i];
105 if ((bv != cfg.getStartVertex()) &&
106 (bv != cfg.getEndVertex())) {
107 labels.put( bv, new Integer( i ));
108 ssm.addState( i, bv );
109
110 CallVisitVertex cvv =
111 new CallVisitVertex( fieldVar, visitRef, i );
112 bv.prefixInstructionList( cvv.copyInstructionList() );
113
114
115 Iterator edges = cfg.getEdges().iterator();
116 while (edges.hasNext()) {
117 Edge cEdge = (Edge) edges.next();
118 if (cfg.getSource( cEdge ) == bv) {
119 // Edge leads away. . .
120 Vertex target = cfg.getTarget(cEdge);
121 if (labels.containsKey( target )) {
122 int iTarget =
123 ((Integer) labels.get(target)).intValue();
124 ssm.addTransition( i, iTarget );
125 }
126 } else {
127 // Edge leads in . . .
128 Vertex source = cfg.getSource(cEdge);
129 if (labels.containsKey( source )) {
130 int iSource =
131 ((Integer) labels.get(source)).intValue();
132 ssm.addTransition( iSource, i );
133 }
134 }
135 }
136 }
137 }
138
139 // Write the StateMachine to the StateMachineRegistry
140 registry.bind( clazz.getClassName(),
141 cfg.getMethodName(),
142 ssm );
143 }
144
145 }
This page was automatically generated by Maven