LocalVariable.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.classfile;

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

  21. import org.apache.bcel.Constants;
  22. import org.apache.bcel.util.Args;

  23. /**
  24.  * This class represents a local variable within a method. It contains its scope, name, signature and index on the
  25.  * method's frame. It is used both to represent an element of the LocalVariableTable as well as an element of the
  26.  * LocalVariableTypeTable. The nomenclature used here may be a bit confusing; while the two items have the same layout
  27.  * in a class file, a LocalVariableTable attribute contains a descriptor_index, not a signatureIndex. The
  28.  * LocalVariableTypeTable attribute does have a signatureIndex.
  29.  *
  30.  * @see org.apache.bcel.classfile.Utility for more details on the difference.
  31.  *
  32.  * @see LocalVariableTable
  33.  * @see LocalVariableTypeTable
  34.  */
  35. public final class LocalVariable implements Cloneable, Node, Constants {

  36.     static final LocalVariable[] EMPTY_ARRAY = {};

  37.     /** Range in which the variable is valid. */
  38.     private int startPc;

  39.     private int length;

  40.     /** Index in constant pool of variable name. */
  41.     private int nameIndex;

  42.     /**
  43.      * Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature
  44.      */
  45.     private int signatureIndex;

  46.     /*
  47.      * Variable is index'th local variable on this method's frame.
  48.      */
  49.     private int index;

  50.     private ConstantPool constantPool;

  51.     /** Never changes; used to match up with LocalVariableTypeTable entries. */
  52.     private final int origIndex;

  53.     /**
  54.      * Constructs object from file stream.
  55.      *
  56.      * @param file Input stream
  57.      * @throws IOException if an I/O error occurs.
  58.      */
  59.     LocalVariable(final DataInput file, final ConstantPool constantPool) throws IOException {
  60.         this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), constantPool);
  61.     }

  62.     /**
  63.      * @param startPc Range in which the variable
  64.      * @param length ... is valid
  65.      * @param nameIndex Index in constant pool of variable name
  66.      * @param signatureIndex Index of variable's signature
  67.      * @param index Variable is 'index'th local variable on the method's frame
  68.      * @param constantPool Array of constants
  69.      */
  70.     public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool) {
  71.         this(startPc, length, nameIndex, signatureIndex, index, constantPool, index);
  72.     }

  73.     /**
  74.      * @param startPc Range in which the variable
  75.      * @param length ... is valid
  76.      * @param nameIndex Index in constant pool of variable name
  77.      * @param signatureIndex Index of variable's signature
  78.      * @param index Variable is 'index'th local variable on the method's frame
  79.      * @param constantPool Array of constants
  80.      * @param origIndex Variable is 'index'th local variable on the method's frame prior to any changes
  81.      */
  82.     public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool,
  83.         final int origIndex) {
  84.         this.startPc = Args.requireU2(startPc, "startPc");
  85.         this.length = Args.requireU2(length, "length");
  86.         this.nameIndex = Args.requireU2(nameIndex, "nameIndex");
  87.         this.signatureIndex = Args.requireU2(signatureIndex, "signatureIndex");
  88.         this.index = Args.requireU2(index, "index");
  89.         this.origIndex = Args.requireU2(origIndex, "origIndex");
  90.         this.constantPool = constantPool;
  91.     }

  92.     /**
  93.      * Initializes from another LocalVariable. Note that both objects use the same references (shallow copy). Use copy() for
  94.      * a physical copy.
  95.      *
  96.      * @param localVariable Another LocalVariable.
  97.      */
  98.     public LocalVariable(final LocalVariable localVariable) {
  99.         this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), localVariable.getSignatureIndex(), localVariable.getIndex(),
  100.             localVariable.getConstantPool());
  101.     }

  102.     /**
  103.      * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
  104.      * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
  105.      *
  106.      * @param v Visitor object
  107.      */
  108.     @Override
  109.     public void accept(final Visitor v) {
  110.         v.visitLocalVariable(this);
  111.     }

  112.     /**
  113.      * @return deep copy of this object
  114.      */
  115.     public LocalVariable copy() {
  116.         try {
  117.             return (LocalVariable) clone();
  118.         } catch (final CloneNotSupportedException e) {
  119.             // TODO should this throw?
  120.         }
  121.         return null;
  122.     }

  123.     /**
  124.      * Dumps local variable to file stream in binary format.
  125.      *
  126.      * @param dataOutputStream Output file stream
  127.      * @throws IOException if an I/O error occurs.
  128.      * @see java.io.FilterOutputStream#out
  129.      */
  130.     public void dump(final DataOutputStream dataOutputStream) throws IOException {
  131.         dataOutputStream.writeShort(startPc);
  132.         dataOutputStream.writeShort(length);
  133.         dataOutputStream.writeShort(nameIndex);
  134.         dataOutputStream.writeShort(signatureIndex);
  135.         dataOutputStream.writeShort(index);
  136.     }

  137.     /**
  138.      * @return Constant pool used by this object.
  139.      */
  140.     public ConstantPool getConstantPool() {
  141.         return constantPool;
  142.     }

  143.     /**
  144.      * @return index of register where variable is stored
  145.      */
  146.     public int getIndex() {
  147.         return index;
  148.     }

  149.     /**
  150.      * @return Variable is valid within getStartPC() .. getStartPC()+getLength()
  151.      */
  152.     public int getLength() {
  153.         return length;
  154.     }

  155.     /**
  156.      * @return Variable name.
  157.      */
  158.     public String getName() {
  159.         return constantPool.getConstantUtf8(nameIndex).getBytes();
  160.     }

  161.     /**
  162.      * @return Index in constant pool of variable name.
  163.      */
  164.     public int getNameIndex() {
  165.         return nameIndex;
  166.     }

  167.     /**
  168.      * @return index of register where variable was originally stored
  169.      */
  170.     public int getOrigIndex() {
  171.         return origIndex;
  172.     }

  173.     /**
  174.      * @return Signature.
  175.      */
  176.     public String getSignature() {
  177.         return constantPool.getConstantUtf8(signatureIndex).getBytes();
  178.     }

  179.     /**
  180.      * @return Index in constant pool of variable signature.
  181.      */
  182.     public int getSignatureIndex() {
  183.         return signatureIndex;
  184.     }

  185.     /**
  186.      * @return Start of range where the variable is valid
  187.      */
  188.     public int getStartPC() {
  189.         return startPc;
  190.     }

  191.     /**
  192.      * @param constantPool Constant pool to be used for this object.
  193.      */
  194.     public void setConstantPool(final ConstantPool constantPool) {
  195.         this.constantPool = constantPool;
  196.     }

  197.     /**
  198.      * @param index the index in the local variable table of this variable
  199.      */
  200.     public void setIndex(final int index) { // TODO unused
  201.         this.index = index;
  202.     }

  203.     /**
  204.      * @param length the length of this local variable
  205.      */
  206.     public void setLength(final int length) {
  207.         this.length = length;
  208.     }

  209.     /**
  210.      * @param nameIndex the index into the constant pool for the name of this variable
  211.      */
  212.     public void setNameIndex(final int nameIndex) { // TODO unused
  213.         this.nameIndex = nameIndex;
  214.     }

  215.     /**
  216.      * @param signatureIndex the index into the constant pool for the signature of this variable
  217.      */
  218.     public void setSignatureIndex(final int signatureIndex) { // TODO unused
  219.         this.signatureIndex = signatureIndex;
  220.     }

  221.     /**
  222.      * @param startPc Specify range where the local variable is valid.
  223.      */
  224.     public void setStartPC(final int startPc) { // TODO unused
  225.         this.startPc = startPc;
  226.     }

  227.     /**
  228.      * @return string representation.
  229.      */
  230.     @Override
  231.     public String toString() {
  232.         return toStringShared(false);
  233.     }

  234.     /*
  235.      * Helper method shared with LocalVariableTypeTable
  236.      */
  237.     String toStringShared(final boolean typeTable) {
  238.         final String name = getName();
  239.         final String signature = Utility.signatureToString(getSignature(), false);
  240.         final String label = "LocalVariable" + (typeTable ? "Types" : "");
  241.         return label + "(startPc = " + startPc + ", length = " + length + ", index = " + index + ":" + signature + " " + name + ")";
  242.     }
  243. }