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 * @see MethodGen 35 * @see CodeException 36 * @see InstructionHandle 37 */ 38 public final class CodeExceptionGen implements InstructionTargeter, Cloneable { 39 40 private InstructionHandle start_pc; 41 private InstructionHandle end_pc; 42 private InstructionHandle handler_pc; 43 private ObjectType catch_type; 44 45 46 /** 47 * Add an exception handler, i.e., specify region where a handler is active and an 48 * instruction where the actual handling is done. 49 * 50 * @param start_pc Start of handled region (inclusive) 51 * @param end_pc End of handled region (inclusive) 52 * @param handler_pc Where handling is done 53 * @param catch_type which exception is handled, null for ANY 54 */ CodeExceptionGen(final InstructionHandle start_pc, final InstructionHandle end_pc, final InstructionHandle handler_pc, final ObjectType catch_type)55 public CodeExceptionGen(final InstructionHandle start_pc, final InstructionHandle end_pc, 56 final InstructionHandle handler_pc, final ObjectType catch_type) { 57 setStartPC(start_pc); 58 setEndPC(end_pc); 59 setHandlerPC(handler_pc); 60 this.catch_type = catch_type; 61 } 62 63 64 /** 65 * Get CodeException object.<BR> 66 * 67 * This relies on that the instruction list has already been dumped 68 * to byte code or or that the `setPositions' methods has been 69 * called for the instruction list. 70 * 71 * @param cp constant pool 72 */ getCodeException( final ConstantPoolGen cp )73 public CodeException getCodeException( final ConstantPoolGen cp ) { 74 return new CodeException(start_pc.getPosition(), end_pc.getPosition() 75 + end_pc.getInstruction().getLength(), handler_pc.getPosition(), 76 (catch_type == null) ? 0 : cp.addClass(catch_type)); 77 } 78 79 80 /* Set start of handler 81 * @param start_pc Start of handled region (inclusive) 82 */ setStartPC( final InstructionHandle start_pc )83 public void setStartPC( final InstructionHandle start_pc ) { // TODO could be package-protected? 84 BranchInstruction.notifyTarget(this.start_pc, start_pc, this); 85 this.start_pc = start_pc; 86 } 87 88 89 /* Set end of handler 90 * @param end_pc End of handled region (inclusive) 91 */ setEndPC( final InstructionHandle end_pc )92 public void setEndPC( final InstructionHandle end_pc ) { // TODO could be package-protected? 93 BranchInstruction.notifyTarget(this.end_pc, end_pc, this); 94 this.end_pc = end_pc; 95 } 96 97 98 /* Set handler code 99 * @param handler_pc Start of handler 100 */ setHandlerPC( final InstructionHandle handler_pc )101 public void setHandlerPC( final InstructionHandle handler_pc ) { // TODO could be package-protected? 102 BranchInstruction.notifyTarget(this.handler_pc, handler_pc, this); 103 this.handler_pc = handler_pc; 104 } 105 106 107 /** 108 * @param old_ih old target, either start or end 109 * @param new_ih new target 110 */ 111 @Override updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih )112 public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { 113 boolean targeted = false; 114 if (start_pc == old_ih) { 115 targeted = true; 116 setStartPC(new_ih); 117 } 118 if (end_pc == old_ih) { 119 targeted = true; 120 setEndPC(new_ih); 121 } 122 if (handler_pc == old_ih) { 123 targeted = true; 124 setHandlerPC(new_ih); 125 } 126 if (!targeted) { 127 throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", " 128 + end_pc + ", " + handler_pc + "}"); 129 } 130 } 131 132 133 /** 134 * @return true, if ih is target of this handler 135 */ 136 @Override containsTarget( final InstructionHandle ih )137 public boolean containsTarget( final InstructionHandle ih ) { 138 return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih); 139 } 140 141 142 /** Sets the type of the Exception to catch. Set 'null' for ANY. */ setCatchType( final ObjectType catch_type )143 public void setCatchType( final ObjectType catch_type ) { 144 this.catch_type = catch_type; 145 } 146 147 148 /** Gets the type of the Exception to catch, 'null' for ANY. */ getCatchType()149 public ObjectType getCatchType() { 150 return catch_type; 151 } 152 153 154 /** @return start of handled region (inclusive) 155 */ getStartPC()156 public InstructionHandle getStartPC() { 157 return start_pc; 158 } 159 160 161 /** @return end of handled region (inclusive) 162 */ getEndPC()163 public InstructionHandle getEndPC() { 164 return end_pc; 165 } 166 167 168 /** @return start of handler 169 */ getHandlerPC()170 public InstructionHandle getHandlerPC() { 171 return handler_pc; 172 } 173 174 175 @Override toString()176 public String toString() { 177 return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")"; 178 } 179 180 181 @Override clone()182 public Object clone() { 183 try { 184 return super.clone(); 185 } catch (final CloneNotSupportedException e) { 186 throw new Error("Clone Not Supported"); // never happens 187 } 188 } 189 } 190