• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (&gt;= 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 (&gt;= 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 (&gt;= 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 (&gt;= 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 (&gt;= 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 (&gt;= 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 (&gt;= 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 (&gt;= 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 (&gt;= 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 (&gt;= 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