1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.generic;
20
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23
24 import org.apache.bcel.classfile.Constant;
25 import org.apache.bcel.classfile.ConstantClass;
26 import org.apache.bcel.classfile.ConstantPool;
27 import org.apache.bcel.classfile.Utility;
28 import org.apache.bcel.util.ByteSequence;
29
30 /**
31 * Abstract super class for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, etc.
32 *
33 * @see ConstantPoolGen
34 * @see LDC
35 * @see INVOKEVIRTUAL
36 */
37 public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
38
39 /**
40 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
41 */
42 @Deprecated
43 protected int index; // index to constant pool
44
45 /**
46 * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
47 */
48 CPInstruction() {
49 }
50
51 /**
52 * @param index to constant pool
53 */
54 protected CPInstruction(final short opcode, final int index) {
55 super(opcode, (short) 3);
56 setIndex(index);
57 }
58
59 /**
60 * Dump instruction as byte code to stream out.
61 *
62 * @param out Output stream
63 */
64 @Override
65 public void dump(final DataOutputStream out) throws IOException {
66 out.writeByte(super.getOpcode());
67 out.writeShort(index);
68 }
69
70 /**
71 * @return index in constant pool referred by this instruction.
72 */
73 @Override
74 public final int getIndex() {
75 return index;
76 }
77
78 /**
79 * @return type related with this instruction.
80 */
81 @Override
82 public Type getType(final ConstantPoolGen cpg) {
83 final ConstantPool cp = cpg.getConstantPool();
84 String name = cp.getConstantString(index, org.apache.bcel.Const.CONSTANT_Class);
85 if (!name.startsWith("[")) {
86 name = "L" + name + ";";
87 }
88 return Type.getType(name);
89 }
90
91 /**
92 * Reads needed data (i.e., index) from file.
93 *
94 * @param bytes input stream
95 * @param wide wide prefix?
96 */
97 @Override
98 protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
99 setIndex(bytes.readUnsignedShort());
100 super.setLength(3);
101 }
102
103 /**
104 * Sets the index to constant pool.
105 *
106 * @param index in constant pool.
107 */
108 @Override
109 public void setIndex(final int index) { // TODO could be package-protected?
110 if (index < 0) {
111 throw new ClassGenException("Negative index value: " + index);
112 }
113 this.index = index;
114 }
115
116 /**
117 * Long output format:
118 *
119 * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool
120 * index>">"
121 *
122 * @param verbose long/short format switch
123 * @return mnemonic for instruction
124 */
125 @Override
126 public String toString(final boolean verbose) {
127 return super.toString(verbose) + " " + index;
128 }
129
130 /**
131 * @return mnemonic for instruction with symbolic references resolved
132 */
133 @Override
134 public String toString(final ConstantPool cp) {
135 final Constant c = cp.getConstant(index);
136 String str = cp.constantToString(c);
137 if (c instanceof ConstantClass) {
138 str = Utility.packageToPath(str);
139 }
140 return org.apache.bcel.Const.getOpcodeName(super.getOpcode()) + " " + str;
141 }
142 }