Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jreversepro/reflect/JConstantPool.java


1   /*
2    * @(#)JConstantPool.java
3    *
4    * JReversePro - Java Decompiler / Disassembler.
5    * Copyright (C) 2000 2001 Karthik Kumar.
6    * EMail: akkumar@users.sourceforge.net
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it , under the terms of the GNU General Public License as published
10   * by the Free Software Foundation; either version 2 of the License,
11   * or (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16   * See the GNU General Public License for more details.
17   * You should have received a copy of the GNU General Public License
18   * along with this program.If not, write to
19   *  The Free Software Foundation, Inc.,
20   *  59 Temple Place - Suite 330,
21   *  Boston, MA 02111-1307, USA.
22   */
23  package jreversepro.reflect;
24  
25  import jreversepro.parser.ClassParserException;
26  
27  import jreversepro.common.KeyWords;
28  import jreversepro.common.Helper;
29  
30  import java.util.List;
31  import java.util.ArrayList;
32  
33  /**
34   * <b>JConstantPool</b> represents the abstraction of the ConstantPool.
35   *
36   * @author      Karthik Kumar
37   */
38  public class JConstantPool  implements KeyWords {
39  
40  
41      /**
42       * STR_INVALID corresponds to an invalid entry in the
43       * ConstantPool.
44       **/
45      public static final String STR_INVALID  = "Invalid String";
46  
47      /**
48       * PTR_INVALID of a pointer of a ConstantPool tag means that
49       * they are not applicable for that ConstantPool tag.
50       **/
51      public static final int PTR_INVALID =  -1;
52  
53      /**
54       * TAG_NOTHING means that the ConstantPool Entry is invalid.
55       **/
56      public static final int TAG_NOTHING = -1;
57  
58      /**
59       * TAG_UTF8 corresponds to CONSTANT_UTF8
60       **/
61      public static final int TAG_UTF8 = 1;
62  
63      /**
64       * TAG_INTEGER corresponds to CONSTANT_INTEGER
65       **/
66      public static final int TAG_INTEGER = 3;
67  
68      /**
69       * TAG_FLOAT corresponds to CONSTANT_FLOAT
70       **/
71      public static final int TAG_FLOAT = 4;
72  
73      /**
74       * TAG_LONG corresponds to CONSTANT_LONG
75       **/
76      public static final int TAG_LONG = 5;
77  
78      /**
79       * TAG_DOUBLE corresponds to CONSTANT_DOUBLE
80       **/
81      public static final int TAG_DOUBLE = 6;
82  
83      /**
84       * TAG_CLASS corresponds to CONSTANT_CLASS
85       **/
86      public static final int TAG_CLASS = 7;
87  
88      /**
89       * TAG_STRING corresponds to CONSTANT_STRING
90       **/
91      public static final int TAG_STRING = 8;
92  
93      /**
94       * TAG_FIELDREF corresponds to CONSTANT_FIELDREF
95       **/
96      public static final int TAG_FIELDREF = 9;
97  
98      /**
99       * TAG_METHODREF corresponds to CONSTANT_METHODREF
100      **/
101     public static final int TAG_METHODREF = 10;
102 
103     /**
104      * TAG_INTERFACEREF corresponds to CONSTANT_INTERFACEREF
105      **/
106     public static final int TAG_INTERFACEREF = 11;
107 
108     /**
109      * TAG_NAMETYPE  corresponds to CONSTANT_NAMETYPE
110      **/
111     public static final int TAG_NAMETYPE = 12;
112 
113     /**
114      * listEntries contains the ConstantPool Entries.
115      * The individual elements of the list are
116      * JConstantPoolEntry.
117      **/
118     private List listEntries;
119 
120     /**
121      * Reference to importedClasses that contains the list
122      * of imported classes.
123      **/
124     private JImport importedClasses;
125 
126     /**
127      * Constructor.
128      * @param cpMax Maximum size of the ConstantPool.
129      **/
130     public JConstantPool(int cpMax) {
131         listEntries = new ArrayList(cpMax);
132         importedClasses = null;
133         //Initially set to null.
134     }
135 
136 
137     /**
138      * Returns the number of ConstantPool Entries.
139      * @return Returns the cp entry count.
140      **/
141     public int getMaxCpEntry() {
142         return listEntries.size();
143     }
144 
145     /**
146      * Returns the constantpool entries.
147      * The individual elements are JConstantPoolEntry.
148      * @return Returns list of constantpool entries.
149      **/
150     public List getEntries() {
151         return listEntries;
152     }
153 
154     /**
155      * Adds a new TAG_FIELDREF entry to the constantpool.
156      * @param ptr1 Pointer to TAG_CLASS
157      * @param ptr2 Pointer to TAG_NAMETYPE
158      **/
159     public void addFieldRefEntry(int ptr1, int ptr2) {
160        listEntries.add(
161                 new JConstantPoolEntry(
162                         TAG_FIELDREF,
163                         STR_INVALID,
164                         ptr1,
165                         ptr2));
166     }
167 
168     /**
169      * Adds a new TAG_METHODREF entry to the constantpool.
170      * @param ptr1 Pointer to TAG_CLASS
171      * @param ptr2 Pointer to TAG_NAMETYPE
172      **/
173     public void addMethodRefEntry(int ptr1, int ptr2) {
174        listEntries.add(
175                 new JConstantPoolEntry(
176                         TAG_METHODREF,
177                         STR_INVALID,
178                         ptr1,
179                         ptr2));
180     }
181 
182     /**
183      * Adds a new TAG_INTERFACEREF entry to the constantpool.
184      * @param ptr1 Pointer to TAG_CLASS
185      * @param ptr2 Pointer to TAG_NAMETYPE
186      **/
187     public void addInterfaceRefEntry(int ptr1, int ptr2) {
188        listEntries.add(
189                 new JConstantPoolEntry(
190                         TAG_INTERFACEREF,
191                         STR_INVALID,
192                         ptr1,
193                         ptr2));
194     }
195 
196     /**
197      * Adds a new TAG_NAMETYPE entry to the constantpool.
198      * @param ptr1 Pointer to TAG_UTF8
199      * @param ptr2 Pointer to TAG_UTF8
200      **/
201     public void addNameTypeEntry(int ptr1, int ptr2)  {
202        listEntries.add(
203                 new JConstantPoolEntry(
204                         TAG_NAMETYPE,
205                         STR_INVALID,
206                         ptr1,
207                         ptr2));
208     }
209 
210     /**
211      * Adds a NULL entry to the ConstantPool.
212      * Mainly useful when we add long/ double.
213      **/
214     public void addNullEntry() {
215        listEntries.add(
216                 new JConstantPoolEntry(
217                         TAG_NOTHING,
218                         STR_INVALID,
219                         PTR_INVALID,
220                         PTR_INVALID));
221     }
222 
223     /**
224      * Adds a new TAG_UTF8 entry to the constantpool.
225      * @param value Value of the UTF8 String.
226      **/
227     public void addUtf8Entry(String value) {
228        listEntries.add(
229                 new JConstantPoolEntry(
230                         TAG_UTF8,
231                         value,
232                         PTR_INVALID,
233                         PTR_INVALID));
234     }
235 
236     /**
237      * Adds a new TAG_INTEGER entry to the constantpool.
238      * @param value Value of the integer.
239      **/
240     public void addIntegerEntry(String value) {
241        listEntries.add(
242                 new JConstantPoolEntry(
243                         TAG_INTEGER,
244                         value,
245                         PTR_INVALID,
246                         PTR_INVALID));
247     }
248 
249     /**
250      * Adds a new TAG_FLOAT entry to the constantpool.
251      * @param value Value of the float number.
252      **/
253     public void addFloatEntry(String value) {
254        listEntries.add(
255                 new JConstantPoolEntry(
256                         TAG_FLOAT,
257                         value,
258                         PTR_INVALID,
259                         PTR_INVALID));
260     }
261 
262     /**
263      * Adds a new TAG_DOUBLE entry to the constantpool.
264      * @param value Value of the double.
265      **/
266     public void addDoubleEntry(String value) {
267        listEntries.add(
268                 new JConstantPoolEntry(
269                         TAG_DOUBLE,
270                         value,
271                         PTR_INVALID,
272                         PTR_INVALID));
273     }
274 
275 
276     /**
277      * Adds a new TAG_LONG entry to the constantpool.
278      * @param value Value of the Long.
279      **/
280     public void addLongEntry(String value) {
281        listEntries.add(
282                 new JConstantPoolEntry(
283                         TAG_LONG,
284                         value,
285                         PTR_INVALID,
286                         PTR_INVALID));
287     }
288 
289     /**
290      * Adds a new TAG_CLASS entry to the constantpool.
291      * @param classIndex Index to UTF8 string containing
292      * class name.
293      **/
294     public void addClassEntry(int classIndex) {
295        listEntries.add(
296                 new JConstantPoolEntry(
297                         TAG_CLASS,
298                         STR_INVALID,
299                         classIndex,
300                         PTR_INVALID));
301     }
302 
303     /**
304      * Adds a new TAG_STRING entry to the constantpool.
305      * @param stringIndex Index to the UTF8 string
306      * containing the stringvalue.
307      **/
308     public void addStringEntry(int stringIndex) {
309        listEntries.add(
310                 new JConstantPoolEntry(
311                         TAG_STRING,
312                         STR_INVALID,
313                         stringIndex,
314                         PTR_INVALID));
315     }
316 
317     /**
318      * Returns the data type of the given ConstantPool Index.
319      * @param index Index to the ConstantPool Entry.
320      * @return long/double/String/integer appropriately
321      **/
322     public String getDataType(int index) {
323         switch (getTagByte(index)) {
324             case TAG_LONG:
325                 return LONG;
326             case TAG_DOUBLE:
327                 return DOUBLE;
328             case TAG_STRING:
329                 return CLASS_STRING;
330             case TAG_INTEGER:
331                 return INT;
332             default:
333                 return NULL;
334         }
335     }
336 
337     /**
338      * Returns if the given index to the ConstantPool
339      * is TAG_DOUBLE or not.
340      * @param index Index to ConstantPool
341      * @return Returns true, if it is a TAG_DOUBLE.
342      * false, otherwise.
343      **/
344     public boolean isTagDouble(int index) {
345         return getTagByte(index) == TAG_DOUBLE;
346     }
347 
348     /**
349      * Returns the first pointer of the ConstantPool Data.
350      * @param index Index to ConstantPool
351      * @return Returns the integer.
352      **/
353     public int getPtr1(int index) {
354         return ((JConstantPoolEntry) listEntries.get(index)).getPtr1();
355     }
356 
357     /**
358      * Returns the second pointer of the ConstantPool Data.
359      * @param index Index to ConstantPool
360      * @return Returns the integer.
361      **/
362     public int getPtr2(int index) {
363         return ((JConstantPoolEntry) listEntries.get(index)).getPtr2();
364     }
365 
366     /**
367      * Returns the tagbyte of the ConstantPool.
368      * @param index Index to ConstantPool
369      * @return Returns the tag byte.
370      **/
371     public int getTagByte(int index) {
372         return ((JConstantPoolEntry) listEntries.get(index)).getTagByte();
373     }
374 
375     /**
376      * Returns the ConstantPool value.
377      * @param index Index to ConstantPool
378      * @return Returns the value of that cp entry.
379      **/
380     public String getCpValue(int index) {
381         return ((JConstantPoolEntry) listEntries.get(index)).getValue();
382     }
383 
384 
385     /**
386      * Returns the Utf8 value pointed by the first pointer
387      * of the index to the ConstantPool.
388      * Say for example, if entry #6 has ptr1 to be #8
389      * and the utf8 value of #8 is "MyString", this method
390      * on given input 6 returns "MyString".
391      * @param index Index to ConstantPool
392      * @return Returns a String a Utf8 value.
393      **/
394     public String getFirstDirectName(int index) {
395         int ptr1 =
396             ((JConstantPoolEntry) listEntries.get(index)).
397                                         getPtr1() ;
398         return ((JConstantPoolEntry) listEntries.get(ptr1)).
399                                         getValue();
400     }
401 
402     /**
403      * Returns the Utf8 value pointed by the II pointer
404      * of the index to the ConstantPool.
405      * Say for example, if entry #6 has ptr2 to be #8
406      * and the utf8 value of #8 is "MyString", this method
407      * on given input 6 returns "MyString".
408      * @param index Index to ConstantPool
409      * @return Returns a String a Utf8 value.
410      **/
411     public String getSecondDirectName(int index)  {
412         int ptr2 =
413             ((JConstantPoolEntry) listEntries.get(index)).
414                                         getPtr2() ;
415         return ((JConstantPoolEntry) listEntries.get(ptr2)).
416                                         getValue();
417     }
418 
419     /**
420      * Given an index to TAG_CLASS this returns the class
421      * name pointed to by it. If the index is 0 then a
422      * class of type ANY is returned.
423      * @param index Index to ConstantPool
424      * @return Returns a String - class name
425      **/
426     public String getClassName(int index) {
427         return (index == 0) ? ANY : getFirstDirectName(index);
428     }
429 
430     /**
431      * Given an index to TAG_NAMETYPE this returns the
432      * name of the member ( field / method )
433      * @param index Index to ConstantPool
434      * @return Returns name of the member
435      **/
436     public String getFieldName(int index) {
437         return getFirstDirectName(index);
438     }
439 
440     /**
441      * Given an index to TAG_NAMETYPE this returns the
442      * type of the member ( field / method )
443      * @param index Index to ConstantPool
444      * @return Returns type of the member
445      **/
446     public String getFieldType(int index) {
447         return getSecondDirectName(index);
448     }
449 
450     /**
451      * Given an index to TAG_UTF8 this returns the
452      * string value.
453      * @param index Index to ConstantPool
454      * @return Returns value of that Cp Entry.
455      **/
456     public String getUtf8String(int index) {
457         return getCpValue(index);
458     }
459 
460     /**
461      * Given an Cp index this returns the proper
462      * constant pool value depending on the tag type.
463      * If TAG_INTEGER, returned as such.
464      * Else if TAG_STRING all the escape characters are
465      * properly quoted and returned.
466      * @param index Index to ConstantPool
467      * @return Returns value of that Cp Entry.
468      * @throws ClassParserException Thrown in case of an wrong 
469      * constantpool index being referrred.
470      **/
471     public String getLdcString(int index)
472             throws ClassParserException {
473         String result = STR_INVALID;
474         int tagByte = getTagByte(index);
475 
476         if (tagByte  == TAG_STRING) {
477             String strVal = getFirstDirectName(index);
478             strVal = Helper.replaceEscapeChars(strVal);
479             result = "\"" +  strVal + "\"";
480         } else if (tagByte == TAG_INTEGER) {
481             result = getCpValue(index);
482         } else {
483             throw new ClassParserException(
484                 "Referring invalid constantpool index " 
485                  + index);
486         }
487         return result;
488     }
489 
490     /**
491      * The constantpool is the one and only source that
492      * contains the references to external types. Hence all
493      * the entries are analyzed for all external types referred to by
494      * this class and are consolidated into a class called JImport.
495      * This JImport can further be used to get the short form of
496      * classname etc.
497      * @return Reference to JImport.
498      **/
499     public JImport getImportedClasses() {
500         if (importedClasses != null) {
501             return importedClasses;
502         } else {
503             importedClasses  =  new JImport();
504             for (int i = 0; i < listEntries.size(); i++) {
505                 JConstantPoolEntry ent
506                         = (JConstantPoolEntry) listEntries.get(i);
507                 switch (ent.getTagByte()) {
508                     case TAG_CLASS:
509                         importedClasses.addClass(
510                             Helper.getJavaDataType(
511                                     getFirstDirectName(i), true));
512                          break;
513 
514                     case TAG_FIELDREF:
515                         String type = getType(ent);
516                         importedClasses.addClass(
517                             Helper.getJavaDataType(type, true));
518                         break;
519 
520                     case TAG_METHODREF:
521                     case TAG_INTERFACEREF:
522                         String methodType = getType(ent);
523                         List args = Helper.getArguments(methodType);
524                         for (int j = 0 ; j < args.size() ; j++) {
525                             String argtype = (String) args.get(j);
526                             importedClasses.addClass (
527                                     Helper.getJavaDataType(argtype, true));
528                         }
529                         importedClasses.addClass(
530                                 Helper.getJavaDataType(
531                                     Helper.getReturnType(methodType), true));
532                         break;
533                 }
534             }
535             return importedClasses;
536         }
537     }
538 
539     /**
540      * Returns the value for the ConstantPool Entries
541      * according to their types.
542      * @param index Index to ConstantPool
543      * @return Returns value of that Cp Entry.
544      * @throws ClassParserException Throws in case the referred 
545      * constantpool index does not represent a basic data type index.
546      **/
547     public String getBasicDataTypeValue(int index) 
548             throws ClassParserException {
549         int tagByte = getTagByte (index);
550         switch (tagByte) {
551             case TAG_LONG:
552             case TAG_FLOAT:
553             case TAG_DOUBLE:
554             case TAG_INTEGER:
555                 return getCpValue(index);
556             case TAG_STRING:
557                 StringBuffer sb = new StringBuffer("\"");
558                 sb.append(Helper.replaceEscapeChars(
559                             getFirstDirectName(index)) +  "\"");
560                 return sb.toString();
561             default:
562                 throw new ClassParserException(
563                     "ConstantPool Index #" + index 
564                     + " doesnt represent a basic datatype ");
565         }
566     }
567 
568 
569     /**
570      * Returns the actual name of the tag .
571      * according to their types.
572      * @param tagByte Tag Byte value
573      * @return Returns the string representation of the
574      * integer tagByte
575      **/
576     public static String getTagName(int tagByte) {
577         switch(tagByte) {
578             case TAG_UTF8:
579                 return ("TAG_UTF8");
580 
581             case TAG_INTEGER:
582                 return ("TAG_INTEGER");
583 
584             case TAG_FLOAT:
585                 return ("TAG_FLOAT");
586 
587             case TAG_LONG:
588                 return ("TAG_LONG");
589 
590             case TAG_DOUBLE:
591                 return ("TAG_DOUBLE");
592 
593             case TAG_CLASS:
594                 return ("TAG_CLASS");
595 
596             case TAG_STRING:
597                 return ("TAG_STRING");
598 
599             case TAG_FIELDREF:
600                 return ("TAG_FIELDREF");
601 
602             case TAG_METHODREF:
603                 return ("TAG_METHODREF");
604 
605             case TAG_INTERFACEREF:
606                 return ("TAG_INTERFACEREF");
607 
608             case TAG_NAMETYPE:
609                 return ("TAG_NAMETYPE");
610 
611             case TAG_NOTHING:
612                 return ("TAG_NOTHING");
613 
614             default:
615                 return ("Invalid Tag");
616         }
617     }
618 
619 
620     /**
621      * Describes the tag in brief. If a tag is relative tag
622      * like TAG_FIELDREF or TAG_METHODREF then it lists out the
623      * related tag information too,
624      * @param index Index to the ConstantPool.
625      * @return Returns a string describing the tag entry.
626      * @throws ClassParserException Thrown in case of an invalid 
627      * constantpool reference.
628      **/
629     public String getTagDescriptor(int index)
630                     throws ClassParserException {
631         StringBuffer result = new StringBuffer("");
632         int tagByte = getTagByte(index);
633         switch(tagByte) {
634             case TAG_METHODREF:
635             case TAG_FIELDREF:
636             case TAG_INTERFACEREF:
637                 JConstantPoolEntry ent =
638                         (JConstantPoolEntry) listEntries.get(index);
639                 result.append(getType(ent) + "," + getName(ent));
640                 break;
641             case TAG_STRING:
642                 result.append(getLdcString(index));
643                 break;
644             case TAG_CLASS:
645                 result.append(getClassName(index));
646                 break;
647         }
648         return result.toString();
649     }
650 
651     /**
652      * Returns the name pointed to by this JConstantPoolEntry.
653      * Usually this tag happens to be one of
654      * TAG_FIELDREF, TAG_METHODREF or TAG_INTERFACEREF.
655      * @param ent Constant Pool Entry
656      * @return Returns name of the member (field/method/interface)
657      * pointed to by the Constant Pool Entry.
658      **/
659     public String getName(JConstantPoolEntry ent) {
660         JConstantPoolEntry  entNameType  =
661                 (JConstantPoolEntry)
662                     listEntries.get(ent.getPtr2());
663         JConstantPoolEntry entName =
664                 (JConstantPoolEntry)
665                     listEntries.get(entNameType.getPtr1());
666         return entName.getValue();
667     }
668 
669    /**
670     * Returns the type pointed to by this JConstantPoolEntry.
671     * Usually this tag happens to be one of
672     * TAG_FIELDREF, TAG_METHODREF or TAG_INTERFACEREF.
673     * @param ent Constant Pool Entry
674     * @return Returns type of the member (field/method/interface)
675     * pointed to by the Constant Pool Entry.
676     **/
677    public String getType(JConstantPoolEntry ent) {
678         JConstantPoolEntry  entNameType  =
679                 (JConstantPoolEntry)
680                           listEntries.get(ent.getPtr2());
681         JConstantPoolEntry entType =
682                 (JConstantPoolEntry)
683                     listEntries.get(entNameType.getPtr2());
684         return entType.getValue();
685    }
686 
687     /**
688      * Returns the whole ConstantPool info in a formatter manner.
689      * @return Returns a string.
690      **/
691     public String getEntryInfo() {
692         StringBuffer sb =  new StringBuffer();
693         for (int i = 0 ; i < listEntries.size() ; i++) {
694             sb.append("\n" + i + " : " +  listEntries.get(i));
695         }
696         return sb.toString();
697     }
698 
699 
700     /**
701      * Returns the name pointed to by this JConstantPoolEntry.
702      * Usually this tag happens to be one of
703      * TAG_FIELDREF, TAG_METHODREF or TAG_INTERFACEREF.
704      * @param cpIndex Index to Constant Pool
705      * @return Returns name of the member (field/method/interface)
706      * pointed to by the Constant Pool Entry.
707      **/
708     public String getEntryInfo(int cpIndex) {
709        StringBuffer sb = new StringBuffer();
710        getSingleEntryInfo(sb, cpIndex);
711        return sb.toString();
712     }
713 
714     /**
715      * Describes the tag in brief. If a tag is relative tag
716      * like TAG_FIELDREF or TAG_METHODREF then it continues to
717      * report the dependent tag information until it reaches a
718      * tag which is not dependent on anything else.
719      * Usually the final tag happens to a TAG_UTF8.
720      * @param sb StringBuffer containing the info of tags dependent on this
721      * already ( cpIndex ).
722      * @param cpIndex Index to ConstantPool.
723      **/
724    private void getSingleEntryInfo(StringBuffer sb, int cpIndex) {
725         if (cpIndex >= 1 && cpIndex < listEntries.size()) {
726             JConstantPoolEntry ent  = (JConstantPoolEntry)
727                                         listEntries.get(cpIndex);
728             sb.append("\n" + cpIndex + " : " +  ent);
729             getSingleEntryInfo(sb, ent.getPtr1());
730             getSingleEntryInfo(sb, ent.getPtr2());
731         }
732    }
733 
734 }