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 
     22 /**
     23  * A <code>catch</code> clause or a <code>finally</code> block.
     24  */
     25 public class Handler extends Expr {
     26     private static String EXCEPTION_NAME = "$1";
     27     private ExceptionTable etable;
     28     private int index;
     29 
     30     /**
     31      * Undocumented constructor.  Do not use; internal-use only.
     32      */
     33     protected Handler(ExceptionTable et, int nth,
     34                       CodeIterator it, CtClass declaring, MethodInfo m) {
     35         super(et.handlerPc(nth), it, declaring, m);
     36         etable = et;
     37         index = nth;
     38     }
     39 
     40     /**
     41      * Returns the method or constructor containing the catch clause.
     42      */
     43     public CtBehavior where() { return super.where(); }
     44 
     45     /**
     46      * Returns the source line number of the catch clause.
     47      *
     48      * @return -1       if this information is not available.
     49      */
     50     public int getLineNumber() {
     51         return super.getLineNumber();
     52     }
     53 
     54     /**
     55      * Returns the source file containing the catch clause.
     56      *
     57      * @return null     if this information is not available.
     58      */
     59     public String getFileName() {
     60         return super.getFileName();
     61     }
     62 
     63     /**
     64      * Returns the list of exceptions that the catch clause may throw.
     65      */
     66     public CtClass[] mayThrow() {
     67         return super.mayThrow();
     68     }
     69 
     70     /**
     71      * Returns the type handled by the catch clause.
     72      * If this is a <code>finally</code> block, <code>null</code> is returned.
     73      */
     74     public CtClass getType() throws NotFoundException {
     75         int type = etable.catchType(index);
     76         if (type == 0)
     77             return null;
     78         else {
     79             ConstPool cp = getConstPool();
     80             String name = cp.getClassInfo(type);
     81             return thisClass.getClassPool().getCtClass(name);
     82         }
     83     }
     84 
     85     /**
     86      * Returns true if this is a <code>finally</code> block.
     87      */
     88     public boolean isFinally() {
     89         return etable.catchType(index) == 0;
     90     }
     91 
     92     /**
     93      * This method has not been implemented yet.
     94      *
     95      * @param statement         a Java statement except try-catch.
     96      */
     97     public void replace(String statement) throws CannotCompileException {
     98         throw new RuntimeException("not implemented yet");
     99     }
    100 
    101     /**
    102      * Inserts bytecode at the beginning of the catch clause.
    103      * The caught exception is stored in <code>$1</code>.
    104      *
    105      * @param src       the source code representing the inserted bytecode.
    106      *                  It must be a single statement or block.
    107      */
    108     public void insertBefore(String src) throws CannotCompileException {
    109         edited = true;
    110 
    111         ConstPool cp = getConstPool();
    112         CodeAttribute ca = iterator.get();
    113         Javac jv = new Javac(thisClass);
    114         Bytecode b = jv.getBytecode();
    115         b.setStackDepth(1);
    116         b.setMaxLocals(ca.getMaxLocals());
    117 
    118         try {
    119             CtClass type = getType();
    120             int var = jv.recordVariable(type, EXCEPTION_NAME);
    121             jv.recordReturnType(type, false);
    122             b.addAstore(var);
    123             jv.compileStmnt(src);
    124             b.addAload(var);
    125 
    126             int oldHandler = etable.handlerPc(index);
    127             b.addOpcode(Opcode.GOTO);
    128             b.addIndex(oldHandler - iterator.getCodeLength()
    129                        - b.currentPc() + 1);
    130 
    131             maxStack = b.getMaxStack();
    132             maxLocals = b.getMaxLocals();
    133 
    134             int pos = iterator.append(b.get());
    135             iterator.append(b.getExceptionTable(), pos);
    136             etable.setHandlerPc(index, pos);
    137         }
    138         catch (NotFoundException e) {
    139             throw new CannotCompileException(e);
    140         }
    141         catch (CompileError e) {
    142             throw new CannotCompileException(e);
    143         }
    144     }
    145 }
    146