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