KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > classfile > ConstantPool


1 /* ====================================================================
2  * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.trove.classfile;
54
55 import java.util.*;
56 import java.io.*;
57
58 /******************************************************************************
59  * This class corresponds to the constant_pool structure as defined in
60  * section 4.4 of <i>The Java Virtual Machine Specification</i>.
61  *
62  * <p>ConstantPool entries are not written out in the order in which they were
63  * added to it. Instead, their ordering is changed such that String, Integer
64  * and Float constants are written out first. This provides a slight
65  * optimization for referencing these constants from a code attribute.
66  * It means that Opcode.LDC will more likely be used (one-byte index) than
67  * Opcode.LDC_W (two-byte index).
68  *
69  * @author Brian S O'Neill
70  * @version
71  * <!--$$Revision:--> 23 <!-- $-->, <!--$$JustDate:--> 9/07/00 <!-- $-->
72  * @see CodeAttr
73  * @see Opcode
74  */

75 public class ConstantPool {
76     // A set of ConstantInfo objects.
77
private Map mConstants = new HashMap();
78     // Indexed list of constants.
79
private Vector mIndexedConstants;
80     private int mEntries;
81
82     // Preserve the order only if the constant pool was read in.
83
private boolean mPreserveOrder;
84
85     ConstantPool() {
86     }
87
88     private ConstantPool(Vector indexedConstants) {
89         mIndexedConstants = indexedConstants;
90
91         int size = indexedConstants.size();
92         for (int i=1; i<size; i++) {
93             ConstantInfo ci = (ConstantInfo)indexedConstants.get(i);
94             if (ci != null) {
95                 mConstants.put(ci, ci);
96                 mEntries += ci.getEntryCount();
97             }
98         }
99
100         mPreserveOrder = true;
101     }
102
103     /**
104      * Returns a constant from the pool by index, or throws an exception if not
105      * found. If this constant pool has not yet been written or was not created
106      * by the read method, indexes are not assigned.
107      *
108      * @throws ArrayIndexOutOfBoundsException if index is out of range.
109      */

110     public ConstantInfo getConstant(int index) {
111         if (mIndexedConstants == null) {
112             throw new ArrayIndexOutOfBoundsException JavaDoc
113                 ("Constant pool indexes have not been assigned");
114         }
115
116         return (ConstantInfo)mIndexedConstants.get(index);
117     }
118
119     /**
120      * Returns all the constants in the pool, in no particular order.
121      */

122     public Set getAllConstants() {
123         return Collections.unmodifiableSet(mConstants.keySet());
124     }
125
126     /**
127      * Returns the number of constants in the pool.
128      */

129     public int getSize() {
130         return mEntries;
131     }
132
133     /**
134      * Get or create a constant from the constant pool representing a class.
135      */

136     public ConstantClassInfo addConstantClass(String JavaDoc className) {
137         return ConstantClassInfo.make(this, className);
138     }
139
140     /**
141      * Get or create a constant from the constant pool representing an array
142      * class.
143      *
144      * @param dim Number of array dimensions.
145      */

146     public ConstantClassInfo addConstantClass(String JavaDoc className, int dim) {
147         return ConstantClassInfo.make(this, className, dim);
148     }
149     
150     /**
151      * Get or create a constant from the constant pool representing a class.
152      */

153     public ConstantClassInfo addConstantClass(TypeDescriptor type) {
154         return ConstantClassInfo.make(this, type);
155     }
156
157     /**
158      * Get or create a constant from the constant pool representing a field in
159      * any class.
160      */

161     public ConstantFieldInfo addConstantField(String JavaDoc className,
162                                               String JavaDoc fieldName,
163                                               TypeDescriptor type) {
164         return ConstantFieldInfo.make
165             (this,
166              ConstantClassInfo.make(this, className),
167              ConstantNameAndTypeInfo.make(this, fieldName, type));
168     }
169
170     /**
171      * Get or create a constant from the constant pool representing a method
172      * in any class. If the method returns void, set ret to null.
173      */

174     public ConstantMethodInfo addConstantMethod(String JavaDoc className,
175                                                 String JavaDoc methodName,
176                                                 TypeDescriptor ret,
177                                                 TypeDescriptor[] params) {
178         
179         MethodDescriptor md = new MethodDescriptor(ret, params);
180
181         return ConstantMethodInfo.make
182             (this,
183              ConstantClassInfo.make(this, className),
184              ConstantNameAndTypeInfo.make(this, methodName, md));
185     }
186     
187     /**
188      * Get or create a constant from the constant pool representing an
189      * interface method in any interface.
190      */

191     public ConstantInterfaceMethodInfo addConstantInterfaceMethod
192         (String JavaDoc className,
193          String JavaDoc methodName,
194          TypeDescriptor ret,
195          TypeDescriptor[] params) {
196         
197         MethodDescriptor md = new MethodDescriptor(ret, params);
198         
199         return ConstantInterfaceMethodInfo.make
200             (this,
201              ConstantClassInfo.make(this, className),
202              ConstantNameAndTypeInfo.make(this, methodName, md));
203     }
204
205     /**
206      * Get or create a constant from the constant pool representing a
207      * constructor in any class.
208      */

209     public ConstantMethodInfo addConstantConstructor(String JavaDoc className,
210                                                      TypeDescriptor[] params) {
211         return addConstantMethod(className, "<init>", null, params);
212     }
213
214     /**
215      * Get or create a constant integer from the constant pool.
216      */

217     public ConstantIntegerInfo addConstantInteger(int value) {
218         return ConstantIntegerInfo.make(this, value);
219     }
220
221     /**
222      * Get or create a constant long from the constant pool.
223      */

224     public ConstantLongInfo addConstantLong(long value) {
225         return ConstantLongInfo.make(this, value);
226     }
227
228     /**
229      * Get or create a constant float from the constant pool.
230      */

231     public ConstantFloatInfo addConstantFloat(float value) {
232         return ConstantFloatInfo.make(this, value);
233     }
234
235     /**
236      * Get or create a constant double from the constant pool.
237      */

238     public ConstantDoubleInfo addConstantDouble(double value) {
239         return ConstantDoubleInfo.make(this, value);
240     }
241
242     /**
243      * Get or create a constant string from the constant pool.
244      */

245     public ConstantStringInfo addConstantString(String JavaDoc str) {
246         return ConstantStringInfo.make(this, str);
247     }
248
249     /**
250      * Get or create a constant UTF string from the constant pool.
251      */

252     public ConstantUTFInfo addConstantUTF(String JavaDoc str) {
253         return ConstantUTFInfo.make(this, str);
254     }
255
256     /**
257      * Get or create a constant name and type structure from the constant pool.
258      */

259     public ConstantNameAndTypeInfo addConstantNameAndType(String JavaDoc name,
260                                                           Descriptor type) {
261         return ConstantNameAndTypeInfo.make(this, name, type);
262     }
263
264     /**
265      * Will only insert into the pool if the constant is not already in the
266      * pool.
267      *
268      * @return The actual constant in the pool.
269      */

270     public ConstantInfo addConstant(ConstantInfo constant) {
271         ConstantInfo info = (ConstantInfo)mConstants.get(constant);
272         if (info != null) {
273             return info;
274         }
275         
276         int entryCount = constant.getEntryCount();
277
278         if (mIndexedConstants != null && mPreserveOrder) {
279             int size = mIndexedConstants.size();
280             mIndexedConstants.setSize(size + entryCount);
281             mIndexedConstants.set(size, constant);
282         }
283
284         mConstants.put(constant, constant);
285         mEntries += entryCount;
286
287         return constant;
288     }
289
290     public void writeTo(DataOutput dout) throws IOException {
291         // Write out the size (number of entries) of the constant pool.
292

293         int size = getSize() + 1; // add one because constant 0 is reserved
294
if (size >= 65535) {
295             throw new RuntimeException JavaDoc
296                 ("Constant pool entry count cannot exceed 65535: " + size);
297         }
298         dout.writeShort(size);
299
300         if (mIndexedConstants == null || !mPreserveOrder) {
301             mIndexedConstants = new Vector(size);
302             mIndexedConstants.setSize(size);
303             int index = 1; // one-based constant pool index
304

305             // First write constants of higher priority -- String, Integer,
306
// Float.
307
// This is a slight optimization. It means that Opcode.LDC will
308
// more likely be used (one-byte index) than Opcode.LDC_W (two-byte
309
// index).
310

311             Iterator it = mConstants.keySet().iterator();
312             while (it.hasNext()) {
313                 ConstantInfo constant = (ConstantInfo)it.next();
314                 if (constant.hasPriority()) {
315                     constant.mIndex = index;
316                     mIndexedConstants.set(index, constant);
317                     index += constant.getEntryCount();
318                 }
319             }
320             
321             // Now write all non-priority constants.
322

323             it = mConstants.keySet().iterator();
324             while (it.hasNext()) {
325                 ConstantInfo constant = (ConstantInfo)it.next();
326                 if (!constant.hasPriority()) {
327                     constant.mIndex = index;
328                     mIndexedConstants.set(index, constant);
329                     index += constant.getEntryCount();
330                 }
331             }
332         }
333
334         // Now actually write out the constants since the indexes have been
335
// resolved.
336

337         for (int i=1; i<size; i++) {
338             Object JavaDoc obj = mIndexedConstants.get(i);
339             if (obj != null) {
340                 ((ConstantInfo)obj).writeTo(dout);
341             }
342         }
343     }
344
345     public static ConstantPool readFrom(DataInput din) throws IOException {
346         int size = din.readUnsignedShort();
347         Vector constants = new Vector(size);
348         constants.setSize(size);
349
350         int index = 1;
351         while (index < size) {
352             int tag = din.readByte();
353             int entryCount = 1;
354             Object JavaDoc constant;
355
356             switch (tag) {
357             case ConstantInfo.TAG_UTF8:
358                 constant = new ConstantUTFInfo(din.readUTF());
359                 break;
360             case ConstantInfo.TAG_INTEGER:
361                 constant = new ConstantIntegerInfo(din.readInt());
362                 break;
363             case ConstantInfo.TAG_FLOAT:
364                 constant = new ConstantFloatInfo(din.readFloat());
365                 break;
366             case ConstantInfo.TAG_LONG:
367                 constant = new ConstantLongInfo(din.readLong());
368                 entryCount++;
369                 break;
370             case ConstantInfo.TAG_DOUBLE:
371                 constant = new ConstantDoubleInfo(din.readDouble());
372                 entryCount++;
373                 break;
374
375             case ConstantInfo.TAG_CLASS:
376             case ConstantInfo.TAG_STRING:
377                 constant = new TempEntry(tag, din.readUnsignedShort());
378                 break;
379
380             case ConstantInfo.TAG_FIELD:
381             case ConstantInfo.TAG_METHOD:
382             case ConstantInfo.TAG_INTERFACE_METHOD:
383             case ConstantInfo.TAG_NAME_AND_TYPE:
384                 constant = new TempEntry
385                     (tag, (din.readShort() << 16) | (din.readUnsignedShort()));
386                 break;
387
388             default:
389                 throw new IOException("Invalid constant pool tag: " + tag);
390             }
391
392             if (constant instanceof ConstantInfo) {
393                 ((ConstantInfo)constant).mIndex = index;
394             }
395
396             constants.set(index, constant);
397             index += entryCount;
398         }
399
400         for (index = 1; index < size; index++) {
401             resolve(constants, index);
402         }
403
404         return new ConstantPool(constants);
405     }
406
407     private static ConstantInfo resolve(List constants, int index) {
408         Object JavaDoc constant = constants.get(index);
409         if (constant == null) {
410             return null;
411         }
412         
413         if (constant instanceof ConstantInfo) {
414             return (ConstantInfo)constant;
415         }
416
417         TempEntry entry = (TempEntry)constant;
418         int data = entry.mData;
419         int index1 = data & 0xffff;
420
421         ConstantInfo ci1;
422         Object JavaDoc constant1 = constants.get(index1);
423
424         if (constant1 instanceof ConstantInfo) {
425             ci1 = (ConstantInfo)constant1;
426         }
427         else {
428             ci1 = resolve(constants, index1);
429         }
430
431         ConstantInfo ci = null;
432
433         switch (entry.mTag) {
434         case ConstantInfo.TAG_CLASS:
435             ci = new ConstantClassInfo((ConstantUTFInfo)ci1);
436             break;
437         case ConstantInfo.TAG_STRING:
438             ci = new ConstantStringInfo((ConstantUTFInfo)ci1);
439             break;
440
441         case ConstantInfo.TAG_FIELD:
442         case ConstantInfo.TAG_METHOD:
443         case ConstantInfo.TAG_INTERFACE_METHOD:
444         case ConstantInfo.TAG_NAME_AND_TYPE:
445             int index2 = data >> 16;
446             
447             ConstantInfo ci2;
448             Object JavaDoc constant2 = constants.get(index2);
449             
450             if (constant2 instanceof ConstantInfo) {
451                 ci2 = (ConstantInfo)constant2;
452             }
453             else {
454                 ci2 = resolve(constants, index2);
455             }
456
457             switch (entry.mTag) {
458             case ConstantInfo.TAG_FIELD:
459                 ci = new ConstantFieldInfo
460                     ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1);
461                 break;
462             case ConstantInfo.TAG_METHOD:
463                 ci = new ConstantMethodInfo
464                     ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1);
465                 break;
466             case ConstantInfo.TAG_INTERFACE_METHOD:
467                 ci = new ConstantInterfaceMethodInfo
468                     ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1);
469                 break;
470             case ConstantInfo.TAG_NAME_AND_TYPE:
471                 ci = new ConstantNameAndTypeInfo
472                     ((ConstantUTFInfo)ci2, (ConstantUTFInfo)ci1);
473                 break;
474             }
475
476             break;
477         }
478
479         ci.mIndex = index;
480         constants.set(index, ci);
481
482         return ci;
483     }
484
485     private static class TempEntry {
486         public int mTag;
487         public int mData;
488
489         public TempEntry(int tag, int data) {
490             mTag = tag;
491             mData = data;
492         }
493     }
494 }
495
Popular Tags