LDC.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */
  17. package org.apache.bcel.generic;

  18. import java.io.DataOutputStream;
  19. import java.io.IOException;

  20. import org.apache.bcel.ExceptionConst;
  21. import org.apache.bcel.util.ByteSequence;

  22. /**
  23.  * LDC - Push item from constant pool.
  24.  *
  25.  * <PRE>
  26.  * Stack: ... -&gt; ..., item
  27.  * </PRE>
  28.  */
  29. public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower {

  30.     /**
  31.      * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
  32.      */
  33.     LDC() {
  34.     }

  35.     public LDC(final int index) {
  36.         super(org.apache.bcel.Const.LDC_W, index);
  37.         setSize();
  38.     }

  39.     /**
  40.      * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
  41.      * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
  42.      *
  43.      * @param v Visitor object
  44.      */
  45.     @Override
  46.     public void accept(final Visitor v) {
  47.         v.visitStackProducer(this);
  48.         v.visitPushInstruction(this);
  49.         v.visitExceptionThrower(this);
  50.         v.visitTypedInstruction(this);
  51.         v.visitCPInstruction(this);
  52.         v.visitLDC(this);
  53.     }

  54.     /**
  55.      * Dump instruction as byte code to stream out.
  56.      *
  57.      * @param out Output stream
  58.      */
  59.     @Override
  60.     public void dump(final DataOutputStream out) throws IOException {
  61.         out.writeByte(super.getOpcode());
  62.         if (super.getLength() == 2) { // TODO useless check?
  63.             out.writeByte(super.getIndex());
  64.         } else {
  65.             out.writeShort(super.getIndex());
  66.         }
  67.     }

  68.     @Override
  69.     public Class<?>[] getExceptions() {
  70.         return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_STRING_RESOLUTION);
  71.     }

  72.     @Override
  73.     public Type getType(final ConstantPoolGen cpg) {
  74.         switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) {
  75.         case org.apache.bcel.Const.CONSTANT_String:
  76.             return Type.STRING;
  77.         case org.apache.bcel.Const.CONSTANT_Float:
  78.             return Type.FLOAT;
  79.         case org.apache.bcel.Const.CONSTANT_Integer:
  80.             return Type.INT;
  81.         case org.apache.bcel.Const.CONSTANT_Class:
  82.             return Type.CLASS;
  83.         case org.apache.bcel.Const.CONSTANT_Dynamic:
  84.             return Type.OBJECT;
  85.         default: // Never reached
  86.             throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex());
  87.         }
  88.     }

  89.     public Object getValue(final ConstantPoolGen cpg) {
  90.         org.apache.bcel.classfile.Constant c = cpg.getConstantPool().getConstant(super.getIndex());
  91.         switch (c.getTag()) {
  92.         case org.apache.bcel.Const.CONSTANT_String:
  93.             final int i = ((org.apache.bcel.classfile.ConstantString) c).getStringIndex();
  94.             c = cpg.getConstantPool().getConstant(i);
  95.             return ((org.apache.bcel.classfile.ConstantUtf8) c).getBytes();
  96.         case org.apache.bcel.Const.CONSTANT_Float:
  97.             return Float.valueOf(((org.apache.bcel.classfile.ConstantFloat) c).getBytes());
  98.         case org.apache.bcel.Const.CONSTANT_Integer:
  99.             return Integer.valueOf(((org.apache.bcel.classfile.ConstantInteger) c).getBytes());
  100.         case org.apache.bcel.Const.CONSTANT_Class:
  101.             final int nameIndex = ((org.apache.bcel.classfile.ConstantClass) c).getNameIndex();
  102.             c = cpg.getConstantPool().getConstant(nameIndex);
  103.             return Type.getType(Type.internalTypeNameToSignature(((org.apache.bcel.classfile.ConstantUtf8) c).getBytes()));
  104.         case org.apache.bcel.Const.CONSTANT_Dynamic:
  105.             // Really not sure what to return here, maybe a BootstrapMethod instance but how do we get it?
  106.             return c;
  107.         default: // Never reached
  108.             throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex());
  109.         }
  110.     }

  111.     /**
  112.      * Read needed data (e.g. index) from file.
  113.      */
  114.     @Override
  115.     protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
  116.         super.setLength(2);
  117.         super.setIndex(bytes.readUnsignedByte());
  118.     }

  119.     /**
  120.      * Sets the index to constant pool and adjust size.
  121.      */
  122.     @Override
  123.     public final void setIndex(final int index) {
  124.         super.setIndex(index);
  125.         setSize();
  126.     }

  127.     // Adjust to proper size
  128.     protected final void setSize() {
  129.         if (super.getIndex() <= org.apache.bcel.Const.MAX_BYTE) { // Fits in one byte?
  130.             super.setOpcode(org.apache.bcel.Const.LDC);
  131.             super.setLength(2);
  132.         } else {
  133.             super.setOpcode(org.apache.bcel.Const.LDC_W);
  134.             super.setLength(3);
  135.         }
  136.     }
  137. }