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  * @version $Id$
  35  * @see     MethodGen
  36  * @see     CodeException
  37  * @see     InstructionHandle
  38  */
  39 public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
  40 
  41     private InstructionHandle start_pc;
  42     private InstructionHandle end_pc;
  43     private InstructionHandle handler_pc;
  44     private ObjectType catch_type;
  45 
  46 
  47     /**
  48      * Add an exception handler, i.e., specify region where a handler is active and an
  49      * instruction where the actual handling is done.
  50      *
  51      * @param start_pc Start of handled region (inclusive)
  52      * @param end_pc End of handled region (inclusive)
  53      * @param handler_pc Where handling is done
  54      * @param catch_type which exception is handled, null for ANY
  55      */
  56     public CodeExceptionGen(final InstructionHandle start_pc, final InstructionHandle end_pc,
  57             final InstructionHandle handler_pc, final ObjectType catch_type) {
  58         setStartPC(start_pc);
  59         setEndPC(end_pc);
  60         setHandlerPC(handler_pc);
  61         this.catch_type = catch_type;
  62     }
  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( final ConstantPoolGen cp ) {
  75         return new CodeException(start_pc.getPosition(), end_pc.getPosition()
  76                 + end_pc.getInstruction().getLength(), handler_pc.getPosition(),
  77                 (catch_type == null) ? 0 : cp.addClass(catch_type));
  78     }
  79 
  80 
  81     /* Set start of handler
  82      * @param start_pc Start of handled region (inclusive)
  83      */
  84     public void setStartPC( final InstructionHandle start_pc ) { // TODO could be package-protected?
  85         BranchInstruction.notifyTarget(this.start_pc, start_pc, this);
  86         this.start_pc = start_pc;
  87     }
  88 
  89 
  90     /* Set end of handler
  91      * @param end_pc End of handled region (inclusive)
  92      */
  93     public void setEndPC( final InstructionHandle end_pc ) { // TODO could be package-protected?
  94         BranchInstruction.notifyTarget(this.end_pc, end_pc, this);
  95         this.end_pc = end_pc;
  96     }
  97 
  98 
  99     /* Set handler code
 100      * @param handler_pc Start of handler
 101      */
 102     public void setHandlerPC( final InstructionHandle handler_pc ) { // TODO could be package-protected?
 103         BranchInstruction.notifyTarget(this.handler_pc, handler_pc, this);
 104         this.handler_pc = handler_pc;
 105     }
 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( final InstructionHandle old_ih, final InstructionHandle new_ih ) {
 114         boolean targeted = false;
 115         if (start_pc == old_ih) {
 116             targeted = true;
 117             setStartPC(new_ih);
 118         }
 119         if (end_pc == old_ih) {
 120             targeted = true;
 121             setEndPC(new_ih);
 122         }
 123         if (handler_pc == old_ih) {
 124             targeted = true;
 125             setHandlerPC(new_ih);
 126         }
 127         if (!targeted) {
 128             throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", "
 129                     + end_pc + ", " + handler_pc + "}");
 130         }
 131     }
 132 
 133 
 134     /**
 135      * @return true, if ih is target of this handler
 136      */
 137     @Override
 138     public boolean containsTarget( final InstructionHandle ih ) {
 139         return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih);
 140     }
 141 
 142 
 143     /** Sets the type of the Exception to catch. Set 'null' for ANY. */
 144     public void setCatchType( final ObjectType catch_type ) {
 145         this.catch_type = catch_type;
 146     }
 147 
 148 
 149     /** Gets the type of the Exception to catch, 'null' for ANY. */
 150     public ObjectType getCatchType() {
 151         return catch_type;
 152     }
 153 
 154 
 155     /** @return start of handled region (inclusive)
 156      */
 157     public InstructionHandle getStartPC() {
 158         return start_pc;
 159     }
 160 
 161 
 162     /** @return end of handled region (inclusive)
 163      */
 164     public InstructionHandle getEndPC() {
 165         return end_pc;
 166     }
 167 
 168 
 169     /** @return start of handler
 170      */
 171     public InstructionHandle getHandlerPC() {
 172         return handler_pc;
 173     }
 174 
 175 
 176     @Override
 177     public String toString() {
 178         return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")";
 179     }
 180 
 181 
 182     @Override
 183     public Object clone() {
 184         try {
 185             return super.clone();
 186         } catch (final CloneNotSupportedException e) {
 187             throw new Error("Clone Not Supported"); // never happens
 188         }
 189     }
 190 }