KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > alt > jiapi > instrumentor > AbstractInstrumentor


1 /*
2  * Copyright (C) 2001 Mika Riekkinen, Joni Suominen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package alt.jiapi.instrumentor;
20
21 import java.util.HashMap JavaDoc;
22
23 import org.apache.log4j.Category;
24
25 import alt.jiapi.reflect.InstructionList;
26 import alt.jiapi.reflect.JiapiClass;
27 import alt.jiapi.reflect.JiapiMethod;
28
29 /**
30  * This abstract class is the base class for all the instrumentors
31  * used by jiapi code.
32  *
33  * @author Mika Riekkinen
34  * @author Joni Suominen
35  * @version $Revision: 1.1 $ $Date: 2004/03/15 14:45:06 $
36  */

37 public abstract class AbstractInstrumentor implements ChainInstrumentor {
38     private Instrumentation instrumentation;
39     private static Category log = alt.jiapi.Runtime.getLogCategory(AbstractInstrumentor.class);
40     private AbstractInstrumentor child;
41
42     /**
43      * Gets an InstrumentorChain, that needs to be processed before
44      * current Instrumentor. If an Instrumentor realizes, that in
45      * order for its instrumented code to work it needs some other
46      * instrumentation support, it may override this method to provide
47      * such extra needs.
48      *
49      * @return A chain, that is to be processed before current Instrumentor,
50      * or null if there is no need for such pre-processing.
51      * @see InstrumentorChain
52      */

53     public InstrumentorChain preInstrument() {
54         return null;
55     }
56
57     /**
58      * Gets an InstrumentorChain, that needs to be processed after
59      * current Instrumentor. Instrumentor may do post-instrumentation
60      * to clean up or finalize instrumented code. This method is often
61      * called in conjunction with preInstrument().
62      *
63      * @return A chain, that is to be processed after current Instrumentor,
64      * or null if there is no need for such post-processing.
65      * @see InstrumentorChain
66      */

67     public InstrumentorChain postInstrument() {
68         return null;
69     }
70
71     /**
72      * Instruments given InstructionList. Instrumentor is free to modify
73      * InstructionList anyway it sees fit. As long as resulting InstructionList
74      * is consistent with all the Java Virtual Machine constraints.<p>
75      *
76      * Some Instrumentors do not modify given InstructionList, but
77      * selects a smaller part, splits it into peaces, and forwards them
78      * one by one to the next Instrumentor in chain.<p>
79      *
80      * Once this method returns, control is transferred back to previous
81      * Instrumentor in chain.
82      *
83      * @see #forward(InstructionList)
84      */

85     public abstract void instrument(InstructionList il);
86
87     /**
88      * This method has a package access. It is called by AbstractInstrumentor
89      * itself to forward a chain with given Instrumentation.
90      */

91     void instrument(InstructionList il, Instrumentation i) {
92         log.info("Instrumenting with " + this);
93         this.instrumentation = i;
94         if (i == null) {
95             log.error("Got null instrumentation");
96         }
97
98         instrument(il);
99     }
100
101
102     public String JavaDoc toString() {
103         return this.getClass().getName();
104     }
105
106     
107
108 // private HashMap preInstrumentations = new HashMap();
109
// private HashMap postInstrumentations = new HashMap();
110

111     /**
112      * Forwards given InstructionList to next Instrumentor in chain.
113      *
114      * @param il InstructionList to forward
115      */

116     protected void forward(InstructionList il) {
117         if (child != null) {
118             JiapiClass jc = getCurrentClass();
119             child.setCurrentClass(jc);
120
121             InstrumentorChain pre = child.preInstrument();
122             if (pre != null) {
123 // if (preInstrumentations.get(jc.getName()) == null) {
124
log.debug("Pre instrumenting with " + pre);
125                     //System.out.println(pre + ", " + il.getDeclaringMethod());
126
pre.instrument(jc);
127 // preInstrumentations.put(jc.getName(), jc);
128
// }
129
}
130             else {
131                 log.debug(child + " has no need for pre-instrumentation");
132             }
133
134             child.instrument(il, instrumentation);
135
136             InstrumentorChain post = child.postInstrument();
137             if (post != null) {
138 // if (postInstrumentations.get(jc.getName()) == null) {
139
log.debug("Post instrumenting with " + post);
140                     post.instrument(jc);
141 // postInstrumentations.put(jc.getName(), jc);
142
// }
143
}
144             else {
145                 log.debug(child + " has no need for post-instrumentation");
146             }
147         }
148     }
149
150
151     private JiapiClass currentClass;
152
153     /**
154      * Gets the current JiapiClass, that instrumentation applies to.
155      *
156      * @return current class
157      */

158     protected JiapiClass getCurrentClass() {
159         return currentClass;
160     }
161
162     /**
163      * Sets the current JiapiClass, that instrumentation applies to.
164      * This method is used internally by Jiapi framework.
165      * @param clazz A JiapiClass to set
166      */

167     void setCurrentClass(JiapiClass clazz) {
168         this.currentClass = clazz;
169     }
170
171     // package access, called by chain
172
// void setInstrumentation(Instrumentation i) {
173
// this.instrumentation = i;
174
// }
175

176
177     /**
178      * Gets an instance of Instrumentation related to this chain.
179      * This method should only be called from instrument(InstructionList)
180      * method.
181      * @return Instrumentation or null, if Instrumentation has not been
182      * triggered.
183      */

184     public Instrumentation getInstrumentation() {
185 // if(instrumentation == null) {
186
// instrumentation = new Instrumentation();
187
// }
188
if(instrumentation == null) {
189               log.warn("Instrumentation is null: " + this.getClass());
190           }
191
192         return instrumentation;
193     }
194
195
196
197     // package access for now. Purpose of these methods is to provide
198
// all the subsequent instrumentors in same descriptor some data
199
// this instrumentor is doing. Like 'just grepped 'test.Foo.foo()'
200
void setDescriptorData() {
201     }
202     Object JavaDoc/*SomeDataType*/ getDescriptorData() {
203         return null;
204     }
205
206
207     // package access for now. Purpose of these methods is to provide
208
// all the subsequent instrumentors within same context some data
209
// this instrumentor is doing. Like 'just grepped 'test.Foo.foo()'
210
void setContexData() {
211     }
212     Object JavaDoc/*SomeDataType*/ getContextData() {
213         return null;
214     }
215
216
217
218
219     // Package access - used to set/get parent-child relations
220
void setChild(AbstractInstrumentor i) {
221         this.child = i;
222     }
223
224     /**
225      * Gets the next Instrumentor in chain.
226      */

227     ChainInstrumentor getChild() {
228         return child;
229     }
230 }
231
232
Popular Tags