1 package org.apache.bcel.classfile;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
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 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache BCEL" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache BCEL", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
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 APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import org.apache.bcel.Constants;
58 import java.io.*;
59
60 /***
61 * This class represents the constant pool, i.e., a table of constants, of
62 * a parsed classfile. It may contain null references, due to the JVM
63 * specification that skips an entry after an 8-byte constant (double,
64 * long) entry. Those interested in generating constant pools
65 * programatically should see <a href="../generic/ConstantPoolGen.html">
66 * ConstantPoolGen</a>.
67
68 * @version $Id: ConstantPool.java,v 1.6 2002/07/11 19:39:04 mdahm Exp $
69 * @see Constant
70 * @see org.apache.bcel.generic.ConstantPoolGen
71 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
72 */
73 public class ConstantPool implements Cloneable, Node, Serializable {
74 private int constant_pool_count;
75 private Constant[] constant_pool;
76
77 /***
78 * @param constant_pool Array of constants
79 */
80 public ConstantPool(Constant[] constant_pool)
81 {
82 setConstantPool(constant_pool);
83 }
84
85 /***
86 * Read constants from given file stream.
87 *
88 * @param file Input stream
89 * @throws IOException
90 * @throws ClassFormatException
91 */
92 ConstantPool(DataInputStream file) throws IOException, ClassFormatException
93 {
94 byte tag;
95
96 constant_pool_count = file.readUnsignedShort();
97 constant_pool = new Constant[constant_pool_count];
98
99 /* constant_pool[0] is unused by the compiler and may be used freely
100 * by the implementation.
101 */
102 for(int i=1; i < constant_pool_count; i++) {
103 constant_pool[i] = Constant.readConstant(file);
104
105 /* Quote from the JVM specification:
106 * "All eight byte constants take up two spots in the constant pool.
107 * If this is the n'th byte in the constant pool, then the next item
108 * will be numbered n+2"
109 *
110 * Thus we have to increment the index counter.
111 */
112 tag = constant_pool[i].getTag();
113 if((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long))
114 i++;
115 }
116 }
117
118 /***
119 * Called by objects that are traversing the nodes of the tree implicitely
120 * defined by the contents of a Java class. I.e., the hierarchy of methods,
121 * fields, attributes, etc. spawns a tree of objects.
122 *
123 * @param v Visitor object
124 */
125 public void accept(Visitor v) {
126 v.visitConstantPool(this);
127 }
128
129 /***
130 * Resolve constant to a string representation.
131 *
132 * @param constant Constant to be printed
133 * @return String representation
134 */
135 public String constantToString(Constant c)
136 throws ClassFormatException
137 {
138 String str;
139 int i;
140 byte tag = c.getTag();
141
142 switch(tag) {
143 case Constants.CONSTANT_Class:
144 i = ((ConstantClass)c).getNameIndex();
145 c = getConstant(i, Constants.CONSTANT_Utf8);
146 str = Utility.compactClassName(((ConstantUtf8)c).getBytes(), false);
147 break;
148
149 case Constants.CONSTANT_String:
150 i = ((ConstantString)c).getStringIndex();
151 c = getConstant(i, Constants.CONSTANT_Utf8);
152 str = "\"" + escape(((ConstantUtf8)c).getBytes()) + "\"";
153 break;
154
155 case Constants.CONSTANT_Utf8: str = ((ConstantUtf8)c).getBytes(); break;
156 case Constants.CONSTANT_Double: str = "" + ((ConstantDouble)c).getBytes(); break;
157 case Constants.CONSTANT_Float: str = "" + ((ConstantFloat)c).getBytes(); break;
158 case Constants.CONSTANT_Long: str = "" + ((ConstantLong)c).getBytes(); break;
159 case Constants.CONSTANT_Integer: str = "" + ((ConstantInteger)c).getBytes(); break;
160
161 case Constants.CONSTANT_NameAndType:
162 str = (constantToString(((ConstantNameAndType)c).getNameIndex(),
163 Constants.CONSTANT_Utf8) + " " +
164 constantToString(((ConstantNameAndType)c).getSignatureIndex(),
165 Constants.CONSTANT_Utf8));
166 break;
167
168 case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref:
169 case Constants.CONSTANT_Fieldref:
170 str = (constantToString(((ConstantCP)c).getClassIndex(),
171 Constants.CONSTANT_Class) + "." +
172 constantToString(((ConstantCP)c).getNameAndTypeIndex(),
173 Constants.CONSTANT_NameAndType));
174 break;
175
176 default: // Never reached
177 throw new RuntimeException("Unknown constant type " + tag);
178 }
179
180 return str;
181 }
182
183 private static final String escape(String str) {
184 int len = str.length();
185 StringBuffer buf = new StringBuffer(len + 5);
186 char[] ch = str.toCharArray();
187
188 for(int i=0; i < len; i++) {
189 switch(ch[i]) {
190 case '\n' : buf.append("//n"); break;
191 case '\r' : buf.append("//r"); break;
192 case '\t' : buf.append("//t"); break;
193 case '\b' : buf.append("//b"); break;
194 case '"' : buf.append("//\""); break;
195 default: buf.append(ch[i]);
196 }
197 }
198
199 return buf.toString();
200 }
201
202
203 /***
204 * Retrieve constant at `index' from constant pool and resolve it to
205 * a string representation.
206 *
207 * @param index of constant in constant pool
208 * @param tag expected type
209 * @return String representation
210 */
211 public String constantToString(int index, byte tag)
212 throws ClassFormatException
213 {
214 Constant c = getConstant(index, tag);
215 return constantToString(c);
216 }
217
218 /***
219 * Dump constant pool to file stream in binary format.
220 *
221 * @param file Output file stream
222 * @throws IOException
223 */
224 public void dump(DataOutputStream file) throws IOException
225 {
226 file.writeShort(constant_pool_count);
227
228 for(int i=1; i < constant_pool_count; i++)
229 if(constant_pool[i] != null)
230 constant_pool[i].dump(file);
231 }
232
233 /***
234 * Get constant from constant pool.
235 *
236 * @param index Index in constant pool
237 * @return Constant value
238 * @see Constant
239 */
240 public Constant getConstant(int index) {
241 if (index >= constant_pool.length || index < 0)
242 throw new ClassFormatException("Invalid constant pool reference: " +
243 index + ". Constant pool size is: " +
244 constant_pool.length);
245 return constant_pool[index];
246 }
247
248 /***
249 * Get constant from constant pool and check whether it has the
250 * expected type.
251 *
252 * @param index Index in constant pool
253 * @param tag Tag of expected constant, i.e., its type
254 * @return Constant value
255 * @see Constant
256 * @throws ClassFormatException
257 */
258 public Constant getConstant(int index, byte tag)
259 throws ClassFormatException
260 {
261 Constant c;
262
263 c = getConstant(index);
264
265 if(c == null)
266 throw new ClassFormatException("Constant pool at index " + index + " is null.");
267
268 if(c.getTag() == tag)
269 return c;
270 else
271 throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag] +
272 "' at index " + index + " and got " + c);
273 }
274
275 /***
276 * @return Array of constants.
277 * @see Constant
278 */
279 public Constant[] getConstantPool() { return constant_pool; }
280 /***
281 * Get string from constant pool and bypass the indirection of
282 * `ConstantClass' and `ConstantString' objects. I.e. these classes have
283 * an index field that points to another entry of the constant pool of
284 * type `ConstantUtf8' which contains the real data.
285 *
286 * @param index Index in constant pool
287 * @param tag Tag of expected constant, either ConstantClass or ConstantString
288 * @return Contents of string reference
289 * @see ConstantClass
290 * @see ConstantString
291 * @throws ClassFormatException
292 */
293 public String getConstantString(int index, byte tag)
294 throws ClassFormatException
295 {
296 Constant c;
297 int i;
298
299 c = getConstant(index, tag);
300
301 /* This switch() is not that elegant, since the two classes have the
302 * same contents, they just differ in the name of the index
303 * field variable.
304 * But we want to stick to the JVM naming conventions closely though
305 * we could have solved these more elegantly by using the same
306 * variable name or by subclassing.
307 */
308 switch(tag) {
309 case Constants.CONSTANT_Class: i = ((ConstantClass)c).getNameIndex(); break;
310 case Constants.CONSTANT_String: i = ((ConstantString)c).getStringIndex(); break;
311 default:
312 throw new RuntimeException("getConstantString called with illegal tag " + tag);
313 }
314
315 // Finally get the string from the constant pool
316 c = getConstant(i, Constants.CONSTANT_Utf8);
317 return ((ConstantUtf8)c).getBytes();
318 }
319 /***
320 * @return Length of constant pool.
321 */
322 public int getLength()
323 {
324 return constant_pool_count;
325 }
326
327 /***
328 * @param constant Constant to set
329 */
330 public void setConstant(int index, Constant constant) {
331 constant_pool[index] = constant;
332 }
333
334 /***
335 * @param constant_pool
336 */
337 public void setConstantPool(Constant[] constant_pool) {
338 this.constant_pool = constant_pool;
339 constant_pool_count = (constant_pool == null)? 0 : constant_pool.length;
340 }
341 /***
342 * @return String representation.
343 */
344 public String toString() {
345 StringBuffer buf = new StringBuffer();
346
347 for(int i=1; i < constant_pool_count; i++)
348 buf.append(i + ")" + constant_pool[i] + "\n");
349
350 return buf.toString();
351 }
352
353 /***
354 * @return deep copy of this constant pool
355 */
356 public ConstantPool copy() {
357 ConstantPool c = null;
358
359 try {
360 c = (ConstantPool)clone();
361 } catch(CloneNotSupportedException e) {}
362
363 c.constant_pool = new Constant[constant_pool_count];
364
365 for(int i=1; i < constant_pool_count; i++) {
366 if(constant_pool[i] != null)
367 c.constant_pool[i] = constant_pool[i].copy();
368 }
369
370 return c;
371 }
372 }
This page was automatically generated by Maven