Home | History | Annotate | Download | only in classfile
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.bcel.classfile;
     19 
     20 import java.io.DataInput;
     21 import java.io.DataOutputStream;
     22 import java.io.IOException;
     23 
     24 import org.apache.bcel.Const;
     25 
     26 /**
     27  * This class represents the table of exceptions that are thrown by a
     28  * method. This attribute may be used once per method.  The name of
     29  * this class is <em>ExceptionTable</em> for historical reasons; The
     30  * Java Virtual Machine Specification, Second Edition defines this
     31  * attribute using the name <em>Exceptions</em> (which is inconsistent
     32  * with the other classes).
     33  *
     34  * @version $Id$
     35  * @see     Code
     36  */
     37 public final class ExceptionTable extends Attribute {
     38 
     39     private int[] exception_index_table; // constant pool
     40 
     41 
     42     /**
     43      * Initialize from another object. Note that both objects use the same
     44      * references (shallow copy). Use copy() for a physical copy.
     45      */
     46     public ExceptionTable(final ExceptionTable c) {
     47         this(c.getNameIndex(), c.getLength(), c.getExceptionIndexTable(), c.getConstantPool());
     48     }
     49 
     50 
     51     /**
     52      * @param name_index Index in constant pool
     53      * @param length Content length in bytes
     54      * @param exception_index_table Table of indices in constant pool
     55      * @param constant_pool Array of constants
     56      */
     57     public ExceptionTable(final int name_index, final int length, final int[] exception_index_table,
     58             final ConstantPool constant_pool) {
     59         super(Const.ATTR_EXCEPTIONS, name_index, length, constant_pool);
     60         this.exception_index_table = exception_index_table != null ? exception_index_table : new int[0];
     61     }
     62 
     63 
     64     /**
     65      * Construct object from input stream.
     66      * @param name_index Index in constant pool
     67      * @param length Content length in bytes
     68      * @param input Input stream
     69      * @param constant_pool Array of constants
     70      * @throws IOException
     71      */
     72     ExceptionTable(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
     73         this(name_index, length, (int[]) null, constant_pool);
     74         final int number_of_exceptions = input.readUnsignedShort();
     75         exception_index_table = new int[number_of_exceptions];
     76         for (int i = 0; i < number_of_exceptions; i++) {
     77             exception_index_table[i] = input.readUnsignedShort();
     78         }
     79     }
     80 
     81 
     82     /**
     83      * Called by objects that are traversing the nodes of the tree implicitely
     84      * defined by the contents of a Java class. I.e., the hierarchy of methods,
     85      * fields, attributes, etc. spawns a tree of objects.
     86      *
     87      * @param v Visitor object
     88      */
     89     @Override
     90     public void accept( final Visitor v ) {
     91         v.visitExceptionTable(this);
     92     }
     93 
     94 
     95     /**
     96      * Dump exceptions attribute to file stream in binary format.
     97      *
     98      * @param file Output file stream
     99      * @throws IOException
    100      */
    101     @Override
    102     public final void dump( final DataOutputStream file ) throws IOException {
    103         super.dump(file);
    104         file.writeShort(exception_index_table.length);
    105         for (final int index : exception_index_table) {
    106             file.writeShort(index);
    107         }
    108     }
    109 
    110 
    111     /**
    112      * @return Array of indices into constant pool of thrown exceptions.
    113      */
    114     public final int[] getExceptionIndexTable() {
    115         return exception_index_table;
    116     }
    117 
    118 
    119     /**
    120      * @return Length of exception table.
    121      */
    122     public final int getNumberOfExceptions() {
    123         return exception_index_table == null ? 0 : exception_index_table.length;
    124     }
    125 
    126 
    127     /**
    128      * @return class names of thrown exceptions
    129      */
    130     public final String[] getExceptionNames() {
    131         final String[] names = new String[exception_index_table.length];
    132         for (int i = 0; i < exception_index_table.length; i++) {
    133             names[i] = super.getConstantPool().getConstantString(exception_index_table[i],
    134                     Const.CONSTANT_Class).replace('/', '.');
    135         }
    136         return names;
    137     }
    138 
    139 
    140     /**
    141      * @param exception_index_table the list of exception indexes
    142      * Also redefines number_of_exceptions according to table length.
    143      */
    144     public final void setExceptionIndexTable( final int[] exception_index_table ) {
    145         this.exception_index_table = exception_index_table != null ? exception_index_table : new int[0];
    146     }
    147 
    148 
    149     /**
    150      * @return String representation, i.e., a list of thrown exceptions.
    151      */
    152     @Override
    153     public final String toString() {
    154         final StringBuilder buf = new StringBuilder();
    155         String str;
    156         buf.append("Exceptions: ");
    157         for (int i = 0; i < exception_index_table.length; i++) {
    158             str = super.getConstantPool().getConstantString(exception_index_table[i], Const.CONSTANT_Class);
    159             buf.append(Utility.compactClassName(str, false));
    160             if (i < exception_index_table.length - 1) {
    161                 buf.append(", ");
    162             }
    163         }
    164         return buf.toString();
    165     }
    166 
    167 
    168     /**
    169      * @return deep copy of this attribute
    170      */
    171     @Override
    172     public Attribute copy( final ConstantPool _constant_pool ) {
    173         final ExceptionTable c = (ExceptionTable) clone();
    174         if (exception_index_table != null) {
    175             c.exception_index_table = new int[exception_index_table.length];
    176             System.arraycopy(exception_index_table, 0, c.exception_index_table, 0,
    177                     exception_index_table.length);
    178         }
    179         c.setConstantPool(_constant_pool);
    180         return c;
    181     }
    182 }
    183