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, i.e., 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, i.e., 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 * @return deep copy of this object
126 */
127 public CodeException copy() {
128 try {
129 return (CodeException) clone();
130 } catch (final CloneNotSupportedException e) {
131 // TODO should this throw?
132 }
133 return null;
134 }
135
136 /**
137 * Dumps code exception to file stream in binary format.
138 *
139 * @param file Output file stream
140 * @throws IOException if an I/O error occurs.
141 */
142 public void dump(final DataOutputStream file) throws IOException {
143 file.writeShort(startPc);
144 file.writeShort(endPc);
145 file.writeShort(handlerPc);
146 file.writeShort(catchType);
147 }
148
149 /**
150 * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught.
151 */
152 public int getCatchType() {
153 return catchType;
154 }
155
156 /**
157 * @return Exclusive end index of the region where the handler is active.
158 */
159 public int getEndPC() {
160 return endPc;
161 }
162
163 /**
164 * @return Starting address of exception handler, relative to the code.
165 */
166 public int getHandlerPC() {
167 return handlerPc;
168 }
169
170 /**
171 * @return Inclusive start index of the region where the handler is active.
172 */
173 public int getStartPC() {
174 return startPc;
175 }
176
177 /**
178 * @param catchType the type of exception that is caught
179 */
180 public void setCatchType(final int catchType) {
181 this.catchType = catchType;
182 }
183
184 /**
185 * @param endPc end of handled block
186 */
187 public void setEndPC(final int endPc) {
188 this.endPc = endPc;
189 }
190
191 /**
192 * @param handlerPc where the actual code is
193 */
194 public void setHandlerPC(final int handlerPc) { // TODO unused
195 this.handlerPc = handlerPc;
196 }
197
198 /**
199 * @param startPc start of handled block
200 */
201 public void setStartPC(final int startPc) { // TODO unused
202 this.startPc = startPc;
203 }
204
205 /**
206 * @return String representation.
207 */
208 @Override
209 public String toString() {
210 return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")";
211 }
212
213 public String toString(final ConstantPool cp) {
214 return toString(cp, true);
215 }
216
217 /**
218 * @param cp constant pool source.
219 * @param verbose Output more if true.
220 * @return String representation.
221 */
222 public String toString(final ConstantPool cp, final boolean verbose) {
223 final String str;
224 if (catchType == 0) {
225 str = "<Any exception>(0)";
226 } else {
227 str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : "");
228 }
229 return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str;
230 }
231 }