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