1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.jdo.impl.enhancer.classfile;
20
21 import java.util.Vector;
22 import java.util.Hashtable;
23 import java.io.*;
24
25 /***
26 * Constant Pool implementation - this represents the constant pool
27 * of a class in a class file.
28 */
29 public class ConstantPool implements VMConstants {
30
31
32 private Vector pool = new Vector();
33
34
35 private boolean hashed = false;
36 private Hashtable utfTable = new Hashtable(11);
37 private Hashtable unicodeTable = new Hashtable(3);
38 private Hashtable stringTable = new Hashtable(11);
39 private Hashtable classTable = new Hashtable(11);
40 private Hashtable intTable = new Hashtable(3);
41 private Hashtable floatTable = new Hashtable(3);
42 private Hashtable longTable = new Hashtable(3);
43 private Hashtable doubleTable = new Hashtable(3);
44
45 private Vector methodRefTable = new Vector();
46 private Vector fieldRefTable = new Vector();
47 private Vector ifaceMethodRefTable = new Vector();
48 private Vector nameAndTypeTable = new Vector();
49
50
51
52 /***
53 * Return the number of pool entries.
54 */
55 public int nEntries() {
56 return pool.size();
57 }
58
59 /***
60 * Return the constant in the pool at the specified entry index
61 */
62 public ConstBasic constantAt (int index) {
63 return (ConstBasic) pool.elementAt(index);
64 }
65
66 /***
67 * Find or create a class constant in the pool
68 */
69 public ConstClass addClass (String className) {
70 hashConstants();
71 ConstClass c = (ConstClass) classTable.get(className);
72 if (c == null) {
73 c = new ConstClass(addUtf8(className));
74 internConstant(c);
75 }
76 return c;
77 }
78
79 /***
80 * Find or create a field constant in the pool
81 */
82 public ConstFieldRef addFieldRef (String className, String fieldName,
83 String type) {
84 hashConstants();
85 ConstFieldRef f = (ConstFieldRef)
86 searchTable(fieldRefTable, className, fieldName, type);
87
88 if (f == null) {
89 f = new ConstFieldRef (addClass(className),
90 addNameAndType(fieldName, type));
91 internConstant(f);
92 }
93 return f;
94 }
95
96 /***
97 * Find or create a method constant in the pool
98 */
99 public ConstMethodRef addMethodRef (String className, String methodName,
100 String type) {
101 hashConstants();
102 ConstMethodRef m = (ConstMethodRef)
103 searchTable(methodRefTable, className, methodName, type);
104 if (m == null) {
105 m = new ConstMethodRef (addClass(className),
106 addNameAndType(methodName, type));
107 internConstant(m);
108 }
109 return m;
110 }
111
112 /***
113 * Find or create an interface method constant in the pool
114 */
115 public ConstInterfaceMethodRef addInterfaceMethodRef (String className,
116 String methodName, String type) {
117 hashConstants();
118 ConstInterfaceMethodRef m = (ConstInterfaceMethodRef)
119 searchTable(ifaceMethodRefTable, className, methodName, type);
120 if (m == null) {
121 m = new ConstInterfaceMethodRef (addClass(className),
122 addNameAndType(methodName, type));
123 internConstant(m);
124 }
125 return m;
126 }
127
128 /***
129 * Find or create a string constant in the pool
130 */
131 public ConstString addString (String s) {
132 hashConstants();
133 ConstString cs = (ConstString) stringTable.get(s);
134 if (cs == null) {
135 cs = new ConstString(addUtf8(s));
136 internConstant(cs);
137 }
138 return cs;
139 }
140
141 /***
142 * Find or create an integer constant in the pool
143 */
144 public ConstInteger addInteger (int i) {
145 hashConstants();
146 Integer io = new Integer(i);
147 ConstInteger ci = (ConstInteger) intTable.get(io);
148 if (ci == null) {
149 ci = new ConstInteger(i);
150 internConstant(ci);
151 }
152 return ci;
153 }
154
155 /***
156 * Find or create a float constant in the pool
157 */
158 public ConstFloat addFloat (float f) {
159 hashConstants();
160 Float fo = new Float(f);
161 ConstFloat cf = (ConstFloat) floatTable.get(fo);
162 if (cf == null) {
163 cf = new ConstFloat(f);
164 internConstant(cf);
165 }
166 return cf;
167 }
168
169 /***
170 * Find or create a long constant in the pool
171 */
172 public ConstLong addLong (long l) {
173 hashConstants();
174 Long lo = new Long(l);
175 ConstLong cl = (ConstLong) longTable.get(lo);
176 if (cl == null) {
177 cl = new ConstLong(l);
178 internConstant(cl);
179 internConstant(null);
180 }
181 return cl;
182 }
183
184 /***
185 * Find or create a double constant in the pool
186 */
187 public ConstDouble addDouble (double d) {
188 hashConstants();
189 Double dobj = new Double(d);
190 ConstDouble cd = (ConstDouble) doubleTable.get(dobj);
191 if (cd == null) {
192 cd = new ConstDouble(d);
193 internConstant(cd);
194 internConstant(null);
195 }
196 return cd;
197 }
198
199 /***
200 * Find or create a name/type constant in the pool
201 */
202 public ConstNameAndType addNameAndType (String name, String type) {
203 hashConstants();
204 for (int i=0; i<nameAndTypeTable.size(); i++) {
205 ConstNameAndType nt = (ConstNameAndType) nameAndTypeTable.elementAt(i);
206 if (nt.name().asString().equals(name) &&
207 nt.signature().asString().equals(type))
208 return nt;
209 }
210
211 ConstNameAndType nt =
212 new ConstNameAndType(addUtf8(name), addUtf8(type));
213 internConstant(nt);
214 return nt;
215 }
216
217 /***
218 * Find or create a utf8 constant in the pool
219 */
220 public ConstUtf8 addUtf8 (String s) {
221 hashConstants();
222 ConstUtf8 u = (ConstUtf8) utfTable.get(s);
223 if (u == null) {
224 u = new ConstUtf8(s);
225 internConstant(u);
226 }
227 return u;
228 }
229
230 /***
231 * Find or create a unicode constant in the pool
232 * Obsolete?
233 */
234 public ConstUnicode addUnicode (String s) {
235 hashConstants();
236 ConstUnicode u = (ConstUnicode) unicodeTable.get(s);
237 if (u == null) {
238 u = new ConstUnicode(s);
239 internConstant(u);
240 }
241 return u;
242 }
243
244 /* package local methods *//package-summary/html">class="comment"> package local methods *//package-summary.html">
245
246 ConstantPool() {
247 pool.addElement(null);
248 }
249
250 ConstantPool(DataInputStream input) throws IOException {
251 pool.addElement(null);
252 int nconstants = input.readUnsignedShort()-1;
253 while (nconstants > 0)
254 nconstants -= readConstant(input);
255
256 resolvePool();
257 }
258
259
260 void print(PrintStream out, int indent) {
261 for (int i=0; i<pool.size(); i++) {
262 ConstBasic c = constantAt(i);
263 if (c != null) {
264 ClassPrint.spaces(out, indent);
265 out.print(i);
266 out.print(": ");
267 out.println(c.toString());
268 }
269 }
270 }
271
272
273 void summarize(PrintStream out, int indent) {
274 int stringSize = 0;
275 int nStrings = 0;
276 for (int i=0; i<pool.size(); i++) {
277 ConstBasic c = constantAt(i);
278 if (c != null && c.tag() == CONSTANTUtf8) {
279 ConstUtf8 utf8 = (ConstUtf8) c;
280 stringSize += utf8.asString().length();
281 nStrings++;
282 }
283 }
284 ClassPrint.spaces(out, indent);
285 out.println("" + nStrings + " constant pool strings totalling " +
286 stringSize + " bytes");
287 }
288
289 void write (DataOutputStream buff) throws IOException {
290 buff.writeShort(pool.size());
291 for (int i=1; i<pool.size(); i++) {
292 ConstBasic cb = (ConstBasic) pool.elementAt(i);
293 if (cb != null) {
294 buff.writeByte((byte) cb.tag());
295 cb.formatData(buff);
296 }
297 }
298 }
299
300
301
302 private void resolvePool() {
303
304 for (int i=0; i<pool.size(); i++) {
305 ConstBasic c = constantAt(i);
306 if (c != null) {
307 c.setIndex(i);
308 c.resolve(this);
309 }
310 }
311 }
312
313 private void hashConstants() {
314 if (hashed)
315 return;
316
317
318 for (int j=0; j<pool.size(); j++) {
319 ConstBasic c = constantAt(j);
320 if (c != null) {
321 recordConstant(c);
322 }
323 }
324
325 hashed = true;
326 }
327
328
329 private int readConstant(DataInputStream input) throws IOException {
330 ConstBasic basic;
331 byte b = input.readByte();
332 int slots = 1;
333 switch (b) {
334 case CONSTANTUtf8:
335 basic = ConstUtf8.read(input);
336 break;
337 case CONSTANTUnicode:
338 basic = ConstUnicode.read(input);
339 break;
340 case CONSTANTInteger:
341 basic = ConstInteger.read(input);
342 break;
343 case CONSTANTFloat:
344 basic = ConstFloat.read(input);
345 break;
346 case CONSTANTLong:
347 basic = ConstLong.read(input);
348 slots = 2;
349 break;
350 case CONSTANTDouble:
351 basic = ConstDouble.read(input);
352 slots = 2;
353 break;
354 case CONSTANTClass:
355 basic = ConstClass.read(input);
356 break;
357 case CONSTANTString:
358 basic = ConstString.read(input);
359 break;
360 case CONSTANTFieldRef:
361 basic = ConstFieldRef.read(input);
362 break;
363 case CONSTANTMethodRef:
364 basic = ConstMethodRef.read(input);
365 break;
366 case CONSTANTInterfaceMethodRef:
367 basic = ConstInterfaceMethodRef.read(input);
368 break;
369 case CONSTANTNameAndType:
370 basic = ConstNameAndType.read(input);
371 break;
372 default:
373 throw new ClassFormatError("Don't know this constant type: " +
374 Integer.toString(b));
375 }
376
377 pool.addElement(basic);
378 if (slots > 1)
379 pool.addElement(null);
380 return slots;
381 }
382
383 private void internConstant (ConstBasic c) {
384 if (c != null) {
385 c.setIndex(pool.size());
386 recordConstant(c);
387 }
388 pool.addElement(c);
389 }
390
391 private void recordConstant (ConstBasic c) {
392 if (c != null) {
393 switch (c.tag()) {
394 case CONSTANTUtf8:
395 utfTable.put(((ConstUtf8)c).asString(), c);
396 break;
397 case CONSTANTUnicode:
398 unicodeTable.put(((ConstUnicode)c).asString(), c);
399 break;
400 case CONSTANTInteger:
401 intTable.put(new Integer(((ConstInteger)c).value()), c);
402 break;
403 case CONSTANTFloat:
404 floatTable.put(new Float(((ConstFloat)c).value()), c);
405 break;
406 case CONSTANTLong:
407 longTable.put(new Long(((ConstLong)c).value()), c);
408 break;
409 case CONSTANTDouble:
410 doubleTable.put(new Double(((ConstDouble)c).value()), c);
411 break;
412 case CONSTANTClass:
413 classTable.put(((ConstClass)c).asString(), c);
414 break;
415 case CONSTANTString:
416 stringTable.put(((ConstString)c).value().asString(), c);
417 break;
418 case CONSTANTFieldRef:
419 fieldRefTable.addElement(c);
420 break;
421 case CONSTANTMethodRef:
422 methodRefTable.addElement(c);
423 break;
424 case CONSTANTInterfaceMethodRef:
425 ifaceMethodRefTable.addElement(c);
426 break;
427 case CONSTANTNameAndType:
428 nameAndTypeTable.addElement(c);
429 break;
430 }
431 }
432 }
433
434 private ConstBasicMemberRef searchTable(Vector table, String cname,
435 String mname, String sig) {
436 for (int i=0; i<table.size(); i++) {
437 ConstBasicMemberRef memRef = (ConstBasicMemberRef) table.elementAt(i);
438 if (memRef.className().asString().equals(cname) &&
439 memRef.nameAndType().name().asString().equals(mname) &&
440 memRef.nameAndType().signature().asString().equals(sig))
441 return memRef;
442 }
443 return null;
444 }
445 }