KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > expr > NewExpr


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 import javassist.compiler.ast.ASTList;
22
23 /**
24  * Object creation (<tt>new</tt> expression).
25  */

26 public class NewExpr extends Expr {
27     String JavaDoc newTypeName;
28     int newPos;
29
30     /**
31      * Undocumented constructor. Do not use; internal-use only.
32      */

33     protected NewExpr(int pos, CodeIterator i, CtClass declaring,
34                       MethodInfo m, String JavaDoc type, int np) {
35         super(pos, i, declaring, m);
36         newTypeName = type;
37         newPos = np;
38     }
39
40     private int getNameAndType(ConstPool cp) {
41         String JavaDoc cname;
42         int pos = currentPos;
43         int c = iterator.byteAt(pos);
44         int index = iterator.u16bitAt(pos + 1);
45
46         if (c == INVOKEINTERFACE)
47             return cp.getInterfaceMethodrefNameAndType(index);
48         else
49             return cp.getMethodrefNameAndType(index);
50     }
51
52     /**
53      * Returns the method or constructor containing the <tt>new</tt>
54      * expression represented by this object.
55      */

56     public CtBehavior where() { return super.where(); }
57
58     /**
59      * Returns the line number of the source line containing the
60      * <tt>new</tt> expression.
61      *
62      * @return -1 if this information is not available.
63      */

64     public int getLineNumber() {
65         return super.getLineNumber();
66     }
67
68     /**
69      * Returns the source file containing the <tt>new</tt> expression.
70      *
71      * @return null if this information is not available.
72      */

73     public String JavaDoc getFileName() {
74         return super.getFileName();
75     }
76
77     /**
78      * Returns the class of the created object.
79      */

80     private CtClass getCtClass() throws NotFoundException {
81         return thisClass.getClassPool().get(newTypeName);
82     }
83
84     /**
85      * Returns the class name of the created object.
86      */

87     public String JavaDoc getClassName() {
88         return newTypeName;
89     }
90
91     /**
92      * Returns the constructor called for creating the object.
93      */

94     public CtConstructor getConstructor() throws NotFoundException {
95         ConstPool cp = getConstPool();
96         int index = iterator.u16bitAt(currentPos + 1);
97         String JavaDoc desc = cp.getMethodrefType(index);
98         return getCtClass().getConstructor(desc);
99     }
100
101     /**
102      * Returns the list of exceptions that the expression may throw.
103      * This list includes both the exceptions that the try-catch statements
104      * including the expression can catch and the exceptions that
105      * the throws declaration allows the method to throw.
106      */

107     public CtClass[] mayThrow() {
108         return super.mayThrow();
109     }
110
111     /*
112      * Returns the parameter types of the constructor.
113
114     public CtClass[] getParameterTypes() throws NotFoundException {
115         ConstPool cp = getConstPool();
116         int index = iterator.u16bitAt(currentPos + 1);
117         String desc = cp.getMethodrefType(index);
118         return Descriptor.getParameterTypes(desc, thisClass.getClassPool());
119     }
120     */

121
122     private int canReplace() throws CannotCompileException {
123         int op = iterator.byteAt(newPos + 3);
124         if (op == Opcode.DUP)
125             return 4;
126         else if (op == Opcode.DUP_X1
127                  && iterator.byteAt(newPos + 4) == Opcode.SWAP)
128             return 5;
129         else
130             throw new CannotCompileException(
131                         "sorry, cannot edit NEW followed by no DUP");
132     }
133
134     /**
135      * Replaces the <tt>new</tt> expression with the bytecode derived from
136      * the given source text.
137      *
138      * <p>$0 is available but the value is null.
139      *
140      * @param statement a Java statement.
141      */

142     public void replace(String JavaDoc statement) throws CannotCompileException {
143         final int bytecodeSize = 3;
144         int pos = newPos;
145
146         int newIndex = iterator.u16bitAt(pos + 1);
147
148         /* delete the preceding NEW and DUP (or DUP_X1, SWAP) instructions.
149          */

150         int end = pos + canReplace();
151         for (int i = pos; i < end; ++i)
152             iterator.writeByte(NOP, i);
153
154         ConstPool constPool = getConstPool();
155         pos = currentPos;
156         int methodIndex = iterator.u16bitAt(pos + 1); // constructor
157

158         String JavaDoc signature = constPool.getMethodrefType(methodIndex);
159
160         Javac jc = new Javac(thisClass);
161         ClassPool cp = thisClass.getClassPool();
162         CodeAttribute ca = iterator.get();
163         try {
164             CtClass[] params = Descriptor.getParameterTypes(signature, cp);
165             CtClass newType = cp.get(newTypeName);
166             int paramVar = ca.getMaxLocals();
167             jc.recordParams(newTypeName, params,
168                             true, paramVar, withinStatic());
169             int retVar = jc.recordReturnType(newType, true);
170             jc.recordProceed(new ProceedForNew(newType, newIndex,
171                                                methodIndex));
172
173             /* Is $_ included in the source code?
174              */

175             checkResultValue(newType, statement);
176
177             Bytecode bytecode = jc.getBytecode();
178             storeStack(params, true, paramVar, bytecode);
179             jc.recordLocalVariables(ca, pos);
180
181             bytecode.addConstZero(newType);
182             bytecode.addStore(retVar, newType); // initialize $_
183

184             jc.compileStmnt(statement);
185             bytecode.addAload(retVar);
186
187             replace0(pos, bytecode, bytecodeSize);
188         }
189         catch (CompileError e) { throw new CannotCompileException(e); }
190         catch (NotFoundException e) { throw new CannotCompileException(e); }
191         catch (BadBytecode e) {
192             throw new CannotCompileException("broken method");
193         }
194     }
195
196     static class ProceedForNew implements ProceedHandler {
197         CtClass newType;
198         int newIndex, methodIndex;
199
200         ProceedForNew(CtClass nt, int ni, int mi) {
201             newType = nt;
202             newIndex = ni;
203             methodIndex = mi;
204         }
205
206         public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
207             throws CompileError
208         {
209             bytecode.addOpcode(NEW);
210             bytecode.addIndex(newIndex);
211             bytecode.addOpcode(DUP);
212             gen.atMethodCallCore(newType, MethodInfo.nameInit, args,
213                                  false, true, -1, null);
214             gen.setType(newType);
215         }
216
217         public void setReturnType(JvstTypeChecker c, ASTList args)
218             throws CompileError
219         {
220             c.atMethodCallCore(newType, MethodInfo.nameInit, args);
221             c.setType(newType);
222         }
223     }
224 }
225
Popular Tags