View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   package com.sun.org.apache.bcel.internal.generic;
6   
7   /* ====================================================================
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 2001 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer.
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution,
26   *    if any, must include the following acknowledgment:
27   *       "This product includes software developed by the
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowledgment may appear in the software itself,
30   *    if and wherever such third-party acknowledgments normally appear.
31   *
32   * 4. The names "Apache" and "Apache Software Foundation" and
33   *    "Apache BCEL" must not be used to endorse or promote products
34   *    derived from this software without prior written permission. For
35   *    written permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache",
38   *    "Apache BCEL", nor may "Apache" appear in their name, without
39   *    prior written permission of the Apache Software Foundation.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   */
60  
61  import com.sun.org.apache.bcel.internal.classfile.*;
62  
63  /**
64   * This class represents an exception handler, i.e., specifies the  region where
65   * a handler is active and an instruction where the actual handling is done.
66   * pool as parameters. Opposed to the JVM specification the end of the handled
67   * region is set to be inclusive, i.e. all instructions between start and end
68   * are protected including the start and end instructions (handles) themselves.
69   * The end of the region is automatically mapped to be exclusive when calling
70   * getCodeException(), i.e., there is no difference semantically.
71   *
72   * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
73   * @see     MethodGen
74   * @see     CodeException
75   * @see     InstructionHandle
76   */
77  public final class CodeExceptionGen
78    implements InstructionTargeter, Cloneable, java.io.Serializable {
79    private InstructionHandle start_pc;
80    private InstructionHandle end_pc;
81    private InstructionHandle handler_pc;
82    private ObjectType        catch_type;
83  
84    /**
85     * Add an exception handler, i.e., specify region where a handler is active and an
86     * instruction where the actual handling is done.
87     *
88     * @param start_pc Start of handled region (inclusive)
89     * @param end_pc End of handled region (inclusive)
90     * @param handler_pc Where handling is done
91     * @param catch_type which exception is handled, null for ANY
92     */
93    public CodeExceptionGen(InstructionHandle start_pc, InstructionHandle end_pc,
94                            InstructionHandle handler_pc, ObjectType catch_type) {
95      setStartPC(start_pc);
96      setEndPC(end_pc);
97      setHandlerPC(handler_pc);
98      this.catch_type = catch_type;
99    }
100 
101   /**
102    * Get CodeException object.<BR>
103    *
104    * This relies on that the instruction list has already been dumped
105    * to byte code or or that the `setPositions' methods has been
106    * called for the instruction list.
107    *
108    * @param cp constant pool
109    */
110   public CodeException getCodeException(ConstantPoolGen cp) {
111     return new CodeException(start_pc.getPosition(),
112                              end_pc.getPosition() + end_pc.getInstruction().getLength(),
113                              handler_pc.getPosition(),
114                              (catch_type == null)? 0 : cp.addClass(catch_type));
115   }
116 
117   /* Set start of handler
118    * @param start_pc Start of handled region (inclusive)
119    */
120   public final void setStartPC(InstructionHandle start_pc) {
121     BranchInstruction.notifyTargetChanging(this.start_pc, this);
122     this.start_pc = start_pc;
123     BranchInstruction.notifyTargetChanged(this.start_pc, this);
124   }
125 
126   /* Set end of handler
127    * @param end_pc End of handled region (inclusive)
128    */
129   public final void setEndPC(InstructionHandle end_pc) {
130     BranchInstruction.notifyTargetChanging(this.end_pc, this);
131     this.end_pc = end_pc;
132     BranchInstruction.notifyTargetChanged(this.end_pc, this);
133   }
134 
135   /* Set handler code
136    * @param handler_pc Start of handler
137    */
138   public final void setHandlerPC(InstructionHandle handler_pc) {
139     BranchInstruction.notifyTargetChanging(this.handler_pc, this);
140     this.handler_pc = handler_pc;
141     BranchInstruction.notifyTargetChanged(this.handler_pc, this);
142   }
143 
144   /**
145    * @param old_ih old target, either start or end
146    * @param new_ih new target
147    */
148   @Override
149   public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
150     boolean targeted = false;
151 
152     if(start_pc == old_ih) {
153       targeted = true;
154       setStartPC(new_ih);
155     }
156 
157     if(end_pc == old_ih) {
158       targeted = true;
159       setEndPC(new_ih);
160     }
161 
162     if(handler_pc == old_ih) {
163       targeted = true;
164       setHandlerPC(new_ih);
165     }
166 
167     if(!targeted)
168       throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", " +
169                                   end_pc + ", " + handler_pc + "}");
170   }
171 
172   /**
173    * @return true, if ih is target of this handler
174    */
175   @Override
176   public boolean containsTarget(InstructionHandle ih) {
177     return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih);
178   }
179 
180   /** Sets the type of the Exception to catch. Set 'null' for ANY. */
181   public void              setCatchType(ObjectType catch_type)        { this.catch_type = catch_type; }
182   /** Gets the type of the Exception to catch, 'null' for ANY. */
183   public ObjectType        getCatchType()                             { return catch_type; }
184 
185   /** @return start of handled region (inclusive)
186    */
187   public InstructionHandle getStartPC()                               { return start_pc; }
188 
189   /** @return end of handled region (inclusive)
190    */
191   public InstructionHandle getEndPC()                                 { return end_pc; }
192 
193   /** @return start of handler
194    */
195   public InstructionHandle getHandlerPC()                             { return handler_pc; }
196 
197   @Override
198   public String toString() {
199     return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")";
200   }
201 
202   @Override
203   public Object clone() {
204     try {
205       return super.clone();
206     } catch(CloneNotSupportedException e) {
207       System.err.println(e);
208       return null;
209     }
210   }
211 }