• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2007 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  * Explicit type cast.
25  */
26 public class Cast extends Expr {
27     /**
28      * Undocumented constructor.  Do not use; internal-use only.
29      */
Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m)30     protected Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
31         super(pos, i, declaring, m);
32     }
33 
34     /**
35      * Returns the method or constructor containing the type cast
36      * expression represented by this object.
37      */
where()38     public CtBehavior where() { return super.where(); }
39 
40     /**
41      * Returns the line number of the source line containing the
42      * type-cast expression.
43      *
44      * @return -1       if this information is not available.
45      */
getLineNumber()46     public int getLineNumber() {
47         return super.getLineNumber();
48     }
49 
50     /**
51      * Returns the source file containing the type-cast expression.
52      *
53      * @return null     if this information is not available.
54      */
getFileName()55     public String getFileName() {
56         return super.getFileName();
57     }
58 
59     /**
60      * Returns the <code>CtClass</code> object representing
61      * the type specified by the cast.
62      */
getType()63     public CtClass getType() throws NotFoundException {
64         ConstPool cp = getConstPool();
65         int pos = currentPos;
66         int index = iterator.u16bitAt(pos + 1);
67         String name = cp.getClassInfo(index);
68         return thisClass.getClassPool().getCtClass(name);
69     }
70 
71     /**
72      * Returns the list of exceptions that the expression may throw.
73      * This list includes both the exceptions that the try-catch statements
74      * including the expression can catch and the exceptions that
75      * the throws declaration allows the method to throw.
76      */
mayThrow()77     public CtClass[] mayThrow() {
78         return super.mayThrow();
79     }
80 
81     /**
82      * Replaces the explicit cast operator with the bytecode derived from
83      * the given source text.
84      *
85      * <p>$0 is available but the value is <code>null</code>.
86      *
87      * @param statement         a Java statement except try-catch.
88      */
replace(String statement)89     public void replace(String statement) throws CannotCompileException {
90         thisClass.getClassFile();   // to call checkModify().
91         ConstPool constPool = getConstPool();
92         int pos = currentPos;
93         int index = iterator.u16bitAt(pos + 1);
94 
95         Javac jc = new Javac(thisClass);
96         ClassPool cp = thisClass.getClassPool();
97         CodeAttribute ca = iterator.get();
98 
99         try {
100             CtClass[] params
101                 = new CtClass[] { cp.get(javaLangObject) };
102             CtClass retType = getType();
103 
104             int paramVar = ca.getMaxLocals();
105             jc.recordParams(javaLangObject, params, true, paramVar,
106                             withinStatic());
107             int retVar = jc.recordReturnType(retType, true);
108             jc.recordProceed(new ProceedForCast(index, retType));
109 
110             /* Is $_ included in the source code?
111              */
112             checkResultValue(retType, statement);
113 
114             Bytecode bytecode = jc.getBytecode();
115             storeStack(params, true, paramVar, bytecode);
116             jc.recordLocalVariables(ca, pos);
117 
118             bytecode.addConstZero(retType);
119             bytecode.addStore(retVar, retType);     // initialize $_
120 
121             jc.compileStmnt(statement);
122             bytecode.addLoad(retVar, retType);
123 
124             replace0(pos, bytecode, 3);
125         }
126         catch (CompileError e) { throw new CannotCompileException(e); }
127         catch (NotFoundException e) { throw new CannotCompileException(e); }
128         catch (BadBytecode e) {
129             throw new CannotCompileException("broken method");
130         }
131     }
132 
133     /* <type> $proceed(Object obj)
134      */
135     static class ProceedForCast implements ProceedHandler {
136         int index;
137         CtClass retType;
138 
ProceedForCast(int i, CtClass t)139         ProceedForCast(int i, CtClass t) {
140             index = i;
141             retType = t;
142         }
143 
doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)144         public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
145             throws CompileError
146         {
147             if (gen.getMethodArgsLength(args) != 1)
148                 throw new CompileError(Javac.proceedName
149                         + "() cannot take more than one parameter "
150                         + "for cast");
151 
152             gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
153             bytecode.addOpcode(Opcode.CHECKCAST);
154             bytecode.addIndex(index);
155             gen.setType(retType);
156         }
157 
setReturnType(JvstTypeChecker c, ASTList args)158         public void setReturnType(JvstTypeChecker c, ASTList args)
159             throws CompileError
160         {
161             c.atMethodArgs(args, new int[1], new int[1], new String[1]);
162             c.setType(retType);
163         }
164     }
165 }
166