KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bcel > classfile > ConstantPool


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.bcel.classfile;
18
19 import java.io.DataInputStream JavaDoc;
20 import java.io.DataOutputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.Serializable JavaDoc;
23 import org.apache.bcel.Constants;
24
25 /**
26  * This class represents the constant pool, i.e., a table of constants, of
27  * a parsed classfile. It may contain null references, due to the JVM
28  * specification that skips an entry after an 8-byte constant (double,
29  * long) entry. Those interested in generating constant pools
30  * programatically should see <a HREF="../generic/ConstantPoolGen.html">
31  * ConstantPoolGen</a>.
32
33  * @version $Id: ConstantPool.java 386056 2006-03-15 11:31:56Z tcurdt $
34  * @see Constant
35  * @see org.apache.bcel.generic.ConstantPoolGen
36  * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
37  */

38 public class ConstantPool implements Cloneable JavaDoc, Node, Serializable JavaDoc {
39
40     private int constant_pool_count;
41     private Constant[] constant_pool;
42
43
44     /**
45      * @param constant_pool Array of constants
46      */

47     public ConstantPool(Constant[] constant_pool) {
48         setConstantPool(constant_pool);
49     }
50
51
52     /**
53      * Read constants from given file stream.
54      *
55      * @param file Input stream
56      * @throws IOException
57      * @throws ClassFormatException
58      */

59     ConstantPool(DataInputStream JavaDoc file) throws IOException JavaDoc, ClassFormatException {
60         byte tag;
61         constant_pool_count = file.readUnsignedShort();
62         constant_pool = new Constant[constant_pool_count];
63         /* constant_pool[0] is unused by the compiler and may be used freely
64          * by the implementation.
65          */

66         for (int i = 1; i < constant_pool_count; i++) {
67             constant_pool[i] = Constant.readConstant(file);
68             /* Quote from the JVM specification:
69              * "All eight byte constants take up two spots in the constant pool.
70              * If this is the n'th byte in the constant pool, then the next item
71              * will be numbered n+2"
72              *
73              * Thus we have to increment the index counter.
74              */

75             tag = constant_pool[i].getTag();
76             if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) {
77                 i++;
78             }
79         }
80     }
81
82
83     /**
84      * Called by objects that are traversing the nodes of the tree implicitely
85      * defined by the contents of a Java class. I.e., the hierarchy of methods,
86      * fields, attributes, etc. spawns a tree of objects.
87      *
88      * @param v Visitor object
89      */

90     public void accept( Visitor v ) {
91         v.visitConstantPool(this);
92     }
93
94
95     /**
96      * Resolve constant to a string representation.
97      *
98      * @param c Constant to be printed
99      * @return String representation
100      */

101     public String JavaDoc constantToString( Constant c ) throws ClassFormatException {
102         String JavaDoc str;
103         int i;
104         byte tag = c.getTag();
105         switch (tag) {
106             case Constants.CONSTANT_Class:
107                 i = ((ConstantClass) c).getNameIndex();
108                 c = getConstant(i, Constants.CONSTANT_Utf8);
109                 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
110                 break;
111             case Constants.CONSTANT_String:
112                 i = ((ConstantString) c).getStringIndex();
113                 c = getConstant(i, Constants.CONSTANT_Utf8);
114                 str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
115                 break;
116             case Constants.CONSTANT_Utf8:
117                 str = ((ConstantUtf8) c).getBytes();
118                 break;
119             case Constants.CONSTANT_Double:
120                 str = "" + ((ConstantDouble) c).getBytes();
121                 break;
122             case Constants.CONSTANT_Float:
123                 str = "" + ((ConstantFloat) c).getBytes();
124                 break;
125             case Constants.CONSTANT_Long:
126                 str = "" + ((ConstantLong) c).getBytes();
127                 break;
128             case Constants.CONSTANT_Integer:
129                 str = "" + ((ConstantInteger) c).getBytes();
130                 break;
131             case Constants.CONSTANT_NameAndType:
132                 str = (constantToString(((ConstantNameAndType) c).getNameIndex(),
133                         Constants.CONSTANT_Utf8)
134                         + " " + constantToString(((ConstantNameAndType) c).getSignatureIndex(),
135                         Constants.CONSTANT_Utf8));
136                 break;
137             case Constants.CONSTANT_InterfaceMethodref:
138             case Constants.CONSTANT_Methodref:
139             case Constants.CONSTANT_Fieldref:
140                 str = (constantToString(((ConstantCP) c).getClassIndex(), Constants.CONSTANT_Class)
141                         + "." + constantToString(((ConstantCP) c).getNameAndTypeIndex(),
142                         Constants.CONSTANT_NameAndType));
143                 break;
144             default: // Never reached
145
throw new RuntimeException JavaDoc("Unknown constant type " + tag);
146         }
147         return str;
148     }
149
150
151     private static final String JavaDoc escape( String JavaDoc str ) {
152         int len = str.length();
153         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(len + 5);
154         char[] ch = str.toCharArray();
155         for (int i = 0; i < len; i++) {
156             switch (ch[i]) {
157                 case '\n':
158                     buf.append("\\n");
159                     break;
160                 case '\r':
161                     buf.append("\\r");
162                     break;
163                 case '\t':
164                     buf.append("\\t");
165                     break;
166                 case '\b':
167                     buf.append("\\b");
168                     break;
169                 case '"':
170                     buf.append("\\\"");
171                     break;
172                 default:
173                     buf.append(ch[i]);
174             }
175         }
176         return buf.toString();
177     }
178
179
180     /**
181      * Retrieve constant at `index' from constant pool and resolve it to
182      * a string representation.
183      *
184      * @param index of constant in constant pool
185      * @param tag expected type
186      * @return String representation
187      */

