KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > expr > Expr


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.CannotCompileException;
19 import javassist.ClassPool;
20 import javassist.CtBehavior;
21 import javassist.CtClass;
22 import javassist.CtConstructor;
23 import javassist.CtPrimitiveType;
24 import javassist.NotFoundException;
25 import javassist.bytecode.AccessFlag;
26 import javassist.bytecode.BadBytecode;
27 import javassist.bytecode.Bytecode;
28 import javassist.bytecode.ClassFile;
29 import javassist.bytecode.CodeAttribute;
30 import javassist.bytecode.CodeIterator;
31 import javassist.bytecode.ConstPool;
32 import javassist.bytecode.ExceptionTable;
33 import javassist.bytecode.ExceptionsAttribute;
34 import javassist.bytecode.MethodInfo;
35 import javassist.bytecode.Opcode;
36 import javassist.compiler.Javac;
37
38 import java.util.Iterator JavaDoc;
39 import java.util.LinkedList JavaDoc;
40
41 /**
42  * Expression.
43  */

44 public abstract class Expr implements Opcode {
45     int currentPos;
46
47     CodeIterator iterator;
48
49     CtClass thisClass;
50
51     MethodInfo thisMethod;
52
53     boolean edited;
54
55     int maxLocals, maxStack;
56
57     static final String JavaDoc javaLangObject = "java.lang.Object";
58
59     /**
60      * Undocumented constructor. Do not use; internal-use only.
61      */

62     protected Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
63         currentPos = pos;
64         iterator = i;
65         thisClass = declaring;
66         thisMethod = m;
67     }
68
69     protected final ConstPool getConstPool() {
70         return thisMethod.getConstPool();
71     }
72
73     protected final boolean edited() {
74         return edited;
75     }
76
77     protected final int locals() {
78         return maxLocals;
79     }
80
81     protected final int stack() {
82         return maxStack;
83     }
84
85     /**
86      * Returns true if this method is static.
87      */

88     protected final boolean withinStatic() {
89         return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0;
90     }
91
92     /**
93      * Returns the constructor or method containing the expression.
94      */

95     public CtBehavior where() {
96         MethodInfo mi = thisMethod;
97         CtBehavior[] cb = thisClass.getDeclaredBehaviors();
98         for (int i = cb.length - 1; i >= 0; --i)
99             if (cb[i].getMethodInfo2() == mi)
100                 return cb[i];
101
102         CtConstructor init = thisClass.getClassInitializer();
103         if (init != null && init.getMethodInfo2() == mi)
104             return init;
105
106         /* getDeclaredBehaviors() returns a list of methods/constructors.
107          * Although the list is cached in a CtClass object, it might be
108          * recreated for some reason. Thus, the member name and the signature
109          * must be also checked.
110          */

111         for (int i = cb.length - 1; i >= 0; --i) {
112             if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName())
113                 && thisMethod.getDescriptor()
114                              .equals(cb[i].getMethodInfo2().getDescriptor())) {
115                 return cb[i];
116             }
117         }
118
119         throw new RuntimeException JavaDoc("fatal: not found");
120     }
121
122     /**
123      * Returns the list of exceptions that the expression may throw. This list
124      * includes both the exceptions that the try-catch statements including the
125      * expression can catch and the exceptions that the throws declaration
126      * allows the method to throw.
127      */

