View Javadoc
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  package org.apache.bcel.classfile;
18  
19  import java.io.DataInput;
20  import java.io.DataOutputStream;
21  import java.io.IOException;
22  
23  import org.apache.bcel.Const;
24  
25  /**
26   * This class represents the type of a local variable or item on stack used in the StackMap entries.
27   *
28   * @see StackMapEntry
29   * @see StackMap
30   * @see Const
31   */
32  public final class StackMapType implements Node, Cloneable {
33  
34      public static final StackMapType[] EMPTY_ARRAY = {}; // BCELifier code generator writes calls to constructor translating null to EMPTY_ARRAY
35  
36      private byte type;
37      private int index = -1; // Index to CONSTANT_Class or offset
38      private ConstantPool constantPool;
39  
40      /**
41       * @param type type tag as defined in the Constants interface
42       * @param index index to constant pool, or byte code offset
43       */
44      public StackMapType(final byte type, final int index, final ConstantPool constantPool) {
45          this.type = checkType(type);
46          this.index = index;
47          this.constantPool = constantPool;
48      }
49  
50      /**
51       * Constructs object from file stream.
52       *
53       * @param file Input stream
54       * @throws IOException if an I/O error occurs.
55       */
56      StackMapType(final DataInput file, final ConstantPool constantPool) throws IOException {
57          this(file.readByte(), -1, constantPool);
58          if (hasIndex()) {
59              this.index = file.readUnsignedShort();
60          }
61          this.constantPool = constantPool;
62      }
63  
64      /**
65       * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
66       * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
67       *
68       * @param v Visitor object
69       * @since 6.8.0
70       */
71      @Override
72      public void accept(final Visitor v) {
73          v.visitStackMapType(this);
74      }
75  
76      private byte checkType(final byte type) {
77          if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) {
78              throw new ClassFormatException("Illegal type for StackMapType: " + type);
79          }
80          return type;
81      }
82  
83      /**
84       * @return deep copy of this object
85       */
86      public StackMapType copy() {
87          try {
88              return (StackMapType) clone();
89          } catch (final CloneNotSupportedException e) {
90              // TODO should this throw?
91          }
92          return null;
93      }
94  
95      /**
96       * Dump type entries to file.
97       *
98       * @param file Output file stream
99       * @throws IOException if an I/O error occurs.
100      */
101     public void dump(final DataOutputStream file) throws IOException {
102         file.writeByte(type);
103         if (hasIndex()) {
104             file.writeShort(getIndex());
105         }
106     }
107 
108     /**
109      * Gets the class name of this StackMapType from the constant pool at index position.
110      * @return the fully qualified name of the class for this StackMapType.
111      * @since 6.8.0
112      */
113     public String getClassName() {
114         return constantPool.constantToString(index, Const.CONSTANT_Class);
115     }
116 
117     /**
118      * @return Constant pool used by this object.
119      */
120     public ConstantPool getConstantPool() {
121         return constantPool;
122     }
123 
124     /**
125      * @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1
126      *         otherwise
127      */
128     public int getIndex() {
129         return index;
130     }
131 
132     public byte getType() {
133         return type;
134     }
135 
136     /**
137      * @return true, if type is either ITEM_Object or ITEM_NewObject
138      */
139     public boolean hasIndex() {
140         return type == Const.ITEM_Object || type == Const.ITEM_NewObject;
141     }
142 
143     private String printIndex() {
144         if (type == Const.ITEM_Object) {
145             if (index < 0) {
146                 return ", class=<unknown>";
147             }
148             return ", class=" + getClassName();
149         }
150         if (type == Const.ITEM_NewObject) {
151             return ", offset=" + index;
152         }
153         return "";
154     }
155 
156     /**
157      * @param constantPool Constant pool to be used for this object.
158      */
159     public void setConstantPool(final ConstantPool constantPool) {
160         this.constantPool = constantPool;
161     }
162 
163     public void setIndex(final int index) {
164         this.index = index;
165     }
166 
167     public void setType(final byte type) {
168         this.type = checkType(type);
169     }
170 
171     /**
172      * @return String representation
173      */
174     @Override
175     public String toString() {
176         return "(type=" + Const.getItemName(type) + printIndex() + ")";
177     }
178 }