1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.bcel.generic;
19
20 import java.util.HashMap;
21 import java.util.Map;
22 import org.apache.bcel.Constants;
23 import org.apache.bcel.classfile.Constant;
24 import org.apache.bcel.classfile.ConstantCP;
25 import org.apache.bcel.classfile.ConstantClass;
26 import org.apache.bcel.classfile.ConstantDouble;
27 import org.apache.bcel.classfile.ConstantFieldref;
28 import org.apache.bcel.classfile.ConstantFloat;
29 import org.apache.bcel.classfile.ConstantInteger;
30 import org.apache.bcel.classfile.ConstantInterfaceMethodref;
31 import org.apache.bcel.classfile.ConstantLong;
32 import org.apache.bcel.classfile.ConstantMethodref;
33 import org.apache.bcel.classfile.ConstantNameAndType;
34 import org.apache.bcel.classfile.ConstantPool;
35 import org.apache.bcel.classfile.ConstantString;
36 import org.apache.bcel.classfile.ConstantUtf8;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class ConstantPoolGen implements java.io.Serializable {
53
54 private static final long serialVersionUID = 6664071417323174824L;
55 protected int size;
56 protected Constant[] constants;
57 protected int index = 1;
58 private static final String METHODREF_DELIM = ":";
59 private static final String IMETHODREF_DELIM = "#";
60 private static final String FIELDREF_DELIM = "&";
61 private static final String NAT_DELIM = "%";
62
63 private static class Index implements java.io.Serializable {
64
65 private static final long serialVersionUID = -9187078620578535161L;
66 int index;
67
68
69 Index(int i) {
70 index = i;
71 }
72 }
73
74
75
76
77
78
79
80 public ConstantPoolGen(Constant[] cs) {
81 StringBuilder sb = new StringBuilder(256);
82
83 size = Math.max(256, cs.length + 64);
84 constants = new Constant[size];
85
86 System.arraycopy(cs, 0, constants, 0, cs.length);
87 if (cs.length > 0) {
88 index = cs.length;
89 }
90
91
92 for (int i = 1; i < index; i++) {
93 Constant c = constants[i];
94 if (c instanceof ConstantString) {
95 ConstantString s = (ConstantString) c;
96 ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
97 String key = u8.getBytes();
98 if (!string_table.containsKey(key)) {
99 string_table.put(key, new Index(i));
100 }
101 } else if (c instanceof ConstantClass) {
102 ConstantClass s = (ConstantClass) c;
103 ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
104 String key = u8.getBytes();
105 if (!class_table.containsKey(key)) {
106 class_table.put(key, new Index(i));
107 }
108 } else if (c instanceof ConstantNameAndType) {
109 ConstantNameAndType n = (ConstantNameAndType) c;
110 ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
111 ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
112
113 sb.append(u8.getBytes());
114 sb.append(NAT_DELIM);
115 sb.append(u8_2.getBytes());
116 String key = sb.toString();
117 sb.delete(0, sb.length());
118
119 if (!n_a_t_table.containsKey(key)) {
120 n_a_t_table.put(key, new Index(i));
121 }
122 } else if (c instanceof ConstantUtf8) {
123 ConstantUtf8 u = (ConstantUtf8) c;
124 String key = u.getBytes();
125 if (!utf8_table.containsKey(key)) {
126 utf8_table.put(key, new Index(i));
127 }
128 } else if (c instanceof ConstantCP) {
129 ConstantCP m = (ConstantCP) c;
130 ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
131 ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
132 ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
133 String class_name = u8.getBytes().replace('/', '.');
134 u8 = (ConstantUtf8) constants[n.getNameIndex()];
135 String method_name = u8.getBytes();
136 u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
137 String signature = u8.getBytes();
138 String delim = METHODREF_DELIM;
139 if (c instanceof ConstantInterfaceMethodref) {
140 delim = IMETHODREF_DELIM;
141 } else if (c instanceof ConstantFieldref) {
142 delim = FIELDREF_DELIM;
143 }
144
145 sb.append(class_name);
146 sb.append(delim);
147 sb.append(method_name);
148 sb.append(delim);
149 sb.append(signature);
150 String key = sb.toString();
151 sb.delete(0, sb.length());
152
153 if (!cp_table.containsKey(key)) {
154 cp_table.put(key, new Index(i));
155 }
156 }
157 }
158 }
159
160
161
162
163
164 public ConstantPoolGen(ConstantPool cp) {
165 this(cp.getConstantPool());
166 }
167
168
169
170
171
172 public ConstantPoolGen() {
173 size = 256;
174 constants = new Constant[size];
175 }
176
177
178
179
180 protected void adjustSize() {
181 if (index + 3 >= size) {
182 Constant[] cs = constants;
183 size *= 2;
184 constants = new Constant[size];
185 System.arraycopy(cs, 0, constants, 0, index);
186 }
187 }
188
189 private Map<String, Index> string_table = new HashMap<String, Index>();
190
191
192
193
194
195
196
197
198 public int lookupString( String str ) {
199 Index index = string_table.get(str);
200 return (index != null) ? index.index : -1;
201 }
202
203
204
205
206
207
208
209
210 public int addString( String str ) {
211 int ret;
212 if ((ret = lookupString(str)) != -1) {
213 return ret;
214 }
215 int utf8 = addUtf8(str);
216 adjustSize();
217 ConstantString s = new ConstantString(utf8);
218 ret = index;
219 constants[index++] = s;
220 if (!string_table.containsKey(str)) {
221 string_table.put(str, new Index(ret));
222 }
223 return ret;
224 }
225
226 private Map<String, Index> class_table = new HashMap<String, Index>();
227
228
229
230
231
232
233
234
235 public int lookupClass( String str ) {
236 Index index = class_table.get(str.replace('.', '/'));
237 return (index != null) ? index.index : -1;
238 }
239
240
241 private int addClass_( String clazz ) {
242 int ret;
243 if ((ret = lookupClass(clazz)) != -1) {
244 return ret;
245 }
246 adjustSize();
247 ConstantClass c = new ConstantClass(addUtf8(clazz));
248 ret = index;
249 constants[index++] = c;
250 if (!class_table.containsKey(clazz)) {
251 class_table.put(clazz, new Index(ret));
252 }
253 return ret;
254 }
255
256
257
258
259
260
261
262
263 public int addClass( String str ) {
264 return addClass_(str.replace('.', '/'));
265 }
266
267
268
269
270
271
272
273
274 public int addClass( ObjectType type ) {
275 return addClass(type.getClassName());
276 }
277
278
279
280
281
282
283
284
285
286 public int addArrayClass( ArrayType type ) {
287 return addClass_(type.getSignature());
288 }
289
290
291
292
293
294
295
296
297 public int lookupInteger( int n ) {
298 for (int i = 1; i < index; i++) {
299 if (constants[i] instanceof ConstantInteger) {
300 ConstantInteger c = (ConstantInteger) constants[i];
301 if (c.getBytes() == n) {
302 return i;
303 }
304 }
305 }
306 return -1;
307 }
308
309
310
311
312
313
314
315
316 public int addInteger( int n ) {
317 int ret;
318 if ((ret = lookupInteger(n)) != -1) {
319 return ret;
320 }
321 adjustSize();
322 ret = index;
323 constants[index++] = new ConstantInteger(n);
324 return ret;
325 }
326
327
328
329
330
331
332
333
334 public int lookupFloat( float n ) {
335 int bits = Float.floatToIntBits(n);
336 for (int i = 1; i < index; i++) {
337 if (constants[i] instanceof ConstantFloat) {
338 ConstantFloat c = (ConstantFloat) constants[i];
339 if (Float.floatToIntBits(c.getBytes()) == bits) {
340 return i;
341 }
342 }
343 }
344 return -1;
345 }
346
347
348
349
350
351
352
353
354 public int addFloat( float n ) {
355 int ret;
356 if ((ret = lookupFloat(n)) != -1) {
357 return ret;
358 }
359 adjustSize();
360 ret = index;
361 constants[index++] = new ConstantFloat(n);
362 return ret;
363 }
364
365 private Map<String, Index> utf8_table = new HashMap<String, Index>();
366
367
368
369
370
371
372
373
374 public int lookupUtf8( String n ) {
375 Index index = utf8_table.get(n);
376 return (index != null) ? index.index : -1;
377 }
378
379
380
381
382
383
384
385
386 public int addUtf8( String n ) {
387 int ret;
388 if ((ret = lookupUtf8(n)) != -1) {
389 return ret;
390 }
391 adjustSize();
392 ret = index;
393 constants[index++] = new ConstantUtf8(n);
394 if (!utf8_table.containsKey(n)) {
395 utf8_table.put(n, new Index(ret));
396 }
397 return ret;
398 }
399
400
401
402
403
404
405
406
407 public int lookupLong( long n ) {
408 for (int i = 1; i < index; i++) {
409 if (constants[i] instanceof ConstantLong) {
410 ConstantLong c = (ConstantLong) constants[i];
411 if (c.getBytes() == n) {
412 return i;
413 }
414 }
415 }
416 return -1;
417 }
418
419
420
421
422
423
424
425
426 public int addLong( long n ) {
427 int ret;
428 if ((ret = lookupLong(n)) != -1) {
429 return ret;
430 }
431 adjustSize();
432 ret = index;
433 constants[index] = new ConstantLong(n);
434 index += 2;
435 return ret;
436 }
437
438
439
440
441
442
443
444
445 public int lookupDouble( double n ) {
446 long bits = Double.doubleToLongBits(n);
447 for (int i = 1; i < index; i++) {
448 if (constants[i] instanceof ConstantDouble) {
449 ConstantDouble c = (ConstantDouble) constants[i];
450 if (Double.doubleToLongBits(c.getBytes()) == bits) {
451 return i;
452 }
453 }
454 }
455 return -1;
456 }
457
458
459
460
461
462
463
464
465 public int addDouble( double n ) {
466 int ret;
467 if ((ret = lookupDouble(n)) != -1) {
468 return ret;
469 }
470 adjustSize();
471 ret = index;
472 constants[index] = new ConstantDouble(n);
473 index += 2;
474 return ret;
475 }
476
477 private Map<String, Index> n_a_t_table = new HashMap<String, Index>();
478
479
480
481
482
483
484
485
486
487 public int lookupNameAndType( String name, String signature ) {
488 Index _index = n_a_t_table.get(name + NAT_DELIM + signature);
489 return (_index != null) ? _index.index : -1;
490 }
491
492
493
494
495
496
497
498
499
500
501 public int addNameAndType( String name, String signature ) {
502 int ret;
503 int name_index, signature_index;
504 if ((ret = lookupNameAndType(name, signature)) != -1) {
505 return ret;
506 }
507 adjustSize();
508 name_index = addUtf8(name);
509 signature_index = addUtf8(signature);
510 ret = index;
511 constants[index++] = new ConstantNameAndType(name_index, signature_index);
512 String key = name + NAT_DELIM + signature;
513 if (!n_a_t_table.containsKey(key)) {
514 n_a_t_table.put(key, new Index(ret));
515 }
516 return ret;
517 }
518
519 private Map<String, Index> cp_table = new HashMap<String, Index>();
520
521
522
523
524
525
526
527
528
529
530 public int lookupMethodref( String class_name, String method_name, String signature ) {
531 Index index = cp_table.get(class_name + METHODREF_DELIM + method_name
532 + METHODREF_DELIM + signature);
533 return (index != null) ? index.index : -1;
534 }
535
536
537 public int lookupMethodref( MethodGen method ) {
538 return lookupMethodref(method.getClassName(), method.getName(), method.getSignature());
539 }
540
541
542
543
544
545
546
547
548
549
550
551 public int addMethodref( String class_name, String method_name, String signature ) {
552 int ret, class_index, name_and_type_index;
553 if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) {
554 return ret;
555 }
556 adjustSize();
557 name_and_type_index = addNameAndType(method_name, signature);
558 class_index = addClass(class_name);
559 ret = index;
560 constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
561 String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature;
562 if (!cp_table.containsKey(key)) {
563 cp_table.put(key, new Index(ret));
564 }
565 return ret;
566 }
567
568
569 public int addMethodref( MethodGen method ) {
570 return addMethodref(method.getClassName(), method.getName(), method.getSignature());
571 }
572
573
574
575
576
577
578
579
580
581
582 public int lookupInterfaceMethodref( String class_name, String method_name, String signature ) {
583 Index index = cp_table.get(class_name + IMETHODREF_DELIM + method_name
584 + IMETHODREF_DELIM + signature);
585 return (index != null) ? index.index : -1;
586 }
587
588
589 public int lookupInterfaceMethodref( MethodGen method ) {
590 return lookupInterfaceMethodref(method.getClassName(), method.getName(), method
591 .getSignature());
592 }
593
594
595
596
597
598
599
600
601
602
603
604 public int addInterfaceMethodref( String class_name, String method_name, String signature ) {
605 int ret, class_index, name_and_type_index;
606 if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) {
607 return ret;
608 }
609 adjustSize();
610 class_index = addClass(class_name);
611 name_and_type_index = addNameAndType(method_name, signature);
612 ret = index;
613 constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
614 String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature;
615 if (!cp_table.containsKey(key)) {
616 cp_table.put(key, new Index(ret));
617 }
618 return ret;
619 }
620
621
622 public int addInterfaceMethodref( MethodGen method ) {
623 return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature());
624 }
625
626
627
628
629
630
631
632
633
634
635 public int lookupFieldref( String class_name, String field_name, String signature ) {
636 Index index = cp_table.get(class_name + FIELDREF_DELIM + field_name
637 + FIELDREF_DELIM + signature);
638 return (index != null) ? index.index : -1;
639 }
640
641
642
643
644
645
646
647
648
649
650
651 public int addFieldref( String class_name, String field_name, String signature ) {
652 int ret;
653 int class_index, name_and_type_index;
654 if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) {
655 return ret;
656 }
657 adjustSize();
658 class_index = addClass(class_name);
659 name_and_type_index = addNameAndType(field_name, signature);
660 ret = index;
661 constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
662 String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature;
663 if (!cp_table.containsKey(key)) {
664 cp_table.put(key, new Index(ret));
665 }
666 return ret;
667 }
668
669
670
671
672
673
674 public Constant getConstant( int i ) {
675 return constants[i];
676 }
677
678
679
680
681
682
683
684
685 public void setConstant( int i, Constant c ) {
686 constants[i] = c;
687 }
688
689
690
691
692
693 public ConstantPool getConstantPool() {
694 return new ConstantPool(constants);
695 }
696
697
698
699
700
701 public int getSize() {
702 return index;
703 }
704
705
706
707
708
709 public ConstantPool getFinalConstantPool() {
710 Constant[] cs = new Constant[index];
711 System.arraycopy(constants, 0, cs, 0, index);
712 return new ConstantPool(cs);
713 }
714
715
716
717
718
719 @Override
720 public String toString() {
721 StringBuilder buf = new StringBuilder();
722 for (int i = 1; i < index; i++) {
723 buf.append(i).append(")").append(constants[i]).append("\n");
724 }
725 return buf.toString();
726 }
727
728
729
730
731 public int addConstant( Constant c, ConstantPoolGen cp ) {
732 Constant[] constants = cp.getConstantPool().getConstantPool();
733 switch (c.getTag()) {
734 case Constants.CONSTANT_String: {
735 ConstantString s = (ConstantString) c;
736 ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
737 return addString(u8.getBytes());
738 }
739 case Constants.CONSTANT_Class: {
740 ConstantClass s = (ConstantClass) c;
741 ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
742 return addClass(u8.getBytes());
743 }
744 case Constants.CONSTANT_NameAndType: {
745 ConstantNameAndType n = (ConstantNameAndType) c;
746 ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
747 ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
748 return addNameAndType(u8.getBytes(), u8_2.getBytes());
749 }
750 case Constants.CONSTANT_Utf8:
751 return addUtf8(((ConstantUtf8) c).getBytes());
752 case Constants.CONSTANT_Double:
753 return addDouble(((ConstantDouble) c).getBytes());
754 case Constants.CONSTANT_Float:
755 return addFloat(((ConstantFloat) c).getBytes());
756 case Constants.CONSTANT_Long:
757 return addLong(((ConstantLong) c).getBytes());
758 case Constants.CONSTANT_Integer:
759 return addInteger(((ConstantInteger) c).getBytes());
760 case Constants.CONSTANT_InterfaceMethodref:
761 case Constants.CONSTANT_Methodref:
762 case Constants.CONSTANT_Fieldref: {
763 ConstantCP m = (ConstantCP) c;
764 ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
765 ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
766 ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
767 String class_name = u8.getBytes().replace('/', '.');
768 u8 = (ConstantUtf8) constants[n.getNameIndex()];
769 String name = u8.getBytes();
770 u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
771 String signature = u8.getBytes();
772 switch (c.getTag()) {
773 case Constants.CONSTANT_InterfaceMethodref:
774 return addInterfaceMethodref(class_name, name, signature);
775 case Constants.CONSTANT_Methodref:
776 return addMethodref(class_name, name, signature);
777 case Constants.CONSTANT_Fieldref:
778 return addFieldref(class_name, name, signature);
779 default:
780 throw new RuntimeException("Unknown constant type " + c);
781 }
782 }
783 default:
784 throw new RuntimeException("Unknown constant type " + c);
785 }
786 }
787 }