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  import java.lang.ClassLoader;
20  
21  import java.util.Iterator;
22  import java.util.Map;
23  import java.util.HashMap;
24  import java.util.SortedMap;
25  import java.util.TreeMap;
26  import java.util.List;
27  import java.util.ArrayList;
28  
29  import java.net.URL;
30  
31  public abstract class MethInstClassLoader
32      extends QuiltClassLoader
33  {
34      private EdgeFactory edgeFactory = new EdgeFactoryImpl();
35  
36      publicMethInstClassLoader( String packages[],/index.html"> MethInstClassLoader( String packages[],
37  				URL path[]) {
38  	super( packages, path );
39      }
40  
41      publicMethInstClassLoader( String packages[],/index.html"> MethInstClassLoader( String packages[],
42  				URL path[],
43  				ClassLoader parent) {
44  	super( packages, path, parent );
45      }
46  
47      /***
48       * modifyClass
49       *
50       * This is a generic version.  It basically cleans some
51       * things in the class (i.e. make it public.)  Pass
52       * each Method and a Graph representing the method
53       * to the super class.
54       */
55  
56      protected JavaClass modifyClass( JavaClass jClass ) {
57        if (jClass == null) {
58  	System.err.println("Warning:  modifyClass called with null JavaClass");
59        }
60  
61        if (!jClass.isClass()) return jClass;
62  
63        InstContext context = new InstContext();
64        
65        ConstantPoolGen pool = new ConstantPoolGen( jClass.getConstantPool() );
66  
67        context.setConstantPoolGen( pool );
68        
69        ClassGen clazz = new ClassGen( jClass );
70        context.setClassGen( clazz );
71  
72        int accFlags = clazz.getAccessFlags();
73  
74        if ((accFlags & org.apache.bcel.Constants.ACC_PRIVATE) > 0) {
75  	  System.err.println("Warning: Changing class " + 
76  			     clazz.getClassName() +
77  			     " to public.");
78  	  accFlags = (accFlags & (~org.apache.bcel.Constants.ACC_PRIVATE)) 
79  	      | org.apache.bcel.Constants.ACC_PUBLIC;
80  	  clazz.setAccessFlags( accFlags );
81        }
82  	
83        if ((accFlags & org.apache.bcel.Constants.ACC_PROTECTED) > 0) {
84  	  System.err.println("Warning: Changing class " + 
85  			     clazz.getClassName() +
86  			     " to public.");
87  	  accFlags = (accFlags & (~org.apache.bcel.Constants.ACC_PROTECTED)) 
88  	      | org.apache.bcel.Constants.ACC_PUBLIC;
89  	  clazz.setAccessFlags( accFlags );
90        }
91  	
92        if ((accFlags & org.apache.bcel.Constants.ACC_PUBLIC) == 0) {
93  	  System.err.println("Warning: Changing class " + 
94  			     clazz.getClassName() +
95  			     " to public.");
96  	  accFlags = accFlags | org.apache.bcel.Constants.ACC_PUBLIC;
97  	  clazz.setAccessFlags( accFlags );
98        }
99  	
100       if (!clazz.isPublic()) {
101 	  System.err.println("Warning: " + clazz.getClassName() + 
102 			     " is not public.");
103       }
104 
105       /*
106 	 * Allow the subclass to modify the pool if they want.
107 	 */
108       instrumentPool( context );
109 
110       Method [] methods = clazz.getMethods();
111 
112       for (int i = 0; i < methods.length; i++) {
113 	  if (isMethodOK( methods[i] )) {
114 	      MethodGen method = new MethodGen( methods[i],
115 						clazz.getClassName(),
116 						pool );
117 	      try {
118 		  ControlFlowGraph cfg = 
119 		      new ControlFlowGraph( context, method );
120 		  cfg.initialize( getEdgeFactory() );
121 		  instrumentMethod( context, cfg );
122 		  clazz.replaceMethod( methods[i],
123 				       cfg.getMethod() );
124 	      } catch (QuiltException e) {
125 		  System.err.println("Warning: Unable to instrument method " +
126 				     method.getName() + " / " + e.toString() );
127 	      }
128 	  }
129       }
130 
131       clazz.setConstantPool( pool );
132       JavaClass RC = clazz.getJavaClass();
133 
134       if (!RC.isPublic())
135 	  System.err.println("Warning:  Class isn't public.");
136       return RC;
137     }
138 
139     /***
140      * Override this abstract method to instrument a method.
141      */
142     public abstract void instrumentMethod( InstContext context,
143 					   ControlFlowGraph graph )
144 	throws QuiltException;
145 
146     /***
147      * Call this to add a Vertex in place of an edge.
148      */
149     public void instrumentEdge( InstContext context,
150 				ControlFlowGraph graph,
151 				FlowControlEdge edge,
152 				BlockVertex vertex ) {
153 	    
154 	if (edge.getTarget() != null) {
155 	    
156 	    //
157 	    // *-------*
158 	    //
159 	    graph.addVertex( vertex );
160 	    
161 	    //
162 	    //     *
163 	    //
164 	    // *-------*
165 	    //
166 	    
167 	    FlowControlEdge outEdge = 
168 		getEdgeFactory().makeNormalEdge( vertex, edge.getTarget() );
169 	    graph.addEdge( outEdge );
170 	    
171 	    //
172 	    //     *---+
173 	    //         |
174 	    // *-------*
175 	    //
176 	    
177 	    edge.setTarget( vertex );
178 	    graph.updateEdge( edge );
179 	    
180 	    //
181 	    // +---*---+
182 	    // |       |
183 	    // *       *
184 	    //
185 	}
186     }
187 
188     /***
189      * instrumentPool
190      *
191      * Gives the subclass a chance to add things into the Constant Pool.
192      * If you need to pass information from here to the instrumentMethod
193      * make sure you drop it in the context.
194      */
195     public void instrumentPool( InstContext context )
196     {}
197 
198     /***
199      * getEdgeFactory() 
200      *
201      * Override this method to provide your own edges. . .
202      */
203     public EdgeFactory getEdgeFactory() {
204 	return edgeFactory;
205     }
206 
207     private boolean isMethodOK( Method method ) {
208 	// Don't instrument the Class Initializer.  Its bad luck.
209 	if (method.getName().equals("<clinit>")) return false;
210 
211 	// Don't instrument any abstract methods.
212 	if (method.getCode() == null) return false;
213 
214 	return true;
215     }
216 
217 
218 }
219 
220 
221 
222 
223 
This page was automatically generated by Maven