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      */
Handler(ExceptionTable et, int nth, CodeIterator it, CtClass declaring, MethodInfo m)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      */
where()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      */
getLineNumber()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      */
getFileName()59     public String getFileName() {
60         return super.getFileName();
61     }
62 
63     /**
64      * Returns the list of exceptions that the catch clause may throw.
65      */
mayThrow()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      */
getType()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      */
isFinally()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      */
replace(String statement)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      */
insertBefore(String src)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