001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.classfile; 018 019import java.io.DataInput; 020import java.io.DataOutputStream; 021import java.io.IOException; 022 023import org.apache.bcel.Const; 024import org.apache.bcel.Constants; 025import org.apache.bcel.util.Args; 026 027/** 028 * This class represents an entry in the exception table of the <em>Code</em> attribute and is used only there. It 029 * contains a range in which a particular exception handler is active. 030 * 031 * <pre> 032 * Code_attribute { 033 * u2 attribute_name_index; 034 * u4 attribute_length; 035 * u2 max_stack; 036 * u2 max_locals; 037 * u4 code_length; 038 * u1 code[code_length]; 039 * u2 exception_table_length; 040 * { 041 * u2 start_pc; 042 * u2 end_pc; 043 * u2 handler_pc; 044 * u2 catch_type; 045 * } exception_table[exception_table_length]; 046 * u2 attributes_count; 047 * attribute_info attributes[attributes_count]; 048 * } 049 * </pre> 050 * 051 * @see Code 052 */ 053public final class CodeException implements Cloneable, Node, Constants { 054 055 /** 056 * Empty array. 057 */ 058 static final CodeException[] EMPTY_ARRAY = {}; 059 060 /** Range in the code the exception handler. */ 061 private int startPc; 062 063 /** Active. startPc is inclusive, endPc exclusive. */ 064 private int endPc; 065 066 /** 067 * Starting address of exception handler, i.e., an offset from start of code. 068 */ 069 private int handlerPc; 070 071 /* 072 * If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught. 073 */ 074 private int catchType; 075 076 /** 077 * Constructs a new instance from another instance. 078 * 079 * @param c Source for copying. 080 */ 081 public CodeException(final CodeException c) { 082 this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); 083 } 084 085 /** 086 * Constructs a new instance from a DataInput. 087 * 088 * @param file Input stream 089 * @throws IOException if an I/O error occurs. 090 */ 091 CodeException(final DataInput file) throws IOException { 092 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort()); 093 } 094 095 /** 096 * Constructs a new instance. 097 * 098 * @param startPc Range in the code the exception handler is active, startPc is inclusive while 099 * @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}