View Javadoc
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   * @see     MethodGen
32   * @see     CodeException
33   * @see     InstructionHandle
34   */
35  public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
36  
37      private InstructionHandle startPc;
38      private InstructionHandle endPc;
39      private InstructionHandle handlerPc;
40      private ObjectType catchType;
41  
42  
43      /**
44       * Add an exception handler, i.e., specify region where a handler is active and an
45       * instruction where the actual handling 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.html#InstructionHandle">InstructionHandle startPc, final InstructionHandle endPc,
53              final InstructionHandle handlerPc, final ObjectType catchType) {
54          setStartPC(startPc);
55          setEndPC(endPc);
56          setHandlerPC(handlerPc);
57          this.catchType = catchType;
58      }
59  
60  
61      /**
62       * Get CodeException object.<BR>
63       *
64       * This relies on that the instruction list has already been dumped
65       * to byte code or or that the `setPositions' methods has been
66       * called for the instruction list.
67       *
68       * @param cp constant pool
69       */
70      public CodeException getCodeException( final ConstantPoolGen cp ) {
71          return new CodeException(startPc.getPosition(), endPc.getPosition()
72                  + endPc.getInstruction().getLength(), handlerPc.getPosition(),
73                  (catchType == null) ? 0 : cp.addClass(catchType));
74      }
75  
76  
77      /* Set start of handler
78       * @param startPc Start of handled region (inclusive)
79       */
80      public void setStartPC( final InstructionHandle start_pc ) { // TODO could be package-protected?
81          BranchInstruction.notifyTarget(this.startPc, start_pc, this);
82          this.startPc = start_pc;
83      }
84  
85  
86      /* Set end of handler
87       * @param endPc End of handled region (inclusive)
88       */
89      public void setEndPC( final InstructionHandle end_pc ) { // TODO could be package-protected?
90          BranchInstruction.notifyTarget(this.endPc, end_pc, this);
91          this.endPc = end_pc;
92      }
93  
94  
95      /* Set handler code
96       * @param handlerPc Start of handler
97       */
98      public void setHandlerPC( final InstructionHandle handler_pc ) { // TODO could be package-protected?
99          BranchInstruction.notifyTarget(this.handlerPc, handler_pc, this);
100         this.handlerPc = handler_pc;
101     }
102 
103 
104     /**
105      * @param old_ih old target, either start or end
106      * @param new_ih new target
107      */
108     @Override
109     public void updateTarget( final InstructionHandlee.html#InstructionHandle">InstructionHandle old_ih, final InstructionHandle new_ih ) {
110         boolean targeted = false;
111         if (startPc == old_ih) {
112             targeted = true;
113             setStartPC(new_ih);
114         }
115         if (endPc == old_ih) {
116             targeted = true;
117             setEndPC(new_ih);
118         }
119         if (handlerPc == old_ih) {
120             targeted = true;
121             setHandlerPC(new_ih);
122         }
123         if (!targeted) {
124             throw new ClassGenException("Not targeting " + old_ih + ", but {" + startPc + ", "
125                     + endPc + ", " + handlerPc + "}");
126         }
127     }
128 
129 
130     /**
131      * @return true, if ih is target of this handler
132      */
133     @Override
134     public boolean containsTarget( final InstructionHandle ih ) {
135         return (startPc == ih) || (endPc == ih) || (handlerPc == ih);
136     }
137 
138 
139     /** Sets the type of the Exception to catch. Set 'null' for ANY. */
140     public void setCatchType( final ObjectType catchType ) {
141         this.catchType = catchType;
142     }
143 
144 
145     /** Gets the type of the Exception to catch, 'null' for ANY. */
146     public ObjectType getCatchType() {
147         return catchType;
148     }
149 
150 
151     /** @return start of handled region (inclusive)
152      */
153     public InstructionHandle getStartPC() {
154         return startPc;
155     }
156 
157 
158     /** @return end of handled region (inclusive)
159      */
160     public InstructionHandle getEndPC() {
161         return endPc;
162     }
163 
164 
165     /** @return start of handler
166      */
167     public InstructionHandle getHandlerPC() {
168         return handlerPc;
169     }
170 
171 
172     @Override
173     public String toString() {
174         return "CodeExceptionGen(" + startPc + ", " + endPc + ", " + handlerPc + ")";
175     }
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     }
186 }