001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License. 
016     *
017     */
018    package org.apache.bcel.classfile;
019    
020    import java.io.DataInputStream;
021    import java.io.DataOutputStream;
022    import java.io.IOException;
023    import org.apache.bcel.Constants;
024    
025    /** 
026     * This class represents the table of exceptions that are thrown by a
027     * method. This attribute may be used once per method.  The name of
028     * this class is <em>ExceptionTable</em> for historical reasons; The
029     * Java Virtual Machine Specification, Second Edition defines this
030     * attribute using the name <em>Exceptions</em> (which is inconsistent
031     * with the other classes).
032     *
033     * @version $Id: ExceptionTable.java 1152077 2011-07-29 02:29:42Z dbrosius $
034     * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
035     * @see     Code
036     */
037    public final class ExceptionTable extends Attribute {
038    
039        private static final long serialVersionUID = 2045358830660883220L;
040        private int number_of_exceptions; // Table of indices into
041        private int[] exception_index_table; // constant pool
042    
043    
044        /**
045         * Initialize from another object. Note that both objects use the same
046         * references (shallow copy). Use copy() for a physical copy.
047         */
048        public ExceptionTable(ExceptionTable c) {
049            this(c.getNameIndex(), c.getLength(), c.getExceptionIndexTable(), c.getConstantPool());
050        }
051    
052    
053        /**
054         * @param name_index Index in constant pool
055         * @param length Content length in bytes
056         * @param exception_index_table Table of indices in constant pool
057         * @param constant_pool Array of constants
058         */
059        public ExceptionTable(int name_index, int length, int[] exception_index_table,
060                ConstantPool constant_pool) {
061            super(Constants.ATTR_EXCEPTIONS, name_index, length, constant_pool);
062            setExceptionIndexTable(exception_index_table);
063        }
064    
065    
066        /**
067         * Construct object from file stream.
068         * @param name_index Index in constant pool
069         * @param length Content length in bytes
070         * @param file Input stream
071         * @param constant_pool Array of constants
072         * @throws IOException
073         */
074        ExceptionTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
075                throws IOException {
076            this(name_index, length, (int[]) null, constant_pool);
077            number_of_exceptions = file.readUnsignedShort();
078            exception_index_table = new int[number_of_exceptions];
079            for (int i = 0; i < number_of_exceptions; i++) {
080                exception_index_table[i] = file.readUnsignedShort();
081            }
082        }
083    
084    
085        /**
086         * Called by objects that are traversing the nodes of the tree implicitely
087         * defined by the contents of a Java class. I.e., the hierarchy of methods,
088         * fields, attributes, etc. spawns a tree of objects.
089         *
090         * @param v Visitor object
091         */
092        @Override
093        public void accept( Visitor v ) {
094            v.visitExceptionTable(this);
095        }
096    
097    
098        /**
099         * Dump exceptions attribute to file stream in binary format.
100         *
101         * @param file Output file stream
102         * @throws IOException
103         */
104        @Override
105        public final void dump( DataOutputStream file ) throws IOException {
106            super.dump(file);
107            file.writeShort(number_of_exceptions);
108            for (int i = 0; i < number_of_exceptions; i++) {
109                file.writeShort(exception_index_table[i]);
110            }
111        }
112    
113    
114        /**
115         * @return Array of indices into constant pool of thrown exceptions.
116         */
117        public final int[] getExceptionIndexTable() {
118            return exception_index_table;
119        }
120    
121    
122        /**
123         * @return Length of exception table.
124         */
125        public final int getNumberOfExceptions() {
126            return number_of_exceptions;
127        }
128    
129    
130        /**
131         * @return class names of thrown exceptions
132         */
133        public final String[] getExceptionNames() {
134            String[] names = new String[number_of_exceptions];
135            for (int i = 0; i < number_of_exceptions; i++) {
136                names[i] = constant_pool.getConstantString(exception_index_table[i],
137                        Constants.CONSTANT_Class).replace('/', '.');
138            }
139            return names;
140        }
141    
142    
143        /**
144         * @param exception_index_table the list of exception indexes
145         * Also redefines number_of_exceptions according to table length.
146         */
147        public final void setExceptionIndexTable( int[] exception_index_table ) {
148            this.exception_index_table = exception_index_table;
149            number_of_exceptions = (exception_index_table == null) ? 0 : exception_index_table.length;
150        }
151    
152    
153        /**
154         * @return String representation, i.e., a list of thrown exceptions.
155         */
156        @Override
157        public final String toString() {
158            StringBuilder buf = new StringBuilder();
159            String str;
160            for (int i = 0; i < number_of_exceptions; i++) {
161                str = constant_pool.getConstantString(exception_index_table[i],
162                        Constants.CONSTANT_Class);
163                buf.append(Utility.compactClassName(str, false));
164                if (i < number_of_exceptions - 1) {
165                    buf.append(", ");
166                }
167            }
168            return buf.toString();
169        }
170    
171    
172        /**
173         * @return deep copy of this attribute
174         */
175        @Override
176        public Attribute copy( ConstantPool _constant_pool ) {
177            ExceptionTable c = (ExceptionTable) clone();
178            if (exception_index_table != null) {
179                c.exception_index_table = new int[exception_index_table.length];
180                System.arraycopy(exception_index_table, 0, c.exception_index_table, 0,
181                        exception_index_table.length);
182            }
183            c.constant_pool = _constant_pool;
184            return c;
185        }
186    }