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