KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jbet > ConstantPool


1 /*
2  * JBET - Java Binary Enhancement Tool
3  * Copyright (c) 2003 Networks Associates Technology, Inc.
4  *
5  * This software was developed under DARPA/SPAWAR contract
6  * N66001-00-C-8602 "SPMA" as part of the
7  * DARPA OASIS research program.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */

30
31 package jbet;
32 import java.io.*;
33 import java.util.*;
34
35 /**
36  * This class represents the constant pool in a class file, and
37  * provides methods to manipulate it.
38  *
39  * The constant pool elements are indexed exactly as in a class file.
40  *
41  * The constant pool is not complex but has a lot of indirection built
42  * into it, so there is a lot of referencing between objects in the
43  * Vector.
44  *
45  * In general, the ConstantPool reflects the organization of the
46  * constant pool format specified by the JVM Specification, 2nd
47  * Edition. This object does, however, add some new structures to
48  * facilitate editing (e.g., descriptor classes).
49  *
50  * $Id: ConstantPool.java,v 1.7 2003/09/09 17:31:53 areisse Exp $
51  *
52  * @author Lee Badger
53  * @author Larry D'Anna
54  * @version 0.1
55  */

56 final class ConstantPool extends CPInterface {
57     private Vector cpVector; // The constant pool
58
private Hashtable hashtable;
59
60
61     /**
62      * Construct an "empty" constant pool.
63      *
64      * The constant pool size is never zero in the JVM Specification, so
65      * we initialize it with a null item. */

66     ConstantPool() {
67     hashtable = new Hashtable();
68     cpVector = new Vector();
69     cpVector.addElement(null);
70     }
71
72
73     /**
74      * Construct a constant pool by reading from a class file.
75      *
76      * @param dataIn An open input stream.
77      * @returns An initialized ConstantPool object.
78      */

79     ConstantPool (DataInputStream dataIn) throws IOException,
80         ClassFileException {
81
82     // the first short of the pool is the size of the pool.
83
int size = dataIn.readUnsignedShort();
84
85     cpVector = new Vector(size);
86     cpVector.setSize(size);
87     hashtable= new Hashtable();
88
89     /*
90      * Pass 1: read in the records and store index values, which
91      * are valid if this is a well-formed class file.
92      */

93         // Start at 1 to skip the initial "nul" entry.
94
//
95
// For each entry in the pool, create an object of the appropriate
96
// type (this is just begging for the ObjectFactory pattern) and
97
// put it in the array. We will put it into the hash table later.
98

99     for (int i=1; i < size /*cpVector.size()*/; i++) {
100         byte tag = (byte) dataIn.readUnsignedByte();
101         switch (tag) {
102         case CONSTANT_Class : {
103         CpClass cp = new CpClass(i, this);
104         cp.nameIndex = dataIn.readUnsignedShort();
105         cpVector.setElementAt(cp, i);
106         break;
107         }
108         case CONSTANT_Fieldref: {
109         CpFieldRef cp = new CpFieldRef(i, this);
110         cp.classIndex = dataIn.readUnsignedShort();
111         cp.nameAndTypeIndex = dataIn.readUnsignedShort();
112         cpVector.setElementAt(cp, i);
113         break;
114         }
115         case CONSTANT_Methodref: {
116         CpMethodRef cp = new CpMethodRef(i, this, false);
117         cp.classIndex = dataIn.readUnsignedShort();
118         cp.nameAndTypeIndex = dataIn.readUnsignedShort();
119         cpVector.setElementAt(cp, i);
120         break;
121         }
122         case CONSTANT_InterfaceMethodref: {
123         /* Note: we intentionally use CpMethodRef to represent
124          * an interface reference to simplify manipulations of
125          * references to methods. */

126         CpMethodRef cp = new CpMethodRef(i, this, true);
127         cp.classIndex = dataIn.readUnsignedShort();
128         cp.nameAndTypeIndex = dataIn.readUnsignedShort();
129         cpVector.setElementAt(cp, i);
130         break;
131         }
132         case CONSTANT_String: {
133         CpString cp = new CpString(i, this);
134         cp.stringIndex = dataIn.readUnsignedShort();
135         cpVector.setElementAt(cp, i);
136         break;
137         }
138         case CONSTANT_Integer: {
139         CpInteger cp = new CpInteger(i, this);
140         cp.value = dataIn.readInt();
141         cpVector.setElementAt(cp, i);
142         break;
143         }
144         case CONSTANT_Float: {
145         CpFloat cp = new CpFloat(i, this);
146         cp.value = dataIn.readFloat();
147         cpVector.setElementAt(cp, i);
148         break;
149         }
150         case CONSTANT_Long: {
151         CpLong cp = new CpLong(i, this);
152         cp.value = dataIn.readLong();
153         cpVector.setElementAt(cp, i);
154         i++; //the next entry is unused
155
break;
156         }
157         case CONSTANT_Double: {
158         CpDouble cp = new CpDouble(i, this);
159         cp.value = dataIn.readDouble();
160         cpVector.setElementAt(cp, i);
161         i++; //the next entry is unused
162
break;
163         }
164         case CONSTANT_NameAndType: {
165         CpNameAndType cp = new CpNameAndType(i, this);
166         cp.nameIndex = dataIn.readUnsignedShort();
167         cp.typeIndex = dataIn.readUnsignedShort();
168         cpVector.setElementAt(cp, i);
169         break;
170         }
171         case CONSTANT_Utf8: {
172         CpUtf8 cp = new CpUtf8(i, this);
173         cp.string = dataIn.readUTF();
174         cpVector.setElementAt(cp, i);
175         break;
176         }
177         default:
178         throw new RuntimeException JavaDoc ("error reading constant pool");
179         }
180     }
181
182     for (int i=1; i< cpVector.size(); i++) {
183         CpEntry cp = (CpEntry)cpVector.elementAt(i);
184         cp.setup();
185         hashtable.put(cp, cp);
186
187             // For the purpose of this test, see the relevant entries above.
188
if ( cp.tag == CONSTANT_Long || cp.tag == CONSTANT_Double )
189         i++;
190     }
191     }
192
193     /**
194      * Write the contents of this constant pool object out as a valid
195      * constant_pool field of a class file.
196      *
197      * Note: before using writeFile(), it is important to call
198      * resolveConstants().
199      *
200      * @throws IOException if there is an error writing the class file.
201      * @param dataOut An open output stream.
202      */

203     void writeFile(DataOutputStream dataOut) throws IOException {
204     dataOut.writeShort( cpVector.size() );
205
206         // Again, start at 1 to skip the inital null.
207
for (int i=1; i<cpVector.size(); i++) {
208
209         CpEntry entry = (CpEntry) cpVector.elementAt(i);
210         entry.write(dataOut);
211
212         if (entry.tag == CONSTANT_Long ||
213         entry.tag == CONSTANT_Double)
214         i++;
215     }
216     }
217
218
219
220     /**
221      * Print the contents of the ConstantPool to a stream.
222      */

223     void printout (LineWriter out) {
224         // For each element, print it.
225
// Here we use the simplier "!null" logic to avoid the elements
226
// after doubles and longs rather than the explicit test logic.
227
for (int i = 1; i < poolCount(); i++)
228         if (elementAt(i) != null)
229         out.println (i + "\t" + elementAt(i).recString());
230     }
231     
232     int tagAt (int i) {
233     return elementAt(i)==null ? 0 : elementAt(i).tag;
234     }
235
236     CpEntry elementAt (int i) {
237     return (CpEntry) cpVector.elementAt(i);
238     }
239
240
241     /**
242      * Return the size of the constant pool.
243      * @return size of the constant pool, as the class file format expects it.
244      */

245     int poolCount() {
246     return(cpVector.size());
247     }
248
249     /**
250      * Each of the following functions finds a record, of a specific
251      * type at a specified index in the ConstantPool. If a record of
252      * the expected type is not present in the ConstantPool at the
253      * specified index, the ClassFileException is thrown.
254      */

255
256     int integerAt (int index) throws ClassFileException {
257     Object JavaDoc obj = cpVector.elementAt(index);
258     if (! (obj instanceof CpInteger))
259         throw new CPException ("not a integer " + index);
260     return ((CpInteger)obj).value;
261     }
262     float floatAt (int index) throws ClassFileException {
263     Object JavaDoc obj = cpVector.elementAt(index);
264     if (! (obj instanceof CpFloat))
265         throw new CPException ("not a float " + index);
266     return ((CpFloat)obj).value;
267     }
268     long longAt (int index) throws ClassFileException {
269     Object JavaDoc obj = cpVector.elementAt(index);
270     if (! (obj instanceof CpLong) )
271         throw new CPException ("not a long " + index);
272     return ((CpLong)obj).value;
273     }
274     double doubleAt (int index) throws ClassFileException {
275     Object JavaDoc obj = cpVector.elementAt(index);
276     if (! (obj instanceof CpDouble) )
277         throw new CPException ("not a double " + index);
278     return ((CpDouble)obj).value;
279     }
280     String JavaDoc utf8At (int index) throws ClassFileException {
281     Object JavaDoc obj = cpVector.elementAt(index);
282     if (! (obj instanceof CpUtf8) )
283         throw new CPException ("not a utf8 " + index);
284     return ((CpUtf8)obj).string;
285     }
286     String JavaDoc stringAt (int index) throws ClassFileException {
287     Object JavaDoc obj = cpVector.elementAt(index);
288     if (! (obj instanceof CpString) )
289         throw new CPException ("not a string " + index);
290     return ((CpString)obj).string();
291     }
292     CpNameAndType cpNameAndTypeAt (int index) throws ClassFileException {
293     Object JavaDoc obj = cpVector.elementAt(index);
294     if (obj instanceof CpNameAndType)
295         return (CpNameAndType) obj;
296     else
297         throw new CPException ("not a name_and_type " + index);
298     }
299     CpInteger cpIntegerAt (int index) throws ClassFileException {
300     Object JavaDoc obj = cpVector.elementAt(index);
301     if (! (obj instanceof CpInteger))
302         throw new CPException ("not a integer " + index);
303     return (CpInteger)obj;
304     }
305     CpFloat cpFloatAt (int index) throws ClassFileException {
306     Object JavaDoc obj = cpVector.elementAt(index);
307     if (! (obj instanceof CpFloat))
308         throw new CPException ("not a float " + index);
309     return ((CpFloat)obj);
310     }
311     CpLong cpLongAt (int index) throws ClassFileException {
312     Object JavaDoc obj = cpVector.elementAt(index);
313     if (! (obj instanceof CpLong) )
314         throw new CPException ("not a long " + index);
315     return ((CpLong)obj);
316     }
317     CpDouble cpDoubleAt (int index) throws ClassFileException {
318     Object JavaDoc obj = cpVector.elementAt(index);
319     if (! (obj instanceof CpDouble) )
320         throw new CPException ("not a double " + index);
321     return ((CpDouble)obj);
322     }
323     CpUtf8 cpUtf8At (int index) throws ClassFileException {
324     Object JavaDoc obj = cpVector.elementAt(index);
325     if (! (obj instanceof CpUtf8) )
326         throw new CPException ("not a utf8 " + index);
327     return ((CpUtf8)obj);
328     }
329     CpClass cpClassAt (int index) throws ClassFileException {
330     Object JavaDoc obj = cpVector.elementAt(index);
331     if (! (obj instanceof CpClass) )
332         throw new CPException ("not a class " + index + " " + ((CpEntry)obj).tag);
333     return (CpClass)obj;
334     }
335     CpString cpStringAt (int index) throws ClassFileException {
336     Object JavaDoc obj = cpVector.elementAt(index);
337     if (! (obj instanceof CpString) )
338         throw new CPException ("not a string " + index);
339     return ((CpString)obj);
340     }
341     CpMethodRef cpMethodRefAt (int index) throws ClassFileException {
342     Object JavaDoc obj = cpVector.elementAt(index);
343     if (! (obj instanceof CpMethodRef) )
344         throw new CPException ("not a methodref " + index);
345     return ((CpMethodRef)obj);
346     }
347     CpFieldRef cpFieldRefAt (int index) throws ClassFileException {
348     Object JavaDoc obj = cpVector.elementAt(index);
349     if (! (obj instanceof CpFieldRef) )
350         throw new CPException ("not a fieldref " + index);
351     return ((CpFieldRef)obj);
352     }
353
354     /**
355      * Each of the following functions finds a record, of a specific
356      * type and having a specific value, in the ConstantPool, if it
357      * exists in the ConstantPool. If the requested record does not
358      * exist, these functions create the record and then return a
359      * reference to it.
360      */

361
362     int internUtf8 (String JavaDoc s) {
363     CpUtf8 val, key = new CpUtf8(this, s);
364     val = (CpUtf8) hashtable.get(key);
365     if (val != null) return val.index;
366     appendRec(key);
367     return key.index;
368     }
369     
370     int internClass (String JavaDoc s) {
371     if (s==null)
372         return 0;
373     CpClass val, key = new CpClass(this, s);
374     val = (CpClass) hashtable.get(key);
375     if (val != null) return val.index;
376     key.nameIndex = internUtf8(s);
377     appendRec(key);
378     return key.index;
379     }
380
381
382     int internString (String JavaDoc s) {
383     CpString val, key = new CpString(this, s);
384     val = (CpString) hashtable.get(key);
385     if (val != null) return val.index;
386     key.stringIndex = internUtf8(s);
387     appendRec(key);
388     return key.index;
389     }
390
391
392     int internMethodRef (String JavaDoc cname, String JavaDoc mname, Descriptor type) {
393     CpMethodRef val, key = new CpMethodRef(this, false, cname, mname, type);
394     val = (CpMethodRef) hashtable.get(key);
395     if (val != null) return val.index;
396     key.classIndex = internClass(cname);
397     key.nameAndTypeIndex = internNameAndType(mname, type);
398     appendRec(key);
399     return key.index;
400     }
401
402     int internInterfaceMethodRef (String JavaDoc cname, String JavaDoc mname, Descriptor type) {
403     CpMethodRef val, key = new CpMethodRef(this, true, cname, mname, type);
404     val = (CpMethodRef) hashtable.get(key);
405     if (val != null) return val.index;
406     key.classIndex = internClass(cname);
407     key.nameAndTypeIndex = internNameAndType(mname, type);
408     appendRec(key);
409     return key.index;
410     }
411
412     int internFieldRef (String JavaDoc cname, String JavaDoc fname, Type type) {
413     CpFieldRef val, key = new CpFieldRef(this, cname, fname, type);
414     val = (CpFieldRef) hashtable.get(key);
415     if (val != null) return val.index;
416     key.classIndex = internClass(cname);
417     key.nameAndTypeIndex = internNameAndType(fname, type);
418     appendRec(key);
419     return key.index;
420     }
421
422
423
424     int internNameAndType (String JavaDoc name, Object JavaDoc type) {
425     CpNameAndType val, key = new CpNameAndType(this, name, type);
426     val = (CpNameAndType) hashtable.get(key);
427     if (val != null) return val.index;
428     key.nameIndex = internUtf8(name);
429     key.typeIndex = internUtf8(type.toString());
430     appendRec(key);
431     return key.index;
432     }
433
434     int internInteger (int i) {
435     CpInteger val, key = new CpInteger(this, i);
436     val = (CpInteger) hashtable.get(key);
437     if (val != null) return val.index;
438     appendRec(key);
439     return key.index;
440     }
441
442     int internFloat (float i) {
443     CpFloat val, key = new CpFloat(this, i);
444     val = (CpFloat) hashtable.get(key);
445     if (val != null) return val.index;
446     appendRec(key);
447     return key.index;
448     }
449
450     int internLong (long i) {
451     CpLong val, key = new CpLong(this, i);
452     val = (CpLong) hashtable.get(key);
453     if (val != null) return val.index;
454     appendRec(key);
455     return key.index;
456     }
457
458
459     int internDouble (double i) {
460     CpDouble val, key = new CpDouble(this, i);
461     val = (CpDouble) hashtable.get(key);
462     if (val != null) return val.index;
463     appendRec(key);
464     return key.index;
465     }
466
467                       
468     /**
469      * Append a record to the end of the ConstantPool Vector.
470      */

471     private int appendRec(CpEntry rec) {
472     cpVector.addElement(rec);
473     rec.index = cpVector.size() - 1;
474     /*
475      * A long or a double takes two slots, so when we add a long
476      * or a double, we allocate an empty slot in the vector.
477      */

478     if ((rec instanceof CpLong) || (rec instanceof CpDouble))
479         cpVector.addElement(null);
480
481     hashtable.put(rec, rec);
482
483     return(rec.index);
484     }
485 }
486
Popular Tags