1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 package com.sun.org.apache.bcel.internal.generic; 22 23 import com.sun.org.apache.bcel.internal.classfile.CodeException; 24 25 /** 26 * This class represents an exception handler, i.e., specifies the region where 27 * a handler is active and an instruction where the actual handling is done. 28 * pool as parameters. Opposed to the JVM specification the end of the handled 29 * region is set to be inclusive, i.e. all instructions between start and end 30 * are protected including the start and end instructions (handles) themselves. 31 * The end of the region is automatically mapped to be exclusive when calling 32 * getCodeException(), i.e., there is no difference semantically. 33 * 34 * @version $Id$ 35 * @see MethodGen 36 * @see CodeException 37 * @see InstructionHandle 38 */ 39 public final class CodeExceptionGen implements InstructionTargeter, Cloneable { 40 41 private InstructionHandle start_pc; 42 private InstructionHandle end_pc; 43 private InstructionHandle handler_pc; 44 private ObjectType catch_type; 45 46 47 /** 48 * Add an exception handler, i.e., specify region where a handler is active and an 49 * instruction where the actual handling is done. 50 * 51 * @param start_pc Start of handled region (inclusive) 52 * @param end_pc End of handled region (inclusive) 53 * @param handler_pc Where handling is done 54 * @param catch_type which exception is handled, null for ANY 55 */ 56 public CodeExceptionGen(final InstructionHandle start_pc, final InstructionHandle end_pc, 57 final InstructionHandle handler_pc, final ObjectType catch_type) { 58 setStartPC(start_pc); 59 setEndPC(end_pc); 60 setHandlerPC(handler_pc); 61 this.catch_type = catch_type; 62 } 63 64 65 /** 66 * Get CodeException object.<BR> 67 * 68 * This relies on that the instruction list has already been dumped 69 * to byte code or or that the `setPositions' methods has been 70 * called for the instruction list. 71 * 72 * @param cp constant pool 73 */ 74 public CodeException getCodeException( final ConstantPoolGen cp ) { 75 return new CodeException(start_pc.getPosition(), end_pc.getPosition() 76 + end_pc.getInstruction().getLength(), handler_pc.getPosition(), 77 (catch_type == null) ? 0 : cp.addClass(catch_type)); 78 } 79 80 81 /* Set start of handler 82 * @param start_pc Start of handled region (inclusive) 83 */ 84 public void setStartPC( final InstructionHandle start_pc ) { // TODO could be package-protected? 85 BranchInstruction.notifyTarget(this.start_pc, start_pc, this); 86 this.start_pc = start_pc; 87 } 88 89 90 /* Set end of handler 91 * @param end_pc End of handled region (inclusive) 92 */ 93 public void setEndPC( final InstructionHandle end_pc ) { // TODO could be package-protected? 94 BranchInstruction.notifyTarget(this.end_pc, end_pc, this); 95 this.end_pc = end_pc; 96 } 97 98 99 /* Set handler code 100 * @param handler_pc Start of handler 101 */ 102 public void setHandlerPC( final InstructionHandle handler_pc ) { // TODO could be package-protected? 103 BranchInstruction.notifyTarget(this.handler_pc, handler_pc, this); 104 this.handler_pc = handler_pc; 105 } 106 107 108 /** 109 * @param old_ih old target, either start or end 110 * @param new_ih new target 111 */ 112 @Override 113 public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { 114 boolean targeted = false; 115 if (start_pc == old_ih) { 116 targeted = true; 117 setStartPC(new_ih); 118 } 119 if (end_pc == old_ih) { 120 targeted = true; 121 setEndPC(new_ih); 122 } 123 if (handler_pc == old_ih) { 124 targeted = true; 125 setHandlerPC(new_ih); 126 } 127 if (!targeted) { 128 throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", " 129 + end_pc + ", " + handler_pc + "}"); 130 } 131 } 132 133 134 /** 135 * @return true, if ih is target of this handler 136 */ 137 @Override 138 public boolean containsTarget( final InstructionHandle ih ) { 139 return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih); 140 } 141 142 143 /** Sets the type of the Exception to catch. Set 'null' for ANY. */ 144 public void setCatchType( final ObjectType catch_type ) { 145 this.catch_type = catch_type; 146 } 147 148 149 /** Gets the type of the Exception to catch, 'null' for ANY. */ 150 public ObjectType getCatchType() { 151 return catch_type; 152 } 153 154 155 /** @return start of handled region (inclusive) 156 */ 157 public InstructionHandle getStartPC() { 158 return start_pc; 159 } 160 161 162 /** @return end of handled region (inclusive) 163 */ 164 public InstructionHandle getEndPC() { 165 return end_pc; 166 } 167 168 169 /** @return start of handler 170 */ 171 public InstructionHandle getHandlerPC() { 172 return handler_pc; 173 } 174 175 176 @Override 177 public String toString() { 178 return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")"; 179 } 180 181 182 @Override 183 public Object clone() { 184 try { 185 return super.clone(); 186 } catch (final CloneNotSupportedException e) { 187 throw new Error("Clone Not Supported"); // never happens 188 } 189 } 190 }