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