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
16package javassist.expr;
17
18import javassist.*;
19import javassist.bytecode.*;
20import javassist.compiler.*;
21
22/**
23 * A <code>catch</code> clause or a <code>finally</code> block.
24 */
25public 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