    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     * &lt;name of opcode&gt; "["&lt;opcode number&gt;"]"
    079     * "("&lt;length of instruction&gt;")" "&lt;"&lt; constant pool index&gt;"&gt;"
    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}