KickJava   Java API By Example, From Geeks To Geeks.

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


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.lang.reflect.Modifier JavaDoc;
22
23 import org.apache.log4j.Category;
24
25 import alt.jiapi.Runtime;
26 import alt.jiapi.reflect.InstructionFactory;
27 import alt.jiapi.reflect.InstructionList;
28 import alt.jiapi.reflect.JiapiClass;
29 import alt.jiapi.reflect.JiapiMethod;
30 import alt.jiapi.reflect.Signature;
31 import alt.jiapi.reflect.MethodExistsException;
32
33 /**
34  * An Instrumentor which creates a new method for a class.
35  *
36  * @author Mika Riekkinen
37  * @author Joni Suominen
38  * @version $Revision: 1.12 $ $Date: 2004/03/15 14:47:53 $
39  */

40 public class CreateMethodInstrumentor extends AbstractInstrumentor {
41     private static Category log = Runtime.getLogCategory(CreateMethodInstrumentor.class);
42
43     public static int FORWARD_ORIGINAL = 1;
44     public static int FORWARD_NEW = 2;
45     public static int FORWARD_BOTH = 3;
46     private static int DEFAULT = FORWARD_NEW;
47
48     private int modifiers;
49     private String JavaDoc returnType;
50     private String JavaDoc methodName;
51     private String JavaDoc[] parameterNames;
52
53     private int forwardMode = DEFAULT;
54     private boolean createReturn = true;
55
56     /**
57      * A constructor which can be used to create a method with
58      * empty argument list and void return value.
59      *
60      * @param modifiers modifier flags
61      * @param methodName name of a method
62      */

63     public CreateMethodInstrumentor(int modifiers, String JavaDoc methodName) {
64         this(modifiers, "void", methodName, new String JavaDoc[0]);
65     }
66
67     /**
68      * A constructor which can be used to create a method with
69      * empty argument list and void return value.
70      *
71      * @param modifiers modifier flags
72      * @param methodName name of a method
73      */

74     public CreateMethodInstrumentor(int modifiers, String JavaDoc returnType,
75                                     String JavaDoc methodName) {
76         this(modifiers, returnType, methodName, new String JavaDoc[0]);
77     }
78
79     /**
80      * A constructor which can be used to create a method with
81      * with a given signature.
82      *
83      * @param modifiers modifier flags
84      * @param methodName name of a method
85      * @param parameterNames signature of a method
86      */

87     public CreateMethodInstrumentor(int modifiers, String JavaDoc methodName,
88                                     String JavaDoc[] parameterNames) {
89         this(modifiers, "void", methodName, parameterNames);
90     }
91
92     /**
93      * A constructor which can be used to create a method using
94      * a given method as a template.
95      *
96      * @param method a method to be used as a template
97      */

98     public CreateMethodInstrumentor(JiapiMethod method) {
99         this(method.getModifiers(), method.getReturnType(), method.getName(),
100              method.getParameterTypeNames());
101     }
102     
103     /**
104      * A constructor which can be used to create a method with
105      * with a given signature.
106      *
107      * @param modifiers modifier flags
108      * @param returnType modifier flags
109      * @param methodName name of a method
110      * @param parameterNames signature of a method
111      */

112     public CreateMethodInstrumentor(int modifiers, String JavaDoc returnType,
113                                     String JavaDoc methodName,
114                                     String JavaDoc[] parameterNames) {
115         this.methodName = methodName;
116         this.modifiers = modifiers;
117         this.parameterNames = parameterNames;
118         this.returnType = returnType;
119     }
120
121     /**
122      * Sets the forward mode for the instrumentor. Forward mode
123      * specifies which InstructionList is sent forward in the chain.
124      * Possible options are:
125      * <li>
126      * <ul>FORWARD_ORIGINAL</ul>
127      * Forwards the original InstructionList, i.e the InstructionList
128      * which was given in instrument-method.
129      * <ul>FORWARD_NEW</ul>
130      * Forwards the just created method's InstructionList.
131      * <ul>FORWARD_BOTH</ul>
132      * Forwards the both InstructionLists
133      * </li>
134      */

135     public void setForwardMode(int forwardMode) {
136         this.forwardMode = forwardMode;
137     }
138
139     /**
140      * Set whether a default body should be created for a method.
141      * If true, an instructions which will return either null, 0, false
142      * or 0.0 will be created. Depending on method's return type.
143      * If set to false, the method body will be left empty.
144      *
145      * @param b set to true if default method body should be created
146      */

147     public void setCreateReturn(boolean b) {
148         createReturn = b;
149     }
150
151     /**
152      * Instrument a JiapiClass.
153      *
154      * @param clazz A Class to be instrumented
155      */

156     public void instrument(InstructionList il) {
157         JiapiClass clazz = getCurrentClass();
158
159         // If the class is interface, then the modifiers must be public.
160
// Interface can have only public methods.
161
if (Modifier.isInterface(clazz.getModifiers())) {
162             if (!Modifier.isPublic(modifiers)) {
163                 log.info("Cannot create non public method " +
164                           methodName + " to interface " + clazz.getName());
165
166                 // NOTE! Throw an exception if mode is FORWARD_NEW (or BOTH)
167
forward(il);
168                 return;
169             }
170         }
171
172         log.info("Creating method " + clazz.getName() + "." + methodName);
173
174         JiapiMethod method = null;
175         try {
176             Signature signature = new Signature(returnType, parameterNames);
177             method = clazz.addMethod((short)modifiers, methodName, signature);
178         }
179         catch (MethodExistsException mee) {
180             log.info("method " + clazz.getName() + "." + methodName +
181                      " already exists");
182
183             method = mee.getMethod();
184         }
185
186         if (forwardMode == FORWARD_ORIGINAL) {
187             forward(il);
188         }
189         else if (forwardMode == FORWARD_NEW) {
190             forward(method.getInstructionList());
191         }
192         else {
193             // Forward both
194
forward(il);
195             forward(method.getInstructionList());
196         }
197
198         if (createReturn) {
199             InstructionFactory factory = method.getInstructionFactory();
200             method.getInstructionList().add(factory.returnMethod(method));
201         }
202     }
203 }
204
205
Popular Tags