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