KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)ModifiedInstructionList.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 java.util.ArrayList JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32
33 import org.apache.bcel.generic.InstructionHandle;
34 import org.apache.bcel.generic.InstructionList;
35
36 /**
37  * Refers to a class file that has been modified with additional logging
38  * statements.
39  * <P>
40  * As of January 22, 2003, the appending of probes to the end of the
41  * instruction list is no longer supported; supporting it would mean that
42  * instructions will be added to a method after the final "return" calls,
43  * which might cause class file validation errors.
44  *
45  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
46  * @version $Date: 2004/04/15 05:48:25 $
47  * @since December 17, 2002
48  */

49 public class ModifiedInstructionList
50 {
51     private static final org.apache.log4j.Logger LOG =
52         org.apache.log4j.Logger.getLogger( ModifiedInstructionList.class );
53     private boolean closed = false;
54     private InstructionList modList; // this is the actual original list
55
private List JavaDoc marked;
56     
57     /**
58      * constant pool index for the name of the class's signature.
59      */

60     private int classSigPoolIndex;
61     
62     /**
63      * constant pool index for the method-ref for invoking the logger.
64      */

65     private int staticMethodPoolIndex;
66     
67     /**
68      * Reference to the owning method's index
69      */

70     private short methodIndex;
71     
72     /**
73      * Keep track of the original instructions vs. their replacement for
74      * target heads and tails.
75      */

76     private ModifiedTargeters targeters;
77     
78     /**
79      * @throws IllegalStateException if the class file has already been
80      * modified (identified by a class name field).
81      */

82     ModifiedInstructionList( short methodIndex, int classSigPoolIndex,
83             int staticMethodPoolIndex, InstructionList list,
84             ModifiedTargeters mt )
85     {
86         if (list == null || mt == null)
87         {
88             throw new IllegalArgumentException JavaDoc("no null args");
89         }
90         this.methodIndex = methodIndex;
91         this.classSigPoolIndex = classSigPoolIndex;
92         this.staticMethodPoolIndex = staticMethodPoolIndex;
93         
94         if (!isValidInstructionList( list ))
95         {
96             throw new IllegalArgumentException JavaDoc( "Instruction list contains "+
97                 "unsupported instruction setup." );
98         }
99         this.modList = list;
100         this.targeters = mt;
101         
102         // there is a bug in the list.copy() that causes some
103
// LOOKUPSWITCH instructions to become corrupted in the original!
104
setupMarkList();
105     }
106     
107     
108     //------------------------------------------------------------------------
109

110     
111     public static boolean isValidInstructionList( InstructionList list )
112     {
113         try
114         {
115             list.getByteCode();
116         }
117         catch (Exception JavaDoc ex)
118         {
119             return false;
120         }
121         return true;
122     }
123     
124     
125     
126     /**
127      * This method can safely be called multiple times.
128      *
129      * Bug: We need to keep track of the original handle, and the corresponding
130      * new handle that goes before it, so that we can go back and recreate the
131      * CodeException objects for the method.
132      */

133     void updateInstructionList()
134     {
135         checkClose();
136         
137         LOG.debug( "********************************" );
138         Iterator JavaDoc iter = this.marked.iterator();
139         while (iter.hasNext())
140         {
141             MarkedInstruction mi = (MarkedInstruction)iter.next();
142             
143             InstructionList list = mi.getMarkedList();
144             if (list != null && list.getLength() > 0)
145             {
146                 InstructionHandle instr = mi.getHandle();
147                 LOG.debug( "Adding list (length = "+list.getLength()+
148                     ", value='"+list+"') before handle '"+instr+"'." );
149                 InstructionHandle probe;
150                 if (mi.getInstruction() instanceof NullInstruction)
151                 {
152                     // the null instruction will not add itself, but will
153
// append its marks to the end of the method.
154
/*
155                     LOG.debug( "Appending probe to end of instructions." );
156                     probe = this.modList.append( list );
157                     this.targeters.appendProbe( probe );
158                     */

159                     LOG.warn(
160                         "Appending probes to end of instructions is no longer allowed" );
161                 }
162                 else
163                 {
164                     // normal instructions will insert their marks before
165
// the instruction is executed.
166
LOG.debug( "Inserting probe before ["+instr+"]" );
167                     probe = this.modList.insert( instr, list );
168                     this.targeters.insertProbe( instr, probe );
169                 }
170             }
171         }
172         this.targeters.update();
173         LOG.debug( "Final modified list = '"+this.modList+"'" );
174     }
175     
176     
177     public int getInstructionCount()
178     {
179         checkClose();
180         
181         // ignore the final NullInstruction
182
return this.marked.size() - 1;
183     }
184     
185     
186     public MarkedInstruction getInstructionAt( int index )
187     {
188         checkClose();
189         
190         return (MarkedInstruction)this.marked.get( index );
191     }
192     
193     
194     void close()
195     {
196         checkClose();
197         
198         this.closed = true;
199         this.modList.dispose();
200         this.marked = null;
201         this.modList = null;
202     }
203     
204     
205     //------------------------------------------------------------------------
206

207     
208     private void setupMarkList()
209     {
210         this.marked = new ArrayList JavaDoc();
211         //Iterator iter = this.instructions.iterator();
212
Iterator JavaDoc iter = this.modList.iterator();
213         while (iter.hasNext())
214         {
215             InstructionHandle ih = (InstructionHandle)iter.next();
216             this.marked.add( new MarkedInstruction( this.methodIndex,
217                 this.classSigPoolIndex, this.staticMethodPoolIndex, ih ) );
218         }
219         
220         // add in the final instruction to allow for marking the end
221
// of the method.
222
InstructionList il = new InstructionList();
223         InstructionHandle ih = il.append( new NullInstruction() );
224         this.marked.add( new MarkedInstruction( this.methodIndex,
225             this.classSigPoolIndex, this.staticMethodPoolIndex, ih ) );
226     }
227     
228     
229     private void checkClose()
230     {
231         if (this.closed)
232         {
233             throw new IllegalStateException JavaDoc("Method has been closed.");
234         }
235     }
236 }
237
238
Popular Tags