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