1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18 package org.apache.bcel.generic;
19
20 import org.apache.bcel.classfile.CodeException;
21
22 /**
23 * This class represents an exception handler, i.e., specifies the region where
24 * a handler is active and an instruction where the actual handling is done.
25 * pool as parameters. Opposed to the JVM specification the end of the handled
26 * region is set to be inclusive, i.e. all instructions between start and end
27 * are protected including the start and end instructions (handles) themselves.
28 * The end of the region is automatically mapped to be exclusive when calling
29 * getCodeException(), i.e., there is no difference semantically.
30 *
31 * @version $Id: CodeExceptionGen.java 1152072 2011-07-29 01:54:05Z dbrosius $
32 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
33 * @see MethodGen
34 * @see CodeException
35 * @see InstructionHandle
36 */
37 public final class CodeExceptionGen implements InstructionTargeter, Cloneable, java.io.Serializable {
38
39 private static final long serialVersionUID = 6548901422158960190L;
40 private InstructionHandle start_pc;
41 private InstructionHandle end_pc;
42 private InstructionHandle handler_pc;
43 private ObjectType catch_type;
44
45
46 /**
47 * Add an exception handler, i.e., specify region where a handler is active and an
48 * instruction where the actual handling is done.
49 *
50 * @param start_pc Start of handled region (inclusive)
51 * @param end_pc End of handled region (inclusive)
52 * @param handler_pc Where handling is done
53 * @param catch_type which exception is handled, null for ANY
54 */
55 public CodeExceptionGen(InstructionHandle start_pc, InstructionHandle end_pc,
56 InstructionHandle handler_pc, ObjectType catch_type) {
57 setStartPC(start_pc);
58 setEndPC(end_pc);
59 setHandlerPC(handler_pc);
60 this.catch_type = catch_type;
61 }
62
63
64 /**
65 * Get CodeException object.<BR>
66 *
67 * This relies on that the instruction list has already been dumped
68 * to byte code or or that the `setPositions' methods has been
69 * called for the instruction list.
70 *
71 * @param cp constant pool
72 */
73 public CodeException getCodeException( ConstantPoolGen cp ) {
74 return new CodeException(start_pc.getPosition(), end_pc.getPosition()
75 + end_pc.getInstruction().getLength(), handler_pc.getPosition(),
76 (catch_type == null) ? 0 : cp.addClass(catch_type));
77 }
78
79
80 /* Set start of handler
81 * @param start_pc Start of handled region (inclusive)
82 */
83 public void setStartPC( InstructionHandle start_pc ) {
84 BranchInstruction.notifyTarget(this.start_pc, start_pc, this);
85 this.start_pc = start_pc;
86 }
87
88
89 /* Set end of handler
90 * @param end_pc End of handled region (inclusive)
91 */
92 public void setEndPC( InstructionHandle end_pc ) {
93 BranchInstruction.notifyTarget(this.end_pc, end_pc, this);
94 this.end_pc = end_pc;
95 }
96
97
98 /* Set handler code
99 * @param handler_pc Start of handler
100 */
101 public void setHandlerPC( InstructionHandle handler_pc ) {
102 BranchInstruction.notifyTarget(this.handler_pc, handler_pc, this);
103 this.handler_pc = handler_pc;
104 }
105
106
107 /**
108 * @param old_ih old target, either start or end
109 * @param new_ih new target
110 */
111 public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
112 boolean targeted = false;
113 if (start_pc == old_ih) {
114 targeted = true;
115 setStartPC(new_ih);
116 }
117 if (end_pc == old_ih) {
118 targeted = true;
119 setEndPC(new_ih);
120 }
121 if (handler_pc == old_ih) {
122 targeted = true;
123 setHandlerPC(new_ih);
124 }
125 if (!targeted) {
126 throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", "
127 + end_pc + ", " + handler_pc + "}");
128 }
129 }
130
131
132 /**
133 * @return true, if ih is target of this handler
134 */
135 public boolean containsTarget( InstructionHandle ih ) {
136 return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih);
137 }
138
139
140 /** Sets the type of the Exception to catch. Set 'null' for ANY. */
141 public void setCatchType( ObjectType catch_type ) {
142 this.catch_type = catch_type;
143 }
144
145
146 /** Gets the type of the Exception to catch, 'null' for ANY. */
147 public ObjectType getCatchType() {
148 return catch_type;
149 }
150
151
152 /** @return start of handled region (inclusive)
153 */
154 public InstructionHandle getStartPC() {
155 return start_pc;
156 }
157
158
159 /** @return end of handled region (inclusive)
160 */
161 public InstructionHandle getEndPC() {
162 return end_pc;
163 }
164
165
166 /** @return start of handler
167 */
168 public InstructionHandle getHandlerPC() {
169 return handler_pc;
170 }
171
172
173 @Override
174 public String toString() {
175 return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")";
176 }
177
178
179 @Override
180 public Object clone() {
181 try {
182 return super.clone();
183 } catch (CloneNotSupportedException e) {
184 System.err.println(e);
185 return null;
186 }
187 }
188 }