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