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 * 017 */ 018package org.apache.bcel.classfile; 019 020import java.io.DataInput; 021import java.io.DataOutputStream; 022import java.io.IOException; 023 024import org.apache.bcel.Const; 025 026/** 027 * This class represents the type of a local variable or item on stack used in the StackMap entries. 028 * 029 * @see StackMapEntry 030 * @see StackMap 031 * @see Const 032 */ 033public final class StackMapType implements Cloneable { 034 035 private byte type; 036 private int index = -1; // Index to CONSTANT_Class or offset 037 private ConstantPool constantPool; 038 039 /** 040 * @param type type tag as defined in the Constants interface 041 * @param index index to constant pool, or byte code offset 042 */ 043 public StackMapType(final byte type, final int index, final ConstantPool constant_pool) { 044 if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) { 045 throw new IllegalArgumentException("Illegal type for StackMapType: " + type); 046 } 047 this.type = type; 048 this.index = index; 049 this.constantPool = constant_pool; 050 } 051 052 /** 053 * Construct object from file stream. 054 * 055 * @param file Input stream 056 * @throws IOException if an I/O error occurs. 057 */ 058 StackMapType(final DataInput file, final ConstantPool constant_pool) throws IOException { 059 this(file.readByte(), -1, constant_pool); 060 if (hasIndex()) { 061 this.index = file.readShort(); 062 } 063 this.constantPool = constant_pool; 064 } 065 066 /** 067 * @return deep copy of this object 068 */ 069 public StackMapType copy() { 070 try { 071 return (StackMapType) clone(); 072 } catch (final CloneNotSupportedException e) { 073 // TODO should this throw? 074 } 075 return null; 076 } 077 078 /** 079 * Dump type entries to file. 080 * 081 * @param file Output file stream 082 * @throws IOException if an I/O error occurs. 083 */ 084 public void dump(final DataOutputStream file) throws IOException { 085 file.writeByte(type); 086 if (hasIndex()) { 087 file.writeShort(getIndex()); 088 } 089 } 090 091 /** 092 * @return Constant pool used by this object. 093 */ 094 public ConstantPool getConstantPool() { 095 return constantPool; 096 } 097 098 /** 099 * @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1 100 * otherwise 101 */ 102 public int getIndex() { 103 return index; 104 } 105 106 public byte getType() { 107 return type; 108 } 109 110 /** 111 * @return true, if type is either ITEM_Object or ITEM_NewObject 112 */ 113 public boolean hasIndex() { 114 return type == Const.ITEM_Object || type == Const.ITEM_NewObject; 115 } 116 117 private String printIndex() { 118 if (type == Const.ITEM_Object) { 119 if (index < 0) { 120 return ", class=<unknown>"; 121 } 122 return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class); 123 } 124 if (type == Const.ITEM_NewObject) { 125 return ", offset=" + index; 126 } 127 return ""; 128 } 129 130 /** 131 * @param constantPool Constant pool to be used for this object. 132 */ 133 public void setConstantPool(final ConstantPool constantPool) { 134 this.constantPool = constantPool; 135 } 136 137 public void setIndex(final int t) { 138 index = t; 139 } 140 141 public void setType(final byte t) { 142 if (t < Const.ITEM_Bogus || t > Const.ITEM_NewObject) { 143 throw new IllegalArgumentException("Illegal type for StackMapType: " + t); 144 } 145 type = t; 146 } 147 148 /** 149 * @return String representation 150 */ 151 @Override 152 public String toString() { 153 return "(type=" + Const.getItemName(type) + printIndex() + ")"; 154 } 155}