001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.bcel.generic;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023
024import org.apache.bcel.Const;
025import org.apache.bcel.classfile.Constant;
026import org.apache.bcel.classfile.ConstantClass;
027import org.apache.bcel.classfile.ConstantPool;
028import org.apache.bcel.classfile.Utility;
029import org.apache.bcel.util.ByteSequence;
030
031/**
032 * Abstract super class for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, etc.
033 *
034 * @see ConstantPoolGen
035 * @see LDC
036 * @see INVOKEVIRTUAL
037 */
038public abstract class CPInstruction extends Instruction implements TypedInstruction, 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     * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
048     */
049    CPInstruction() {
050    }
051
052    /**
053     * Constructs a CPInstruction.
054     *
055     * @param opcode The opcode.
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     * Dumps instruction as byte code to stream out.
065     *
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     * @return index in constant pool referred by this instruction.
076     */
077    @Override
078    public final int getIndex() {
079        return index;
080    }
081
082    /**
083     * @return type related with this instruction.
084     */
085    @Override
086    public Type getType(final ConstantPoolGen cpg) {
087        final ConstantPool cp = cpg.getConstantPool();
088        String name = cp.getConstantString(index, Const.CONSTANT_Class);
089        if (!name.startsWith("[")) {
090            name = "L" + name + ";";
091        }
092        return Type.getType(name);
093    }
094
095    /**
096     * Reads needed data (that is, index) from file.
097     *
098     * @param bytes input stream.
099     * @param wide wide prefix?.
100     */
101    @Override
102    protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
103        setIndex(bytes.readUnsignedShort());
104        super.setLength(3);
105    }
106
107    /**
108     * Sets the index to constant pool.
109     *
110     * @param index in constant pool.
111     * @throws ClassGenException Thrown if index is out of bounds.
112     */
113    @Override
114    public void setIndex(final int index) { // TODO could be package-protected?
115        if (!isNonNegativeUShort(index)) {
116            throw new ClassGenException("Illegal index: " + index);
117        }
118        this.index = index;
119    }
120
121    /**
122     * Long output format:
123     *
124     * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool
125     * index>">"
126     *
127     * @param verbose long/short format switch.
128     * @return mnemonic for instruction.
129     */
130    @Override
131    public String toString(final boolean verbose) {
132        return super.toString(verbose) + " " + index;
133    }
134
135    /**
136     * @return mnemonic for instruction with symbolic references resolved.
137     */
138    @Override
139    public String toString(final ConstantPool cp) {
140        final Constant c = cp.getConstant(index);
141        String str = cp.constantToString(c);
142        if (c instanceof ConstantClass) {
143            str = Utility.packageToPath(str);
144        }
145        return Const.getOpcodeName(super.getOpcode()) + " " + str;
146    }
147}