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