KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > classfile > ConstantPool


1 /*
2  * ConstantPool.java
3  *
4  * The contents of this file are subject to the terms of the Common Development
5  * and Distribution License (the License). You may not use this file except in
6  * compliance with the License.
7  *
8  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
9  * or http://www.netbeans.org/cddl.txt.
10  *
11  * When distributing Covered Code, include this CDDL Header Notice in each file
12  * and include the License file at http://www.netbeans.org/cddl.txt.
13  * If applicable, add the following below the CDDL Header, with the fields
14  * enclosed by brackets [] replaced by your own identifying information:
15  * "Portions Copyrighted [year] [name of copyright owner]"
16  *
17  * The Original Software is NetBeans. The Initial Developer of the Original
18  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
19  * Microsystems, Inc. All Rights Reserved.
20  *
21  * Contributor(s): Thomas Ball
22  *
23  * Version: $Revision: 1.18 $
24  */

25
26 package org.netbeans.modules.classfile;
27
28 import java.io.*;
29 import java.util.*;
30
31 /**
32  * Class representing a Java class file constant pool.
33  *
34  * @author Thomas Ball
35  */

36 public final class ConstantPool {
37
38     private static final int CONSTANT_POOL_START = 1;
39
40     // Constant Type enums (JVM spec table 4.3)
41
static final int CONSTANT_Utf8 = 1;
42     static final int CONSTANT_Integer = 3;
43     static final int CONSTANT_Float = 4;
44     static final int CONSTANT_Long = 5;
45     static final int CONSTANT_Double = 6;
46     static final int CONSTANT_Class = 7;
47     static final int CONSTANT_String = 8;
48     static final int CONSTANT_FieldRef = 9;
49     static final int CONSTANT_MethodRef = 10;
50     static final int CONSTANT_InterfaceMethodRef = 11;
51     static final int CONSTANT_NameAndType = 12;
52
53     CPEntry[] cpEntries;
54     
55     int constantPoolCount = 0;
56
57     /**
58      * Create a ConstantPool object from a stream of bytes.
59      *
60      * @param size number of entries in this constant pool.
61      * @param bytes a stream of bytes defining the constant pool.
62      */

63     /* package-private */ ConstantPool(int size, InputStream bytes)
64       throws IOException {
65         if (size < 0)
66             throw new IllegalArgumentException JavaDoc("size cannot be negative");
67         if (bytes == null)
68             throw new IllegalArgumentException JavaDoc("byte stream not specified");
69         constantPoolCount = size;
70         cpEntries = new CPEntry[constantPoolCount];
71         load(bytes);
72     }
73     
74     /**
75      * Create a new ConstantPool object with no entries.
76      * NOTE: not supported until classfile writing is.
77      */

78     /*public*/ ConstantPool() {
79         constantPoolCount = CONSTANT_POOL_START;
80         cpEntries = new CPEntry[constantPoolCount];
81     }
82
83     /**
84      * Get the CPEntry at a specific constant pool index.
85      *
86      * @param index the constant pool index for the entry
87      */

88     public final CPEntry get(int index) {
89         if (index <= 0 || index >= cpEntries.length)
90             throw new IndexOutOfBoundsException JavaDoc(Integer.toString(index));
91         return cpEntries[index];
92     }
93
94     /**
95      * Get the CPClassInfo at a specific index.
96      *
97      * @param index the constant pool index for the entry
98      */

99     public final CPClassInfo getClass(int index) {
100         if (index <= 0)
101             throw new IndexOutOfBoundsException JavaDoc(Integer.toString(index));
102         return (CPClassInfo)get(index);
103     }
104
105     /* Return an array of all constants of a specified class type.
106      *
107      * @param type the constant pool type to return.
108      */

109     public final Collection getAllConstants(Class JavaDoc classType) {
110         return Collections.unmodifiableCollection(
111            getAllConstantsImpl(classType));
112     }
113
114     private Collection<CPEntry> getAllConstantsImpl(Class JavaDoc classType) {
115         int n = cpEntries.length;
116         Collection<CPEntry> c = new ArrayList<CPEntry>(n);
117         for (int i = CONSTANT_POOL_START; i < n; i++) {
118             if (cpEntries[i] != null &&
119                 cpEntries[i].getClass().equals(classType)) {
120                 c.add(cpEntries[i]);
121             }
122         }
123         return c;
124     }
125
126     /* Return the collection of all unique class references in pool.
127      *
128      * @return a Set of ClassNames specifying the referenced classnames.
129      *
130      * @deprecated use <code>ClassFile.getAllClassNames()</code>,
131      * as all class references cannot be reliably determined from just
132      * the constant pool structure.
133      */

134     public final Set getAllClassNames() {
135         Set<ClassName> set = new HashSet<ClassName>();
136
137         // include all class name constants
138
Collection c = getAllConstantsImpl(CPClassInfo.class);
139         for (Iterator i = c.iterator(); i.hasNext();) {
140             CPClassInfo ci = (CPClassInfo)i.next();
141             set.add(ci.getClassName());
142         }
143         return Collections.unmodifiableSet(set);
144     }
145
146     final String JavaDoc getString(int index) {
147         CPUTF8Info utf = (CPUTF8Info)cpEntries[index];
148         return utf.getName();
149     }
150     
151     private void load(InputStream cpBytes) throws IOException {
152         try {
153         ConstantPoolReader cpr = new ConstantPoolReader(cpBytes);
154
155             // Read in pool entries.
156
for (int i = CONSTANT_POOL_START; i < constantPoolCount; i++) {
157                 CPEntry newEntry = getConstantPoolEntry(cpr);
158                 cpEntries[i] = newEntry;
159         
160                 if (newEntry.usesTwoSlots())
161                     i++;
162             }
163     
164             // Resolve pool entries.
165
for (int i = CONSTANT_POOL_START; i < constantPoolCount; i++) {
166                 CPEntry entry = cpEntries[i];
167                 if (entry == null) {
168                     continue;
169                 }
170                 entry.resolve(cpEntries);
171             }
172         } catch (IllegalArgumentException JavaDoc ioe) {
173             throw new InvalidClassFormatException(ioe);
174     } catch (IndexOutOfBoundsException JavaDoc iobe) {
175             throw new InvalidClassFormatException(iobe);
176         }
177     }
178
179     private CPEntry getConstantPoolEntry(ConstantPoolReader cpr)
180             throws IOException {
181         CPEntry newEntry;
182         byte type = cpr.readByte();
183         switch (type) {
184           case CONSTANT_Utf8:
185               newEntry = new CPUTF8Info(this, cpr.readRawUTF());
186               break;
187
188           case CONSTANT_Integer:
189               newEntry = new CPIntegerInfo(this, cpr.readInt());
190               break;
191
192           case CONSTANT_Float:
193               newEntry = new CPFloatInfo(this, cpr.readFloat());
194               break;
195
196           case CONSTANT_Long:
197               newEntry = new CPLongInfo(this, cpr.readLong());
198               break;
199
200           case CONSTANT_Double:
201               newEntry = new CPDoubleInfo(this, cpr.readDouble());
202               break;
203
204           case CONSTANT_Class: {
205               int nameIndex = cpr.readUnsignedShort();
206               newEntry = new CPClassInfo(this, nameIndex);
207               break;
208           }
209
210           case CONSTANT_String: {
211               int nameIndex = cpr.readUnsignedShort();
212               newEntry = new CPStringInfo(this, nameIndex);
213               break;
214           }
215
216           case CONSTANT_FieldRef: {
217               int classIndex = cpr.readUnsignedShort();
218               int natIndex = cpr.readUnsignedShort();
219               newEntry = new CPFieldInfo(this, classIndex, natIndex);
220               break;
221           }
222
223           case CONSTANT_MethodRef: {
224               int classIndex = cpr.readUnsignedShort();
225               int natIndex = cpr.readUnsignedShort();
226               newEntry = new CPMethodInfo(this, classIndex, natIndex);
227               break;
228           }
229
230           case CONSTANT_InterfaceMethodRef: {
231               int classIndex = cpr.readUnsignedShort();
232               int natIndex = cpr.readUnsignedShort();
233               newEntry = new CPInterfaceMethodInfo(this, classIndex, natIndex);
234               break;
235           }
236
237           case CONSTANT_NameAndType: {
238               int nameIndex = cpr.readUnsignedShort();
239               int descIndex = cpr.readUnsignedShort();
240               newEntry = new CPNameAndTypeInfo(this, nameIndex, descIndex);
241               break;
242           }
243
244           default:
245               throw new IllegalArgumentException JavaDoc(
246                           "invalid constant pool type: " + type);
247         }
248
249         return newEntry;
250     }
251 }
252
Popular Tags