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}