Home | History | Annotate | Download | only in bytecode
      1 /*
      2  * Javassist, a Java-bytecode translator toolkit.
      3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License.  Alternatively, the contents of this file may be used under
      8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  */
     15 
     16 package javassist.bytecode;
     17 
     18 import java.io.DataInputStream;
     19 import java.io.DataOutputStream;
     20 import java.io.IOException;
     21 import java.util.ArrayList;
     22 import java.util.Map;
     23 
     24 class ExceptionTableEntry {
     25     int startPc;
     26     int endPc;
     27     int handlerPc;
     28     int catchType;
     29 
     30     ExceptionTableEntry(int start, int end, int handle, int type) {
     31         startPc = start;
     32         endPc = end;
     33         handlerPc = handle;
     34         catchType = type;
     35     }
     36 }
     37 
     38 /**
     39  * <code>exception_table[]</code> of <code>Code_attribute</code>.
     40  */
     41 public class ExceptionTable implements Cloneable {
     42     private ConstPool constPool;
     43     private ArrayList entries;
     44 
     45     /**
     46      * Constructs an <code>exception_table[]</code>.
     47      *
     48      * @param cp        constant pool table.
     49      */
     50     public ExceptionTable(ConstPool cp) {
     51         constPool = cp;
     52         entries = new ArrayList();
     53     }
     54 
     55     ExceptionTable(ConstPool cp, DataInputStream in) throws IOException {
     56         constPool = cp;
     57         int length = in.readUnsignedShort();
     58         ArrayList list = new ArrayList(length);
     59         for (int i = 0; i < length; ++i) {
     60             int start = in.readUnsignedShort();
     61             int end = in.readUnsignedShort();
     62             int handle = in.readUnsignedShort();
     63             int type = in.readUnsignedShort();
     64             list.add(new ExceptionTableEntry(start, end, handle, type));
     65         }
     66 
     67         entries = list;
     68     }
     69 
     70     /**
     71      * Creates and returns a copy of this object.
     72      * The constant pool object is shared between this object
     73      * and the cloned object.
     74      */
     75     public Object clone() throws CloneNotSupportedException {
     76         ExceptionTable r = (ExceptionTable)super.clone();
     77         r.entries = new ArrayList(entries);
     78         return r;
     79     }
     80 
     81     /**
     82      * Returns <code>exception_table_length</code>, which is the number
     83      * of entries in the <code>exception_table[]</code>.
     84      */
     85     public int size() {
     86         return entries.size();
     87     }
     88 
     89     /**
     90      * Returns <code>startPc</code> of the <i>n</i>-th entry.
     91      *
     92      * @param nth               the <i>n</i>-th (&gt;= 0).
     93      */
     94     public int startPc(int nth) {
     95         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
     96         return e.startPc;
     97     }
     98 
     99     /**
    100      * Sets <code>startPc</code> of the <i>n</i>-th entry.
    101      *
    102      * @param nth               the <i>n</i>-th (&gt;= 0).
    103      * @param value             new value.
    104      */
    105     public void setStartPc(int nth, int value) {
    106         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
    107         e.startPc = value;
    108     }
    109 
    110     /**
    111      * Returns <code>endPc</code> of the <i>n</i>-th entry.
    112      *
    113      * @param nth               the <i>n</i>-th (&gt;= 0).
    114      */
    115     public int endPc(int nth) {
    116         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
    117         return e.endPc;
    118     }
    119 
    120     /**
    121      * Sets <code>endPc</code> of the <i>n</i>-th entry.
    122      *
    123      * @param nth               the <i>n</i>-th (&gt;= 0).
    124      * @param value             new value.
    125      */
    126     public void setEndPc(int nth, int value) {
    127         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
    128         e.endPc = value;
    129     }
    130 
    131     /**
    132      * Returns <code>handlerPc</code> of the <i>n</i>-th entry.
    133      *
    134      * @param nth               the <i>n</i>-th (&gt;= 0).
    135      */
    136     public int handlerPc(int nth) {
    137         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
    138         return e.handlerPc;
    139     }
    140 
    141     /**
    142      * Sets <code>handlerPc</code> of the <i>n</i>-th entry.
    143      *
    144      * @param nth               the <i>n</i>-th (&gt;= 0).
    145      * @param value             new value.
    146      */
    147     public void setHandlerPc(int nth, int value) {
    148         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
    149         e.handlerPc = value;
    150     }
    151 
    152     /**
    153      * Returns <code>catchType</code> of the <i>n</i>-th entry.
    154      *
    155      * @param nth               the <i>n</i>-th (&gt;= 0).
    156      * @return an index into the <code>constant_pool</code> table,
    157      *          or zero if this exception handler is for all exceptions.
    158      */
    159     public int catchType(int nth) {
    160         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
    161         return e.catchType;
    162     }
    163 
    164     /**
    165      * Sets <code>catchType</code> of the <i>n</i>-th entry.
    166      *
    167      * @param nth               the <i>n</i>-th (&gt;= 0).
    168      * @param value             new value.
    169      */
    170     public void setCatchType(int nth, int value) {
    171         ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
    172         e.catchType = value;
    173     }
    174 
    175     /**
    176      * Copies the given exception table at the specified position
    177      * in the table.
    178      *
    179      * @param index     index (&gt;= 0) at which the entry is to be inserted.
    180      * @param offset    the offset added to the code position.
    181      */
    182     public void add(int index, ExceptionTable table, int offset) {
    183         int len = table.size();
    184         while (--len >= 0) {
    185             ExceptionTableEntry e
    186                 = (ExceptionTableEntry)table.entries.get(len);
    187             add(index, e.startPc + offset, e.endPc + offset,
    188                 e.handlerPc + offset, e.catchType);
    189         }
    190     }
    191 
    192     /**
    193      * Adds a new entry at the specified position in the table.
    194      *
    195      * @param index     index (&gt;= 0) at which the entry is to be inserted.
    196      * @param start     <code>startPc</code>
    197      * @param end       <code>endPc</code>
    198      * @param handler   <code>handlerPc</code>
    199      * @param type      <code>catchType</code>
    200      */
    201     public void add(int index, int start, int end, int handler, int type) {
    202         if (start < end)
    203             entries.add(index,
    204                     new ExceptionTableEntry(start, end, handler, type));
    205     }
    206 
    207     /**
    208      * Appends a new entry at the end of the table.
    209      *
    210      * @param start     <code>startPc</code>
    211      * @param end       <code>endPc</code>
    212      * @param handler   <code>handlerPc</code>
    213      * @param type      <code>catchType</code>
    214      */
    215     public void add(int start, int end, int handler, int type) {
    216         if (start < end)
    217             entries.add(new ExceptionTableEntry(start, end, handler, type));
    218     }
    219 
    220     /**
    221      * Removes the entry at the specified position in the table.
    222      *
    223      * @param index     the index of the removed entry.
    224      */
    225     public void remove(int index) {
    226         entries.remove(index);
    227     }
    228 
    229     /**
    230      * Makes a copy of this <code>exception_table[]</code>.
    231      * Class names are replaced according to the
    232      * given <code>Map</code> object.
    233      *
    234      * @param newCp     the constant pool table used by the new copy.
    235      * @param classnames        pairs of replaced and substituted
    236      *                          class names.
    237      */
    238     public ExceptionTable copy(ConstPool newCp, Map classnames) {
    239         ExceptionTable et = new ExceptionTable(newCp);
    240         ConstPool srcCp = constPool;
    241         int len = size();
    242         for (int i = 0; i < len; ++i) {
    243             ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i);
    244             int type = srcCp.copy(e.catchType, newCp, classnames);
    245             et.add(e.startPc, e.endPc, e.handlerPc, type);
    246         }
    247 
    248         return et;
    249     }
    250 
    251     void shiftPc(int where, int gapLength, boolean exclusive) {
    252         int len = size();
    253         for (int i = 0; i < len; ++i) {
    254             ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i);
    255             e.startPc = shiftPc(e.startPc, where, gapLength, exclusive);
    256             e.endPc = shiftPc(e.endPc, where, gapLength, exclusive);
    257             e.handlerPc = shiftPc(e.handlerPc, where, gapLength, exclusive);
    258         }
    259     }
    260 
    261     private static int shiftPc(int pc, int where, int gapLength,
    262                                boolean exclusive) {
    263         if (pc > where || (exclusive && pc == where))
    264             pc += gapLength;
    265 
    266         return pc;
    267     }
    268 
    269     void write(DataOutputStream out) throws IOException {
    270         int len = size();
    271         out.writeShort(len);            // exception_table_length
    272         for (int i = 0; i < len; ++i) {
    273             ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i);
    274             out.writeShort(e.startPc);
    275             out.writeShort(e.endPc);
    276             out.writeShort(e.handlerPc);
    277             out.writeShort(e.catchType);
    278         }
    279     }
    280 }
    281