KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > codecoverage > v2 > compiler > ModifiedMethod


1 /*
2  * @(#)ModifiedMethod.java
3  *
4  * Copyright (C) 2002-2004 Matt Albrecht
5  * groboclown@users.sourceforge.net
6  * http://groboutils.sourceforge.net
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */

26
27 package net.sourceforge.groboutils.codecoverage.v2.compiler;
28
29 import org.apache.bcel.classfile.JavaClass;
30 import org.apache.bcel.classfile.Method;
31 import org.apache.bcel.generic.InstructionList;
32 import org.apache.bcel.generic.MethodGen;
33
34 /**
35  * Refers to a class file that has been modified with additional logging
36  * statements.
37  *
38  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
39  * @version $Date: 2004/04/15 05:48:25 $
40  * @since December 17, 2002
41  */

42 public class ModifiedMethod
43 {
44     private static final org.apache.log4j.Logger LOG =
45         org.apache.log4j.Logger.getLogger( ModifiedMethod.class );
46     private JavaClass origClass;
47     private Method origMethod;
48     private MethodGen modMethGen;
49     private Method modMeth;
50     private boolean closed = false;
51     private ModifiedInstructionList modInstructions;
52     
53     /**
54      * constant pool index for the name of the class's signature.
55      */

56     private int classSigPoolIndex;
57     
58     /**
59      * constant pool index for the method-ref for invoking the logger.
60      */

61     private int staticMethodPoolIndex;
62     
63     /**
64      * the original class file's checksum.
65      */

66     private long checksum;
67     
68     /**
69      * Reference to this method's index
70      */

71     private final short methodIndex;
72     
73     /**
74      * @throws IllegalStateException if the class file has already been
75      * modified (identified by a class name field).
76      */

77     ModifiedMethod( short methodIndex, int classSigPoolIndex,
78             int staticMethodPoolIndex, JavaClass origC, Method origM,
79             MethodGen mg )
80     {
81         if (mg == null || origC == null || origM == null)
82         {
83             throw new IllegalArgumentException JavaDoc("no null args");
84         }
85         this.methodIndex = methodIndex;
86         this.classSigPoolIndex = classSigPoolIndex;
87         this.staticMethodPoolIndex = staticMethodPoolIndex;
88         
89         this.modMethGen = mg;
90         this.origClass = origC;
91         this.origMethod = origM;
92     }
93     
94     
95     public short getMethodIndex()
96     {
97         return this.methodIndex;
98     }
99     
100     
101     public String JavaDoc getMethodName()
102     {
103         return this.origMethod.getName() + this.origMethod.getSignature();
104     }
105     
106     
107     /**
108      * If the method cannot be modified, then this will return <tt>null</tt>.
109      */

110     public ModifiedInstructionList getInstructionList()
111     {
112         checkClose();
113         if (this.modInstructions == null && canAddMarks())
114         {
115             createInstructionList();
116             
117             // the above call can create a null list if the generated list
118
// is bad.
119
}
120         return this.modInstructions;
121     }
122     
123     
124     public JavaClass getOriginalClass()
125     {
126         return this.origClass;
127     }
128     
129     
130     public Method getOriginalMethod()
131     {
132         return this.origMethod;
133     }
134     
135     
136     /**
137      * Returns <tt>true</tt> if the method can be modified, otherwise returns
138      * <tt>false</tt>. A method can be modified only if it is not native,
139      * not abstract, and it has a code attribute.
140      */

141     public boolean canAddMarks()
142     {
143         return ModifiedClass.isMarkable( this.origMethod );
144     }
145     
146     
147     //------------------------------------------------------------------------
148

149     
150     /**
151      * The modified method generator is only valid <i>before</i> a close.
152      */

153     MethodGen getModifiedMethodGen()
154     {
155         checkClose();
156         return this.modMethGen;
157     }
158     
159     
160     /**
161      * This should only be called *after* a close.
162      */

163     Method getNewMethod()
164     {
165         if (!this.closed || this.modMeth == null)
166         {
167             throw new IllegalStateException JavaDoc(
168                 "ModifiedMethod has not been closed." );
169         }
170         return this.modMeth;
171     }
172     
173     
174     void close()
175     {
176         checkClose();
177         
178         this.closed = true;
179         if (this.modInstructions != null)
180         {
181             LOG.debug( "Setting the modified instruction list." );
182             this.modInstructions.updateInstructionList();
183             this.modMethGen.setMaxLocals();
184             this.modMethGen.setMaxStack();
185             this.modMeth = this.modMethGen.getMethod();
186             this.modInstructions.close();
187             this.modInstructions = null;
188             
189             /*
190             InstructionList finalList = this.modMethGen.getInstructionList();
191             LOG.debug( "Final modified method: ["+this.modMethGen+
192                 "], instructions (size="+finalList.getLength()+") ["+finalList+
193                 "]." );
194             */

195             this.modMethGen = null;
196         }
197         else
198         if (this.modMeth == null)
199         {
200             this.modMeth = this.modMethGen.getMethod();
201             
202             /*
203             InstructionList finalList = this.modMethGen.getInstructionList();
204             LOG.debug( "Final modified method: ["+this.modMethGen+
205                 "], instructions (size="+finalList.getLength()+") ["+finalList+
206                 "]." );
207             */

208             this.modMethGen = null;
209         }
210     }
211     
212     
213     //------------------------------------------------------------------------
214

215     
216     /*
217      * The class cannot be closed when this is called, or else an NPE will
218      * be thrown.
219      */

220     private void createInstructionList()
221     {
222         InstructionList list = getModifiedMethodGen().getInstructionList();
223         if (ModifiedInstructionList.isValidInstructionList( list ))
224         {
225             this.modInstructions = new ModifiedInstructionList(
226                 this.methodIndex, this.classSigPoolIndex,
227                 this.staticMethodPoolIndex, list,
228                 new ModifiedTargeters( this.modMethGen ) );
229         }
230         else
231         {
232             LOG.warn( "Instruction list for method ["+getMethodName()+
233                 "] in class ["+getOriginalClass().getClassName()+
234                 "] is invalid." );
235         }
236         // else the list is invalid.
237
}
238     
239     
240     private void checkClose()
241     {
242         if (this.closed)
243         {
244             throw new IllegalStateException JavaDoc("Method has been closed.");
245         }
246     }
247 }
248
249
Popular Tags