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.ExceptionConst; 025import org.apache.bcel.util.ByteSequence; 026 027/** 028 * LDC - Push item from constant pool. 029 * 030 * <pre> 031 * Stack: ... -> ..., item 032 * </pre> 033 */ 034public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower { 035 036 /** 037 * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. 038 */ 039 LDC() { 040 } 041 042 /** 043 * Constructs an LDC instruction. 044 * 045 * @param index index into constant pool. 046 */ 047 public LDC(final int index) { 048 super(org.apache.bcel.Const.LDC_W, index); 049 setSize(); 050 } 051 052 /** 053 * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call 054 * methods according to the class hierarchy in descending order, that is, the most specific visitXXX() call comes last. 055 * 056 * @param v Visitor object. 057 */ 058 @Override 059 public void accept(final Visitor v) { 060 v.visitStackProducer(this); 061 v.visitPushInstruction(this); 062 v.visitExceptionThrower(this); 063 v.visitTypedInstruction(this); 064 v.visitCPInstruction(this); 065 v.visitLDC(this); 066 } 067 068 /** 069 * Dumps instruction as byte code to stream out. 070 * 071 * @param out Output stream. 072 */ 073 @Override 074 public void dump(final DataOutputStream out) throws IOException { 075 out.writeByte(super.getOpcode()); 076 if (super.getLength() == 2) { // TODO useless check? 077 out.writeByte(super.getIndex()); 078 } else { 079 out.writeShort(super.getIndex()); 080 } 081 } 082 083 @Override 084 public Class<?>[] getExceptions() { 085 return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_STRING_RESOLUTION); 086 } 087 088 @Override 089 public Type getType(final ConstantPoolGen cpg) { 090 switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) { 091 case org.apache.bcel.Const.CONSTANT_String: 092 return Type.STRING; 093 case org.apache.bcel.Const.CONSTANT_Float: 094 return Type.FLOAT; 095 case org.apache.bcel.Const.CONSTANT_Integer: 096 return Type.INT; 097 case org.apache.bcel.Const.CONSTANT_Class: 098 return Type.CLASS; 099 case org.apache.bcel.Const.CONSTANT_Dynamic: 100 return Type.OBJECT; 101 default: // Never reached 102 throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); 103 } 104 } 105 106 /** 107 * Gets the constant value from the constant pool. 108 * 109 * @param cpg constant pool generator. 110 * @return The constant value. 111 */ 112 public Object getValue(final ConstantPoolGen cpg) { 113 org.apache.bcel.classfile.Constant c = cpg.getConstantPool().getConstant(super.getIndex()); 114 switch (c.getTag()) { 115 case org.apache.bcel.Const.CONSTANT_String: 116 final int i = ((org.apache.bcel.classfile.ConstantString) c).getStringIndex(); 117 c = cpg.getConstantPool().getConstant(i); 118 return ((org.apache.bcel.classfile.ConstantUtf8) c).getBytes(); 119 case org.apache.bcel.Const.CONSTANT_Float: 120 return Float.valueOf(((org.apache.bcel.classfile.ConstantFloat) c).getBytes()); 121 case org.apache.bcel.Const.CONSTANT_Integer: 122 return Integer.valueOf(((org.apache.bcel.classfile.ConstantInteger) c).getBytes()); 123 case org.apache.bcel.Const.CONSTANT_Class: 124 final int nameIndex = ((org.apache.bcel.classfile.ConstantClass) c).getNameIndex(); 125 c = cpg.getConstantPool().getConstant(nameIndex); 126 return Type.getType(Type.internalTypeNameToSignature(((org.apache.bcel.classfile.ConstantUtf8) c).getBytes())); 127 case org.apache.bcel.Const.CONSTANT_Dynamic: 128 // Really not sure what to return here, maybe a BootstrapMethod instance but how do we get it? 129 return c; 130 default: // Never reached 131 throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); 132 } 133 } 134 135 /** 136 * Reads needed data (for example index) from file. 137 */ 138 @Override 139 protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { 140 super.setLength(2); 141 super.setIndex(bytes.readUnsignedByte()); 142 } 143 144 /** 145 * Sets the index to constant pool and adjust size. 146 */ 147 @Override 148 public final void setIndex(final int index) { 149 super.setIndex(index); 150 setSize(); 151 } 152 153 /** 154 * Adjusts to proper size. 155 */ 156 protected final void setSize() { 157 if (super.getIndex() <= org.apache.bcel.Const.MAX_BYTE) { // Fits in one byte? 158 super.setOpcode(org.apache.bcel.Const.LDC); 159 super.setLength(2); 160 } else { 161 super.setOpcode(org.apache.bcel.Const.LDC_W); 162 super.setLength(3); 163 } 164 } 165}