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