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.generic;
019
020import java.io.DataOutputStream;
021import java.io.IOException;
022
023import org.apache.bcel.classfile.Constant;
024import org.apache.bcel.classfile.ConstantClass;
025import org.apache.bcel.classfile.ConstantPool;
026import org.apache.bcel.util.ByteSequence;
027
028/**
029 * Abstract super class for instructions that use an index into the
030 * constant pool such as LDC, INVOKEVIRTUAL, etc.
031 *
032 * @see ConstantPoolGen
033 * @see LDC
034 * @see INVOKEVIRTUAL
035 *
036 */
037public abstract class CPInstruction extends Instruction implements TypedInstruction,
038        IndexedInstruction {
039
040    /**
041     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
042     */
043    @Deprecated
044    protected int index; // index to constant pool
045
046
047    /**
048     * Empty constructor needed for Instruction.readInstruction.
049     * Not to be used otherwise.
050     */
051    CPInstruction() {
052    }
053
054
055    /**
056     * @param index to constant pool
057     */
058    protected CPInstruction(final short opcode, final int index) {
059        super(opcode, (short) 3);
060        setIndex(index);
061    }
062
063
064    /**
065     * Dump instruction as byte code to stream out.
066     * @param out Output stream
067     */
068    @Override
069    public void dump( final DataOutputStream out ) throws IOException {
070        out.writeByte(super.getOpcode());
071        out.writeShort(index);
072    }
073
074
075    /**
076     * Long output format:
077     *
078     * <name of opcode> "["<opcode number>"]"
079     * "("<length of instruction>")" "<"< constant pool index>">"
080     *
081     * @param verbose long/short format switch
082     * @return mnemonic for instruction
083     */
084    @Override
085    public String toString( final boolean verbose ) {
086        return super.toString(verbose) + " " + index;
087    }
088
089
090    /**
091     * @return mnemonic for instruction with symbolic references resolved
092     */
093    @Override
094    public String toString( final ConstantPool cp ) {
095        final Constant c = cp.getConstant(index);
096        String str = cp.constantToString(c);
097        if (c instanceof ConstantClass) {
098            str = str.replace('.', '/');
099        }
100        return org.apache.bcel.Const.getOpcodeName(super.getOpcode()) + " " + str;
101    }
102
103
104    /**
105     * Read needed data (i.e., index) from file.
106     * @param bytes input stream
107     * @param wide wide prefix?
108     */
109    @Override
110    protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
111        setIndex(bytes.readUnsignedShort());
112        super.setLength(3);
113    }
114
115
116    /**
117     * @return index in constant pool referred by this instruction.
118     */
119    @Override
120    public final int getIndex() {
121        return index;
122    }
123
124
125    /**
126     * Set the index to constant pool.
127     * @param index in  constant pool.
128     */
129    @Override
130    public void setIndex( final int index ) { // TODO could be package-protected?
131        if (index < 0) {
132            throw new ClassGenException("Negative index value: " + index);
133        }
134        this.index = index;
135    }
136
137
138    /** @return type related with this instruction.
139     */
140    @Override
141    public Type getType( final ConstantPoolGen cpg ) {
142        final ConstantPool cp = cpg.getConstantPool();
143        String name = cp.getConstantString(index, org.apache.bcel.Const.CONSTANT_Class);
144        if (!name.startsWith("[")) {
145            name = "L" + name + ";";
146        }
147        return Type.getType(name);
148    }
149}