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 }