169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.expr;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.*;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A <code>catch</code> clause or a <code>finally</code> block.
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Handler extends Expr {
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static String EXCEPTION_NAME = "$1";
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ExceptionTable etable;
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int index;
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Undocumented constructor.  Do not use; internal-use only.
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected Handler(ExceptionTable et, int nth,
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                      CodeIterator it, CtClass declaring, MethodInfo m) {
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(et.handlerPc(nth), it, declaring, m);
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        etable = et;
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        index = nth;
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the method or constructor containing the catch clause.
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtBehavior where() { return super.where(); }
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the source line number of the catch clause.
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return -1       if this information is not available.
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getLineNumber() {
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return super.getLineNumber();
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the source file containing the catch clause.
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null     if this information is not available.
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getFileName() {
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return super.getFileName();
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the list of exceptions that the catch clause may throw.
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass[] mayThrow() {
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return super.mayThrow();
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the type handled by the catch clause.
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If this is a <code>finally</code> block, <code>null</code> is returned.
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass getType() throws NotFoundException {
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int type = etable.catchType(index);
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type == 0)
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return null;
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ConstPool cp = getConstPool();
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String name = cp.getClassInfo(type);
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return thisClass.getClassPool().getCtClass(name);
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if this is a <code>finally</code> block.
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isFinally() {
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return etable.catchType(index) == 0;
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method has not been implemented yet.
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param statement         a Java statement except try-catch.
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void replace(String statement) throws CannotCompileException {
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throw new RuntimeException("not implemented yet");
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts bytecode at the beginning of the catch clause.
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The caught exception is stored in <code>$1</code>.
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source code representing the inserted bytecode.
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It must be a single statement or block.
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertBefore(String src) throws CannotCompileException {
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        edited = true;
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = getConstPool();
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = iterator.get();
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Javac jv = new Javac(thisClass);
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Bytecode b = jv.getBytecode();
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.setStackDepth(1);
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.setMaxLocals(ca.getMaxLocals());
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass type = getType();
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int var = jv.recordVariable(type, EXCEPTION_NAME);
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.recordReturnType(type, false);
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addAstore(var);
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jv.compileStmnt(src);
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addAload(var);
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int oldHandler = etable.handlerPc(index);
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addOpcode(Opcode.GOTO);
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addIndex(oldHandler - iterator.getCodeLength()
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                       - b.currentPc() + 1);
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            maxStack = b.getMaxStack();
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            maxLocals = b.getMaxLocals();
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = iterator.append(b.get());
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.append(b.getExceptionTable(), pos);
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            etable.setHandlerPc(index, pos);
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) {
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
146