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; 025 026/** 027 * This class represents an entry in the exception table of the <em>Code</em> attribute and is used only there. It 028 * contains a range in which a particular exception handler is active. 029 * 030 * @see Code 031 */ 032public final class CodeException implements Cloneable, Node, Constants { 033 034 /** 035 * Empty array. 036 */ 037 static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {}; 038 private int startPc; // Range in the code the exception handler is 039 private int endPc; // active. startPc is inclusive, endPc exclusive 040 private int handlerPc; /* 041 * Starting address of exception handler, i.e., an offset from start of code. 042 */ 043 044 private int catchType; /* 045 * If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught. 046 */ 047 048 /** 049 * Initialize from another object. 050 */ 051 public CodeException(final CodeException c) { 052 this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); 053 } 054 055 /** 056 * Construct object from file stream. 057 * 058 * @param file Input stream 059 * @throws IOException if an I/O error occurs. 060 */ 061 CodeException(final DataInput file) throws IOException { 062 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort()); 063 } 064 065 /** 066 * @param startPc Range in the code the exception handler is active, startPc is inclusive while 067 * @param endPc is exclusive 068 * @param handlerPc Starting address of exception handler, i.e., an offset from start of code. 069 * @param catchType If zero the handler catches any exception, otherwise it points to the exception class which is to be 070 * caught. 071 */ 072 public CodeException(final int startPc, final int endPc, final int handlerPc, final int catchType) { 073 this.startPc = startPc; 074 this.endPc = endPc; 075 this.handlerPc = handlerPc; 076 this.catchType = catchType; 077 } 078 079 /** 080 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 081 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 082 * 083 * @param v Visitor object 084 */ 085 @Override 086 public void accept(final Visitor v) { 087 v.visitCodeException(this); 088 } 089 090 /** 091 * @return deep copy of this object 092 */ 093 public CodeException copy() { 094 try { 095 return (CodeException) clone(); 096 } catch (final CloneNotSupportedException e) { 097 // TODO should this throw? 098 } 099 return null; 100 } 101 102 /** 103 * Dump code exception to file stream in binary format. 104 * 105 * @param file Output file stream 106 * @throws IOException if an I/O error occurs. 107 */ 108 public void dump(final DataOutputStream file) throws IOException { 109 file.writeShort(startPc); 110 file.writeShort(endPc); 111 file.writeShort(handlerPc); 112 file.writeShort(catchType); 113 } 114 115 /** 116 * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught. 117 */ 118 public int getCatchType() { 119 return catchType; 120 } 121 122 /** 123 * @return Exclusive end index of the region where the handler is active. 124 */ 125 public int getEndPC() { 126 return endPc; 127 } 128 129 /** 130 * @return Starting address of exception handler, relative to the code. 131 */ 132 public int getHandlerPC() { 133 return handlerPc; 134 } 135 136 /** 137 * @return Inclusive start index of the region where the handler is active. 138 */ 139 public int getStartPC() { 140 return startPc; 141 } 142 143 /** 144 * @param catchType the type of exception that is caught 145 */ 146 public void setCatchType(final int catchType) { 147 this.catchType = catchType; 148 } 149 150 /** 151 * @param endPc end of handled block 152 */ 153 public void setEndPC(final int endPc) { 154 this.endPc = endPc; 155 } 156 157 /** 158 * @param handlerPc where the actual code is 159 */ 160 public void setHandlerPC(final int handlerPc) { // TODO unused 161 this.handlerPc = handlerPc; 162 } 163 164 /** 165 * @param startPc start of handled block 166 */ 167 public void setStartPC(final int startPc) { // TODO unused 168 this.startPc = startPc; 169 } 170 171 /** 172 * @return String representation. 173 */ 174 @Override 175 public String toString() { 176 return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")"; 177 } 178 179 public String toString(final ConstantPool cp) { 180 return toString(cp, true); 181 } 182 183 /** 184 * @return String representation. 185 */ 186 public String toString(final ConstantPool cp, final boolean verbose) { 187 String str; 188 if (catchType == 0) { 189 str = "<Any exception>(0)"; 190 } else { 191 str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : ""); 192 } 193 return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str; 194 } 195}