• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ExceptionTableEntry(int start, int end, int handle, int type)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      */
ExceptionTable(ConstPool cp)50     public ExceptionTable(ConstPool cp) {
51         constPool = cp;
52         entries = new ArrayList();
53     }
54 
ExceptionTable(ConstPool cp, DataInputStream in)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      */
clone()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      */
size()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 (&gt;= 0).
93      */
startPc(int nth)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 (&gt;= 0).
103      * @param value             new value.
104      */
setStartPc(int nth, int value)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 (&gt;= 0).
114      */
endPc(int nth)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 (&gt;= 0).
124      * @param value             new value.
125      */
setEndPc(int nth, int value)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 (&gt;= 0).
135      */
handlerPc(int nth)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 (&gt;= 0).
145      * @param value             new value.
146      */
setHandlerPc(int nth, int value)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 (&gt;= 0).
156      * @return an index into the <code>constant_pool</code> table,
157      *          or zero if this exception handler is for all exceptions.
158      */
catchType(int nth)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 (&gt;= 0).
168      * @param value             new value.
169      */
setCatchType(int nth, int value)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 (&gt;= 0) at which the entry is to be inserted.
180      * @param offset    the offset added to the code position.
181      */
add(int index, ExceptionTable table, int offset)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 (&gt;= 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      */
add(int index, int start, int end, int handler, int type)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      */
add(int start, int end, int handler, int type)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      */
remove(int index)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      */
copy(ConstPool newCp, Map classnames)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 
shiftPc(int where, int gapLength, boolean exclusive)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 
shiftPc(int pc, int where, int gapLength, boolean exclusive)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 
write(DataOutputStream out)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