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 start_pc; // Range in the code the exception handler is
037    private int end_pc; // active. start_pc is inclusive, end_pc exclusive
038    private int handler_pc; /* Starting address of exception handler, i.e.,
039     * an offset from start of code.
040     */
041    private int catch_type; /* 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 start_pc Range in the code the exception handler is active,
068     * start_pc is inclusive while
069     * @param end_pc is exclusive
070     * @param handler_pc Starting address of exception handler, i.e.,
071     * an offset from start of code.
072     * @param catch_type 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 start_pc, final int end_pc, final int handler_pc, final int catch_type) {
077        this.start_pc = start_pc;
078        this.end_pc = end_pc;
079        this.handler_pc = handler_pc;
080        this.catch_type = catch_type;
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(start_pc);
105        file.writeShort(end_pc);
106        file.writeShort(handler_pc);
107        file.writeShort(catch_type);
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 catch_type;
117    }
118
119
120    /**
121     * @return Exclusive end index of the region where the handler is active.
122     */
123    public int getEndPC() {
124        return end_pc;
125    }
126
127
128    /**
129     * @return Starting address of exception handler, relative to the code.
130     */
131    public int getHandlerPC() {
132        return handler_pc;
133    }
134
135
136    /**
137     * @return Inclusive start index of the region where the handler is active.
138     */
139    public int getStartPC() {
140        return start_pc;
141    }
142
143
144    /**
145     * @param catch_type the type of exception that is caught
146     */
147    public void setCatchType( final int catch_type ) {
148        this.catch_type = catch_type;
149    }
150
151
152    /**
153     * @param end_pc end of handled block
154     */
155    public void setEndPC( final int end_pc ) {
156        this.end_pc = end_pc;
157    }
158
159
160    /**
161     * @param handler_pc where the actual code is
162     */
163    public void setHandlerPC( final int handler_pc ) { // TODO unused
164        this.handler_pc = handler_pc;
165    }
166
167
168    /**
169     * @param start_pc start of handled block
170     */
171    public void setStartPC( final int start_pc ) { // TODO unused
172        this.start_pc = start_pc;
173    }
174
175
176    /**
177     * @return String representation.
178     */
179    @Override
180    public String toString() {
181        return "CodeException(start_pc = " + start_pc + ", end_pc = " + end_pc + ", handler_pc = "
182                + handler_pc + ", catch_type = " + catch_type + ")";
183    }
184
185
186    /**
187     * @return String representation.
188     */
189    public String toString( final ConstantPool cp, final boolean verbose ) {
190        String str;
191        if (catch_type == 0) {
192            str = "<Any exception>(0)";
193        } else {
194            str = Utility.compactClassName(cp.getConstantString(catch_type, Const.CONSTANT_Class), false)
195                    + (verbose ? "(" + catch_type + ")" : "");
196        }
197        return start_pc + "\t" + end_pc + "\t" + handler_pc + "\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}