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