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 
  22 package com.sun.org.apache.bcel.internal.generic;
  23 
  24 
  25 import com.sun.org.apache.bcel.internal.classfile.*;
  26 
  27 /**
  28  * 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.
  30  * 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
  32  * are protected including the start and end instructions (handles) themselves.
  33  * The end of the region is automatically mapped to be exclusive when calling
  34  * getCodeException(), i.e., there is no difference semantically.
  35  *
  36  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  37  * @see     MethodGen
  38  * @see     CodeException
  39  * @see     InstructionHandle
  40  */
  41 public final class CodeExceptionGen
  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 
  48   /**
  49    * Add an exception handler, i.e., specify region where a handler is active and an
  50    * instruction where the actual handling is done.
  51    *
  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 
  65   /**
  66    * Get CodeException object.<BR>
  67    *
  68    * This relies on that the instruction list has already been dumped
  69    * to byte code or or that the `setPositions' methods has been
  70    * called for the instruction list.
  71    *
  72    * @param cp constant pool
  73    */
  74   public CodeException getCodeException(ConstantPoolGen cp) {
  75     return new CodeException(start_pc.getPosition(),
  76                              end_pc.getPosition() + end_pc.getInstruction().getLength(),
  77                              handler_pc.getPosition(),
  78                              (catch_type == null)? 0 : cp.addClass(catch_type));
  79   }
  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     }
 120 
 121     if(end_pc == old_ih) {
 122       targeted = true;
 123       setEndPC(new_ih);
 124     }
 125 
 126     if(handler_pc == old_ih) {
 127       targeted = true;
 128       setHandlerPC(new_ih);
 129     }
 130 
 131     if(!targeted)
 132       throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", " +
 133                                   end_pc + ", " + handler_pc + "}");
 134   }
 135 
 136   /**
 137    * @return true, if ih is target of this handler
 138    */
 139   @Override
 140   public boolean containsTarget(InstructionHandle ih) {
 141     return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih);
 142   }
 143 
 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 
 149   /** @return start of handled region (inclusive)
 150    */
 151   public InstructionHandle getStartPC()                               { return start_pc; }
 152 
 153   /** @return end of handled region (inclusive)
 154    */
 155   public InstructionHandle getEndPC()                                 { return end_pc; }
 156 
 157   /** @return start of handler
 158    */
 159   public InstructionHandle getHandlerPC()                             { return handler_pc; }
 160 
 161   @Override
 162   public String toString() {
 163     return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")";
 164   }
 165 
 166   @Override
 167   public Object clone() {
 168     try {
 169       return super.clone();
 170     } catch(CloneNotSupportedException e) {
 171       System.err.println(e);
 172       return null;
 173     }
 174   }
 175 }