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