128     public CtClass[] mayThrow() {
129         ClassPool pool = thisClass.getClassPool();
130         ConstPool cp = thisMethod.getConstPool();
131         LinkedList JavaDoc list = new LinkedList JavaDoc();
132         try {
133             CodeAttribute ca = thisMethod.getCodeAttribute();
134             ExceptionTable et = ca.getExceptionTable();
135             int pos = currentPos;
136             int n = et.size();
137             for (int i = 0; i < n; ++i)
138                 if (et.startPc(i) <= pos && pos < et.endPc(i)) {
139                     int t = et.catchType(i);
140                     if (t > 0)
141                         try {
142                             addClass(list, pool.get(cp.getClassInfo(t)));
143                         }
144                         catch (NotFoundException e) {
145                         }
146                 }
147         }
148         catch (NullPointerException JavaDoc e) {
149         }
150
151         ExceptionsAttribute ea = thisMethod.getExceptionsAttribute();
152         if (ea != null) {
153             String JavaDoc[] exceptions = ea.getExceptions();
154             if (exceptions != null) {
155                 int n = exceptions.length;
156                 for (int i = 0; i < n; ++i)
157                     try {
158                         addClass(list, pool.get(exceptions[i]));
159                     }
160                     catch (NotFoundException e) {
161                     }
162             }
163         }
164
165         return (CtClass[])list.toArray(new CtClass[list.size()]);
166     }
167
168     private static void addClass(LinkedList JavaDoc list, CtClass c) {
169         Iterator it = list.iterator();
170         while (it.hasNext())
171             if (it.next() == c)
172                 return;
173
174         list.add(c);
175     }
176
177     /**
178      * Returns the index of the bytecode corresponding to the expression. It is
179      * the index into the byte array containing the Java bytecode that
180      * implements the method.
181      */

182     public int indexOfBytecode() {
183         return currentPos;
184     }
185
186     /**
187      * Returns the line number of the source line containing the expression.
188      *
189      * @return -1 if this information is not available.
190      */

191     public int getLineNumber() {
192         return thisMethod.getLineNumber(currentPos);
193     }
194
195     /**
196      * Returns the source file containing the expression.
197      *
198      * @return null if this information is not available.
199      */

200     public String JavaDoc getFileName() {
201         ClassFile cf = thisClass.getClassFile2();
202         if (cf == null)
203             return null;
204         else
205             return cf.getSourceFile();
206     }
207
208     static final boolean checkResultValue(CtClass retType, String JavaDoc prog)
209             throws CannotCompileException {
210         /*
211          * Is $_ included in the source code?
212          */

213         boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
214         if (!hasIt && retType != CtClass.voidType)
215             throw new CannotCompileException(
216                     "the resulting value is not stored in "
217                             + Javac.resultVarName);
218
219         return hasIt;
220     }
221
222     /*
223      * If isStaticCall is true, null is assigned to $0. So $0 must be declared
224      * by calling Javac.recordParams().
225      *
226      * After executing this method, the current stack depth might be less than
227      * 0.
228      */

229     static final void storeStack(CtClass[] params, boolean isStaticCall,
230             int regno, Bytecode bytecode) {
231         storeStack0(0, params.length, params, regno + 1, bytecode);
232         if (isStaticCall)
233             bytecode.addOpcode(ACONST_NULL);
234
235         bytecode.addAstore(regno);
236     }
237
238     private static void storeStack0(int i, int n, CtClass[] params, int regno,
239             Bytecode bytecode) {
240         if (i >= n)
241             return;
242         else {
243             CtClass c = params[i];
244             int size;
245             if (c instanceof CtPrimitiveType)
246                 size = ((CtPrimitiveType)c).getDataSize();
247             else
248                 size = 1;
249
250             storeStack0(i + 1, n, params, regno + size, bytecode);
251             bytecode.addStore(regno, c);
252         }
253     }
254
255     protected void replace0(int pos, Bytecode bytecode, int size)
256             throws BadBytecode {
257         byte[] code = bytecode.get();
258         edited = true;
259         int gap = code.length - size;
260         for (int i = 0; i < size; ++i)
261             iterator.writeByte(NOP, pos + i);
262
263         if (gap > 0)
264             iterator.insertGap(pos, gap);
265
266         iterator.write(code, pos);
267         iterator.insert(bytecode.getExceptionTable(), pos);
268         maxLocals = bytecode.getMaxLocals();
269         maxStack = bytecode.getMaxStack();
270     }
271 }
272
Popular Tags