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