1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.classfile;
20
21 import java.io.DataInput;
22 import java.io.DataOutputStream;
23 import java.io.IOException;
24
25 import org.apache.bcel.Const;
26 import org.apache.bcel.Constants;
27 import org.apache.bcel.util.Args;
28
29 /**
30 * This class represents an entry in the exception table of the <em>Code</em> attribute and is used only there. It
31 * contains a range in which a particular exception handler is active.
32 *
33 * <pre>
34 * Code_attribute {
35 * u2 attribute_name_index;
36 * u4 attribute_length;
37 * u2 max_stack;
38 * u2 max_locals;
39 * u4 code_length;
40 * u1 code[code_length];
41 * u2 exception_table_length;
42 * {
43 * u2 start_pc;
44 * u2 end_pc;
45 * u2 handler_pc;
46 * u2 catch_type;
47 * } exception_table[exception_table_length];
48 * u2 attributes_count;
49 * attribute_info attributes[attributes_count];
50 * }
51 * </pre>
52 *
53 * @see Code
54 */
55 public final class CodeException implements Cloneable, Node, Constants {
56
57 /**
58 * Empty array.
59 */
60 static final CodeException[] EMPTY_ARRAY = {};
61
62 /** Range in the code the exception handler. */
63 private int startPc;
64
65 /** Active. startPc is inclusive, endPc exclusive. */
66 private int endPc;
67
68 /**
69 * Starting address of exception handler, that is, an offset from start of code.
70 */
71 private int handlerPc;
72
73 /*
74 * If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught.
75 */
76 private int catchType;
77
78 /**
79 * Constructs a new instance from another instance.
80 *
81 * @param c Source for copying.
82 */
83 public CodeException(final CodeException c) {
84 this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType());
85 }
86
87 /**
88 * Constructs a new instance from a DataInput.
89 *
90 * @param file Input stream.
91 * @throws IOException if an I/O error occurs.
92 */
93 CodeException(final DataInput file) throws IOException {
94 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort());
95 }
96
97 /**
98 * Constructs a new instance.
99 *
100 * @param startPc Range in the code the exception handler is active, startPc is inclusive while.
101 * @param endPc is exclusive.
102 * @param handlerPc Starting address of exception handler, that is, an offset from start of code.
103 * @param catchType If zero the handler catches any exception, otherwise it points to the exception class which is to be
104 * caught.
105 */
106 public CodeException(final int startPc, final int endPc, final int handlerPc, final int catchType) {
107 this.startPc = Args.requireU2(startPc, "startPc");
108 this.endPc = Args.requireU2(endPc, "endPc");
109 this.handlerPc = Args.requireU2(handlerPc, "handlerPc");
110 this.catchType = Args.requireU2(catchType, "catchType");
111 }
112
113 /**
114 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
115 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
116 *
117 * @param v Visitor object.
118 */
119 @Override
120 public void accept(final Visitor v) {
121 v.visitCodeException(this);
122 }
123
124 /**
125 * Creates a deep copy of this object.
126 *
127 * @return deep copy of this object.
128 */
129 public CodeException copy() {
130 try {
131 return (CodeException) clone();
132 } catch (final CloneNotSupportedException e) {
133 // TODO should this throw?
134 }
135 return null;
136 }
137
138 /**
139 * Dumps code exception to file stream in binary format.
140 *
141 * @param file Output file stream.
142 * @throws IOException if an I/O error occurs.
143 */
144 public void dump(final DataOutputStream file) throws IOException {
145 file.writeShort(startPc);
146 file.writeShort(endPc);
147 file.writeShort(handlerPc);
148 file.writeShort(catchType);
149 }
150
151 /**
152 * Gets the type of exception that is caught.
153 *
154 * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught.
155 */
156 public int getCatchType() {
157 return catchType;
158 }
159
160 /**
161 * Gets the exclusive end index of the region where the handler is active.
162 *
163 * @return Exclusive end index of the region where the handler is active.
164 */
165 public int getEndPC() {
166 return endPc;
167 }
168
169 /**
170 * Gets the starting address of exception handler, relative to the code.
171 *
172 * @return Starting address of exception handler, relative to the code.
173 */
174 public int getHandlerPC() {
175 return handlerPc;
176 }
177
178 /**
179 * Gets the inclusive start index of the region where the handler is active.
180 *
181 * @return Inclusive start index of the region where the handler is active.
182 */
183 public int getStartPC() {
184 return startPc;
185 }
186
187 /**
188 * Sets the type of exception that is caught.
189 *
190 * @param catchType the type of exception that is caught.
191 */
192 public void setCatchType(final int catchType) {
193 this.catchType = catchType;
194 }
195
196 /**
197 * Sets the end of handled block.
198 *
199 * @param endPc end of handled block.
200 */
201 public void setEndPC(final int endPc) {
202 this.endPc = endPc;
203 }
204
205 /**
206 * Sets where the actual code is.
207 *
208 * @param handlerPc where the actual code is.
209 */
210 public void setHandlerPC(final int handlerPc) { // TODO unused
211 this.handlerPc = handlerPc;
212 }
213
214 /**
215 * Sets the start of handled block.
216 *
217 * @param startPc start of handled block.
218 */
219 public void setStartPC(final int startPc) { // TODO unused
220 this.startPc = startPc;
221 }
222
223 /**
224 * Gets a string representation.
225 *
226 * @return String representation.
227 */
228 @Override
229 public String toString() {
230 return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")";
231 }
232
233 /**
234 * Gets a string representation with constant pool.
235 *
236 * @param cp constant pool source.
237 * @return String representation.
238 */
239 public String toString(final ConstantPool cp) {
240 return toString(cp, true);
241 }
242
243 /**
244 * Gets a string representation with constant pool.
245 *
246 * @param cp constant pool source.
247 * @param verbose Output more if true.
248 * @return String representation.
249 */
250 public String toString(final ConstantPool cp, final boolean verbose) {
251 final String str;
252 if (catchType == 0) {
253 str = "<Any exception>(0)";
254 } else {
255 str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : "");
256 }
257 return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str;
258 }
259 }