1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 package org.apache.bcel.classfile;
19 
20 import java.io.DataInput;
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 
24 import org.apache.bcel.Const;
25 import org.apache.bcel.Constants;
26 
27 /**
28  * This class represents an entry in the exception table of the <em>Code</em>
29  * attribute and is used only there. It contains a range in which a
30  * particular exception handler is active.
31  *
32  * @version $Id$
33  * @see     Code
34  */
35 public final class CodeException implements Cloneable, Node, Constants {
36 
37     private int start_pc; // Range in the code the exception handler is
38     private int end_pc; // active. start_pc is inclusive, end_pc exclusive
39     private int handler_pc; /* Starting address of exception handler, i.e.,
40      * an offset from start of code.
41      */
42     private int catch_type; /* If this is zero the handler catches any
43      * exception, otherwise it points to the
44      * exception class which is to be caught.
45      */
46 
47 
48     /**
49      * Initialize from another object.
50      */
CodeException(final CodeException c)51     public CodeException(final CodeException c) {
52         this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType());
53     }
54 
55 
56     /**
57      * Construct object from file stream.
58      * @param file Input stream
59      * @throws IOException
60      */
CodeException(final DataInput file)61     CodeException(final DataInput file) throws IOException {
62         this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
63                 .readUnsignedShort());
64     }
65 
66 
67     /**
68      * @param start_pc Range in the code the exception handler is active,
69      * start_pc is inclusive while
70      * @param end_pc is exclusive
71      * @param handler_pc Starting address of exception handler, i.e.,
72      * an offset from start of code.
73      * @param catch_type If zero the handler catches any
74      * exception, otherwise it points to the exception class which is
75      * to be caught.
76      */
CodeException(final int start_pc, final int end_pc, final int handler_pc, final int catch_type)77     public CodeException(final int start_pc, final int end_pc, final int handler_pc, final int catch_type) {
78         this.start_pc = start_pc;
79         this.end_pc = end_pc;
80         this.handler_pc = handler_pc;
81         this.catch_type = catch_type;
82     }
83 
84 
85     /**
86      * Called by objects that are traversing the nodes of the tree implicitely
87      * defined by the contents of a Java class. I.e., the hierarchy of methods,
88      * fields, attributes, etc. spawns a tree of objects.
89      *
90      * @param v Visitor object
91      */
92     @Override
accept( final Visitor v )93     public void accept( final Visitor v ) {
94         v.visitCodeException(this);
95     }
96 
97 
98     /**
99      * Dump code exception to file stream in binary format.
100      *
101      * @param file Output file stream
102      * @throws IOException
103      */
dump( final DataOutputStream file )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      */
getCatchType()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      */
getEndPC()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      */
getHandlerPC()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      */
getStartPC()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      */
setCatchType( final int catch_type )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      */
setEndPC( final int end_pc )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      */
setHandlerPC( final int handler_pc )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      */
setStartPC( final int start_pc )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
toString()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      */
toString( final ConstantPool cp, final boolean verbose )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 
toString( final ConstantPool cp )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      */
copy()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 }
219