View Javadoc

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