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