1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /*
6  * Licensed to the Apache Software Foundation (ASF) under one or more
7  * contributor license agreements.  See the NOTICE file distributed with
8  * this work for additional information regarding copyright ownership.
9  * The ASF licenses this file to You under the Apache License, Version 2.0
10  * (the "License"); you may not use this file except in compliance with
11  * the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 package com.sun.org.apache.bcel.internal.generic;
22 
23 import com.sun.org.apache.bcel.internal.classfile.CodeException;
24 
25 /**
26  * This class represents an exception handler, i.e., specifies the  region where
27  * a handler is active and an instruction where the actual handling is done.
28  * pool as parameters. Opposed to the JVM specification the end of the handled
29  * region is set to be inclusive, i.e. all instructions between start and end
30  * are protected including the start and end instructions (handles) themselves.
31  * The end of the region is automatically mapped to be exclusive when calling
32  * getCodeException(), i.e., there is no difference semantically.
33  *
34  * @see     MethodGen
35  * @see     CodeException
36  * @see     InstructionHandle
37  */
38 public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
39 
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      */
CodeExceptionGen(final InstructionHandle start_pc, final InstructionHandle end_pc, final InstructionHandle handler_pc, final ObjectType catch_type)55     public CodeExceptionGen(final InstructionHandle start_pc, final InstructionHandle end_pc,
56             final InstructionHandle handler_pc, final 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      */
getCodeException( final ConstantPoolGen cp )73     public CodeException getCodeException( final 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      */
setStartPC( final InstructionHandle start_pc )83     public void setStartPC( final InstructionHandle start_pc ) { // TODO could be package-protected?
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      */
setEndPC( final InstructionHandle end_pc )92     public void setEndPC( final InstructionHandle end_pc ) { // TODO could be package-protected?
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      */
setHandlerPC( final InstructionHandle handler_pc )101     public void setHandlerPC( final InstructionHandle handler_pc ) { // TODO could be package-protected?
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     @Override
updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih )112     public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) {
113         boolean targeted = false;
114         if (start_pc == old_ih) {
115             targeted = true;
116             setStartPC(new_ih);
117         }
118         if (end_pc == old_ih) {
119             targeted = true;
120             setEndPC(new_ih);
121         }
122         if (handler_pc == old_ih) {
123             targeted = true;
124             setHandlerPC(new_ih);
125         }
126         if (!targeted) {
127             throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", "
128                     + end_pc + ", " + handler_pc + "}");
129         }
130     }
131 
132 
133     /**
134      * @return true, if ih is target of this handler
135      */
136     @Override
containsTarget( final InstructionHandle ih )137     public boolean containsTarget( final InstructionHandle ih ) {
138         return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih);
139     }
140 
141 
142     /** Sets the type of the Exception to catch. Set 'null' for ANY. */
setCatchType( final ObjectType catch_type )143     public void setCatchType( final ObjectType catch_type ) {
144         this.catch_type = catch_type;
145     }
146 
147 
148     /** Gets the type of the Exception to catch, 'null' for ANY. */
getCatchType()149     public ObjectType getCatchType() {
150         return catch_type;
151     }
152 
153 
154     /** @return start of handled region (inclusive)
155      */
getStartPC()156     public InstructionHandle getStartPC() {
157         return start_pc;
158     }
159 
160 
161     /** @return end of handled region (inclusive)
162      */
getEndPC()163     public InstructionHandle getEndPC() {
164         return end_pc;
165     }
166 
167 
168     /** @return start of handler
169      */
getHandlerPC()170     public InstructionHandle getHandlerPC() {
171         return handler_pc;
172     }
173 
174 
175     @Override
toString()176     public String toString() {
177         return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")";
178     }
179 
180 
181     @Override
clone()182     public Object clone() {
183         try {
184             return super.clone();
185         } catch (final CloneNotSupportedException e) {
186             throw new Error("Clone Not Supported"); // never happens
187         }
188     }
189 }
190