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      */
  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      */
  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      */
  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      */
  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      */
 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
 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
 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. */
 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. */
 149     public ObjectType getCatchType() {
 150         return catch_type;
 151     }
 152 
 153 
 154     /** @return start of handled region (inclusive)
 155      */
 156     public InstructionHandle getStartPC() {
 157         return start_pc;
 158     }
 159 
 160 
 161     /** @return end of handled region (inclusive)
 162      */
 163     public InstructionHandle getEndPC() {
 164         return end_pc;
 165     }
 166 
 167 
 168     /** @return start of handler
 169      */
 170     public InstructionHandle getHandlerPC() {
 171         return handler_pc;
 172     }
 173 
 174 
 175     @Override
 176     public String toString() {
 177         return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")";
 178     }
 179 
 180 
 181     @Override
 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 }