KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)DefaultMethodCode.java
3  *
4  * Copyright (C) 2002,2003 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 net.sourceforge.groboutils.codecoverage.v2.IAnalysisMetaData;
30 import net.sourceforge.groboutils.codecoverage.v2.IAnalysisModule;
31 import net.sourceforge.groboutils.codecoverage.v2.IMethodCode;
32 import net.sourceforge.groboutils.codecoverage.v2.datastore.ClassRecord;
33 import net.sourceforge.groboutils.codecoverage.v2.datastore.MarkRecord;
34
35 import org.apache.bcel.classfile.LineNumberTable;
36 import org.apache.bcel.classfile.Method;
37 import org.apache.bcel.generic.Instruction;
38
39
40 /**
41  * Implements the per-module interface to the method's code and marking
42  * the code. Controls the module's index and the current module's mark
43  * index for this method.
44  *
45  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
46  * @author Stefano Turri (stefano.turri AT it.ibm.com)
47  * @version $Date: 2004/04/20 23:12:06 $
48  * @since December 17, 2002
49  */

50 public class DefaultMethodCode implements IMethodCode
51 {
52     private static final org.apache.log4j.Logger LOG =
53         org.apache.log4j.Logger.getLogger( DefaultMethodCode.class );
54     
55     private final ModifiedMethod method;
56     private final ModifiedInstructionList list;
57     private final String JavaDoc className;
58     private final String JavaDoc methodName;
59     private final IAnalysisModule analysisModule;
60     private final short measureIndex;
61     private final ClassRecord cr;
62     private short markCount = 0;
63     
64     
65     DefaultMethodCode( short measureIndex, ModifiedMethod mm, ClassRecord cr )
66     {
67         if (mm == null || cr == null)
68         {
69             throw new IllegalArgumentException JavaDoc("no null args");
70         }
71         
72         this.method = mm;
73         this.list = mm.getInstructionList();
74         if (this.list == null)
75         {
76             throw new IllegalStateException JavaDoc("abstract method "+mm);
77         }
78         this.className = mm.getOriginalClass().getClassName();
79         this.methodName = mm.getMethodName();
80         this.measureIndex = measureIndex;
81         this.cr = cr;
82         this.analysisModule = this.cr.getAnalysisModuleSet().
83             getAnalysisModuleAt( measureIndex );
84         
85         // ensure the class record is kosher
86
if (!this.className.equals( cr.getClassName() ))
87         {
88             throw new IllegalArgumentException JavaDoc(
89                 "modified method class ("+this.className+
90                 ") and class record class name ("+cr.getClassName()+
91                 ") do not match: " );
92         }
93         if (cr.getMethodIndex( this.methodName ) < 0)
94         {
95             throw new IllegalArgumentException JavaDoc(
96                 "method name ("+this.methodName+
97                 ") and class record do not match" );
98         }
99     }
100     
101     
102     /**
103      * Returns the original BCEL Method object.
104      *
105      * @return the original BCEL Method object
106      */

107     public Method getOriginalMethod()
108     {
109         return this.method.getOriginalMethod();
110     }
111     
112     
113     /**
114      * Returns the line number table for the original BCEL method object.
115      *
116      * @return the LineNumberTable, or <tt>null</tt> if there isn't one
117      * for this method.
118      */

119     public LineNumberTable getLineNumberTable()
120     {
121         return getOriginalMethod().getLineNumberTable();
122     }
123     
124     
125     /**
126      * A helper to get the method name.
127      *
128      * @return the method name
129      */

130     public String JavaDoc getMethodName()
131     {
132         return this.methodName;
133     }
134     
135     
136     /**
137      * A helper to get the class name.
138      *
139      * @return the class name
140      */

141     public String JavaDoc getClassName()
142     {
143         return this.className;
144     }
145     
146     
147     /**
148      * Returns the number of bytecode instructions in the method.
149      *
150      * @return the number of bytecode instructions
151      */

152     public int getInstructionCount()
153     {
154         return this.list.getInstructionCount();
155     }
156     
157     
158     /**
159      * Returns the bytecode instruction at the given index. If the index
160      * is out of range (&lt; 0 or &gt;= <tt>getInstructionCount()</tt>),
161      * then a <tt>IndexOutOfBoundsException</tt> is thrown.
162      *
163      * @param index the 0-based index of the method's instruction list
164      * @return the instruction at <tt>index</tt>
165      */

166     public Instruction getInstructionAt( int index )
167     {
168         // even though the list allows us to get the "last" instruction,
169
// don't allow the user to do this.
170
if (index == getInstructionCount())
171         {
172             throw new IndexOutOfBoundsException JavaDoc(
173                 "Even though you can put a mark at one more than the last "+
174                 "instruction, you cannot retrieve any such instruction." );
175         }
176         
177         MarkedInstruction mi = this.list.getInstructionAt( index );
178         return mi.getInstruction();
179     }
180     
181     
182     /**
183      * Marks an instruction for coverage analysis. If the index
184      * is out of range (&lt; 0 or &gt; <tt>getInstructionCount()</tt>),
185      * then a <tt>IndexOutOfBoundsException</tt> is thrown. Marks are
186      * added before the instruction at the given index is executed. Note that
187      * to mark the end of the method, you should use index equal to
188      * <tt>getInstructionCount()</tt>
189      *
190      * @param index the 0-based index of the method's instruction list
191      * @param meta meta-data the analysis module records in association with
192      * the mark. This cannot be <tt>null</tt>.
193      */

194     public synchronized void markInstruction( int index,
195             IAnalysisMetaData meta )
196     {
197         if (meta == null)
198         {
199             throw new IllegalArgumentException JavaDoc("no null args");
200         }
201         short count = this.markCount;
202         ++this.markCount;
203         
204         LOG.debug( "Mark "+this+" at instruction "+index+"." );
205         
206         // first, mark the instruction
207
MarkedInstruction mi = this.list.getInstructionAt( index );
208         mi.addMark( this.measureIndex, count );
209         
210         
211         MarkRecord mr = new MarkRecord( meta,
212             this.analysisModule.getMeasureName(), getMethodName(), count,
213             getSourceLine( mi ) );
214         cr.addMark( mr );
215     }
216     
217     
218     /**
219      * Output a friendly version of the object.
220      */

221     public String JavaDoc toString()
222     {
223         return getClassName() + "#" + getMethodName();
224     }
225     
226     
227     private int getSourceLine( MarkedInstruction mi )
228     {
229         int ret = -1;
230         LineNumberTable lnt = getLineNumberTable();
231         if (lnt != null)
232         {
233             // see bug 938439
234
// Fix by Stefano Turri
235
try
236             {
237                 ret = lnt.getSourceLine( mi.getInstructionPosition() );
238             }
239             catch (ArrayIndexOutOfBoundsException JavaDoc e)
240             {
241                 ret = -1;
242             }
243         }
244         return ret;
245     }
246 }
247
248
Popular Tags