/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