    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 *  Unless required by applicable law or agreed to in writing, software
    012 *  distributed under the License is distributed on an "AS IS" BASIS,
    013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 *  See the License for the specific language governing permissions and
    015 *  limitations under the License.
    016 *
    017 */
    018package org.apache.bcel.classfile;
    019
    020import java.io.DataInput;
    021import java.io.DataOutputStream;
    022import java.io.IOException;
    023
    024import org.apache.bcel.Const;
    025import org.apache.bcel.Constants;
    026
    027/**
    028 * This class represents a local variable within a method. It contains its
    029 * scope, name, signature and index on the method's frame.
    030 *
    031 * @version $Id$
    032 * @see     LocalVariableTable
    033 */
    034public final class LocalVariable implements Cloneable, Node, Constants {
    035
    036    private int start_pc; // Range in which the variable is valid
    037    private int length;
    038    private int name_index; // Index in constant pool of variable name
    039    private int signature_index; // Index of variable signature
    040    private int index; /* Variable is `index'th local variable on
    041     * this method's frame.
    042     */
    043    private ConstantPool constant_pool;
    044    private int orig_index; // never changes; used to match up with LocalVariableTypeTable entries
    045
    046
    047    /**
    048     * Initialize from another object. Note that both objects use the same
    049     * references (shallow copy). Use copy() for a physical copy.
    050     */
    051    public LocalVariable(final LocalVariable c) {
    052        this(c.getStartPC(), c.getLength(), c.getNameIndex(), c.getSignatureIndex(), c.getIndex(),
    053                c.getConstantPool());
    054        this.orig_index = c.getOrigIndex();
    055    }
    056
    057
    058    /**
    059     * Construct object from file stream.
    060     * @param file Input stream
    061     * @throws IOException
    062     */
    063    LocalVariable(final DataInput file, final ConstantPool constant_pool) throws IOException {
    064        this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
    065                .readUnsignedShort(), file.readUnsignedShort(), constant_pool);
    066    }
    067
    068
    069    /**
    070     * @param start_pc Range in which the variable
    071     * @param length ... is valid
    072     * @param name_index Index in constant pool of variable name
    073     * @param signature_index Index of variable's signature
    074     * @param index Variable is `index'th local variable on the method's frame
    075     * @param constant_pool Array of constants
    076     */
    077    public LocalVariable(final int start_pc, final int length, final int name_index, final int signature_index, final int index,
    078            final ConstantPool constant_pool) {
    079        this.start_pc = start_pc;
    080        this.length = length;
    081        this.name_index = name_index;
    082        this.signature_index = signature_index;
    083        this.index = index;
    084        this.constant_pool = constant_pool;
    085        this.orig_index = index;
    086    }
    087
    088
    089    /**
    090     * @param start_pc Range in which the variable
    091     * @param length ... is valid
    092     * @param name_index Index in constant pool of variable name
    093     * @param signature_index Index of variable's signature
    094     * @param index Variable is `index'th local variable on the method's frame
    095     * @param constant_pool Array of constants
    096     * @param orig_index Variable is `index'th local variable on the method's frame prior to any changes
    097     */
    098    public LocalVariable(final int start_pc, final int length, final int name_index, final int signature_index, final int index,
    099            final ConstantPool constant_pool, final int orig_index) {
    100        this.start_pc = start_pc;
    101        this.length = length;
    102        this.name_index = name_index;
    103        this.signature_index = signature_index;
    104        this.index = index;
    105        this.constant_pool = constant_pool;
    106        this.orig_index = orig_index;
    107    }
    108
    109
    110    /**
    111     * Called by objects that are traversing the nodes of the tree implicitely
    112     * defined by the contents of a Java class. I.e., the hierarchy of methods,
    113     * fields, attributes, etc. spawns a tree of objects.
    114     *
    115     * @param v Visitor object
    116     */
    117    @Override
    118    public void accept( final Visitor v ) {
    119        v.visitLocalVariable(this);
    120    }
    121
    122
    123    /**
    124     * Dump local variable to file stream in binary format.
    125     *
    126     * @param file Output file stream
    127     * @throws IOException
    128     */
    129    public final void dump( final DataOutputStream file ) throws IOException {
    130        file.writeShort(start_pc);
    131        file.writeShort(length);
    132        file.writeShort(name_index);
    133        file.writeShort(signature_index);
    134        file.writeShort(index);
    135    }
    136
    137
    138    /**
    139     * @return Constant pool used by this object.
    140     */
    141    public final ConstantPool getConstantPool() {
    142        return constant_pool;
    143    }
    144
    145
    146    /**
    147     * @return Variable is valid within getStartPC() .. getStartPC()+getLength()
    148     */
    149    public final int getLength() {
    150        return length;
    151    }
    152
    153
    154    /**
    155     * @return Variable name.
    156     */
    157    public final String getName() {
    158        ConstantUtf8 c;
    159        c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
    160        return c.getBytes();
    161    }
    162
    163
    164    /**
    165     * @return Index in constant pool of variable name.
    166     */
    167    public final int getNameIndex() {
    168        return name_index;
    169    }
    170
    171
    172    /**
    173     * @return Signature.
    174     */
    175    public final String getSignature() {
    176        ConstantUtf8 c;
    177        c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8);
    178        return c.getBytes();
    179    }
    180
    181
    182    /**
    183     * @return Index in constant pool of variable signature.
    184     */
    185    public final int getSignatureIndex() {
    186        return signature_index;
    187    }
    188
    189
    190    /**
    191     * @return index of register where variable is stored
    192     */
    193    public final int getIndex() {
    194        return index;
    195    }
    196
    197
    198    /**
    199     * @return index of register where variable was originally stored
    200     */
    201    public final int getOrigIndex() {
    202        return orig_index;
    203    }
    204
    205
    206    /**
    207     * @return Start of range where he variable is valid
    208     */
    209    public final int getStartPC() {
    210        return start_pc;
    211    }
    212
    213
    214    /*
    215     * Helper method shared with LocalVariableTypeTable
    216     */
    217    final String toStringShared( final boolean typeTable ) {
    218        final String name = getName();
    219        final String signature = Utility.signatureToString(getSignature(), false);
    220        final String label = "LocalVariable" + (typeTable ? "Types" : "" );
    221        return label + "(start_pc = " + start_pc + ", length = " + length + ", index = "
    222                + index + ":" + signature + " " + name + ")";
    223    }
    224
    225
    226    /**
    227     * @param constant_pool Constant pool to be used for this object.
    228     */
    229    public final void setConstantPool( final ConstantPool constant_pool ) {
    230        this.constant_pool = constant_pool;
    231    }
    232
    233
    234    /**
    235     * @param length the length of this local variable
    236     */
    237    public final void setLength( final int length ) {
    238        this.length = length;
    239    }
    240
    241
    242    /**
    243     * @param name_index the index into the constant pool for the name of this variable
    244     */
    245    public final void setNameIndex( final int name_index ) { // TODO unused
    246        this.name_index = name_index;
    247    }
    248
    249
    250    /**
    251     * @param signature_index the index into the constant pool for the signature of this variable
    252     */
    253    public final void setSignatureIndex( final int signature_index ) { // TODO unused
    254        this.signature_index = signature_index;
    255    }
    256
    257
    258    /**
    259     * @param index the index in the local variable table of this variable
    260     */
    261    public final void setIndex( final int index ) { // TODO unused
    262        this.index = index;
    263    }
    264
    265
    266    /**
    267     * @param start_pc Specify range where the local variable is valid.
    268     */
    269    public final void setStartPC( final int start_pc ) { // TODO unused
    270        this.start_pc = start_pc;
    271    }
    272
    273
    274    /**
    275     * @return string representation.
    276     */
    277    @Override
    278    public final String toString() {
    279        return toStringShared(false);
    280    }
    281
    282
    283    /**
    284     * @return deep copy of this object
    285     */
    286    public LocalVariable copy() {
    287        try {
    288            return (LocalVariable) clone();
    289        } catch (final CloneNotSupportedException e) {
    290            // TODO should this throw?
    291        }
    292        return null;
    293    }
    294}