001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.classfile; 020 021import java.io.DataInput; 022import java.io.DataOutputStream; 023import java.io.IOException; 024 025import org.apache.bcel.Const; 026 027/** 028 * This class represents the type of a local variable or item on stack used in the StackMap entries. 029 * 030 * @see StackMapEntry 031 * @see StackMap 032 * @see Const 033 */ 034public final class StackMapType implements Node, Cloneable { 035 036 /** 037 * Empty array constant. 038 */ 039 public static final StackMapType[] EMPTY_ARRAY = {}; // BCELifier code generator writes calls to constructor translating null to EMPTY_ARRAY 040 041 private byte type; 042 private int index = -1; // Index to CONSTANT_Class or offset 043 private ConstantPool constantPool; 044 045 /** 046 * Constructs a StackMapType. 047 * 048 * @param type type tag as defined in the Constants interface. 049 * @param index index to constant pool, or byte code offset. 050 * @param constantPool The constant pool. 051 */ 052 public StackMapType(final byte type, final int index, final ConstantPool constantPool) { 053 this.type = checkType(type); 054 this.index = index; 055 this.constantPool = constantPool; 056 } 057 058 /** 059 * Constructs object from file stream. 060 * 061 * @param file Input stream. 062 * @param constantPool The constant pool. 063 * @throws IOException Thrown if an I/O error occurs. 064 */ 065 StackMapType(final DataInput file, final ConstantPool constantPool) throws IOException { 066 this(file.readByte(), -1, constantPool); 067 if (hasIndex()) { 068 this.index = file.readUnsignedShort(); 069 } 070 this.constantPool = constantPool; 071 } 072 073 /** 074 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 075 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 076 * 077 * @param v Visitor object. 078 * @since 6.8.0 079 */ 080 @Override 081 public void accept(final Visitor v) { 082 v.visitStackMapType(this); 083 } 084 085 private byte checkType(final byte type) { 086 if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) { 087 throw new ClassFormatException("Illegal type for StackMapType: " + type); 088 } 089 return type; 090 } 091 092 /** 093 * Creates a deep copy of this object. 094 * 095 * @return deep copy of this object. 096 */ 097 public StackMapType copy() { 098 try { 099 return (StackMapType) clone(); 100 } catch (final CloneNotSupportedException e) { 101 // TODO should this throw? 102 } 103 return null; 104 } 105 106 /** 107 * Dumps type entries to file. 108 * 109 * @param file Output file stream. 110 * @throws IOException Thrown if an I/O error occurs. 111 */ 112 public void dump(final DataOutputStream file) throws IOException { 113 file.writeByte(type); 114 if (hasIndex()) { 115 file.writeShort(getIndex()); 116 } 117 } 118 119 /** 120 * Gets the class name of this StackMapType from the constant pool at index position. 121 * 122 * @return The fully qualified name of the class for this StackMapType. 123 * @since 6.8.0 124 */ 125 public String getClassName() { 126 return constantPool.constantToString(index, Const.CONSTANT_Class); 127 } 128 129 /** 130 * Gets the constant pool. 131 * 132 * @return Constant pool used by this object. 133 */ 134 public ConstantPool getConstantPool() { 135 return constantPool; 136 } 137 138 /** 139 * Gets the index. 140 * 141 * @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1 142 * otherwise. 143 */ 144 public int getIndex() { 145 return index; 146 } 147 148 /** 149 * Gets the type. 150 * 151 * @return The type. 152 */ 153 public byte getType() { 154 return type; 155 } 156 157 /** 158 * Checks if this type has an index. 159 * 160 * @return true, if type is either ITEM_Object or ITEM_NewObject. 161 */ 162 public boolean hasIndex() { 163 return type == Const.ITEM_Object || type == Const.ITEM_NewObject; 164 } 165 166 private String printIndex() { 167 if (type == Const.ITEM_Object) { 168 if (index < 0) { 169 return ", class=<unknown>"; 170 } 171 return ", class=" + getClassName(); 172 } 173 if (type == Const.ITEM_NewObject) { 174 return ", offset=" + index; 175 } 176 return ""; 177 } 178 179 /** 180 * Sets the constant pool. 181 * 182 * @param constantPool Constant pool to be used for this object. 183 */ 184 public void setConstantPool(final ConstantPool constantPool) { 185 this.constantPool = constantPool; 186 } 187 188 /** 189 * Sets the index. 190 * 191 * @param index The index. 192 */ 193 public void setIndex(final int index) { 194 this.index = index; 195 } 196 197 /** 198 * Sets the type. 199 * 200 * @param type The type. 201 */ 202 public void setType(final byte type) { 203 this.type = checkType(type); 204 } 205 206 /** 207 * @return String representation. 208 */ 209 @Override 210 public String toString() { 211 return "(type=" + Const.getItemName(type) + printIndex() + ")"; 212 } 213}