KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > expr > MethodCall


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.expr;
17
18 import javassist.*;
19 import javassist.bytecode.*;
20 import javassist.compiler.*;
21
22 /**
23  * Method invocation (caller-side expression).
24  */

25 public class MethodCall extends Expr {
26     /**
27      * Undocumented constructor. Do not use; internal-use only.
28      */

29     protected MethodCall(int pos, CodeIterator i, CtClass declaring,
30                          MethodInfo m) {
31         super(pos, i, declaring, m);
32     }
33
34     private int getNameAndType(ConstPool cp) {
35         String JavaDoc cname;
36         int pos = currentPos;
37         int c = iterator.byteAt(pos);
38         int index = iterator.u16bitAt(pos + 1);
39
40         if (c == INVOKEINTERFACE)
41             return cp.getInterfaceMethodrefNameAndType(index);
42         else
43             return cp.getMethodrefNameAndType(index);
44     }
45
46     /**
47      * Returns the method or constructor containing the method-call
48      * expression represented by this object.
49      */

50     public CtBehavior where() { return super.where(); }
51
52     /**
53      * Returns the line number of the source line containing the
54      * method call.
55      *
56      * @return -1 if this information is not available.
57      */

58     public int getLineNumber() {
59         return super.getLineNumber();
60     }
61
62     /**
63      * Returns the source file containing the method call.
64      *
65      * @return null if this information is not available.
66      */

67     public String JavaDoc getFileName() {
68         return super.getFileName();
69     }
70
71     /**
72      * Returns the class of the target object,
73      * which the method is called on.
74      */

75     private CtClass getCtClass() throws NotFoundException {
76         return thisClass.getClassPool().get(getClassName());
77     }
78
79     /**
80      * Returns the class name of the target object,
81      * which the method is called on.
82      */

83     public String JavaDoc getClassName() {
84         String JavaDoc cname;
85
86         ConstPool cp = getConstPool();
87         int pos = currentPos;
88         int c = iterator.byteAt(pos);
89         int index = iterator.u16bitAt(pos + 1);
90
91         if (c == INVOKEINTERFACE)
92             cname = cp.getInterfaceMethodrefClassName(index);
93         else
94             cname = cp.getMethodrefClassName(index);
95
96         return cname;
97     }
98
99     /**
100      * Returns the name of the called method.
101      */

102     public String JavaDoc getMethodName() {
103         ConstPool cp = getConstPool();
104         int nt = getNameAndType(cp);
105         return cp.getUtf8Info(cp.getNameAndTypeName(nt));
106     }
107
108     /**
109      * Returns the called method.
110      */

111     public CtMethod getMethod() throws NotFoundException {
112         return getCtClass().getMethod(getMethodName(), getMethodDesc());
113     }
114
115     private String JavaDoc getMethodDesc() {
116         ConstPool cp = getConstPool();
117         int nt = getNameAndType(cp);
118         return cp.getUtf8Info(cp.getNameAndTypeDescriptor(nt));
119     }
120
121     /**
122      * Returns the list of exceptions that the expression may throw.
123      * This list includes both the exceptions that the try-catch statements
124      * including the expression can catch and the exceptions that
125      * the throws declaration allows the method to throw.
126      */

127     public CtClass[] mayThrow() {
128         return super.mayThrow();
129     }
130
131     /**
132      * Returns true if the called method is of a superclass of the current
133      * class.
134      */

135     public boolean isSuper() {
136         return iterator.byteAt(currentPos) == INVOKESPECIAL
137             && !where().getDeclaringClass().getName().equals(getClassName());
138     }
139
140     /*
141      * Returns the parameter types of the called method.
142
143     public CtClass[] getParameterTypes() throws NotFoundException {
144         return Descriptor.getParameterTypes(getMethodDesc(),
145                                             thisClass.getClassPool());
146     }
147     */

148
149     /*
150      * Returns the return type of the called method.
151
152     public CtClass getReturnType() throws NotFoundException {
153         return Descriptor.getReturnType(getMethodDesc(),
154                                         thisClass.getClassPool());
155     }
156     */

157
158     /**
159      * Replaces the method call with the bytecode derived from
160      * the given source text.
161      *
162      * <p>$0 is available even if the called method is static.
163      *
164      * @param statement a Java statement.
165      */

166     public void replace(String JavaDoc statement) throws CannotCompileException {
167         ConstPool constPool = getConstPool();
168         int pos = currentPos;
169         int index = iterator.u16bitAt(pos + 1);
170
171         String JavaDoc classname, methodname, signature;
172         int opcodeSize;
173         int c = iterator.byteAt(pos);
174         if (c == INVOKEINTERFACE) {
175             opcodeSize = 5;
176             classname = constPool.getInterfaceMethodrefClassName(index);
177             methodname = constPool.getInterfaceMethodrefName(index);
178             signature = constPool.getInterfaceMethodrefType(index);
179         }
180         else if (c == INVOKESTATIC
181                  || c == INVOKESPECIAL || c == INVOKEVIRTUAL) {
182             opcodeSize = 3;
183             classname = constPool.getMethodrefClassName(index);
184             methodname = constPool.getMethodrefName(index);
185             signature = constPool.getMethodrefType(index);
186         }
187         else
188             throw new CannotCompileException("not method invocation");
189
190         Javac jc = new Javac(thisClass);
191         ClassPool cp = thisClass.getClassPool();
192         CodeAttribute ca = iterator.get();
193         try {
194             CtClass[] params = Descriptor.getParameterTypes(signature, cp);
195             CtClass retType = Descriptor.getReturnType(signature, cp);
196             int paramVar = ca.getMaxLocals();
197             jc.recordParams(classname, params,
198                             true, paramVar, withinStatic());
199             int retVar = jc.recordReturnType(retType, true);
200             if (c == INVOKESTATIC)
201                 jc.recordStaticProceed(classname, methodname);
202             else if (c == INVOKESPECIAL)
203                 jc.recordSpecialProceed(Javac.param0Name, classname,
204                                         methodname, signature);
205             else
206                 jc.recordProceed(Javac.param0Name, methodname);
207
208             /* Is $_ included in the source code?
209              */

210             checkResultValue(retType, statement);
211
212             Bytecode bytecode = jc.getBytecode();
213             storeStack(params, c == INVOKESTATIC, paramVar, bytecode);
214             jc.recordLocalVariables(ca, pos);
215
216             if (retType != CtClass.voidType) {
217                 bytecode.addConstZero(retType);
218                 bytecode.addStore(retVar, retType); // initialize $_
219
}
220
221             jc.compileStmnt(statement);
222             if (retType != CtClass.voidType)
223                 bytecode.addLoad(retVar, retType);
224
225             replace0(pos, bytecode, opcodeSize);
226         }
227         catch (CompileError e) { throw new CannotCompileException(e); }
228         catch (NotFoundException e) { throw new CannotCompileException(e); }
229         catch (BadBytecode e) {
230             throw new CannotCompileException("broken method");
231         }
232     }
233 }
234
Popular Tags