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