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