1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.bcel.classfile; 18 19 import java.io.DataInput; 20 import java.io.DataOutputStream; 21 import java.io.IOException; 22 23 import org.apache.bcel.Const; 24 import org.apache.bcel.Constants; 25 import org.apache.bcel.util.Args; 26 27 /** 28 * This class represents an entry in the exception table of the <em>Code</em> attribute and is used only there. It 29 * contains a range in which a particular exception handler is active. 30 * 31 * <pre> 32 * Code_attribute { 33 * u2 attribute_name_index; 34 * u4 attribute_length; 35 * u2 max_stack; 36 * u2 max_locals; 37 * u4 code_length; 38 * u1 code[code_length]; 39 * u2 exception_table_length; 40 * { 41 * u2 start_pc; 42 * u2 end_pc; 43 * u2 handler_pc; 44 * u2 catch_type; 45 * } exception_table[exception_table_length]; 46 * u2 attributes_count; 47 * attribute_info attributes[attributes_count]; 48 * } 49 * </pre> 50 * 51 * @see Code 52 */ 53 public final class CodeException implements Cloneable, Node, Constants { 54 55 /** 56 * Empty array. 57 */ 58 static final CodeException[] EMPTY_ARRAY = {}; 59 60 /** Range in the code the exception handler. */ 61 private int startPc; 62 63 /** Active. startPc is inclusive, endPc exclusive. */ 64 private int endPc; 65 66 /** 67 * Starting address of exception handler, i.e., an offset from start of code. 68 */ 69 private int handlerPc; 70 71 /* 72 * If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught. 73 */ 74 private int catchType; 75 76 /** 77 * Constructs a new instance from another instance. 78 * 79 * @param c Source for copying. 80 */ 81 public CodeException(final CodeException c) { 82 this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); 83 } 84 85 /** 86 * Constructs a new instance from a DataInput. 87 * 88 * @param file Input stream 89 * @throws IOException if an I/O error occurs. 90 */ 91 CodeException(final DataInput file) throws IOException { 92 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort()); 93 } 94 95 /** 96 * Constructs a new instance. 97 * 98 * @param startPc Range in the code the exception handler is active, startPc is inclusive while 99 * @param endPc is exclusive 100 * @param handlerPc Starting address of exception handler, i.e., an offset from start of code. 101 * @param catchType If zero the handler catches any exception, otherwise it points to the exception class which is to be 102 * caught. 103 */ 104 public CodeException(final int startPc, final int endPc, final int handlerPc, final int catchType) { 105 this.startPc = Args.requireU2(startPc, "startPc"); 106 this.endPc = Args.requireU2(endPc, "endPc"); 107 this.handlerPc = Args.requireU2(handlerPc, "handlerPc"); 108 this.catchType = Args.requireU2(catchType, "catchType"); 109 } 110 111 /** 112 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 113 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 114 * 115 * @param v Visitor object 116 */ 117 @Override 118 public void accept(final Visitor v) { 119 v.visitCodeException(this); 120 } 121 122 /** 123 * @return deep copy of this object 124 */ 125 public CodeException copy() { 126 try { 127 return (CodeException) clone(); 128 } catch (final CloneNotSupportedException e) { 129 // TODO should this throw? 130 } 131 return null; 132 } 133 134 /** 135 * Dumps code exception to file stream in binary format. 136 * 137 * @param file Output file stream 138 * @throws IOException if an I/O error occurs. 139 */ 140 public void dump(final DataOutputStream file) throws IOException { 141 file.writeShort(startPc); 142 file.writeShort(endPc); 143 file.writeShort(handlerPc); 144 file.writeShort(catchType); 145 } 146 147 /** 148 * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught. 149 */ 150 public int getCatchType() { 151 return catchType; 152 } 153 154 /** 155 * @return Exclusive end index of the region where the handler is active. 156 */ 157 public int getEndPC() { 158 return endPc; 159 } 160 161 /** 162 * @return Starting address of exception handler, relative to the code. 163 */ 164 public int getHandlerPC() { 165 return handlerPc; 166 } 167 168 /** 169 * @return Inclusive start index of the region where the handler is active. 170 */ 171 public int getStartPC() { 172 return startPc; 173 } 174 175 /** 176 * @param catchType the type of exception that is caught 177 */ 178 public void setCatchType(final int catchType) { 179 this.catchType = catchType; 180 } 181 182 /** 183 * @param endPc end of handled block 184 */ 185 public void setEndPC(final int endPc) { 186 this.endPc = endPc; 187 } 188 189 /** 190 * @param handlerPc where the actual code is 191 */ 192 public void setHandlerPC(final int handlerPc) { // TODO unused 193 this.handlerPc = handlerPc; 194 } 195 196 /** 197 * @param startPc start of handled block 198 */ 199 public void setStartPC(final int startPc) { // TODO unused 200 this.startPc = startPc; 201 } 202 203 /** 204 * @return String representation. 205 */ 206 @Override 207 public String toString() { 208 return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")"; 209 } 210 211 public String toString(final ConstantPool cp) { 212 return toString(cp, true); 213 } 214 215 /** 216 * @param cp constant pool source. 217 * @param verbose Output more if true. 218 * @return String representation. 219 */ 220 public String toString(final ConstantPool cp, final boolean verbose) { 221 String str; 222 if (catchType == 0) { 223 str = "<Any exception>(0)"; 224 } else { 225 str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : ""); 226 } 227 return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str; 228 } 229 }