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 */
017package org.apache.bcel.classfile;
018
019import java.io.DataInput;
020import java.io.DataOutputStream;
021import java.io.IOException;
022
023import org.apache.bcel.Const;
024import org.apache.bcel.Constants;
025
026/**
027 * This class represents an entry in the exception table of the <em>Code</em> attribute and is used only there. It
028 * contains a range in which a particular exception handler is active.
029 *
030 * @see Code
031 */
032public final class CodeException implements Cloneable, Node, Constants {
033
034    /**
035     * Empty array.
036     */
037    static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {};
038    private int startPc; // Range in the code the exception handler is
039    private int endPc; // active. startPc is inclusive, endPc exclusive
040    private int handlerPc; /*
041                            * Starting address of exception handler, i.e., an offset from start of code.
042                            */
043
044    private int catchType; /*
045                            * If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught.
046                            */
047
048    /**
049     * Initialize from another object.
050     */
051    public CodeException(final CodeException c) {
052        this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType());
053    }
054
055    /**
056     * Construct object from file stream.
057     *
058     * @param file Input stream
059     * @throws IOException if an I/O error occurs.
060     */
061    CodeException(final DataInput file) throws IOException {
062        this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort());
063    }
064
065    /**
066     * @param startPc Range in the code the exception handler is active, startPc is inclusive while
067     * @param endPc is exclusive
068     * @param handlerPc Starting address of exception handler, i.e., an offset from start of code.
069     * @param catchType If zero the handler catches any exception, otherwise it points to the exception class which is to be
070     *        caught.
071     */
072    public CodeException(final int startPc, final int endPc, final int handlerPc, final int catchType) {
073        this.startPc = startPc;
074        this.endPc = endPc;
075        this.handlerPc = handlerPc;
076        this.catchType = catchType;
077    }
078
079    /**
080     * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
081     * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
082     *
083     * @param v Visitor object
084     */
085    @Override
086    public void accept(final Visitor v) {
087        v.visitCodeException(this);
088    }
089
090    /**
091     * @return deep copy of this object
092     */
093    public CodeException copy() {
094        try {
095            return (CodeException) clone();
096        } catch (final CloneNotSupportedException e) {
097            // TODO should this throw?
098        }
099        return null;
100    }
101
102    /**
103     * Dump code exception to file stream in binary format.
104     *
105     * @param file Output file stream
106     * @throws IOException if an I/O error occurs.
107     */
108    public void dump(final DataOutputStream file) throws IOException {
109        file.writeShort(startPc);
110        file.writeShort(endPc);
111        file.writeShort(handlerPc);
112        file.writeShort(catchType);
113    }
114
115    /**
116     * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught.
117     */
118    public int getCatchType() {
119        return catchType;
120    }
121
122    /**
123     * @return Exclusive end index of the region where the handler is active.
124     */
125    public int getEndPC() {
126        return endPc;
127    }
128
129    /**
130     * @return Starting address of exception handler, relative to the code.
131     */
132    public int getHandlerPC() {
133        return handlerPc;
134    }
135
136    /**
137     * @return Inclusive start index of the region where the handler is active.
138     */
139    public int getStartPC() {
140        return startPc;
141    }
142
143    /**
144     * @param catchType the type of exception that is caught
145     */
146    public void setCatchType(final int catchType) {
147        this.catchType = catchType;
148    }
149
150    /**
151     * @param endPc end of handled block
152     */
153    public void setEndPC(final int endPc) {
154        this.endPc = endPc;
155    }
156
157    /**
158     * @param handlerPc where the actual code is
159     */
160    public void setHandlerPC(final int handlerPc) { // TODO unused
161        this.handlerPc = handlerPc;
162    }
163
164    /**
165     * @param startPc start of handled block
166     */
167    public void setStartPC(final int startPc) { // TODO unused
168        this.startPc = startPc;
169    }
170
171    /**
172     * @return String representation.
173     */
174    @Override
175    public String toString() {
176        return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")";
177    }
178
179    public String toString(final ConstantPool cp) {
180        return toString(cp, true);
181    }
182
183    /**
184     * @return String representation.
185     */
186    public String toString(final ConstantPool cp, final boolean verbose) {
187        String str;
188        if (catchType == 0) {
189            str = "<Any exception>(0)";
190        } else {
191            str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : "");
192        }
193        return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str;
194    }
195}