KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > CtNewWrappedMethod


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 import javassist.compiler.JvstCodeGen;
20 import java.util.Hashtable JavaDoc;
21 import javassist.CtMethod.ConstParameter;
22
23 class CtNewWrappedMethod {
24
25     private static final String JavaDoc addedWrappedMethod = "_added_m$";
26
27     public static CtMethod wrapped(CtClass returnType, String JavaDoc mname,
28                                    CtClass[] parameterTypes,
29                                    CtClass[] exceptionTypes,
30                                    CtMethod body, ConstParameter constParam,
31                                    CtClass declaring)
32         throws CannotCompileException
33     {
34         CtMethod mt = new CtMethod(returnType, mname, parameterTypes,
35                                    declaring);
36         mt.setModifiers(body.getModifiers());
37         try {
38             mt.setExceptionTypes(exceptionTypes);
39         }
40         catch (NotFoundException e) {
41             throw new CannotCompileException(e);
42         }
43
44         Bytecode code = makeBody(declaring, declaring.getClassFile2(), body,
45                                  parameterTypes, returnType, constParam);
46         mt.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
47         return mt;
48     }
49
50     static Bytecode makeBody(CtClass clazz, ClassFile classfile,
51                              CtMethod wrappedBody,
52                              CtClass[] parameters,
53                              CtClass returnType,
54                              ConstParameter cparam)
55         throws CannotCompileException
56     {
57         boolean isStatic = Modifier.isStatic(wrappedBody.getModifiers());
58         Bytecode code = new Bytecode(classfile.getConstPool(), 0, 0);
59         int stacksize = makeBody0(clazz, classfile, wrappedBody, isStatic,
60                                   parameters, returnType, cparam, code);
61         code.setMaxStack(stacksize);
62         code.setMaxLocals(isStatic, parameters, 0);
63         return code;
64     }
65
66     protected static int makeBody0(CtClass clazz, ClassFile classfile,
67                                    CtMethod wrappedBody,
68                                    boolean isStatic, CtClass[] parameters,
69                                    CtClass returnType, ConstParameter cparam,
70                                    Bytecode code)
71         throws CannotCompileException
72     {
73         if (!(clazz instanceof CtClassType))
74             throw new CannotCompileException("bad declaring class"
75                                              + clazz.getName());
76
77         if (!isStatic)
78             code.addAload(0);
79
80         int stacksize = compileParameterList(code, parameters,
81                                              (isStatic ? 0 : 1));
82         int stacksize2;
83         String JavaDoc desc;
84         if (cparam == null) {
85             stacksize2 = 0;
86             desc = ConstParameter.defaultDescriptor();
87         }
88         else {
89             stacksize2 = cparam.compile(code);
90             desc = cparam.descriptor();
91         }
92
93         checkSignature(wrappedBody, desc);
94
95         String JavaDoc bodyname;
96         try {
97             bodyname = addBodyMethod((CtClassType)clazz, classfile,
98                                      wrappedBody);
99             /* if an exception is thrown below, the method added above
100              * should be removed. (future work :<)
101              */

102         }
103         catch (BadBytecode e) {
104             throw new CannotCompileException(e);
105         }
106
107         if (isStatic)
108             code.addInvokestatic(Bytecode.THIS, bodyname, desc);
109         else
110             code.addInvokespecial(Bytecode.THIS, bodyname, desc);
111
112         compileReturn(code, returnType); // consumes 2 stack entries
113

114         if (stacksize < stacksize2 + 2)
115             stacksize = stacksize2 + 2;
116
117         return stacksize;
118     }
119
120     private static void checkSignature(CtMethod wrappedBody,
121                                        String JavaDoc descriptor)
122         throws CannotCompileException
123     {
124         if (!descriptor.equals(wrappedBody.getMethodInfo2().getDescriptor()))
125             throw new CannotCompileException(
126                         "wrapped method with a bad signature: "
127                         + wrappedBody.getDeclaringClass().getName()
128                         + '.' + wrappedBody.getName());
129     }
130
131     private static String JavaDoc addBodyMethod(CtClassType clazz,
132                                         ClassFile classfile,
133                                         CtMethod src)
134         throws BadBytecode, CannotCompileException
135     {
136         Hashtable JavaDoc bodies = clazz.getHiddenMethods();
137         String JavaDoc bodyname = (String JavaDoc)bodies.get(src);
138         if (bodyname == null) {
139             do {
140                 bodyname = addedWrappedMethod + clazz.getUniqueNumber();
141             } while (classfile.getMethod(bodyname) != null);
142             ClassMap map = new ClassMap();
143             map.put(src.getDeclaringClass().getName(), clazz.getName());
144             MethodInfo body = new MethodInfo(classfile.getConstPool(),
145                                              bodyname, src.getMethodInfo2(),
146                                              map);
147             int acc = body.getAccessFlags();
148             body.setAccessFlags(AccessFlag.setPrivate(acc));
149             classfile.addMethod(body);
150             bodies.put(src, bodyname);
151         }
152
153         return bodyname;
154     }
155
156     /* compileParameterList() returns the stack size used
157      * by the produced code.
158      *
159      * @param regno the index of the local variable in which
160      * the first argument is received.
161      * (0: static method, 1: regular method.)
162      */

163     static int compileParameterList(Bytecode code,
164                                     CtClass[] params, int regno) {
165         return JvstCodeGen.compileParameterList(code, params, regno);
166     }
167
168     /*
169      * The produced codes cosume 1 or 2 stack entries.
170      */

171     private static void compileReturn(Bytecode code, CtClass type) {
172         if (type.isPrimitive()) {
173             CtPrimitiveType pt = (CtPrimitiveType)type;
174             if (pt != CtClass.voidType) {
175                 String JavaDoc wrapper = pt.getWrapperName();
176                 code.addCheckcast(wrapper);
177                 code.addInvokevirtual(wrapper, pt.getGetMethodName(),
178                                       pt.getGetMethodDescriptor());
179             }
180
181             code.addOpcode(pt.getReturnOp());
182         }
183         else {
184             code.addCheckcast(type);
185             code.addOpcode(Bytecode.ARETURN);
186         }
187     }
188 }
189
Popular Tags