KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > CtMethod


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist;
17
18 import javassist.bytecode.*;
19
20 /**
21  * An instance of <code>CtMethod</code> represents a method.
22  *
23  * <p>See the super class <code>CtBehavior</code> since
24  * a number of useful methods are in <code>CtBehavior</code>.
25  *
26  * @see CtClass#getDeclaredMethods()
27  * @see CtNewMethod
28  */

29 public final class CtMethod extends CtBehavior {
30     protected String JavaDoc cachedStringRep;
31
32     CtMethod(MethodInfo minfo, CtClass declaring) {
33         super(declaring, minfo);
34         next = null;
35         cachedStringRep = null;
36     }
37
38     /**
39      * Creates a public abstract method. The created method must be
40      * added to a class with <code>CtClass.addMethod()</code>.
41      *
42      * @param declaring the class to which the created method is added.
43      * @param returnType the type of the returned value
44      * @param mname the method name
45      * @param parameters a list of the parameter types
46      *
47      * @see CtClass#addMethod(CtMethod)
48      */

49     public CtMethod(CtClass returnType, String JavaDoc mname,
50                     CtClass[] parameters, CtClass declaring) {
51         this(null, declaring);
52         ConstPool cp = declaring.getClassFile2().getConstPool();
53         String JavaDoc desc = Descriptor.ofMethod(returnType, parameters);
54         methodInfo = new MethodInfo(cp, mname, desc);
55         setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT);
56     }
57
58     /**
59      * Creates a copy of a <code>CtMethod</code> object.
60      * The created method must be
61      * added to a class with <code>CtClass.addMethod()</code>.
62      *
63      * <p>All occurrences of class names in the created method
64      * are replaced with names specified by
65      * <code>map</code> if <code>map</code> is not <code>null</code>.
66      *
67      * <p>For example, suppose that a method <code>at()</code> is as
68      * follows:
69      *
70      * <ul><pre>public X at(int i) {
71      * return (X)super.elementAt(i);
72      * }</pre></ul>
73      *
74      * <p>(<code>X</code> is a class name.) If <code>map</code> substitutes
75      * <code>String</code> for <code>X</code>, then the created method is:
76      *
77      * <ul><pre>public String at(int i) {
78      * return (String)super.elementAt(i);
79      * }</pre></ul>
80      *
81      * <p>By default, all the occurrences of the names of the class
82      * declaring <code>at()</code> and the superclass are replaced
83      * with the name of the class and the superclass that the
84      * created method is added to.
85      * This is done whichever <code>map</code> is null or not.
86      * To prevent this replacement, call <code>ClassMap.fix()</code>.
87      *
88      * <p><b>Note:</b> if the <code>.class</code> notation (for example,
89      * <code>String.class</code>) is included in an expression, the
90      * Javac compiler may produce a helper method.
91      * Since this constructor never
92      * copies this helper method, the programmers have the responsiblity of
93      * copying it. Otherwise, use <code>Class.forName()</code> in the
94      * expression.
95      *
96      * @param src the source method.
97      * @param declaring the class to which the created method is added.
98      * @param map the hashtable associating original class names
99      * with substituted names.
100      * It can be <code>null</code>.
101      *
102      * @see CtClass#addMethod(CtMethod)
103      * @see ClassMap#fix(String)
104      */

105     public CtMethod(CtMethod src, CtClass declaring, ClassMap map)
106         throws CannotCompileException
107     {
108         this(null, declaring);
109         MethodInfo srcInfo = src.methodInfo;
110         CtClass srcClass = src.getDeclaringClass();
111         ConstPool cp = declaring.getClassFile2().getConstPool();
112         if (map == null)
113             map = new ClassMap();
114
115         map.put(srcClass.getName(), declaring.getName());
116         try {
117             CtClass srcSuper = srcClass.getSuperclass();
118             if (srcSuper != null) {
119                 String JavaDoc srcSuperName = srcSuper.getName();
120                 if (!srcSuperName.equals(CtClass.javaLangObject))
121                     map.put(srcSuperName,
122                             declaring.getSuperclass().getName());
123             }
124
125             methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
126         }
127         catch (NotFoundException e) {
128             throw new CannotCompileException(e);
129         }
130         catch (BadBytecode e) {
131             throw new CannotCompileException(e);
132         }
133     }
134
135     /**
136      * Returns a hash code value for the method.
137      * If two methods have the same name and signature, then
138      * the hash codes for the two methods are equal.
139      */

