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 
26 /**
27  * This class represents the type of a local variable or item on stack
28  * used in the StackMap entries.
29  *
30  * @version $Id$
31  * @see     StackMapEntry
32  * @see     StackMap
33  * @see     Const
34  */
35 public final class StackMapType implements Cloneable {
36 
37     private byte type;
38     private int index = -1; // Index to CONSTANT_Class or offset
39     private ConstantPool constant_pool;
40 
41 
42     /**
43      * Construct object from file stream.
44      * @param file Input stream
45      * @throws IOException
46      */
StackMapType(final DataInput file, final ConstantPool constant_pool)47     StackMapType(final DataInput file, final ConstantPool constant_pool) throws IOException {
48         this(file.readByte(), -1, constant_pool);
49         if (hasIndex()) {
50             this.index = file.readShort();
51         }
52         this.constant_pool = constant_pool;
53     }
54 
55 
56     /**
57      * @param type type tag as defined in the Constants interface
58      * @param index index to constant pool, or byte code offset
59      */
StackMapType(final byte type, final int index, final ConstantPool constant_pool)60     public StackMapType(final byte type, final int index, final ConstantPool constant_pool) {
61         if ((type < Const.ITEM_Bogus) || (type > Const.ITEM_NewObject)) {
62             throw new RuntimeException("Illegal type for StackMapType: " + type);
63         }
64         this.type = type;
65         this.index = index;
66         this.constant_pool = constant_pool;
67     }
68 
69 
setType( final byte t )70     public void setType( final byte t ) {
71         if ((t < Const.ITEM_Bogus) || (t > Const.ITEM_NewObject)) {
72             throw new RuntimeException("Illegal type for StackMapType: " + t);
73         }
74         type = t;
75     }
76 
77 
getType()78     public byte getType() {
79         return type;
80     }
81 
82 
setIndex( final int t )83     public void setIndex( final int t ) {
84         index = t;
85     }
86 
87 
88     /** @return index to constant pool if type == ITEM_Object, or offset
89      * in byte code, if type == ITEM_NewObject, and -1 otherwise
90      */
getIndex()91     public int getIndex() {
92         return index;
93     }
94 
95 
96     /**
97      * Dump type entries to file.
98      *
99      * @param file Output file stream
100      * @throws IOException
101      */
dump( final DataOutputStream file )102     public final void dump( final DataOutputStream file ) throws IOException {
103         file.writeByte(type);
104         if (hasIndex()) {
105             file.writeShort(getIndex());
106         }
107     }
108 
109 
110     /** @return true, if type is either ITEM_Object or ITEM_NewObject
111      */
hasIndex()112     public final boolean hasIndex() {
113         return type == Const.ITEM_Object || type == Const.ITEM_NewObject;
114     }
115 
116 
printIndex()117     private String printIndex() {
118         if (type == Const.ITEM_Object) {
119             if (index < 0) {
120                 return ", class=<unknown>";
121             }
122             return ", class=" + constant_pool.constantToString(index, Const.CONSTANT_Class);
123         } else if (type == Const.ITEM_NewObject) {
124             return ", offset=" + index;
125         } else {
126             return "";
127         }
128     }
129 
130 
131     /**
132      * @return String representation
133      */
134     @Override
toString()135     public final String toString() {
136         return "(type=" + Const.getItemName(type) + printIndex() + ")";
137     }
138 
139 
140     /**
141      * @return deep copy of this object
142      */
copy()143     public StackMapType copy() {
144         try {
145             return (StackMapType) clone();
146         } catch (final CloneNotSupportedException e) {
147             // TODO should this throw?
148         }
149         return null;
150     }
151 
152 
153     /**
154      * @return Constant pool used by this object.
155      */
getConstantPool()156     public final ConstantPool getConstantPool() {
157         return constant_pool;
158     }
159 
160 
161     /**
162      * @param constant_pool Constant pool to be used for this object.
163      */
setConstantPool( final ConstantPool constant_pool )164     public final void setConstantPool( final ConstantPool constant_pool ) {
165         this.constant_pool = constant_pool;
166     }
167 }
168