188     public String JavaDoc constantToString( int index, byte tag ) throws ClassFormatException {
189         Constant c = getConstant(index, tag);
190         return constantToString(c);
191     }
192
193
194     /**
195      * Dump constant pool to file stream in binary format.
196      *
197      * @param file Output file stream
198      * @throws IOException
199      */

200     public void dump( DataOutputStream JavaDoc file ) throws IOException JavaDoc {
201         file.writeShort(constant_pool_count);
202         for (int i = 1; i < constant_pool_count; i++) {
203             if (constant_pool[i] != null) {
204                 constant_pool[i].dump(file);
205             }
206         }
207     }
208
209
210     /**
211      * Get constant from constant pool.
212      *
213      * @param index Index in constant pool
214      * @return Constant value
215      * @see Constant
216      */

217     public Constant getConstant( int index ) {
218         if (index >= constant_pool.length || index < 0) {
219             throw new ClassFormatException("Invalid constant pool reference: " + index
220                     + ". Constant pool size is: " + constant_pool.length);
221         }
222         return constant_pool[index];
223     }
224
225
226     /**
227      * Get constant from constant pool and check whether it has the
228      * expected type.
229      *
230      * @param index Index in constant pool
231      * @param tag Tag of expected constant, i.e., its type
232      * @return Constant value
233      * @see Constant
234      * @throws ClassFormatException
235      */

236     public Constant getConstant( int index, byte tag ) throws ClassFormatException {
237         Constant c;
238         c = getConstant(index);
239         if (c == null) {
240             throw new ClassFormatException("Constant pool at index " + index + " is null.");
241         }
242         if (c.getTag() != tag) {
243             throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag]
244                     + "' at index " + index + " and got " + c);
245         }
246         return c;
247     }
248
249
250     /**
251      * @return Array of constants.
252      * @see Constant
253      */

254     public Constant[] getConstantPool() {
255         return constant_pool;
256     }
257
258
259     /**
260      * Get string from constant pool and bypass the indirection of
261      * `ConstantClass' and `ConstantString' objects. I.e. these classes have
262      * an index field that points to another entry of the constant pool of
263      * type `ConstantUtf8' which contains the real data.
264      *
265      * @param index Index in constant pool
266      * @param tag Tag of expected constant, either ConstantClass or ConstantString
267      * @return Contents of string reference
268      * @see ConstantClass
269      * @see ConstantString
270      * @throws ClassFormatException
271      */

272     public String JavaDoc getConstantString( int index, byte tag ) throws ClassFormatException {
273         Constant c;
274         int i;
275         c = getConstant(index, tag);
276         /* This switch() is not that elegant, since the two classes have the
277          * same contents, they just differ in the name of the index
278          * field variable.
279          * But we want to stick to the JVM naming conventions closely though
280          * we could have solved these more elegantly by using the same
281          * variable name or by subclassing.
282          */

283         switch (tag) {
284             case Constants.CONSTANT_Class:
285                 i = ((ConstantClass) c).getNameIndex();
286                 break;
287             case Constants.CONSTANT_String:
288                 i = ((ConstantString) c).getStringIndex();
289                 break;
290             default:
291                 throw new RuntimeException JavaDoc("getConstantString called with illegal tag " + tag);
292         }
293         // Finally get the string from the constant pool
294
c = getConstant(i, Constants.CONSTANT_Utf8);
295         return ((ConstantUtf8) c).getBytes();
296     }
297
298
299     /**
300      * @return Length of constant pool.
301      */

302     public int getLength() {
303         return constant_pool_count;
304     }
305
306
307     /**
308      * @param constant Constant to set
309      */

310     public void setConstant( int index, Constant constant ) {
311         constant_pool[index] = constant;
312     }
313
314
315     /**
316      * @param constant_pool
317      */

318     public void setConstantPool( Constant[] constant_pool ) {
319         this.constant_pool = constant_pool;
320         constant_pool_count = (constant_pool == null) ? 0 : constant_pool.length;
321     }
322
323
324     /**
325      * @return String representation.
326      */

327     public String JavaDoc toString() {
328         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
329         for (int i = 1; i < constant_pool_count; i++) {
330             buf.append(i).append(")").append(constant_pool[i]).append("\n");
331         }
332         return buf.toString();
333     }
334
335
336     /**
337      * @return deep copy of this constant pool
338      */

339     public ConstantPool copy() {
340         ConstantPool c = null;
341         try {
342             c = (ConstantPool) clone();
343             c.constant_pool = new Constant[constant_pool_count];
344             for (int i = 1; i < constant_pool_count; i++) {
345                 if (constant_pool[i] != null) {
346                     c.constant_pool[i] = constant_pool[i].copy();
347                 }
348             }
349         } catch (CloneNotSupportedException JavaDoc e) {
350         }
351         return c;
352     }
353 }
354
Popular Tags