140     public int hashCode() {
141         return getStringRep().hashCode();
142     }
143
144     /* This method is also called by CtClassType.getMethods0().
145      */

146     final String JavaDoc getStringRep() {
147         if (cachedStringRep == null)
148             cachedStringRep = methodInfo.getName()
149                 + Descriptor.getParamDescriptor(methodInfo.getDescriptor());
150
151         return cachedStringRep;
152     }
153
154     /**
155      * Indicates whether <code>obj</code> has the same name and the
156      * same signature as this method.
157      */

158     public boolean equals(Object JavaDoc obj) {
159         return obj != null && obj instanceof CtMethod
160                && ((CtMethod)obj).getStringRep().equals(getStringRep());
161     }
162
163     /**
164      * Obtains the name of this method.
165      */

166     public String JavaDoc getName() {
167         return methodInfo.getName();
168     }
169
170     /**
171      * Changes the name of this method.
172      */

173     public void setName(String JavaDoc newname) {
174         declaringClass.checkModify();
175         methodInfo.setName(newname);
176     }
177
178     /**
179      * Obtains the type of the returned value.
180      */

181     public CtClass getReturnType() throws NotFoundException {
182         return getReturnType0();
183     }
184
185     /**
186      * Returns true if the method body is empty, that is, <code>{}</code>.
187      * It also returns true if the method is an abstract method.
188      */

189     public boolean isEmpty() {
190         CodeAttribute ca = getMethodInfo2().getCodeAttribute();
191         if (ca == null) // abstract or native
192
return (getModifiers() & Modifier.ABSTRACT) != 0;
193
194         CodeIterator it = ca.iterator();
195         try {
196             return it.hasNext() && it.byteAt(it.next()) == Opcode.RETURN
197                 && !it.hasNext();
198         }
199         catch (BadBytecode e) {}
200         return false;
201     }
202
203     /**
204      * Copies a method body from another method.
205      * If this method is abstract, the abstract modifier is removed
206      * after the method body is copied.
207      *
208      * <p>All occurrences of the class names in the copied method body
209      * are replaced with the names specified by
210      * <code>map</code> if <code>map</code> is not <code>null</code>.
211      *
212      * @param src the method that the body is copied from.
213      * @param map the hashtable associating original class names
214      * with substituted names.
215      * It can be <code>null</code>.
216      */

217     public void setBody(CtMethod src, ClassMap map)
218         throws CannotCompileException
219     {
220         setBody0(src.declaringClass, src.methodInfo,
221                  declaringClass, methodInfo, map);
222     }
223
224     /**
225      * Replace a method body with a new method body wrapping the
226      * given method.
227      *
228      * @param mbody the wrapped method
229      * @param constParam the constant parameter given to
230      * the wrapped method
231      * (maybe <code>null</code>).
232      *
233      * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
234      */

235     public void setWrappedBody(CtMethod mbody, ConstParameter constParam)
236         throws CannotCompileException
237     {
238         declaringClass.checkModify();
239
240         CtClass clazz = getDeclaringClass();
241         CtClass[] params;
242         CtClass retType;
243         try {
244             params = getParameterTypes();
245             retType = getReturnType();
246         }
247         catch (NotFoundException e) {
248             throw new CannotCompileException(e);
249         }
250
251         Bytecode code = CtNewWrappedMethod.makeBody(clazz,
252                                                     clazz.getClassFile2(),
253                                                     mbody,
254                                                     params, retType,
255                                                     constParam);
256         CodeAttribute cattr = code.toCodeAttribute();
257         methodInfo.setCodeAttribute(cattr);
258         methodInfo.setAccessFlags(methodInfo.getAccessFlags()
259                                   & ~AccessFlag.ABSTRACT);
260     }
261
262     // inner classes
263

