KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sli > kim > classfile > ConstPoolEntry


1 package sli.kim.classfile;
2
3 import java.io.*;
4
5 public final class ConstPoolEntry implements Cloneable JavaDoc {
6     public static final int UTF = 1;
7     public static final int UNICODE = 2;
8     public static final int INT = 3;
9     public static final int FLOAT = 4;
10     public static final int LONG = 5;
11     public static final int DOUBLE = 6;
12     public static final int CLASS = 7;
13     public static final int STRING = 8;
14     public static final int FIELDREF = 9;
15     public static final int METHODREF = 10;
16     public static final int INTERFACEMETHODREF = 11;
17     public static final int NAMEANDTYPE = 12;
18
19     private byte typecode = -1;
20
21     private String JavaDoc stringValue;
22     private int intValue;
23     private long longValue;
24     private float floatValue;
25     private double doubleValue;
26     private short index1, index2;
27
28     public boolean equals(Object JavaDoc o) {
29         ConstPoolEntry other;
30         try {
31             other = (ConstPoolEntry)o;
32         } catch (ClassCastException JavaDoc e) {
33             return false;
34         }
35
36         // For equality purposes, UTF and UNICODE typecodes are equivalent.
37
// We special case UTF and UNICODE comparison by ignoring typecode and
38
// just looking at stringValue.
39
if (stringValue != null && other.stringValue != null)
40             return stringValue.equals(other.stringValue);
41
42         if (typecode != other.typecode)
43             return false;
44
45         // This relies on fact that all unused fields are 0.
46
return (other.intValue == intValue &&
47             other.longValue == longValue &&
48             other.index1 == index1 &&
49             other.index2 == index2 &&
50             other.floatValue == floatValue &&
51             other.doubleValue == doubleValue);
52     }
53     public int hashCode() {
54         int result = typecode * 97;
55         if (stringValue != null)
56             result += stringValue.hashCode()*43;
57         result += intValue*37 + longValue*31 + index1*29 + index2*23;
58         return result;
59     }
60     public Object JavaDoc clone() {
61         ConstPoolEntry result = new ConstPoolEntry();
62         result.typecode = typecode;
63         result.stringValue = stringValue;
64         result.intValue = intValue;
65         result.longValue = longValue;
66         result.index1 = index1;
67         result.index2 = index2;
68         result.floatValue = floatValue;
69         result.doubleValue = doubleValue;
70         return result;
71     }
72     public String JavaDoc toString() {
73         if (UTF == typecode)
74             return "UTF \"" + stringValue + "\"";
75         else if (UNICODE == typecode)
76             return "UNICODE \"" + stringValue + "\"";
77         else if (INT == typecode)
78             return "INT " + intValue;
79         else if (FLOAT == typecode)
80             return "FLOAT " + floatValue;
81         else if (LONG == typecode)
82             return "LONG " + longValue;
83         else if (DOUBLE == typecode)
84             return "DOUBLE " + doubleValue;
85         else if (CLASS == typecode)
86             return "CLASS " + index1;
87         else if (STRING == typecode)
88             return "STRING " + index1;
89         else if (FIELDREF == typecode)
90             return "FIELDREF " + index1 + " " + index2;
91         else if (METHODREF == typecode)
92             return "METHODREF " + index1 + " " + index2;
93         else if (INTERFACEMETHODREF == typecode)
94             return "INTERFACEMETHODREF " + index1 + " " + index2;
95         else if (NAMEANDTYPE == typecode)
96             return "NAMEANDTYPE " + index1 + " " + index2;
97         else
98             return "Unknown typecode " + typecode;
99     }
100
101     public byte typecode() {
102         return typecode;
103     }
104
105
106     // used by set methods to erase evidence of any previous set method
107
private void clearType() {
108         typecode = -1;
109         stringValue = null;
110         index1 = 0;
111         index2 = 0;
112         intValue = 0;
113         longValue = 0;
114         floatValue = 0;
115         doubleValue = 0;
116     }
117     /**
118     * Some const pool entries don't actually exist -- like the ones after a
119     * LONG or DOUBLE, or entry 0. These entries are unused.
120     */

121     public ConstPoolEntry setUnused() {
122         typecode = -1;
123         return this;
124     }
125     public boolean isUnused() {
126         return (typecode == -1);
127     }
128     public ConstPoolEntry setUTF(String JavaDoc value) {
129         clearType();
130         typecode = UTF;
131         stringValue = value;
132         if (null == stringValue)
133             throw new ConstPoolEntryError("ConstPoolEntry.setUTF called with null string");
134         return this;
135     }
136     public ConstPoolEntry setUnicode(String JavaDoc value) {
137         clearType();
138         typecode = UNICODE;
139         stringValue = value;
140         if (null == stringValue)
141             throw new ConstPoolEntryError("ConstPoolEntry.setUTF called with null string");
142         return this;
143     }
144     public ConstPoolEntry setInt(int value) {
145         clearType();
146         typecode = INT;
147         intValue = value;
148         return this;
149     }
150     public ConstPoolEntry setLong(long value) {
151         clearType();
152         typecode = LONG;
153         longValue = value;
154         return this;
155     }
156     public ConstPoolEntry setFloat(float value) {
157         clearType();
158         typecode = FLOAT;
159         floatValue = value;
160         return this;
161     }
162     public ConstPoolEntry setDouble(double value) {
163         clearType();
164         typecode = DOUBLE;
165         doubleValue = value;
166         return this;
167     }
168     public ConstPoolEntry setString(short index) {
169         clearType();
170         typecode = STRING;
171         index1 = index;
172         return this;
173     }
174     public ConstPoolEntry setClass(short index) {
175         clearType();
176         typecode = CLASS;
177         index1 = index;
178         return this;
179     }
180     public ConstPoolEntry setFieldRef(short index1, short index2) {
181         clearType();
182         typecode = FIELDREF;
183         this.index1 = index1;
184         this.index2 = index2;
185         return this;
186     }
187     public ConstPoolEntry setMethodRef(short index1, short index2) {
188         clearType();
189         typecode = METHODREF;
190         this.index1 = index1;
191         this.index2 = index2;
192         return this;
193     }
194     public ConstPoolEntry setInterfaceMethodRef(short index1, short index2) {
195         clearType();
196         typecode = INTERFACEMETHODREF;
197         this.index1 = index1;
198         this.index2 = index2;
199         return this;
200     }
201     public ConstPoolEntry setNameAndType(short index1, short index2) {
202         clearType();
203         typecode = NAMEANDTYPE;
204         this.index1 = index1;
205         this.index2 = index2;
206         return this;
207     }
208
209
210     /**
211     * For UTF and UNICODE entries.
212     */

213     public String JavaDoc getString() {
214         if (UTF == typecode || UNICODE == typecode)
215             return stringValue;
216         throw getError("getString()");
217     }
218     /**
219     * For STRING entries.
220     */

221     public short getStringIndex() {
222         if (STRING == typecode)
223             return index1;
224         throw getError("getStringIndex()");
225     }
226     /**
227     * For INT entries.
228     */

229     public int getInt() {
230         if (INT == typecode)
231             return intValue;
232         throw getError("getInt()");
233     }
234     /**
235     * For LONG entries.
236     */

237     public long getLong() {
238         if (LONG == typecode)
239             return longValue;
240         throw getError("getLong()");
241     }
242     /**
243     * For FLOAT entries.
244     */

245     public float getFloat() {
246         if (FLOAT == typecode)
247             return floatValue;
248         throw getError("getFloat()");
249     }
250     /**
251     * For DOUBLE entries.
252     */

253     public double getDouble() {
254         if (DOUBLE == typecode)
255             return doubleValue;
256         throw getError("getDouble()");
257     }
258     /**
259     * For INT, LONG, FLOAT, DOUBLE, UTF, or UNICODE entries,
260     * returns an Integer, Long, Float, Double, or String, respectively.
261     */

262     public Object JavaDoc getPrimitiveTypeValue() {
263         if (UTF == typecode || UNICODE == typecode)
264             return stringValue;
265         if (INT == typecode)
266             return new Integer JavaDoc(intValue);
267         if (LONG == typecode)
268             return new Long JavaDoc(longValue);
269         if (FLOAT == typecode)
270             return new Float JavaDoc(floatValue);
271         if (DOUBLE == typecode)
272             return new Double JavaDoc(doubleValue);
273         throw getError("getPrimitiveTypeValue()");
274     }
275     /**
276     * For CLASS entries.
277     */

278     public short getClassNameIndex() {
279         if (CLASS == typecode)
280             return index1;
281         throw getError("getClassNameIndex()");
282     }
283     /**
284     * For FIELDREF, METHODREF, or INTERFACEMETHODREF entries.
285     */

286     public short getClassIndex() {
287         if (FIELDREF == typecode || METHODREF == typecode
288             || INTERFACEMETHODREF == typecode)
289             return index1;
290         throw getError("getClassIndex()");
291     }
292     /**
293     * For FIELDREF, METHODREF, or INTERFACEMETHODREF entries.
294     */

295     public short getNameAndTypeIndex() {
296         if (FIELDREF == typecode || METHODREF == typecode
297             || INTERFACEMETHODREF == typecode)
298             return index2;
299         throw getError("getNameAndTypeIndex()");
300     }
301     /**
302     * For NAMEANDTYPE entries.
303     */

304     public short getNameIndex() {
305         if (NAMEANDTYPE == typecode)
306             return index1;
307         throw getError("getNameIndex()");
308     }
309     /**
310     * For NAMEANDTYPE entries.
311     */

312     public short getTypeIndex() {
313         if (NAMEANDTYPE == typecode)
314             return index2;
315         throw getError("getTypeIndex()");
316     }
317
318     // utility method -- called when getXXXX() is called for inappropriate typecode
319
private ConstPoolEntryError getError(String JavaDoc method) {
320         return new ConstPoolEntryError(method + " called on ConstPoolEntry with typecode " +
321             typecode());
322     }
323
324
325     
326     /**
327     * Read in a constant pool entry from a stream.
328     * @throws ClassFileParseException if the class file is corrupt.
329     * @throws IOException if the DataInput throws an IOException.
330     */

331     public void read(DataInput in, ConstPoolEntry entry)
332         throws IOException, ClassFileParseException
333     {
334         byte tag = in.readByte();
335         switch (tag) {
336         case UTF:
337             entry.setUTF(in.readUTF());
338             break;
339         case UNICODE:
340             {
341                 int length = in.readShort();
342                 char[] chars = new char[length];
343                 for (int i = 0; i < length; i++)
344                     chars[i] = in.readChar();
345                 String JavaDoc str = new String JavaDoc(chars);
346                 entry.setUnicode(str);
347                 break;
348             }
349         case INT:
350             entry.setInt(in.readInt());
351             break;
352         case FLOAT:
353             entry.setFloat(in.readFloat());
354             break;
355         case LONG:
356             entry.setLong(in.readLong());
357             break;
358         case DOUBLE:
359             entry.setDouble(in.readDouble());
360             break;
361         case CLASS:
362             entry.setClass(in.readShort());
363             break;
364         case STRING:
365             entry.setString(in.readShort());
366             break;
367         case FIELDREF:
368             entry.setFieldRef(in.readShort(), in.readShort());
369             break;
370         case METHODREF:
371             entry.setMethodRef(in.readShort(), in.readShort());
372             break;
373         case INTERFACEMETHODREF:
374             entry.setInterfaceMethodRef(in.readShort(), in.readShort());
375             break;
376         case NAMEANDTYPE:
377             entry.setNameAndType(in.readShort(), in.readShort());
378             break;
379         default:
380             throw new ClassFileParseException("Unknown constant pool tag: " + tag);
381         }
382     }
383
384     /**
385     * Write a constant pool entry to a stream.
386     * @throws IOException if the DataOutput throws an IOException.
387     */

388     public void write(DataOutput out, ConstPoolEntry entry) throws IOException {
389         out.writeByte(entry.typecode());
390         switch (entry.typecode()) {
391         case UTF:
392             out.writeUTF(entry.getString());
393             break;
394         case UNICODE:
395             {
396                 char[] chars = entry.getString().toCharArray();
397                 out.writeShort(chars.length);
398                 for (int i = 0; i < chars.length; i++)
399                     out.writeChar(chars[i]);
400                 break;
401             }
402         case INT:
403             out.writeInt(entry.getInt());
404             break;
405         case FLOAT:
406             out.writeFloat(entry.getFloat());
407             break;
408         case LONG:
409             out.writeLong(entry.getLong());
410             break;
411         case DOUBLE:
412             out.writeDouble(entry.getDouble());
413             break;
414         case CLASS:
415             short idx = entry.getClassNameIndex();
416             out.writeShort(entry.getClassNameIndex());
417             break;
418         case STRING:
419             out.writeShort(entry.getStringIndex());
420             break;
421         case FIELDREF:
422         case METHODREF:
423         case INTERFACEMETHODREF:
424             out.writeShort(entry.getClassIndex());
425             out.writeShort(entry.getNameAndTypeIndex());
426             break;
427         case NAMEANDTYPE:
428             out.writeShort(entry.getNameIndex());
429             out.writeShort(entry.getTypeIndex());
430             break;
431         default:
432             throw new ConstPoolEntryError("Internal error: Unknown constant pool typecode: " +
433                 entry.typecode());
434         }
435     }
436 }
Popular Tags