001 package serp.bytecode;
002
003 import java.io.*;
004
005 import serp.bytecode.lowlevel.*;
006 import serp.bytecode.visitor.*;
007
008 /**
009 * A constant value for a member field.
010 *
011 * @author Abe White
012 */
013 public class ConstantValue extends Attribute {
014 int _valueIndex = 0;
015
016 ConstantValue(int nameIndex, Attributes owner) {
017 super(nameIndex, owner);
018 }
019
020 int getLength() {
021 return 2;
022 }
023
024 /**
025 * Return the owning field.
026 */
027 public BCField getField() {
028 return (BCField) getOwner();
029 }
030
031 /**
032 * Return the {@link ConstantPool} index of the {@link ConstantEntry}
033 * holding the value of this constant. Defaults to 0.
034 */
035 public int getValueIndex() {
036 return _valueIndex;
037 }
038
039 /**
040 * Set the {@link ConstantPool} of the {@link ConstantEntry}
041 * holding the value of this constant.
042 */
043 public void setValueIndex(int valueIndex) {
044 _valueIndex = valueIndex;
045 }
046
047 /**
048 * Return the type of constant this attribute represents, or null if
049 * not set.
050 */
051 public String getTypeName() {
052 Class type = getType();
053 if (type == null)
054 return null;
055 return type.getName();
056 }
057
058 /**
059 * Return the type of constant this attribute represents (String.class,
060 * int.class, etc), or null if not set.
061 */
062 public Class getType() {
063 Object value = getValue();
064 if (value == null)
065 return null;
066
067 Class type = value.getClass();
068 if (type == Integer.class)
069 return int.class;
070 if (type == Float.class)
071 return float.class;
072 if (type == Double.class)
073 return double.class;
074 if (type == Long.class)
075 return long.class;
076 return String.class;
077 }
078
079 /**
080 * Return the bytecode for the type of constant this attribute represents.
081 */
082 public BCClass getTypeBC() {
083 return getProject().loadClass(getType());
084 }
085
086 /**
087 * Return the value of this constant as an Object of the appropriate
088 * type (String, Integer, Double, etc), or null if not set.
089 */
090 public Object getValue() {
091 if (_valueIndex <= 0)
092 return null;
093 return ((ConstantEntry) getPool().getEntry(_valueIndex)).getConstant();
094 }
095
096 /**
097 * Set the value of this constant using the appropriate wrapper Object
098 * type (String, Integer, Double, etc). Types that are not directly
099 * supported will be converted accordingly if possible.
100 */
101 public void setValue(Object value) {
102 Class type = value.getClass();
103 if (type == Boolean.class)
104 setIntValue((((Boolean) value).booleanValue()) ? 1 : 0);
105 else if (type == Character.class)
106 setIntValue((int) ((Character) value).charValue());
107 else if (type == Byte.class || type == Integer.class
108 || type == Short.class)
109 setIntValue(((Number) value).intValue());
110 else if (type == Float.class)
111 setFloatValue(((Number) value).floatValue());
112 else if (type == Double.class)
113 setDoubleValue(((Number) value).doubleValue());
114 else if (type == Long.class)
115 setLongValue(((Number) value).longValue());
116 else
117 setStringValue(value.toString());
118 }
119
120 /**
121 * Get the value of this int constant, or 0 if not set.
122 */
123 public int getIntValue() {
124 if (getValueIndex() <= 0)
125 return 0;
126 return ((IntEntry) getPool().getEntry(getValueIndex())).getValue();
127 }
128
129 /**
130 * Set the value of this int constant.
131 */
132 public void setIntValue(int value) {
133 setValueIndex(getPool().findIntEntry(value, true));
134 }
135
136 /**
137 * Get the value of this float constant.
138 */
139 public float getFloatValue() {
140 if (getValueIndex() <= 0)
141 return 0F;
142 return ((FloatEntry) getPool().getEntry(getValueIndex())).getValue();
143 }
144
145 /**
146 * Set the value of this float constant.
147 */
148 public void setFloatValue(float value) {
149 setValueIndex(getPool().findFloatEntry(value, true));
150 }
151
152 /**
153 * Get the value of this double constant.
154 */
155 public double getDoubleValue() {
156 if (getValueIndex() <= 0)
157 return 0D;
158 return ((DoubleEntry) getPool().getEntry(getValueIndex())).getValue();
159 }
160
161 /**
162 * Set the value of this double constant.
163 */
164 public void setDoubleValue(double value) {
165 setValueIndex(getPool().findDoubleEntry(value, true));
166 }
167
168 /**
169 * Get the value of this long constant.
170 */
171 public long getLongValue() {
172 if (getValueIndex() <= 0)
173 return 0L;
174 return ((LongEntry) getPool().getEntry(getValueIndex())).getValue();
175 }
176
177 /**
178 * Set the value of this long constant.
179 */
180 public void setLongValue(long value) {
181 setValueIndex(getPool().findLongEntry(value, true));
182 }
183
184 /**
185 * Get the value of this string constant.
186 */
187 public String getStringValue() {
188 if (getValueIndex() <= 0)
189 return null;
190 return ((StringEntry) getPool().getEntry(getValueIndex())).
191 getStringEntry().getValue();
192 }
193
194 /**
195 * Set the value of this string constant.
196 */
197 public void setStringValue(String value) {
198 setValueIndex(getPool().findStringEntry(value, true));
199 }
200
201 public void acceptVisit(BCVisitor visit) {
202 visit.enterConstantValue(this);
203 visit.exitConstantValue(this);
204 }
205
206 void read(Attribute other) {
207 setValue(((ConstantValue) other).getValue());
208 }
209
210 void read(DataInput in, int length) throws IOException {
211 setValueIndex(in.readUnsignedShort());
212 }
213
214 void write(DataOutput out, int length) throws IOException {
215 out.writeShort(getValueIndex());
216 }
217 }