1*f1fbf3c2SXin Li /* 2*f1fbf3c2SXin Li * Javassist, a Java-bytecode translator toolkit. 3*f1fbf3c2SXin Li * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. 4*f1fbf3c2SXin Li * 5*f1fbf3c2SXin Li * The contents of this file are subject to the Mozilla Public License Version 6*f1fbf3c2SXin Li * 1.1 (the "License"); you may not use this file except in compliance with 7*f1fbf3c2SXin Li * the License. Alternatively, the contents of this file may be used under 8*f1fbf3c2SXin Li * the terms of the GNU Lesser General Public License Version 2.1 or later, 9*f1fbf3c2SXin Li * or the Apache License Version 2.0. 10*f1fbf3c2SXin Li * 11*f1fbf3c2SXin Li * Software distributed under the License is distributed on an "AS IS" basis, 12*f1fbf3c2SXin Li * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13*f1fbf3c2SXin Li * for the specific language governing rights and limitations under the 14*f1fbf3c2SXin Li * License. 15*f1fbf3c2SXin Li */ 16*f1fbf3c2SXin Li 17*f1fbf3c2SXin Li package javassist.expr; 18*f1fbf3c2SXin Li 19*f1fbf3c2SXin Li import javassist.CannotCompileException; 20*f1fbf3c2SXin Li import javassist.ClassPool; 21*f1fbf3c2SXin Li import javassist.CtBehavior; 22*f1fbf3c2SXin Li import javassist.CtClass; 23*f1fbf3c2SXin Li import javassist.NotFoundException; 24*f1fbf3c2SXin Li import javassist.bytecode.BadBytecode; 25*f1fbf3c2SXin Li import javassist.bytecode.Bytecode; 26*f1fbf3c2SXin Li import javassist.bytecode.CodeAttribute; 27*f1fbf3c2SXin Li import javassist.bytecode.CodeIterator; 28*f1fbf3c2SXin Li import javassist.bytecode.ConstPool; 29*f1fbf3c2SXin Li import javassist.bytecode.MethodInfo; 30*f1fbf3c2SXin Li import javassist.bytecode.Opcode; 31*f1fbf3c2SXin Li import javassist.compiler.CompileError; 32*f1fbf3c2SXin Li import javassist.compiler.Javac; 33*f1fbf3c2SXin Li import javassist.compiler.JvstCodeGen; 34*f1fbf3c2SXin Li import javassist.compiler.JvstTypeChecker; 35*f1fbf3c2SXin Li import javassist.compiler.ProceedHandler; 36*f1fbf3c2SXin Li import javassist.compiler.ast.ASTList; 37*f1fbf3c2SXin Li 38*f1fbf3c2SXin Li /** 39*f1fbf3c2SXin Li * Explicit type cast. 40*f1fbf3c2SXin Li */ 41*f1fbf3c2SXin Li public class Cast extends Expr { 42*f1fbf3c2SXin Li /** 43*f1fbf3c2SXin Li * Undocumented constructor. Do not use; internal-use only. 44*f1fbf3c2SXin Li */ Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m)45*f1fbf3c2SXin Li protected Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { 46*f1fbf3c2SXin Li super(pos, i, declaring, m); 47*f1fbf3c2SXin Li } 48*f1fbf3c2SXin Li 49*f1fbf3c2SXin Li /** 50*f1fbf3c2SXin Li * Returns the method or constructor containing the type cast 51*f1fbf3c2SXin Li * expression represented by this object. 52*f1fbf3c2SXin Li */ 53*f1fbf3c2SXin Li @Override where()54*f1fbf3c2SXin Li public CtBehavior where() { return super.where(); } 55*f1fbf3c2SXin Li 56*f1fbf3c2SXin Li /** 57*f1fbf3c2SXin Li * Returns the line number of the source line containing the 58*f1fbf3c2SXin Li * type-cast expression. 59*f1fbf3c2SXin Li * 60*f1fbf3c2SXin Li * @return -1 if this information is not available. 61*f1fbf3c2SXin Li */ 62*f1fbf3c2SXin Li @Override getLineNumber()63*f1fbf3c2SXin Li public int getLineNumber() { 64*f1fbf3c2SXin Li return super.getLineNumber(); 65*f1fbf3c2SXin Li } 66*f1fbf3c2SXin Li 67*f1fbf3c2SXin Li /** 68*f1fbf3c2SXin Li * Returns the source file containing the type-cast expression. 69*f1fbf3c2SXin Li * 70*f1fbf3c2SXin Li * @return null if this information is not available. 71*f1fbf3c2SXin Li */ 72*f1fbf3c2SXin Li @Override getFileName()73*f1fbf3c2SXin Li public String getFileName() { 74*f1fbf3c2SXin Li return super.getFileName(); 75*f1fbf3c2SXin Li } 76*f1fbf3c2SXin Li 77*f1fbf3c2SXin Li /** 78*f1fbf3c2SXin Li * Returns the <code>CtClass</code> object representing 79*f1fbf3c2SXin Li * the type specified by the cast. 80*f1fbf3c2SXin Li */ getType()81*f1fbf3c2SXin Li public CtClass getType() throws NotFoundException { 82*f1fbf3c2SXin Li ConstPool cp = getConstPool(); 83*f1fbf3c2SXin Li int pos = currentPos; 84*f1fbf3c2SXin Li int index = iterator.u16bitAt(pos + 1); 85*f1fbf3c2SXin Li String name = cp.getClassInfo(index); 86*f1fbf3c2SXin Li return thisClass.getClassPool().getCtClass(name); 87*f1fbf3c2SXin Li } 88*f1fbf3c2SXin Li 89*f1fbf3c2SXin Li /** 90*f1fbf3c2SXin Li * Returns the list of exceptions that the expression may throw. 91*f1fbf3c2SXin Li * This list includes both the exceptions that the try-catch statements 92*f1fbf3c2SXin Li * including the expression can catch and the exceptions that 93*f1fbf3c2SXin Li * the throws declaration allows the method to throw. 94*f1fbf3c2SXin Li */ 95*f1fbf3c2SXin Li @Override mayThrow()96*f1fbf3c2SXin Li public CtClass[] mayThrow() { 97*f1fbf3c2SXin Li return super.mayThrow(); 98*f1fbf3c2SXin Li } 99*f1fbf3c2SXin Li 100*f1fbf3c2SXin Li /** 101*f1fbf3c2SXin Li * Replaces the explicit cast operator with the bytecode derived from 102*f1fbf3c2SXin Li * the given source text. 103*f1fbf3c2SXin Li * 104*f1fbf3c2SXin Li * <p>$0 is available but the value is <code>null</code>. 105*f1fbf3c2SXin Li * 106*f1fbf3c2SXin Li * @param statement a Java statement except try-catch. 107*f1fbf3c2SXin Li */ 108*f1fbf3c2SXin Li @Override replace(String statement)109*f1fbf3c2SXin Li public void replace(String statement) throws CannotCompileException { 110*f1fbf3c2SXin Li thisClass.getClassFile(); // to call checkModify(). 111*f1fbf3c2SXin Li @SuppressWarnings("unused") 112*f1fbf3c2SXin Li ConstPool constPool = getConstPool(); 113*f1fbf3c2SXin Li int pos = currentPos; 114*f1fbf3c2SXin Li int index = iterator.u16bitAt(pos + 1); 115*f1fbf3c2SXin Li 116*f1fbf3c2SXin Li Javac jc = new Javac(thisClass); 117*f1fbf3c2SXin Li ClassPool cp = thisClass.getClassPool(); 118*f1fbf3c2SXin Li CodeAttribute ca = iterator.get(); 119*f1fbf3c2SXin Li 120*f1fbf3c2SXin Li try { 121*f1fbf3c2SXin Li CtClass[] params 122*f1fbf3c2SXin Li = new CtClass[] { cp.get(javaLangObject) }; 123*f1fbf3c2SXin Li CtClass retType = getType(); 124*f1fbf3c2SXin Li 125*f1fbf3c2SXin Li int paramVar = ca.getMaxLocals(); 126*f1fbf3c2SXin Li jc.recordParams(javaLangObject, params, true, paramVar, 127*f1fbf3c2SXin Li withinStatic()); 128*f1fbf3c2SXin Li int retVar = jc.recordReturnType(retType, true); 129*f1fbf3c2SXin Li jc.recordProceed(new ProceedForCast(index, retType)); 130*f1fbf3c2SXin Li 131*f1fbf3c2SXin Li /* Is $_ included in the source code? 132*f1fbf3c2SXin Li */ 133*f1fbf3c2SXin Li checkResultValue(retType, statement); 134*f1fbf3c2SXin Li 135*f1fbf3c2SXin Li Bytecode bytecode = jc.getBytecode(); 136*f1fbf3c2SXin Li storeStack(params, true, paramVar, bytecode); 137*f1fbf3c2SXin Li jc.recordLocalVariables(ca, pos); 138*f1fbf3c2SXin Li 139*f1fbf3c2SXin Li bytecode.addConstZero(retType); 140*f1fbf3c2SXin Li bytecode.addStore(retVar, retType); // initialize $_ 141*f1fbf3c2SXin Li 142*f1fbf3c2SXin Li jc.compileStmnt(statement); 143*f1fbf3c2SXin Li bytecode.addLoad(retVar, retType); 144*f1fbf3c2SXin Li 145*f1fbf3c2SXin Li replace0(pos, bytecode, 3); 146*f1fbf3c2SXin Li } 147*f1fbf3c2SXin Li catch (CompileError e) { throw new CannotCompileException(e); } 148*f1fbf3c2SXin Li catch (NotFoundException e) { throw new CannotCompileException(e); } 149*f1fbf3c2SXin Li catch (BadBytecode e) { 150*f1fbf3c2SXin Li throw new CannotCompileException("broken method"); 151*f1fbf3c2SXin Li } 152*f1fbf3c2SXin Li } 153*f1fbf3c2SXin Li 154*f1fbf3c2SXin Li /* <type> $proceed(Object obj) 155*f1fbf3c2SXin Li */ 156*f1fbf3c2SXin Li static class ProceedForCast implements ProceedHandler { 157*f1fbf3c2SXin Li int index; 158*f1fbf3c2SXin Li CtClass retType; 159*f1fbf3c2SXin Li ProceedForCast(int i, CtClass t)160*f1fbf3c2SXin Li ProceedForCast(int i, CtClass t) { 161*f1fbf3c2SXin Li index = i; 162*f1fbf3c2SXin Li retType = t; 163*f1fbf3c2SXin Li } 164*f1fbf3c2SXin Li 165*f1fbf3c2SXin Li @Override doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)166*f1fbf3c2SXin Li public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) 167*f1fbf3c2SXin Li throws CompileError 168*f1fbf3c2SXin Li { 169*f1fbf3c2SXin Li if (gen.getMethodArgsLength(args) != 1) 170*f1fbf3c2SXin Li throw new CompileError(Javac.proceedName 171*f1fbf3c2SXin Li + "() cannot take more than one parameter " 172*f1fbf3c2SXin Li + "for cast"); 173*f1fbf3c2SXin Li 174*f1fbf3c2SXin Li gen.atMethodArgs(args, new int[1], new int[1], new String[1]); 175*f1fbf3c2SXin Li bytecode.addOpcode(Opcode.CHECKCAST); 176*f1fbf3c2SXin Li bytecode.addIndex(index); 177*f1fbf3c2SXin Li gen.setType(retType); 178*f1fbf3c2SXin Li } 179*f1fbf3c2SXin Li 180*f1fbf3c2SXin Li @Override setReturnType(JvstTypeChecker c, ASTList args)181*f1fbf3c2SXin Li public void setReturnType(JvstTypeChecker c, ASTList args) 182*f1fbf3c2SXin Li throws CompileError 183*f1fbf3c2SXin Li { 184*f1fbf3c2SXin Li c.atMethodArgs(args, new int[1], new int[1], new String[1]); 185*f1fbf3c2SXin Li c.setType(retType); 186*f1fbf3c2SXin Li } 187*f1fbf3c2SXin Li } 188*f1fbf3c2SXin Li } 189