001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.bytecode;
017:
018: import java.io.DataInputStream;
019: import java.io.DataOutputStream;
020: import java.io.IOException;
021: import java.util.ArrayList;
022: import java.util.Map;
023:
024: class ExceptionTableEntry {
025: int startPc;
026: int endPc;
027: int handlerPc;
028: int catchType;
029:
030: ExceptionTableEntry(int start, int end, int handle, int type) {
031: startPc = start;
032: endPc = end;
033: handlerPc = handle;
034: catchType = type;
035: }
036: }
037:
038: /**
039: * <code>exception_table[]</code> of <code>Code_attribute</code>.
040: */
041: public class ExceptionTable implements Cloneable {
042: private ConstPool constPool;
043: private ArrayList entries;
044:
045: /**
046: * Constructs an <code>exception_table[]</code>.
047: *
048: * @param cp constant pool table.
049: */
050: public ExceptionTable(ConstPool cp) {
051: constPool = cp;
052: entries = new ArrayList();
053: }
054:
055: ExceptionTable(ConstPool cp, DataInputStream in) throws IOException {
056: constPool = cp;
057: int length = in.readUnsignedShort();
058: ArrayList list = new ArrayList(length);
059: for (int i = 0; i < length; ++i) {
060: int start = in.readUnsignedShort();
061: int end = in.readUnsignedShort();
062: int handle = in.readUnsignedShort();
063: int type = in.readUnsignedShort();
064: list.add(new ExceptionTableEntry(start, end, handle, type));
065: }
066:
067: entries = list;
068: }
069:
070: /**
071: * Creates and returns a copy of this object.
072: * The constant pool object is shared between this object
073: * and the cloned object.
074: */
075: public Object clone() throws CloneNotSupportedException {
076: ExceptionTable r = (ExceptionTable) super .clone();
077: r.entries = new ArrayList(entries);
078: return r;
079: }
080:
081: /**
082: * Returns <code>exception_table_length</code>, which is the number
083: * of entries in the <code>exception_table[]</code>.
084: */
085: public int size() {
086: return entries.size();
087: }
088:
089: /**
090: * Returns <code>startPc</code> of the <i>n</i>-th entry.
091: *
092: * @param nth the <i>n</i>-th (>= 0).
093: */
094: public int startPc(int nth) {
095: ExceptionTableEntry e = (ExceptionTableEntry) entries.get(nth);
096: return e.startPc;
097: }
098:
099: /**
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: */
157: public int catchType(int nth) {
158: ExceptionTableEntry e = (ExceptionTableEntry) entries.get(nth);
159: return e.catchType;
160: }
161:
162: /**
163: * Sets <code>catchType</code> of the <i>n</i>-th entry.
164: *
165: * @param nth the <i>n</i>-th (>= 0).
166: * @param value new value.
167: */
168: public void setCatchType(int nth, int value) {
169: ExceptionTableEntry e = (ExceptionTableEntry) entries.get(nth);
170: e.catchType = value;
171: }
172:
173: /**
174: * Copies the given exception table at the specified position
175: * in the table.
176: *
177: * @param index index (>= 0) at which the entry is to be inserted.
178: * @param offset the offset added to the code position.
179: */
180: public void add(int index, ExceptionTable table, int offset) {
181: int len = table.size();
182: while (--len >= 0) {
183: ExceptionTableEntry e = (ExceptionTableEntry) table.entries
184: .get(len);
185: add(index, e.startPc + offset, e.endPc + offset,
186: e.handlerPc + offset, e.catchType);
187: }
188: }
189:
190: /**
191: * Adds a new entry at the specified position in the table.
192: *
193: * @param index index (>= 0) at which the entry is to be inserted.
194: * @param start <code>startPc</code>
195: * @param end <code>endPc</code>
196: * @param handler <code>handlerPc</code>
197: * @param type <code>catchType</code>
198: */
199: public void add(int index, int start, int end, int handler, int type) {
200: if (start < end)
201: entries.add(index, new ExceptionTableEntry(start, end,
202: handler, type));
203: }
204:
205: /**
206: * Appends a new entry at the end of the table.
207: *
208: * @param start <code>startPc</code>
209: * @param end <code>endPc</code>
210: * @param handler <code>handlerPc</code>
211: * @param type <code>catchType</code>
212: */
213: public void add(int start, int end, int handler, int type) {
214: if (start < end)
215: entries.add(new ExceptionTableEntry(start, end, handler,
216: type));
217: }
218:
219: /**
220: * Removes the entry at the specified position in the table.
221: *
222: * @param index the index of the removed entry.
223: */
224: public void remove(int index) {
225: entries.remove(index);
226: }
227:
228: /**
229: * Makes a copy of this <code>exception_table[]</code>.
230: * Class names are replaced according to the
231: * given <code>Map</code> object.
232: *
233: * @param newCp the constant pool table used by the new copy.
234: * @param classnames pairs of replaced and substituted
235: * class names.
236: */
237: public ExceptionTable copy(ConstPool newCp, Map classnames) {
238: ExceptionTable et = new ExceptionTable(newCp);
239: ConstPool srcCp = constPool;
240: int len = size();
241: for (int i = 0; i < len; ++i) {
242: ExceptionTableEntry e = (ExceptionTableEntry) entries
243: .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
255: .get(i);
256: e.startPc = shiftPc(e.startPc, where, gapLength, exclusive);
257: e.endPc = shiftPc(e.endPc, where, gapLength, exclusive);
258: e.handlerPc = shiftPc(e.handlerPc, where, gapLength,
259: exclusive);
260: }
261: }
262:
263: private static int shiftPc(int pc, int where, int gapLength,
264: boolean exclusive) {
265: if (pc > where || (exclusive && pc == where))
266: pc += gapLength;
267:
268: return pc;
269: }
270:
271: void write(DataOutputStream out) throws IOException {
272: int len = size();
273: out.writeShort(len); // exception_table_length
274: for (int i = 0; i < len; ++i) {
275: ExceptionTableEntry e = (ExceptionTableEntry) entries
276: .get(i);
277: out.writeShort(e.startPc);
278: out.writeShort(e.endPc);
279: out.writeShort(e.handlerPc);
280: out.writeShort(e.catchType);
281: }
282: }
283: }
|