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.generic;
20
21 import org.apache.bcel.classfile.CodeException;
22
23 /**
24 * This class represents an exception handler, that is, specifies the region where a handler is active and an instruction
25 * where the actual handling is done. pool as parameters. Opposed to the JVM specification the end of the handled region
26 * is set to be inclusive, for example all instructions between start and end are protected including the start and end
27 * instructions (handles) themselves. The end of the region is automatically mapped to be exclusive when calling
28 * getCodeException(), that is, there is no difference semantically.
29 *
30 * @see MethodGen
31 * @see CodeException
32 * @see InstructionHandle
33 */
34 public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
35
36 static final CodeExceptionGen[] EMPTY_ARRAY = {};
37
38 private InstructionHandle startPc;
39 private InstructionHandle endPc;
40 private InstructionHandle handlerPc;
41 private ObjectType catchType;
42
43 /**
44 * Add an exception handler, that is, specify region where a handler is active and an instruction where the actual handling
45 * is done.
46 *
47 * @param startPc Start of handled region (inclusive).
48 * @param endPc End of handled region (inclusive).
49 * @param handlerPc Where handling is done.
50 * @param catchType which exception is handled, null for ANY.
51 */
52 public CodeExceptionGen(final InstructionHandle startPc, final InstructionHandle endPc, final InstructionHandle handlerPc, final ObjectType catchType) {
53 setStartPC(startPc);
54 setEndPC(endPc);
55 setHandlerPC(handlerPc);
56 this.catchType = catchType;
57 }
58
59 @Override
60 public Object clone() {
61 try {
62 return super.clone();
63 } catch (final CloneNotSupportedException e) {
64 throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
65 }
66 }
67
68 /**
69 * @return true, if ih is target of this handler.
70 */
71 @Override
72 public boolean containsTarget(final InstructionHandle ih) {
73 return startPc == ih || endPc == ih || handlerPc == ih;
74 }
75
76 /**
77 * Gets the type of the Exception to catch, 'null' for ANY.
78 *
79 * @return the type of the Exception to catch, 'null' for ANY.
80 */
81 public ObjectType getCatchType() {
82 return catchType;
83 }
84
85 /**
86 * Gets CodeException object.
87 *
88 * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
89 * has been called for the instruction list.
90 *
91 * @param cp constant pool.
92 * @return the CodeException object.
93 */
94 public CodeException getCodeException(final ConstantPoolGen cp) {
95 return new CodeException(startPc.getPosition(), endPc.getPosition() + endPc.getInstruction().getLength(), handlerPc.getPosition(),
96 catchType == null ? 0 : cp.addClass(catchType));
97 }
98
99 /**
100 * Gets the end of handled region (inclusive).
101 *
102 * @return end of handled region (inclusive).
103 */
104 public InstructionHandle getEndPC() {
105 return endPc;
106 }
107
108 /**
109 * Gets the start of handler.
110 *
111 * @return start of handler.
112 */
113 public InstructionHandle getHandlerPC() {
114 return handlerPc;
115 }
116
117 /**
118 * Gets the start of handled region (inclusive).
119 *
120 * @return start of handled region (inclusive).
121 */
122 public InstructionHandle getStartPC() {
123 return startPc;
124 }
125
126 /**
127 * Sets the type of the Exception to catch. Set 'null' for ANY.
128 *
129 * @param catchType the type of the Exception to catch.
130 */
131 public void setCatchType(final ObjectType catchType) {
132 this.catchType = catchType;
133 }
134
135 /**
136 * Sets end of handler.
137 *
138 * @param endPc End of handled region (inclusive).
139 */
140 public void setEndPC(final InstructionHandle endPc) { // TODO could be package-protected?
141 BranchInstruction.notifyTarget(this.endPc, endPc, this);
142 this.endPc = endPc;
143 }
144
145 /**
146 * Sets handler code.
147 *
148 * @param handlerPc Start of handler.
149 */
150 public void setHandlerPC(final InstructionHandle handlerPc) { // TODO could be package-protected?
151 BranchInstruction.notifyTarget(this.handlerPc, handlerPc, this);
152 this.handlerPc = handlerPc;
153 }
154
155 /**
156 * Sets start of handler.
157 *
158 * @param startPc Start of handled region (inclusive).
159 */
160 public void setStartPC(final InstructionHandle startPc) { // TODO could be package-protected?
161 BranchInstruction.notifyTarget(this.startPc, startPc, this);
162 this.startPc = startPc;
163 }
164
165 @Override
166 public String toString() {
167 return "CodeExceptionGen(" + startPc + ", " + endPc + ", " + handlerPc + ")";
168 }
169
170 /**
171 * @param oldIh old target, either start or end.
172 * @param newIh new target.
173 */
174 @Override
175 public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) {
176 boolean targeted = false;
177 if (startPc == oldIh) {
178 targeted = true;
179 setStartPC(newIh);
180 }
181 if (endPc == oldIh) {
182 targeted = true;
183 setEndPC(newIh);
184 }
185 if (handlerPc == oldIh) {
186 targeted = true;
187 setHandlerPC(newIh);
188 }
189 if (!targeted) {
190 throw new ClassGenException("Not targeting " + oldIh + ", but {" + startPc + ", " + endPc + ", " + handlerPc + "}");
191 }
192 }
193 }