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;
025
026/**
027 * This class is derived from <em>Attribute</em> and represents a constant value, i.e., a default value for initializing
028 * a class field. This class is instantiated by the <em>Attribute.readAttribute()</em> method.
029 *
030 * @see Attribute
031 */
032public final class ConstantValue extends Attribute {
033
034    private int constantValueIndex;
035
036    /**
037     * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
038     * physical copy.
039     */
040    public ConstantValue(final ConstantValue c) {
041        this(c.getNameIndex(), c.getLength(), c.getConstantValueIndex(), c.getConstantPool());
042    }
043
044    /**
045     * Construct object from input stream.
046     *
047     * @param name_index Name index in constant pool
048     * @param length Content length in bytes
049     * @param input Input stream
050     * @param constant_pool Array of constants
051     * @throws IOException if an I/O error occurs.
052     */
053    ConstantValue(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
054        this(name_index, length, input.readUnsignedShort(), constant_pool);
055    }
056
057    /**
058     * @param name_index Name index in constant pool
059     * @param length Content length in bytes
060     * @param constantValueIndex Index in constant pool
061     * @param constant_pool Array of constants
062     */
063    public ConstantValue(final int name_index, final int length, final int constantValueIndex, final ConstantPool constant_pool) {
064        super(Const.ATTR_CONSTANT_VALUE, name_index, length, constant_pool);
065        this.constantValueIndex = constantValueIndex;
066    }
067
068    /**
069     * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
070     * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
071     *
072     * @param v Visitor object
073     */
074    @Override
075    public void accept(final Visitor v) {
076        v.visitConstantValue(this);
077    }
078
079    /**
080     * @return deep copy of this attribute
081     */
082    @Override
083    public Attribute copy(final ConstantPool constantPool) {
084        final ConstantValue c = (ConstantValue) clone();
085        c.setConstantPool(constantPool);
086        return c;
087    }
088
089    /**
090     * Dump constant value attribute to file stream on binary format.
091     *
092     * @param file Output file stream
093     * @throws IOException if an I/O error occurs.
094     */
095    @Override
096    public void dump(final DataOutputStream file) throws IOException {
097        super.dump(file);
098        file.writeShort(constantValueIndex);
099    }
100
101    /**
102     * @return Index in constant pool of constant value.
103     */
104    public int getConstantValueIndex() {
105        return constantValueIndex;
106    }
107
108    /**
109     * @param constantValueIndex the index info the constant pool of this constant value
110     */
111    public void setConstantValueIndex(final int constantValueIndex) {
112        this.constantValueIndex = constantValueIndex;
113    }
114
115    /**
116     * @return String representation of constant value.
117     */
118    @Override
119    public String toString() {
120        Constant c = super.getConstantPool().getConstant(constantValueIndex);
121        String buf;
122        int i;
123        // Print constant to string depending on its type
124        switch (c.getTag()) {
125        case Const.CONSTANT_Long:
126            buf = String.valueOf(((ConstantLong) c).getBytes());
127            break;
128        case Const.CONSTANT_Float:
129            buf = String.valueOf(((ConstantFloat) c).getBytes());
130            break;
131        case Const.CONSTANT_Double:
132            buf = String.valueOf(((ConstantDouble) c).getBytes());
133            break;
134        case Const.CONSTANT_Integer:
135            buf = String.valueOf(((ConstantInteger) c).getBytes());
136            break;
137        case Const.CONSTANT_String:
138            i = ((ConstantString) c).getStringIndex();
139            c = super.getConstantPool().getConstantUtf8(i);
140            buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
141            break;
142        default:
143            throw new IllegalStateException("Type of ConstValue invalid: " + c);
144        }
145        return buf;
146    }
147}