001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.classfile; 018 019import java.io.DataInput; 020import java.io.DataOutputStream; 021import java.io.IOException; 022 023import org.apache.bcel.Const; 024 025/** 026 * This class represents the type of a local variable or item on stack used in the StackMap entries. 027 * 028 * @see StackMapEntry 029 * @see StackMap 030 * @see Const 031 */ 032public final class StackMapType implements Cloneable { 033 034 public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it 035 036 private byte type; 037 private int index = -1; // Index to CONSTANT_Class or offset 038 private ConstantPool constantPool; 039 040 /** 041 * @param type type tag as defined in the Constants interface 042 * @param index index to constant pool, or byte code offset 043 */ 044 public StackMapType(final byte type, final int index, final ConstantPool constantPool) { 045 this.type = checkType(type); 046 this.index = index; 047 this.constantPool = constantPool; 048 } 049 050 /** 051 * Construct object from file stream. 052 * 053 * @param file Input stream 054 * @throws IOException if an I/O error occurs. 055 */ 056 StackMapType(final DataInput file, final ConstantPool constantPool) throws IOException { 057 this(file.readByte(), -1, constantPool); 058 if (hasIndex()) { 059 this.index = file.readUnsignedShort(); 060 } 061 this.constantPool = constantPool; 062 } 063 064 private byte checkType(final byte type) { 065 if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) { 066 throw new ClassFormatException("Illegal type for StackMapType: " + type); 067 } 068 return type; 069 } 070 071 /** 072 * @return deep copy of this object 073 */ 074 public StackMapType copy() { 075 try { 076 return (StackMapType) clone(); 077 } catch (final CloneNotSupportedException e) { 078 // TODO should this throw? 079 } 080 return null; 081 } 082 083 /** 084 * Dump type entries to file. 085 * 086 * @param file Output file stream 087 * @throws IOException if an I/O error occurs. 088 */ 089 public void dump(final DataOutputStream file) throws IOException { 090 file.writeByte(type); 091 if (hasIndex()) { 092 file.writeShort(getIndex()); 093 } 094 } 095 096 /** 097 * @return Constant pool used by this object. 098 */ 099 public ConstantPool getConstantPool() { 100 return constantPool; 101 } 102 103 /** 104 * @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1 105 * otherwise 106 */ 107 public int getIndex() { 108 return index; 109 } 110 111 public byte getType() { 112 return type; 113 } 114 115 /** 116 * @return true, if type is either ITEM_Object or ITEM_NewObject 117 */ 118 public boolean hasIndex() { 119 return type == Const.ITEM_Object || type == Const.ITEM_NewObject; 120 } 121 122 private String printIndex() { 123 if (type == Const.ITEM_Object) { 124 if (index < 0) { 125 return ", class=<unknown>"; 126 } 127 return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class); 128 } 129 if (type == Const.ITEM_NewObject) { 130 return ", offset=" + index; 131 } 132 return ""; 133 } 134 135 /** 136 * @param constantPool Constant pool to be used for this object. 137 */ 138 public void setConstantPool(final ConstantPool constantPool) { 139 this.constantPool = constantPool; 140 } 141 142 public void setIndex(final int index) { 143 this.index = index; 144 } 145 146 public void setType(final byte type) { 147 this.type = checkType(type); 148 } 149 150 /** 151 * @return String representation 152 */ 153 @Override 154 public String toString() { 155 return "(type=" + Const.getItemName(type) + printIndex() + ")"; 156 } 157}