/Users/lyon/j4p/src/javassist/bytecode/ConstPool.java
|
1 /*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15
16 package javassist.bytecode;
17
18 import java.io.DataInputStream;
19 import java.io.DataOutputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.PrintWriter;
22 import java.io.IOException;
23 import java.util.Map;
24 import java.util.Hashtable;
25
26 import javassist.CtClass;
27
28 /**
29 * Constant pool table.
30 */
31 public final class ConstPool {
32 LongVector items;
33 int numOfItems;
34 Hashtable classes;
35 Hashtable strings;
36 int thisClassInfo;
37 private static final int SIZE = 128;
38
39 /**
40 * <code>CONSTANT_Class</code>
41 */
42 public static final int CONST_Class = ClassInfo.tag;
43
44 /**
45 * <code>CONSTANT_Fieldref</code>
46 */
47 public static final int CONST_Fieldref = FieldrefInfo.tag;
48
49 /**
50 * <code>CONSTANT_Methodref</code>
51 */
52 public static final int CONST_Methodref = MethodrefInfo.tag;
53
54 /**
55 * <code>CONSTANT_InterfaceMethodref</code>
56 */
57 public static final int CONST_InterfaceMethodref
58 = InterfaceMethodrefInfo.tag;
59
60 /**
61 * <code>CONSTANT_String</code>
62 */
63 public static final int CONST_String = StringInfo.tag;
64
65 /**
66 * <code>CONSTANT_Integer</code>
67 */
68 public static final int CONST_Integer = IntegerInfo.tag;
69
70 /**
71 * <code>CONSTANT_Float</code>
72 */
73 public static final int CONST_Float = IntegerInfo.tag;
74
75 /**
76 * <code>CONSTANT_Long</code>
77 */
78 public static final int CONST_Long = LongInfo.tag;
79
80 /**
81 * <code>CONSTANT_Double</code>
82 */
83 public static final int CONST_Double = DoubleInfo.tag;
84
85 /**
86 * <code>CONSTANT_NameAndType</code>
87 */
88 public static final int CONST_NameAndType = NameAndTypeInfo.tag;
89
90 /**
91 * <code>CONSTANT_Utf8</code>
92 */
93 public static final int CONST_Utf8 = Utf8Info.tag;
94
95 /**
96 * Represents the class using this constant pool table.
97 */
98 public static final CtClass THIS = null;
99
100 /**
101 * Constructs a constant pool table.
102 *
103 * @param thisclass the name of the class using this constant
104 * pool table
105 */
106 public ConstPool(String thisclass) {
107 this();
108 thisClassInfo = addClassInfo(thisclass);
109 }
110
111 /**
112 * Constructs a constant pool table from the given byte stream.
113 *
114 * @param in byte stream.
115 */
116 public ConstPool(DataInputStream in) throws IOException {
117 this();
118 read(in);
119 }
120
121 private ConstPool() {
122 items = new LongVector(SIZE);
123 numOfItems = 0;
124 addItem(null); // index 0 is reserved by the JVM.
125 classes = new Hashtable();
126 strings = new Hashtable();
127 thisClassInfo = 0;
128 }
129
130 /**
131 * Returns the name of the class using this constant pool table.
132 */
133 public String getClassName() {
134 return getClassInfo(thisClassInfo);
135 }
136
137 /**
138 * Returns the index of <code>CONSTANT_Class_info</code> structure
139 * specifying the class using this constant pool table.
140 */
141 public int getThisClassInfo() {
142 return thisClassInfo;
143 }
144
145 void setThisClassInfo(int i) {
146 thisClassInfo = i;
147 }
148
149 ConstInfo getItem(int n) {
150 return (ConstInfo) items.elementAt(n);
151 }
152
153 /**
154 * Returns the <code>tag</code> field of the constant pool table
155 * entry at the given index.
156 */
157 public int getTag(int index) {
158 return getItem(index).getTag();
159 }
160
161 /**
162 * Reads <code>CONSTANT_Class_info</code> structure
163 * at the given index.
164 *
165 * @return a fully-qualified class or interface name specified
166 * by <code>name_index</code>.
167 */
168 public String getClassInfo(int index) {
169 ClassInfo c = (ClassInfo) getItem(index);
170 if (c == null)
171 return null;
172 else
173 return Descriptor.toJavaName(getUtf8Info(c.name));
174 }
175
176 /**
177 * Reads the <code>name_index</code> field of the
178 * <code>CONSTANT_NameAndType_info</code> structure
179 * at the given index.
180 */
181 public int getNameAndTypeName(int index) {
182 NameAndTypeInfo ntinfo = (NameAndTypeInfo) getItem(index);
183 return ntinfo.memberName;
184 }
185
186 /**
187 * Reads the <code>descriptor_index</code> field of the
188 * <code>CONSTANT_NameAndType_info</code> structure
189 * at the given index.
190 */
191 public int getNameAndTypeDescriptor(int index) {
192 NameAndTypeInfo ntinfo = (NameAndTypeInfo) getItem(index);
193 return ntinfo.typeDescriptor;
194 }
195
196 /**
197 * Reads the <code>class_index</code> field of the
198 * <code>CONSTANT_Fieldref_info</code> structure
199 * at the given index.
200 */
201 public int getFieldrefClass(int index) {
202 FieldrefInfo finfo = (FieldrefInfo) getItem(index);
203 return finfo.classIndex;
204 }
205
206 /**
207 * Reads the <code>class_index</code> field of the
208 * <code>CONSTANT_Fieldref_info</code> structure
209 * at the given index.
210 *
211 * @return the name of the class at that <code>class_index</code>.
212 */
213 public String getFieldrefClassName(int index) {
214 FieldrefInfo f = (FieldrefInfo) getItem(index);
215 if (f == null)
216 return null;
217 else
218 return getClassInfo(f.classIndex);
219 }
220
221 /**
222 * Reads the <code>name_and_type_index</code> field of the
223 * <code>CONSTANT_Fieldref_info</code> structure
224 * at the given index.
225 */
226 public int getFieldrefNameAndType(int index) {
227 FieldrefInfo finfo = (FieldrefInfo) getItem(index);
228 return finfo.nameAndTypeIndex;
229 }
230
231 /**
232 * Reads the <code>name_index</code> field of the
233 * <code>CONSTANT_NameAndType_info</code> structure
234 * indirectly specified by the given index.
235 *
236 * @param index an index to a <code>CONSTANT_Fieldref_info</code>.
237 * @return the name of the field.
238 */
239 public String getFieldrefName(int index) {
240 FieldrefInfo f = (FieldrefInfo) getItem(index);
241 if (f == null)
242 return null;
243 else {
244 NameAndTypeInfo n = (NameAndTypeInfo) getItem(f.nameAndTypeIndex);
245 if (n == null)
246 return null;
247 else
248 return getUtf8Info(n.memberName);
249 }
250 }
251
252 /**
253 * Reads the <code>descriptor_index</code> field of the
254 * <code>CONSTANT_NameAndType_info</code> structure
255 * indirectly specified by the given index.
256 *
257 * @param index an index to a <code>CONSTANT_Fieldref_info</code>.
258 * @return the type descriptor of the field.
259 */
260 public String getFieldrefType(int index) {
261 FieldrefInfo f = (FieldrefInfo) getItem(index);
262 if (f == null)
263 return null;
264 else {
265 NameAndTypeInfo n = (NameAndTypeInfo) getItem(f.nameAndTypeIndex);
266 if (n == null)
267 return null;
268 else
269 return getUtf8Info(n.typeDescriptor);
270 }
271 }
272
273 /**
274 * Reads the <code>class_index</code> field of the
275 * <code>CONSTANT_Methodref_info</code> structure
276 * at the given index.
277 */
278 public int getMethodrefClass(int index) {
279 MethodrefInfo minfo = (MethodrefInfo) getItem(index);
280 return minfo.classIndex;
281 }
282
283 /**
284 * Reads the <code>class_index</code> field of the
285 * <code>CONSTANT_Methodref_info</code> structure
286 * at the given index.
287 *
288 * @return the name of the class at that <code>class_index</code>.
289 */
290 public String getMethodrefClassName(int index) {
291 MethodrefInfo minfo = (MethodrefInfo) getItem(index);
292 if (minfo == null)
293 return null;
294 else
295 return getClassInfo(minfo.classIndex);
296 }
297
298 /**
299 * Reads the <code>name_and_type_index</code> field of the
300 * <code>CONSTANT_Methodref_info</code> structure
301 * at the given index.
302 */
303 public int getMethodrefNameAndType(int index) {
304 MethodrefInfo minfo = (MethodrefInfo) getItem(index);
305 return minfo.nameAndTypeIndex;
306 }
307
308 /**
309 * Reads the <code>name_index</code> field of the
310 * <code>CONSTANT_NameAndType_info</code> structure
311 * indirectly specified by the given index.
312 *
313 * @param index an index to a <code>CONSTANT_Methodref_info</code>.
314 * @return the name of the method.
315 */
316 public String getMethodrefName(int index) {
317 MethodrefInfo minfo = (MethodrefInfo) getItem(index);
318 if (minfo == null)
319 return null;
320 else {
321 NameAndTypeInfo n
322 = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
323 if (n == null)
324 return null;
325 else
326 return getUtf8Info(n.memberName);
327 }
328 }
329
330 /**
331 * Reads the <code>descriptor_index</code> field of the
332 * <code>CONSTANT_NameAndType_info</code> structure
333 * indirectly specified by the given index.
334 *
335 * @param index an index to a <code>CONSTANT_Methodref_info</code>.
336 * @return the descriptor of the method.
337 */
338 public String getMethodrefType(int index) {
339 MethodrefInfo minfo = (MethodrefInfo) getItem(index);
340 if (minfo == null)
341 return null;
342 else {
343 NameAndTypeInfo n
344 = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
345 if (n == null)
346 return null;
347 else
348 return getUtf8Info(n.typeDescriptor);
349 }
350 }
351
352 /**
353 * Reads the <code>class_index</code> field of the
354 * <code>CONSTANT_InterfaceMethodref_info</code> structure
355 * at the given index.
356 */
357 public int getInterfaceMethodrefClass(int index) {
358 InterfaceMethodrefInfo minfo
359 = (InterfaceMethodrefInfo) getItem(index);
360 return minfo.classIndex;
361 }
362
363 /**
364 * Reads the <code>class_index</code> field of the
365 * <code>CONSTANT_InterfaceMethodref_info</code> structure
366 * at the given index.
367 *
368 * @return the name of the class at that <code>class_index</code>.
369 */
370 public String getInterfaceMethodrefClassName(int index) {
371 InterfaceMethodrefInfo minfo
372 = (InterfaceMethodrefInfo) getItem(index);
373 return getClassInfo(minfo.classIndex);
374 }
375
376 /**
377 * Reads the <code>name_and_type_index</code> field of the
378 * <code>CONSTANT_InterfaceMethodref_info</code> structure
379 * at the given index.
380 */
381 public int getInterfaceMethodrefNameAndType(int index) {
382 InterfaceMethodrefInfo minfo
383 = (InterfaceMethodrefInfo) getItem(index);
384 return minfo.nameAndTypeIndex;
385 }
386
387 /**
388 * Reads the <code>name_index</code> field of the
389 * <code>CONSTANT_NameAndType_info</code> structure
390 * indirectly specified by the given index.
391 *
392 * @param index an index to
393 * a <code>CONSTANT_InterfaceMethodref_info</code>.
394 * @return the name of the method.
395 */
396 public String getInterfaceMethodrefName(int index) {
397 InterfaceMethodrefInfo minfo
398 = (InterfaceMethodrefInfo) getItem(index);
399 if (minfo == null)
400 return null;
401 else {
402 NameAndTypeInfo n
403 = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
404 if (n == null)
405 return null;
406 else
407 return getUtf8Info(n.memberName);
408 }
409 }
410
411 /**
412 * Reads the <code>descriptor_index</code> field of the
413 * <code>CONSTANT_NameAndType_info</code> structure
414 * indirectly specified by the given index.
415 *
416 * @param index an index to
417 * a <code>CONSTANT_InterfaceMethodref_info</code>.
418 * @return the descriptor of the method.
419 */
420 public String getInterfaceMethodrefType(int index) {
421 InterfaceMethodrefInfo minfo
422 = (InterfaceMethodrefInfo) getItem(index);
423 if (minfo == null)
424 return null;
425 else {
426 NameAndTypeInfo n
427 = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
428 if (n == null)
429 return null;
430 else
431 return getUtf8Info(n.typeDescriptor);
432 }
433 }
434
435 /**
436 * Reads <code>CONSTANT_Integer_info</code>, <code>_Float_info</code>,
437 * <code>_Long_info</code>, <code>_Double_info</code>, or
438 * <code>_String_info</code> structure.
439 * These are used with the LDC instruction.
440 *
441 * @return a <code>String</code> value or a wrapped primitive-type
442 * value.
443 */
444 public Object getLdcValue(int index) {
445 ConstInfo constInfo = this.getItem(index);
446 Object value = null;
447 if (constInfo instanceof StringInfo)
448 value = this.getStringInfo(index);
449 else if (constInfo instanceof FloatInfo)
450 value = new Float(getFloatInfo(index));
451 else if (constInfo instanceof IntegerInfo)
452 value = new Integer(getIntegerInfo(index));
453 else if (constInfo instanceof LongInfo)
454 value = new Long(getLongInfo(index));
455 else if (constInfo instanceof DoubleInfo)
456 value = new Double(getDoubleInfo(index));
457 else
458 value = null;
459
460 return value;
461 }
462
463 /**
464 * Reads <code>CONSTANT_Integer_info</code> structure
465 * at the given index.
466 *
467 * @return the value specified by this entry.
468 */
469 public int getIntegerInfo(int index) {
470 IntegerInfo i = (IntegerInfo) getItem(index);
471 return i.value;
472 }
473
474 /**
475 * Reads <code>CONSTANT_Float_info</code> structure
476 * at the given index.
477 *
478 * @return the value specified by this entry.
479 */
480 public float getFloatInfo(int index) {
481 FloatInfo i = (FloatInfo) getItem(index);
482 return i.value;
483 }
484
485 /**
486 * Reads <code>CONSTANT_Long_info</code> structure
487 * at the given index.
488 *
489 * @return the value specified by this entry.
490 */
491 public long getLongInfo(int index) {
492 LongInfo i = (LongInfo) getItem(index);
493 return i.value;
494 }
495
496 /**
497 * Reads <code>CONSTANT_Double_info</code> structure
498 * at the given index.
499 *
500 * @return the value specified by this entry.
501 */
502 public double getDoubleInfo(int index) {
503 DoubleInfo i = (DoubleInfo) getItem(index);
504 return i.value;
505 }
506
507 /**
508 * Reads <code>CONSTANT_String_info</code> structure
509 * at the given index.
510 *
511 * @return the string specified by <code>string_index</code>.
512 */
513 public String getStringInfo(int index) {
514 StringInfo si = (StringInfo) getItem(index);
515 return getUtf8Info(si.string);
516 }
517
518 /**
519 * Reads <code>CONSTANT_utf8_info</code> structure
520 * at the given index.
521 *
522 * @return the string specified by this entry.
523 */
524 public String getUtf8Info(int index) {
525 Utf8Info utf = (Utf8Info) getItem(index);
526 return utf.string;
527 }
528
529 /**
530 * Determines whether <code>CONSTANT_Methodref_info</code>
531 * structure at the given index represents the constructor
532 * of the given class.
533 *
534 * @return the <code>descriptor_index</code> specifying
535 * the type descriptor of the that constructor.
536 * If it is not that constructor,
537 * <code>isConstructor()</code> returns 0.
538 */
539 public int isConstructor(String classname, int index) {
540 return isMember(classname, MethodInfo.nameInit, index);
541 }
542
543 /**
544 * Determines whether <code>CONSTANT_Methodref_info</code>,
545 * <code>CONSTANT_Fieldref_info</code>, or
546 * <code>CONSTANT_InterfaceMethodref_info</code> structure
547 * at the given index represents the member with the specified
548 * name and declaring class.
549 *
550 * @param classname the class declaring the member
551 * @param membername the member name
552 * @param index the index into the constant pool table
553 *
554 * @return the <code>descriptor_index</code> specifying
555 * the type descriptor of that member.
556 * If it is not that member,
557 * <code>isMember()</code> returns 0.
558 */
559 public int isMember(String classname, String membername, int index) {
560 MemberrefInfo minfo = (MemberrefInfo) getItem(index);
561 if (getClassInfo(minfo.classIndex).equals(classname)) {
562 NameAndTypeInfo ntinfo
563 = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
564 if (getUtf8Info(ntinfo.memberName).equals(membername))
565 return ntinfo.typeDescriptor;
566 }
567
568 return 0; // false
569 }
570
571 private int addItem(ConstInfo info) {
572 items.addElement(info);
573 return numOfItems++;
574 }
575
576 /**
577 * Copies the n-th item in this ConstPool object into the destination
578 * ConstPool object.
579 * The class names that the item refers to are renamed according
580 * to the given map.
581 *
582 * @param n the <i>n</i>-th item
583 * @param dest destination constant pool table
584 * @param classnames the map or null.
585 */
586 public int copy(int n, ConstPool dest, Map classnames) {
587 if (n == 0)
588 return 0;
589
590 ConstInfo info = getItem(n);
591 return info.copy(this, dest, classnames);
592 }
593
594 int addConstInfoPadding() {
595 return addItem(new ConstInfoPadding());
596 }
597
598 /**
599 * Adds a new <code>CONSTANT_Class_info</code> structure.
600 *
601 * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
602 * for storing the class name.
603 *
604 * @return the index of the added entry.
605 */
606 public int addClassInfo(CtClass c) {
607 if (c == THIS)
608 return thisClassInfo;
609 else if (!c.isArray())
610 return addClassInfo(c.getName());
611 else {
612 // an array type is recorded in the hashtable with
613 // the key "[L<classname>;" instead of "<classname>".
614 //
615 // note: toJvmName(toJvmName(c)) is equal to toJvmName(c).
616
617 return addClassInfo(Descriptor.toJvmName(c));
618 }
619 }
620
621 /**
622 * Adds a new <code>CONSTANT_Class_info</code> structure.
623 *
624 * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
625 * for storing the class name.
626 *
627 * @param qname a fully-qualified class name
628 * (or the JVM-internal representation of that name).
629 * @return the index of the added entry.
630 */
631 public int addClassInfo(String qname) {
632 ClassInfo info = (ClassInfo) classes.get(qname);
633 if (info != null)
634 return info.index;
635 else {
636 int utf8 = addUtf8Info(Descriptor.toJvmName(qname));
637 info = new ClassInfo(utf8, numOfItems);
638 classes.put(qname, info);
639 return addItem(info);
640 }
641 }
642
643 /**
644 * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
645 *
646 * <p>This also adds <code>CONSTANT_Utf8_info</code> structures.
647 *
648 * @param name <code>name_index</code>
649 * @param type <code>descriptor_index</code>
650 * @return the index of the added entry.
651 */
652 public int addNameAndTypeInfo(String name, String type) {
653 return addNameAndTypeInfo(addUtf8Info(name), addUtf8Info(type));
654 }
655
656 /**
657 * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
658 *
659 * @param name <code>name_index</code>
660 * @param type <code>descriptor_index</code>
661 * @return the index of the added entry.
662 */
663 public int addNameAndTypeInfo(int name, int type) {
664 return addItem(new NameAndTypeInfo(name, type));
665 }
666
667 /**
668 * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
669 *
670 * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
671 * structure.
672 *
673 * @param classInfo <code>class_index</code>
674 * @param name <code>name_index</code>
675 * of <code>CONSTANT_NameAndType_info</code>.
676 * @param type <code>descriptor_index</code>
677 * of <code>CONSTANT_NameAndType_info</code>.
678 * @return the index of the added entry.
679 */
680 public int addFieldrefInfo(int classInfo, String name, String type) {
681 int nt = addNameAndTypeInfo(name, type);
682 return addFieldrefInfo(classInfo, nt);
683 }
684
685 /**
686 * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
687 *
688 * @param classInfo <code>class_index</code>
689 * @param nameandtypeinfo <code>name_and_type_index</code>.
690 * @return the index of the added entry.
691 */
692 public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) {
693 return addItem(new FieldrefInfo(classInfo, nameAndTypeInfo));
694 }
695
696 /**
697 * Adds a new <code>CONSTANT_Methodref_info</code> structure.
698 *
699 * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
700 * structure.
701 *
702 * @param classInfo <code>class_index</code>
703 * @param name <code>name_index</code>
704 * of <code>CONSTANT_NameAndType_info</code>.
705 * @param type <code>descriptor_index</code>
706 * of <code>CONSTANT_NameAndType_info</code>.
707 * @return the index of the added entry.
708 */
709 public int addMethodrefInfo(int classInfo, String name, String type) {
710 int nt = addNameAndTypeInfo(name, type);
711 return addMethodrefInfo(classInfo, nt);
712 }
713
714 /**
715 * Adds a new <code>CONSTANT_Methodref_info</code> structure.
716 *
717 * @param classInfo <code>class_index</code>
718 * @param nameandtypeinfo <code>name_and_type_index</code>.
719 * @return the index of the added entry.
720 */
721 public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) {
722 return addItem(new MethodrefInfo(classInfo, nameAndTypeInfo));
723 }
724
725 /**
726 * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
727 * structure.
728 *
729 * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
730 * structure.
731 *
732 * @param classInfo <code>class_index</code>
733 * @param name <code>name_index</code>
734 * of <code>CONSTANT_NameAndType_info</code>.
735 * @param type <code>descriptor_index</code>
736 * of <code>CONSTANT_NameAndType_info</code>.
737 * @return the index of the added entry.
738 */
739 public int addInterfaceMethodrefInfo(int classInfo, String name,
740 String type) {
741 int nt = addNameAndTypeInfo(name, type);
742 return addInterfaceMethodrefInfo(classInfo, nt);
743 }
744
745 /**
746 * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
747 * structure.
748 *
749 * @param classInfo <code>class_index</code>
750 * @param nameandtypeinfo <code>name_and_type_index</code>.
751 * @return the index of the added entry.
752 */
753 public int addInterfaceMethodrefInfo(int classInfo,
754 int nameAndTypeInfo) {
755 return addItem(new InterfaceMethodrefInfo(classInfo,
756 nameAndTypeInfo));
757 }
758
759 /**
760 * Adds a new <code>CONSTANT_String_info</code>
761 * structure.
762 *
763 * <p>This also adds a new <code>CONSTANT_Utf8_info</code>
764 * structure.
765 *
766 * @return the index of the added entry.
767 */
768 public int addStringInfo(String str) {
769 return addItem(new StringInfo(addUtf8Info(str)));
770 }
771
772 /**
773 * Adds a new <code>CONSTANT_Integer_info</code>
774 * structure.
775 *
776 * @return the index of the added entry.
777 */
778 public int addIntegerInfo(int i) {
779 return addItem(new IntegerInfo(i));
780 }
781
782 /**
783 * Adds a new <code>CONSTANT_Float_info</code>
784 * structure.
785 *
786 * @return the index of the added entry.
787 */
788 public int addFloatInfo(float f) {
789 return addItem(new FloatInfo(f));
790 }
791
792 /**
793 * Adds a new <code>CONSTANT_Long_info</code>
794 * structure.
795 *
796 * @return the index of the added entry.
797 */
798 public int addLongInfo(long l) {
799 int i = addItem(new LongInfo(l));
800 addItem(new ConstInfoPadding());
801 return i;
802 }
803
804 /**
805 * Adds a new <code>CONSTANT_Double_info</code>
806 * structure.
807 *
808 * @return the index of the added entry.
809 */
810 public int addDoubleInfo(double d) {
811 int i = addItem(new DoubleInfo(d));
812 addItem(new ConstInfoPadding());
813 return i;
814 }
815
816 /**
817 * Adds a new <code>CONSTANT_Utf8_info</code>
818 * structure.
819 *
820 * <p>If the given utf8 string has been already recorded in the
821 * table, then this method does not add a new entry to avoid adding
822 * a duplicated entry.
823 * Instead, it returns the index of the entry already recorded.
824 *
825 * @return the index of the added entry.
826 */
827 public int addUtf8Info(String utf8) {
828 Utf8Info info = (Utf8Info) strings.get(utf8);
829 if (info != null)
830 return info.index;
831 else {
832 info = new Utf8Info(utf8, numOfItems);
833 strings.put(utf8, info);
834 return addItem(info);
835 }
836 }
837
838 /**
839 * Replaces all occurrences of a class name.
840 *
841 * @param oldName the replaced name
842 * @param newName the substituted name.
843 */
844 public void renameClass(String oldName, String newName) {
845 LongVector v = items;
846 int size = numOfItems;
847 for (int i = 1; i < size; ++i)
848 ((ConstInfo) v.elementAt(i)).renameClass(this, oldName, newName);
849 }
850
851 /**
852 * Replaces all occurrences of class names.
853 *
854 * @param classnames specifies pairs of replaced and substituted
855 * name.
856 */
857 public void renameClass(Map classnames) {
858 LongVector v = items;
859 int size = numOfItems;
860 for (int i = 1; i < size; ++i)
861 ((ConstInfo) v.elementAt(i)).renameClass(this, classnames);
862 }
863
864 private void read(DataInputStream in) throws IOException {
865 int n = in.readUnsignedShort();
866 while (--n > 0) { // index 0 is reserved by JVM
867 int tag = readOne(in);
868 if ((tag == LongInfo.tag) || (tag == DoubleInfo.tag)) {
869 addItem(new ConstInfoPadding());
870 --n;
871 }
872 }
873 }
874
875 private int readOne(DataInputStream in) throws IOException {
876 ConstInfo info;
877 int tag = in.readUnsignedByte();
878 switch (tag) {
879 case Utf8Info.tag: // 1
880 info = new Utf8Info(in, numOfItems);
881 strings.put(((Utf8Info) info).string, info);
882 break;
883 case IntegerInfo.tag: // 3
884 info = new IntegerInfo(in);
885 break;
886 case FloatInfo.tag: // 4
887 info = new FloatInfo(in);
888 break;
889 case LongInfo.tag: // 5
890 info = new LongInfo(in);
891 break;
892 case DoubleInfo.tag: // 6
893 info = new DoubleInfo(in);
894 break;
895 case ClassInfo.tag: // 7
896 info = new ClassInfo(in, numOfItems);
897 // classes.put(<classname>, info);
898 break;
899 case StringInfo.tag: // 8
900 info = new StringInfo(in);
901 break;
902 case FieldrefInfo.tag: // 9
903 info = new FieldrefInfo(in);
904 break;
905 case MethodrefInfo.tag: // 10
906 info = new MethodrefInfo(in);
907 break;
908 case InterfaceMethodrefInfo.tag: // 11
909 info = new InterfaceMethodrefInfo(in);
910 break;
911 case NameAndTypeInfo.tag: // 12
912 info = new NameAndTypeInfo(in);
913 break;
914 default :
915 throw new IOException("invalid constant type: " + tag);
916 }
917
918 addItem(info);
919 return tag;
920 }
921
922 /**
923 * Writes the contents of the constant pool table.
924 */
925 public void write(DataOutputStream out) throws IOException {
926 out.writeShort(numOfItems);
927 LongVector v = items;
928 int size = numOfItems;
929 for (int i = 1; i < size; ++i)
930 ((ConstInfo) v.elementAt(i)).write(out);
931 }
932
933 /**
934 * Prints the contents of the constant pool table.
935 */
936 public void print() {
937 print(new PrintWriter(System.out, true));
938 }
939
940 /**
941 * Prints the contents of the constant pool table.
942 */
943 public void print(PrintWriter out) {
944 int size = numOfItems;
945 for (int i = 1; i < size; ++i) {
946 out.print(i);
947 out.print(" ");
948 ((ConstInfo) items.elementAt(i)).print(out);
949 }
950 }
951 }
952
953 abstract class ConstInfo {
954 public abstract int getTag();
955
956 public void renameClass(ConstPool cp, String oldName, String newName) {
957 }
958
959 public void renameClass(ConstPool cp, Map classnames) {
960 }
961
962 public abstract int copy(ConstPool src, ConstPool dest, Map classnames);
963 // ** classnames is a mapping between JVM names.
964
965 public abstract void write(DataOutputStream out) throws IOException;
966
967 public abstract void print(PrintWriter out);
968
969 public String toString() {
970 ByteArrayOutputStream bout = new ByteArrayOutputStream();
971 PrintWriter out = new PrintWriter(bout);
972 print(out);
973 return bout.toString();
974 }
975 }
976
977 /* padding following DoubleInfo or LongInfo.
978 */
979
980 class ConstInfoPadding extends ConstInfo {
981 public int getTag() {
982 return 0;
983 }
984
985 public int copy(ConstPool src, ConstPool dest, Map map) {
986 return dest.addConstInfoPadding();
987 }
988
989 public void write(DataOutputStream out) throws IOException {
990 }
991
992 public void print(PrintWriter out) {
993 out.println("padding");
994 }
995 }
996
997 class ClassInfo extends ConstInfo {
998 static final int tag = 7;
999 int name;
1000 int index;
1001
1002 public ClassInfo(int className, int i) {
1003 name = className;
1004 index = i;
1005 }
1006
1007 public ClassInfo(DataInputStream in, int i) throws IOException {
1008 name = in.readUnsignedShort();
1009 index = i;
1010 }
1011
1012 public int getTag() {
1013 return tag;
1014 }
1015
1016 public void renameClass(ConstPool cp, String oldName, String newName) {
1017 String nameStr = cp.getUtf8Info(name);
1018 if (nameStr.equals(oldName))
1019 name = cp.addUtf8Info(newName);
1020 else if (nameStr.charAt(0) == '[') {
1021 String nameStr2 = Descriptor.rename(nameStr, oldName, newName);
1022 if (nameStr != nameStr2)
1023 name = cp.addUtf8Info(nameStr2);
1024 }
1025 }
1026
1027 public void renameClass(ConstPool cp, Map map) {
1028 String oldName = cp.getUtf8Info(name);
1029 if (oldName.charAt(0) == '[') {
1030 String newName = Descriptor.rename(oldName, map);
1031 if (oldName != newName)
1032 name = cp.addUtf8Info(newName);
1033 } else {
1034 String newName = (String) map.get(oldName);
1035 if (newName != null && !newName.equals(oldName))
1036 name = cp.addUtf8Info(newName);
1037 }
1038 }
1039
1040 public int copy(ConstPool src, ConstPool dest, Map map) {
1041 String classname = src.getUtf8Info(name);
1042 if (map != null) {
1043 String newname = (String) map.get(classname);
1044 if (newname != null)
1045 classname = newname;
1046 }
1047
1048 return dest.addClassInfo(classname);
1049 }
1050
1051 public void write(DataOutputStream out) throws IOException {
1052 out.writeByte(tag);
1053 out.writeShort(name);
1054 }
1055
1056 public void print(PrintWriter out) {
1057 out.print("Class #");
1058 out.println(name);
1059 }
1060 }
1061
1062 class NameAndTypeInfo extends ConstInfo {
1063 static final int tag = 12;
1064 int memberName;
1065 int typeDescriptor;
1066
1067 public NameAndTypeInfo(int name, int type) {
1068 memberName = name;
1069 typeDescriptor = type;
1070 }
1071
1072 public NameAndTypeInfo(DataInputStream in) throws IOException {
1073 memberName = in.readUnsignedShort();
1074 typeDescriptor = in.readUnsignedShort();
1075 }
1076
1077 public int getTag() {
1078 return tag;
1079 }
1080
1081 public void renameClass(ConstPool cp, String oldName, String newName) {
1082 String type = cp.getUtf8Info(typeDescriptor);
1083 String type2 = Descriptor.rename(type, oldName, newName);
1084 if (type != type2)
1085 typeDescriptor = cp.addUtf8Info(type2);
1086 }
1087
1088 public void renameClass(ConstPool cp, Map map) {
1089 String type = cp.getUtf8Info(typeDescriptor);
1090 String type2 = Descriptor.rename(type, map);
1091 if (type != type2)
1092 typeDescriptor = cp.addUtf8Info(type2);
1093 }
1094
1095 public int copy(ConstPool src, ConstPool dest, Map map) {
1096 String mname = src.getUtf8Info(memberName);
1097 String tdesc = src.getUtf8Info(typeDescriptor);
1098 tdesc = Descriptor.rename(tdesc, map);
1099 return dest.addNameAndTypeInfo(dest.addUtf8Info(mname),
1100 dest.addUtf8Info(tdesc));
1101 }
1102
1103 public void write(DataOutputStream out) throws IOException {
1104 out.writeByte(tag);
1105 out.writeShort(memberName);
1106 out.writeShort(typeDescriptor);
1107 }
1108
1109 public void print(PrintWriter out) {
1110 out.print("NameAndType #");
1111 out.print(memberName);
1112 out.print(", type #");
1113 out.println(typeDescriptor);
1114 }
1115 }
1116
1117 abstract class MemberrefInfo extends ConstInfo {
1118 int classIndex;
1119 int nameAndTypeIndex;
1120
1121 public MemberrefInfo(int cindex, int ntindex) {
1122 classIndex = cindex;
1123 nameAndTypeIndex = ntindex;
1124 }
1125
1126 public MemberrefInfo(DataInputStream in) throws IOException {
1127 classIndex = in.readUnsignedShort();
1128 nameAndTypeIndex = in.readUnsignedShort();
1129 }
1130
1131 public int copy(ConstPool src, ConstPool dest, Map map) {
1132 int classIndex2 = src.getItem(classIndex).copy(src, dest, map);
1133 int ntIndex2 = src.getItem(nameAndTypeIndex).copy(src, dest, map);
1134 return copy2(dest, classIndex2, ntIndex2);
1135 }
1136
1137 abstract protected int copy2(ConstPool dest, int cindex, int ntindex);
1138
1139 public void write(DataOutputStream out) throws IOException {
1140 out.writeByte(getTag());
1141 out.writeShort(classIndex);
1142 out.writeShort(nameAndTypeIndex);
1143 }
1144
1145 public void print(PrintWriter out) {
1146 out.print(getTagName() + " #");
1147 out.print(classIndex);
1148 out.print(", name&type #");
1149 out.println(nameAndTypeIndex);
1150 }
1151
1152 public abstract String getTagName();
1153 }
1154
1155 class FieldrefInfo extends MemberrefInfo {
1156 static final int tag = 9;
1157
1158 public FieldrefInfo(int cindex, int ntindex) {
1159 super(cindex, ntindex);
1160 }
1161
1162 public FieldrefInfo(DataInputStream in) throws IOException {
1163 super(in);
1164 }
1165
1166 public int getTag() {
1167 return tag;
1168 }
1169
1170 public String getTagName() {
1171 return "Field";
1172 }
1173
1174 protected int copy2(ConstPool dest, int cindex, int ntindex) {
1175 return dest.addFieldrefInfo(cindex, ntindex);
1176 }
1177 }
1178
1179 class MethodrefInfo extends MemberrefInfo {
1180 static final int tag = 10;
1181
1182 public MethodrefInfo(int cindex, int ntindex) {
1183 super(cindex, ntindex);
1184 }
1185
1186 public MethodrefInfo(DataInputStream in) throws IOException {
1187 super(in);
1188 }
1189
1190 public int getTag() {
1191 return tag;
1192 }
1193
1194 public String getTagName() {
1195 return "Method";
1196 }
1197
1198 protected int copy2(ConstPool dest, int cindex, int ntindex) {
1199 return dest.addMethodrefInfo(cindex, ntindex);
1200 }
1201 }
1202
1203 class InterfaceMethodrefInfo extends MemberrefInfo {
1204 static final int tag = 11;
1205
1206 public InterfaceMethodrefInfo(int cindex, int ntindex) {
1207 super(cindex, ntindex);
1208 }
1209
1210 public InterfaceMethodrefInfo(DataInputStream in) throws IOException {
1211 super(in);
1212 }
1213
1214 public int getTag() {
1215 return tag;
1216 }
1217
1218 public String getTagName() {
1219 return "Interface";
1220 }
1221
1222 protected int copy2(ConstPool dest, int cindex, int ntindex) {
1223 return dest.addInterfaceMethodrefInfo(cindex, ntindex);
1224 }
1225 }
1226
1227 class StringInfo extends ConstInfo {
1228 static final int tag = 8;
1229 int string;
1230
1231 public StringInfo(int str) {
1232 string = str;
1233 }
1234
1235 public StringInfo(DataInputStream in) throws IOException {
1236 string = in.readUnsignedShort();
1237 }
1238
1239 public int getTag() {
1240 return tag;
1241 }
1242
1243 public int copy(ConstPool src, ConstPool dest, Map map) {
1244 return dest.addStringInfo(src.getUtf8Info(string));
1245 }
1246
1247 public void write(DataOutputStream out) throws IOException {
1248 out.writeByte(tag);
1249 out.writeShort(string);
1250 }
1251
1252 public void print(PrintWriter out) {
1253 out.print("String #");
1254 out.println(string);
1255 }
1256 }
1257
1258 class IntegerInfo extends ConstInfo {
1259 static final int tag = 3;
1260 int value;
1261
1262 public IntegerInfo(int i) {
1263 value = i;
1264 }
1265
1266 public IntegerInfo(DataInputStream in) throws IOException {
1267 value = in.readInt();
1268 }
1269
1270 public int getTag() {
1271 return tag;
1272 }
1273
1274 public int copy(ConstPool src, ConstPool dest, Map map) {
1275 return dest.addIntegerInfo(value);
1276 }
1277
1278 public void write(DataOutputStream out) throws IOException {
1279 out.writeByte(tag);
1280 out.writeInt(value);
1281 }
1282
1283 public void print(PrintWriter out) {
1284 out.print("Integer ");
1285 out.println(value);
1286 }
1287 }
1288
1289 class FloatInfo extends ConstInfo {
1290 static final int tag = 4;
1291 float value;
1292
1293 public FloatInfo(float f) {
1294 value = f;
1295 }
1296
1297 public FloatInfo(DataInputStream in) throws IOException {
1298 value = in.readFloat();
1299 }
1300
1301 public int getTag() {
1302 return tag;
1303 }
1304
1305 public int copy(ConstPool src, ConstPool dest, Map map) {
1306 return dest.addFloatInfo(value);
1307 }
1308
1309 public void write(DataOutputStream out) throws IOException {
1310 out.writeByte(tag);
1311 out.writeFloat(value);
1312 }
1313
1314 public void print(PrintWriter out) {
1315 out.print("Float ");
1316 out.println(value);
1317 }
1318 }
1319
1320 class LongInfo extends ConstInfo {
1321 static final int tag = 5;
1322 long value;
1323
1324 public LongInfo(long l) {
1325 value = l;
1326 }
1327
1328 public LongInfo(DataInputStream in) throws IOException {
1329 value = in.readLong();
1330 }
1331
1332 public int getTag() {
1333 return tag;
1334 }
1335
1336 public int copy(ConstPool src, ConstPool dest, Map map) {
1337 return dest.addLongInfo(value);
1338 }
1339
1340 public void write(DataOutputStream out) throws IOException {
1341 out.writeByte(tag);
1342 out.writeLong(value);
1343 }
1344
1345 public void print(PrintWriter out) {
1346 out.print("Long ");
1347 out.println(value);
1348 }
1349 }
1350
1351 class DoubleInfo extends ConstInfo {
1352 static final int tag = 6;
1353 double value;
1354
1355 public DoubleInfo(double d) {
1356 value = d;
1357 }
1358
1359 public DoubleInfo(DataInputStream in) throws IOException {
1360 value = in.readDouble();
1361 }
1362
1363 public int getTag() {
1364 return tag;
1365 }
1366
1367 public int copy(ConstPool src, ConstPool dest, Map map) {
1368 return dest.addDoubleInfo(value);
1369 }
1370
1371 public void write(DataOutputStream out) throws IOException {
1372 out.writeByte(tag);
1373 out.writeDouble(value);
1374 }
1375
1376 public void print(PrintWriter out) {
1377 out.print("Double ");
1378 out.println(value);
1379 }
1380 }
1381
1382 class Utf8Info extends ConstInfo {
1383 static final int tag = 1;
1384 String string;
1385 int index;
1386
1387 public Utf8Info(String utf8, int i) {
1388 string = utf8;
1389 index = i;
1390 }
1391
1392 public Utf8Info(DataInputStream in, int i) throws IOException {
1393 string = in.readUTF();
1394 index = i;
1395 }
1396
1397 public int getTag() {
1398 return tag;
1399 }
1400
1401 public int copy(ConstPool src, ConstPool dest, Map map) {
1402 return dest.addUtf8Info(string);
1403 }
1404
1405 public void write(DataOutputStream out) throws IOException {
1406 out.writeByte(tag);
1407 out.writeUTF(string);
1408 }
1409
1410 public void print(PrintWriter out) {
1411 out.print("UTF8 \"");
1412 out.print(string);
1413 out.println("\"");
1414 }
1415 }
1416