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  * Explicit type cast.
     25  */
     26 public class Cast extends Expr {
     27     /**
     28      * Undocumented constructor.  Do not use; internal-use only.
     29      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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 
    139         ProceedForCast(int i, CtClass t) {
    140             index = i;
    141             retType = t;
    142         }
    143 
    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 
    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