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