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