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