View Javadoc
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.ExceptionConst;
25  import org.apache.bcel.util.ByteSequence;
26  
27  /**
28   * LDC - Push item from constant pool.
29   *
30   * <pre>
31   * Stack: ... -&gt; ..., item
32   * </pre>
33   */
34  public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower {
35  
36      /**
37       * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
38       */
39      LDC() {
40      }
41  
42      /**
43       * Constructs an LDC instruction.
44       *
45       * @param index index into constant pool.
46       */
47      public LDC(final int index) {
48          super(org.apache.bcel.Const.LDC_W, index);
49          setSize();
50      }
51  
52      /**
53       * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
54       * methods according to the class hierarchy in descending order, that is, the most specific visitXXX() call comes last.
55       *
56       * @param v Visitor object.
57       */
58      @Override
59      public void accept(final Visitor v) {
60          v.visitStackProducer(this);
61          v.visitPushInstruction(this);
62          v.visitExceptionThrower(this);
63          v.visitTypedInstruction(this);
64          v.visitCPInstruction(this);
65          v.visitLDC(this);
66      }
67  
68      /**
69       * Dumps instruction as byte code to stream out.
70       *
71       * @param out Output stream.
72       */
73      @Override
74      public void dump(final DataOutputStream out) throws IOException {
75          out.writeByte(super.getOpcode());
76          if (super.getLength() == 2) { // TODO useless check?
77              out.writeByte(super.getIndex());
78          } else {
79              out.writeShort(super.getIndex());
80          }
81      }
82  
83      @Override
84      public Class<?>[] getExceptions() {
85          return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_STRING_RESOLUTION);
86      }
87  
88      @Override
89      public Type getType(final ConstantPoolGen cpg) {
90          switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) {
91          case org.apache.bcel.Const.CONSTANT_String:
92              return Type.STRING;
93          case org.apache.bcel.Const.CONSTANT_Float:
94              return Type.FLOAT;
95          case org.apache.bcel.Const.CONSTANT_Integer:
96              return Type.INT;
97          case org.apache.bcel.Const.CONSTANT_Class:
98              return Type.CLASS;
99          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 }