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 * @version $Id: CodeException.java 1806200 2017-08-25 16:33:06Z ggregory $
033 * @see     Code
034 */
035public final class CodeException implements Cloneable, Node, Constants {
036
037    private int start_pc; // Range in the code the exception handler is
038    private int end_pc; // active. start_pc is inclusive, end_pc exclusive
039    private int handler_pc; /* Starting address of exception handler, i.e.,
040     * an offset from start of code.
041     */
042    private int catch_type; /* If this is zero the handler catches any
043     * exception, otherwise it points to the
044     * exception class which is to be caught.
045     */
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    /**
057     * Construct object from file stream.
058     * @param file Input stream
059     * @throws IOException
060     */
061    CodeException(final DataInput file) throws IOException {
062        this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
063                .readUnsignedShort());
064    }
065
066
067    /**
068     * @param start_pc Range in the code the exception handler is active,
069     * start_pc is inclusive while
070     * @param end_pc is exclusive
071     * @param handler_pc Starting address of exception handler, i.e.,
072     * an offset from start of code.
073     * @param catch_type If zero the handler catches any
074     * exception, otherwise it points to the exception class which is
075     * to be caught.
076     */
077    public CodeException(final int start_pc, final int end_pc, final int handler_pc, final int catch_type) {
078        this.start_pc = start_pc;
079        this.end_pc = end_pc;
080        this.handler_pc = handler_pc;
081        this.catch_type = catch_type;
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( final Visitor v ) {
094        v.visitCodeException(this);
095    }
096
097
098    /**
099     * Dump code exception to file stream in binary format.
100     *
101     * @param file Output file stream
102     * @throws IOException
103     */
104    public final void dump( final DataOutputStream file ) throws IOException {
105        file.writeShort(start_pc);
106        file.writeShort(end_pc);
107        file.writeShort(handler_pc);
108        file.writeShort(catch_type);
109    }
110
111
112    /**
113     * @return 0, if the handler catches any exception, otherwise it points to
114     * the exception class which is to be caught.
115     */
116    public final int getCatchType() {
117        return catch_type;
118    }
119
120
121    /**
122     * @return Exclusive end index of the region where the handler is active.
123     */
124    public final int getEndPC() {
125        return end_pc;
126    }
127
128
129    /**
130     * @return Starting address of exception handler, relative to the code.
131     */
132    public final int getHandlerPC() {
133        return handler_pc;
134    }
135
136
137    /**
138     * @return Inclusive start index of the region where the handler is active.
139     */
140    public final int getStartPC() {
141        return start_pc;
142    }
143
144
145    /**
146     * @param catch_type the type of exception that is caught
147     */
148    public final void setCatchType( final int catch_type ) {
149        this.catch_type = catch_type;
150    }
151
152
153    /**
154     * @param end_pc end of handled block
155     */
156    public final void setEndPC( final int end_pc ) {
157        this.end_pc = end_pc;
158    }
159
160
161    /**
162     * @param handler_pc where the actual code is
163     */
164    public final void setHandlerPC( final int handler_pc ) { // TODO unused
165        this.handler_pc = handler_pc;
166    }
167
168
169    /**
170     * @param start_pc start of handled block
171     */
172    public final void setStartPC( final int start_pc ) { // TODO unused
173        this.start_pc = start_pc;
174    }
175
176
177    /**
178     * @return String representation.
179     */
180    @Override
181    public final String toString() {
182        return "CodeException(start_pc = " + start_pc + ", end_pc = " + end_pc + ", handler_pc = "
183                + handler_pc + ", catch_type = " + catch_type + ")";
184    }
185
186
187    /**
188     * @return String representation.
189     */
190    public final String toString( final ConstantPool cp, final boolean verbose ) {
191        String str;
192        if (catch_type == 0) {
193            str = "<Any exception>(0)";
194        } else {
195            str = Utility.compactClassName(cp.getConstantString(catch_type, Const.CONSTANT_Class), false)
196                    + (verbose ? "(" + catch_type + ")" : "");
197        }
198        return start_pc + "\t" + end_pc + "\t" + handler_pc + "\t" + str;
199    }
200
201
202    public final String toString( final ConstantPool cp ) {
203        return toString(cp, true);
204    }
205
206
207    /**
208     * @return deep copy of this object
209     */
210    public CodeException copy() {
211        try {
212            return (CodeException) clone();
213        } catch (final CloneNotSupportedException e) {
214            // TODO should this throw?
215        }
216        return null;
217    }
218}