264     /**
265      * Instances of this class represent a constant parameter.
266      * They are used to specify the parameter given to the methods
267      * created by <code>CtNewMethod.wrapped()</code>.
268      *
269      * @see CtMethod#setWrappedBody(CtMethod,CtMethod.ConstParameter)
270      * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
271      * @see CtNewConstructor#make(CtClass[],CtClass[],int,CtMethod,CtMethod.ConstParameter,CtClass)
272      */

273     public static class ConstParameter {
274         /**
275          * Makes an integer constant.
276          *
277          * @param i the constant value.
278          */

279         public static ConstParameter integer(int i) {
280             return new IntConstParameter(i);
281         }
282
283         /**
284          * Makes a long integer constant.
285          *
286          * @param i the constant value.
287          */

288         public static ConstParameter integer(long i) {
289             return new LongConstParameter(i);
290         }
291
292         /**
293          * Makes an <code>String</code> constant.
294          *
295          * @param s the constant value.
296          */

297         public static ConstParameter string(String JavaDoc s) {
298             return new StringConstParameter(s);
299         }
300
301         ConstParameter() {}
302
303         /**
304          * @return the size of the stack consumption.
305          */

306         int compile(Bytecode code) throws CannotCompileException {
307             return 0;
308         }
309
310         String JavaDoc descriptor() {
311             return defaultDescriptor();
312         }
313
314         /**
315          * @see CtNewWrappedMethod
316          */

317         static String JavaDoc defaultDescriptor() {
318             return "([Ljava/lang/Object;)Ljava/lang/Object;";
319         }
320
321         /**
322          * Returns the descriptor for constructors.
323          *
324          * @see CtNewWrappedConstructor
325          */

326         String JavaDoc constDescriptor() {
327             return defaultConstDescriptor();
328         }
329
330         /**
331          * Returns the default descriptor for constructors.
332          */

333         static String JavaDoc defaultConstDescriptor() {
334             return "([Ljava/lang/Object;)V";
335         }
336     }
337
338     static class IntConstParameter extends ConstParameter {
339         int param;
340
341         IntConstParameter(int i) {
342             param = i;
343         }
344
345         int compile(Bytecode code) throws CannotCompileException {
346             code.addIconst(param);
347             return 1;
348         }
349
350         String JavaDoc descriptor() {
351             return "([Ljava/lang/Object;I)Ljava/lang/Object;";
352         }
353
354         String JavaDoc constDescriptor() {
355             return "([Ljava/lang/Object;I)V";
356         }
357     }
358
359     static class LongConstParameter extends ConstParameter {
360         long param;
361
362         LongConstParameter(long l) {
363             param = l;
364         }
365
366         int compile(Bytecode code) throws CannotCompileException {
367             code.addLconst(param);
368             return 2;
369         }
370
371         String JavaDoc descriptor() {
372             return "([Ljava/lang/Object;J)Ljava/lang/Object;";
373         }
374
375         String JavaDoc constDescriptor() {
376             return "([Ljava/lang/Object;J)V";
377         }
378     }
379
380     static class StringConstParameter extends ConstParameter {
381         String JavaDoc param;
382
383         StringConstParameter(String JavaDoc s) {
384             param = s;
385         }
386
387         int compile(Bytecode code) throws CannotCompileException {
388             code.addLdc(param);
389             return 1;
390         }
391
392         String JavaDoc descriptor() {
393             return "([Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;";
394         }
395
396         String JavaDoc constDescriptor() {
397             return "([Ljava/lang/Object;Ljava/lang/String;)V";
398         }
399     }
400 }
401
Popular Tags