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 superclass for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, and so on. 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 * Gets the constant pool index referred to by this instruction. 076 * 077 * @return index in constant pool referred by this instruction. 078 */ 079 @Override 080 public final int getIndex() { 081 return index; 082 } 083 084 /** 085 * Gets the type associated with this instruction. 086 * 087 * @return type related with this instruction. 088 */ 089 @Override 090 public Type getType(final ConstantPoolGen cpg) { 091 final ConstantPool cp = cpg.getConstantPool(); 092 String name = cp.getConstantString(index, Const.CONSTANT_Class); 093 if (!name.startsWith("[")) { 094 name = "L" + name + ";"; 095 } 096 return Type.getType(name); 097 } 098 099 /** 100 * Reads needed data (that is, index) from file. 101 * 102 * @param bytes input stream. 103 * @param wide wide prefix?. 104 */ 105 @Override 106 protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { 107 setIndex(bytes.readUnsignedShort()); 108 super.setLength(3); 109 } 110 111 /** 112 * Sets the index to constant pool. 113 * 114 * @param index in constant pool. 115 * @throws ClassGenException Thrown if index is out of bounds. 116 */ 117 @Override 118 public void setIndex(final int index) { // TODO could be package-protected? 119 if (!isNonNegativeUShort(index)) { 120 throw new ClassGenException("Illegal index: " + index); 121 } 122 this.index = index; 123 } 124 125 /** 126 * Long output format: 127 * 128 * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool 129 * index>">" 130 * 131 * @param verbose long/short format switch. 132 * @return mnemonic for instruction. 133 */ 134 @Override 135 public String toString(final boolean verbose) { 136 return super.toString(verbose) + " " + index; 137 } 138 139 /** 140 * @return mnemonic for instruction with symbolic references resolved. 141 */ 142 @Override 143 public String toString(final ConstantPool cp) { 144 final Constant c = cp.getConstant(index); 145 String str = cp.constantToString(c); 146 if (c instanceof ConstantClass) { 147 str = Utility.packageToPath(str); 148 } 149 return Const.getOpcodeName(super.getOpcode()) + " " + str; 150 } 151}