001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.classfile; 020 021import java.io.DataInput; 022import java.io.DataOutputStream; 023import java.io.IOException; 024 025import org.apache.bcel.Const; 026import org.apache.bcel.util.Args; 027 028/** 029 * This class is derived from <em>Attribute</em> and represents a constant value, that is, a default value for initializing 030 * a class field. This class is instantiated by the <em>Attribute.readAttribute()</em> method. 031 * 032 * <pre> 033 * ConstantValue_attribute { 034 * u2 attribute_name_index; 035 * u4 attribute_length; 036 * u2 constantvalue_index; 037 * } 038 * </pre> 039 * 040 * @see Attribute 041 */ 042public final class ConstantValue extends Attribute { 043 044 private int constantValueIndex; 045 046 /** 047 * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a 048 * physical copy. 049 * 050 * @param c Source to copy. 051 */ 052 public ConstantValue(final ConstantValue c) { 053 this(c.getNameIndex(), c.getLength(), c.getConstantValueIndex(), c.getConstantPool()); 054 } 055 056 /** 057 * Constructs object from input stream. 058 * 059 * @param nameIndex Name index in constant pool. 060 * @param length Content length in bytes. 061 * @param input Input stream. 062 * @param constantPool Array of constants. 063 * @throws IOException if an I/O error occurs. 064 */ 065 ConstantValue(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { 066 this(nameIndex, length, input.readUnsignedShort(), constantPool); 067 } 068 069 /** 070 * Constructs a ConstantValue. 071 * 072 * @param nameIndex Name index in constant pool. 073 * @param length Content length in bytes. 074 * @param constantValueIndex Index in constant pool. 075 * @param constantPool Array of constants. 076 */ 077 public ConstantValue(final int nameIndex, final int length, final int constantValueIndex, final ConstantPool constantPool) { 078 super(Const.ATTR_CONSTANT_VALUE, nameIndex, Args.require(length, 2, "ConstantValue attribute length"), constantPool); 079 this.constantValueIndex = constantValueIndex; 080 } 081 082 /** 083 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 084 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 085 * 086 * @param v Visitor object. 087 */ 088 @Override 089 public void accept(final Visitor v) { 090 v.visitConstantValue(this); 091 } 092 093 /** 094 * Creates a deep copy of this attribute. 095 * 096 * @param constantPool the constant pool. 097 * @return deep copy of this attribute. 098 */ 099 @Override 100 public Attribute copy(final ConstantPool constantPool) { 101 final ConstantValue c = (ConstantValue) clone(); 102 c.setConstantPool(constantPool); 103 return c; 104 } 105 106 /** 107 * Dumps constant value attribute to file stream on binary format. 108 * 109 * @param file Output file stream. 110 * @throws IOException if an I/O error occurs. 111 */ 112 @Override 113 public void dump(final DataOutputStream file) throws IOException { 114 super.dump(file); 115 file.writeShort(constantValueIndex); 116 } 117 118 /** 119 * Gets the index in constant pool of constant value. 120 * 121 * @return Index in constant pool of constant value. 122 */ 123 public int getConstantValueIndex() { 124 return constantValueIndex; 125 } 126 127 /** 128 * Sets the constant value index. 129 * 130 * @param constantValueIndex the index info the constant pool of this constant value. 131 */ 132 public void setConstantValueIndex(final int constantValueIndex) { 133 this.constantValueIndex = constantValueIndex; 134 } 135 136 /** 137 * @return String representation of constant value. 138 */ 139 @Override 140 public String toString() { 141 Constant c = super.getConstantPool().getConstant(constantValueIndex); 142 final String buf; 143 final int i; 144 // Print constant to string depending on its type 145 switch (c.getTag()) { 146 case Const.CONSTANT_Long: 147 buf = String.valueOf(((ConstantLong) c).getBytes()); 148 break; 149 case Const.CONSTANT_Float: 150 buf = String.valueOf(((ConstantFloat) c).getBytes()); 151 break; 152 case Const.CONSTANT_Double: 153 buf = String.valueOf(((ConstantDouble) c).getBytes()); 154 break; 155 case Const.CONSTANT_Integer: 156 buf = String.valueOf(((ConstantInteger) c).getBytes()); 157 break; 158 case Const.CONSTANT_String: 159 i = ((ConstantString) c).getStringIndex(); 160 c = super.getConstantPool().getConstantUtf8(i); 161 buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\""; 162 break; 163 default: 164 throw new IllegalStateException("Type of ConstValue invalid: " + c); 165 } 166 return buf; 167 } 168}