Home | History | Annotate | Download | only in expr
      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      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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 
    144         ProceedForInstanceof(int i) {
    145             index = i;
    146         }
    147 
    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 
    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