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