1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16 package javassist.bytecode; 17 18 import java.io.DataInputStream; 19 import java.io.DataOutputStream; 20 import java.io.IOException; 21 import java.util.ArrayList; 22 import java.util.Map; 23 24 class ExceptionTableEntry { 25 int startPc; 26 int endPc; 27 int handlerPc; 28 int catchType; 29 30 ExceptionTableEntry(int start, int end, int handle, int type) { 31 startPc = start; 32 endPc = end; 33 handlerPc = handle; 34 catchType = type; 35 } 36 } 37 38 /** 39 * <code>exception_table[]</code> of <code>Code_attribute</code>. 40 */ 41 public class ExceptionTable implements Cloneable { 42 private ConstPool constPool; 43 private ArrayList entries; 44 45 /** 46 * Constructs an <code>exception_table[]</code>. 47 * 48 * @param cp constant pool table. 49 */ 50 public ExceptionTable(ConstPool cp) { 51 constPool = cp; 52 entries = new ArrayList(); 53 } 54 55 ExceptionTable(ConstPool cp, DataInputStream in) throws IOException { 56 constPool = cp; 57 int length = in.readUnsignedShort(); 58 ArrayList list = new ArrayList(length); 59 for (int i = 0; i < length; ++i) { 60 int start = in.readUnsignedShort(); 61 int end = in.readUnsignedShort(); 62 int handle = in.readUnsignedShort(); 63 int type = in.readUnsignedShort(); 64 list.add(new ExceptionTableEntry(start, end, handle, type)); 65 } 66 67 entries = list; 68 } 69 70 /** 71 * Creates and returns a copy of this object. 72 * The constant pool object is shared between this object 73 * and the cloned object. 74 */ 75 public Object clone() throws CloneNotSupportedException { 76 ExceptionTable r = (ExceptionTable)super.clone(); 77 r.entries = new ArrayList(entries); 78 return r; 79 } 80 81 /** 82 * Returns <code>exception_table_length</code>, which is the number 83 * of entries in the <code>exception_table[]</code>. 84 */ 85 public int size() { 86 return entries.size(); 87 } 88 89 /** 90 * Returns <code>startPc</code> of the <i>n</i>-th entry. 91 * 92 * @param nth the <i>n</i>-th (>= 0). 93 */ 94 public int startPc(int nth) { 95 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 96 return e.startPc; 97 } 98 99 /** 100 * Sets <code>startPc</code> of the <i>n</i>-th entry. 101 * 102 * @param nth the <i>n</i>-th (>= 0). 103 * @param value new value. 104 */ 105 public void setStartPc(int nth, int value) { 106 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 107 e.startPc = value; 108 } 109 110 /** 111 * Returns <code>endPc</code> of the <i>n</i>-th entry. 112 * 113 * @param nth the <i>n</i>-th (>= 0). 114 */ 115 public int endPc(int nth) { 116 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 117 return e.endPc; 118 } 119 120 /** 121 * Sets <code>endPc</code> of the <i>n</i>-th entry. 122 * 123 * @param nth the <i>n</i>-th (>= 0). 124 * @param value new value. 125 */ 126 public void setEndPc(int nth, int value) { 127 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 128 e.endPc = value; 129 } 130 131 /** 132 * Returns <code>handlerPc</code> of the <i>n</i>-th entry. 133 * 134 * @param nth the <i>n</i>-th (>= 0). 135 */ 136 public int handlerPc(int nth) { 137 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 138 return e.handlerPc; 139 } 140 141 /** 142 * Sets <code>handlerPc</code> of the <i>n</i>-th entry. 143 * 144 * @param nth the <i>n</i>-th (>= 0). 145 * @param value new value. 146 */ 147 public void setHandlerPc(int nth, int value) { 148 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 149 e.handlerPc = value; 150 } 151 152 /** 153 * Returns <code>catchType</code> of the <i>n</i>-th entry. 154 * 155 * @param nth the <i>n</i>-th (>= 0). 156 * @return an index into the <code>constant_pool</code> table, 157 * or zero if this exception handler is for all exceptions. 158 */ 159 public int catchType(int nth) { 160 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 161 return e.catchType; 162 } 163 164 /** 165 * Sets <code>catchType</code> of the <i>n</i>-th entry. 166 * 167 * @param nth the <i>n</i>-th (>= 0). 168 * @param value new value. 169 */ 170 public void setCatchType(int nth, int value) { 171 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth); 172 e.catchType = value; 173 } 174 175 /** 176 * Copies the given exception table at the specified position 177 * in the table. 178 * 179 * @param index index (>= 0) at which the entry is to be inserted. 180 * @param offset the offset added to the code position. 181 */ 182 public void add(int index, ExceptionTable table, int offset) { 183 int len = table.size(); 184 while (--len >= 0) { 185 ExceptionTableEntry e 186 = (ExceptionTableEntry)table.entries.get(len); 187 add(index, e.startPc + offset, e.endPc + offset, 188 e.handlerPc + offset, e.catchType); 189 } 190 } 191 192 /** 193 * Adds a new entry at the specified position in the table. 194 * 195 * @param index index (>= 0) at which the entry is to be inserted. 196 * @param start <code>startPc</code> 197 * @param end <code>endPc</code> 198 * @param handler <code>handlerPc</code> 199 * @param type <code>catchType</code> 200 */ 201 public void add(int index, int start, int end, int handler, int type) { 202 if (start < end) 203 entries.add(index, 204 new ExceptionTableEntry(start, end, handler, type)); 205 } 206 207 /** 208 * Appends a new entry at the end of the table. 209 * 210 * @param start <code>startPc</code> 211 * @param end <code>endPc</code> 212 * @param handler <code>handlerPc</code> 213 * @param type <code>catchType</code> 214 */ 215 public void add(int start, int end, int handler, int type) { 216 if (start < end) 217 entries.add(new ExceptionTableEntry(start, end, handler, type)); 218 } 219 220 /** 221 * Removes the entry at the specified position in the table. 222 * 223 * @param index the index of the removed entry. 224 */ 225 public void remove(int index) { 226 entries.remove(index); 227 } 228 229 /** 230 * Makes a copy of this <code>exception_table[]</code>. 231 * Class names are replaced according to the 232 * given <code>Map</code> object. 233 * 234 * @param newCp the constant pool table used by the new copy. 235 * @param classnames pairs of replaced and substituted 236 * class names. 237 */ 238 public ExceptionTable copy(ConstPool newCp, Map classnames) { 239 ExceptionTable et = new ExceptionTable(newCp); 240 ConstPool srcCp = constPool; 241 int len = size(); 242 for (int i = 0; i < len; ++i) { 243 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i); 244 int type = srcCp.copy(e.catchType, newCp, classnames); 245 et.add(e.startPc, e.endPc, e.handlerPc, type); 246 } 247 248 return et; 249 } 250 251 void shiftPc(int where, int gapLength, boolean exclusive) { 252 int len = size(); 253 for (int i = 0; i < len; ++i) { 254 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i); 255 e.startPc = shiftPc(e.startPc, where, gapLength, exclusive); 256 e.endPc = shiftPc(e.endPc, where, gapLength, exclusive); 257 e.handlerPc = shiftPc(e.handlerPc, where, gapLength, exclusive); 258 } 259 } 260 261 private static int shiftPc(int pc, int where, int gapLength, 262 boolean exclusive) { 263 if (pc > where || (exclusive && pc == where)) 264 pc += gapLength; 265 266 return pc; 267 } 268 269 void write(DataOutputStream out) throws IOException { 270 int len = size(); 271 out.writeShort(len); // exception_table_length 272 for (int i = 0; i < len; ++i) { 273 ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i); 274 out.writeShort(e.startPc); 275 out.writeShort(e.endPc); 276 out.writeShort(e.handlerPc); 277 out.writeShort(e.catchType); 278 } 279 } 280 } 281