View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   *
17   */
18  package org.apache.bcel.generic;
19  
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import org.apache.bcel.Const;
24  import org.apache.bcel.classfile.Constant;
25  import org.apache.bcel.classfile.ConstantCP;
26  import org.apache.bcel.classfile.ConstantClass;
27  import org.apache.bcel.classfile.ConstantDouble;
28  import org.apache.bcel.classfile.ConstantFieldref;
29  import org.apache.bcel.classfile.ConstantFloat;
30  import org.apache.bcel.classfile.ConstantInteger;
31  import org.apache.bcel.classfile.ConstantInterfaceMethodref;
32  import org.apache.bcel.classfile.ConstantInvokeDynamic;
33  import org.apache.bcel.classfile.ConstantLong;
34  import org.apache.bcel.classfile.ConstantMethodref;
35  import org.apache.bcel.classfile.ConstantNameAndType;
36  import org.apache.bcel.classfile.ConstantPool;
37  import org.apache.bcel.classfile.ConstantString;
38  import org.apache.bcel.classfile.ConstantUtf8;
39  
40  /**
41   * This class is used to build up a constant pool. The user adds
42   * constants via `addXXX' methods, `addString', `addClass',
43   * etc.. These methods return an index into the constant
44   * pool. Finally, `getFinalConstantPool()' returns the constant pool
45   * built up. Intermediate versions of the constant pool can be
46   * obtained with `getConstantPool()'. A constant pool has capacity for
47   * Constants.MAX_SHORT entries. Note that the first (0) is used by the
48   * JVM and that Double and Long constants need two slots.
49   *
50   * @see Constant
51   */
52  public class ConstantPoolGen {
53  
54      private static final int DEFAULT_BUFFER_SIZE = 256;
55  
56      /**
57       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
58       */
59      @Deprecated
60      protected int size;
61  
62      /**
63       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
64       */
65      @Deprecated
66      protected Constant[] constants;
67  
68      /**
69       * @deprecated (since 6.0) will be made private; do not access directly, use getSize()
70       */
71      @Deprecated
72      protected int index = 1; // First entry (0) used by JVM
73  
74      private static final String METHODREF_DELIM = ":";
75      private static final String IMETHODREF_DELIM = "#";
76      private static final String FIELDREF_DELIM = "&";
77      private static final String NAT_DELIM = "%"; // Name and Type
78  
79      private static class Index {
80  
81          final int index;
82  
83  
84          Index(final int i) {
85              index = i;
86          }
87      }
88  
89  
90      /**
91       * Initialize with given array of constants.
92       *
93       * @param cs array of given constants, new ones will be appended
94       */
95      public ConstantPoolGen(final Constant[] cs) {
96          final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
97  
98          size = Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64);
99          constants = new Constant[size];
100 
101         System.arraycopy(cs, 0, constants, 0, cs.length);
102         if (cs.length > 0) {
103             index = cs.length;
104         }
105 
106 
107         for (int i = 1; i < index; i++) {
108             final Constant c = constants[i];
109             if (c instanceof ConstantString) {
110                 final ConstantString../../../org/apache/bcel/classfile/ConstantString.html#ConstantString">ConstantString s = (ConstantString) c;
111                 final ConstantUtf8/../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
112                 final String key = u8.getBytes();
113                 if (!stringTable.containsKey(key)) {
114                     stringTable.put(key, new Index(i));
115                 }
116             } else if (c instanceof ConstantClass) {
117                 final ConstantClass/../../../org/apache/bcel/classfile/ConstantClass.html#ConstantClass">ConstantClass s = (ConstantClass) c;
118                 final ConstantUtf8/../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
119                 final String key = u8.getBytes();
120                 if (!classTable.containsKey(key)) {
121                     classTable.put(key, new Index(i));
122                 }
123             } else if (c instanceof ConstantNameAndType) {
124                 final ConstantNameAndType/../org/apache/bcel/classfile/ConstantNameAndType.html#ConstantNameAndType">ConstantNameAndType n = (ConstantNameAndType) c;
125                 final ConstantUtf8/../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
126                 final ConstantUtf8./../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
127 
128                 sb.append(u8.getBytes());
129                 sb.append(NAT_DELIM);
130                 sb.append(u8_2.getBytes());
131                 final String key = sb.toString();
132                 sb.delete(0, sb.length());
133 
134                 if (!natTable.containsKey(key)) {
135                     natTable.put(key, new Index(i));
136                 }
137             } else if (c instanceof ConstantUtf8) {
138                 final ConstantUtf8./../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u = (ConstantUtf8) c;
139                 final String key = u.getBytes();
140                 if (!utf8Table.containsKey(key)) {
141                     utf8Table.put(key, new Index(i));
142                 }
143             } else if (c instanceof ConstantCP) {
144                 final ConstantCP"../../../../org/apache/bcel/classfile/ConstantCP.html#ConstantCP">ConstantCP m = (ConstantCP) c;
145                 String class_name;
146                 ConstantUtf8 u8;
147 
148                 if (c instanceof ConstantInvokeDynamic) {
149                     class_name = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex());
150                     // since name can't begin with digit, can  use
151                     // METHODREF_DELIM with out fear of duplicates.
152                 } else {
153                 final ConstantClass../../org/apache/bcel/classfile/ConstantClass.html#ConstantClass">ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
154                     u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
155                     class_name = u8.getBytes().replace('/', '.');
156                 }
157 
158                 final ConstantNameAndType/../org/apache/bcel/classfile/ConstantNameAndType.html#ConstantNameAndType">ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
159                 u8 = (ConstantUtf8) constants[n.getNameIndex()];
160                 final String method_name = u8.getBytes();
161                 u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
162                 final String signature = u8.getBytes();
163 
164                 String delim = METHODREF_DELIM;
165                 if (c instanceof ConstantInterfaceMethodref) {
166                     delim = IMETHODREF_DELIM;
167                 } else if (c instanceof ConstantFieldref) {
168                     delim = FIELDREF_DELIM;
169                 }
170 
171                 sb.append(class_name);
172                 sb.append(delim);
173                 sb.append(method_name);
174                 sb.append(delim);
175                 sb.append(signature);
176                 final String key = sb.toString();
177                 sb.delete(0, sb.length());
178 
179                 if (!cpTable.containsKey(key)) {
180                     cpTable.put(key, new Index(i));
181                 }
182             } else if (c == null) { // entries may be null
183                 // nothing to do
184             } else if (c instanceof ConstantInteger) {
185                 // nothing to do
186             } else if (c instanceof ConstantLong) {
187                 // nothing to do
188             } else if (c instanceof ConstantFloat) {
189                 // nothing to do
190             } else if (c instanceof ConstantDouble) {
191                 // nothing to do
192             } else if (c instanceof org.apache.bcel.classfile.ConstantMethodType) {
193                 // TODO should this be handled somehow?
194             } else if (c instanceof org.apache.bcel.classfile.ConstantMethodHandle) {
195                 // TODO should this be handled somehow?
196             } else if (c instanceof org.apache.bcel.classfile.ConstantModule) {
197                 // TODO should this be handled somehow?
198             } else if (c instanceof org.apache.bcel.classfile.ConstantPackage) {
199                 // TODO should this be handled somehow?
200             } else {
201                 assert false : "Unexpected constant type: " + c.getClass().getName();
202             }
203         }
204     }
205 
206 
207     /**
208      * Initialize with given constant pool.
209      */
210     public ConstantPoolGen(final ConstantPool cp) {
211         this(cp.getConstantPool());
212     }
213 
214 
215     /**
216      * Create empty constant pool.
217      */
218     public ConstantPoolGen() {
219         size = DEFAULT_BUFFER_SIZE;
220         constants = new Constant[size];
221     }
222 
223 
224     /** Resize internal array of constants.
225      */
226     protected void adjustSize() {
227         if (index + 3 >= size) {
228             final Constant[] cs = constants;
229             size *= 2;
230             constants = new Constant[size];
231             System.arraycopy(cs, 0, constants, 0, index);
232         }
233     }
234 
235     private final Map<String, Index> stringTable = new HashMap<>();
236 
237 
238     /**
239      * Look for ConstantString in ConstantPool containing String `str'.
240      *
241      * @param str String to search for
242      * @return index on success, -1 otherwise
243      */
244     public int lookupString( final String str ) {
245         final Index index = stringTable.get(str);
246         return (index != null) ? index.index : -1;
247     }
248 
249 
250     /**
251      * Add a new String constant to the ConstantPool, if it is not already in there.
252      *
253      * @param str String to add
254      * @return index of entry
255      */
256     public int addString( final String str ) {
257         int ret;
258         if ((ret = lookupString(str)) != -1) {
259             return ret; // Already in CP
260         }
261         final int utf8 = addUtf8(str);
262         adjustSize();
263         final ConstantStringantString.html#ConstantString">ConstantString s = new ConstantString(utf8);
264         ret = index;
265         constants[index++] = s;
266         if (!stringTable.containsKey(str)) {
267             stringTable.put(str, new Index(ret));
268         }
269         return ret;
270     }
271 
272     private final Map<String, Index> classTable = new HashMap<>();
273 
274 
275     /**
276      * Look for ConstantClass in ConstantPool named `str'.
277      *
278      * @param str String to search for
279      * @return index on success, -1 otherwise
280      */
281     public int lookupClass( final String str ) {
282         final Index index = classTable.get(str.replace('.', '/'));
283         return (index != null) ? index.index : -1;
284     }
285 
286 
287     private int addClass_( final String clazz ) {
288         int ret;
289         if ((ret = lookupClass(clazz)) != -1) {
290             return ret; // Already in CP
291         }
292         adjustSize();
293         final ConstantClasstantClass.html#ConstantClass">ConstantClass c = new ConstantClass(addUtf8(clazz));
294         ret = index;
295         constants[index++] = c;
296         if (!classTable.containsKey(clazz)) {
297             classTable.put(clazz, new Index(ret));
298         }
299         return ret;
300     }
301 
302 
303     /**
304      * Add a new Class reference to the ConstantPool, if it is not already in there.
305      *
306      * @param str Class to add
307      * @return index of entry
308      */
309     public int addClass( final String str ) {
310         return addClass_(str.replace('.', '/'));
311     }
312 
313 
314     /**
315      * Add a new Class reference to the ConstantPool for a given type.
316      *
317      * @param type Class to add
318      * @return index of entry
319      */
320     public int addClass( final ObjectType type ) {
321         return addClass(type.getClassName());
322     }
323 
324 
325     /**
326      * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY
327      * instruction, e.g. to the ConstantPool.
328      *
329      * @param type type of array class
330      * @return index of entry
331      */
332     public int addArrayClass( final ArrayType type ) {
333         return addClass_(type.getSignature());
334     }
335 
336 
337     /**
338      * Look for ConstantInteger in ConstantPool.
339      *
340      * @param n integer number to look for
341      * @return index on success, -1 otherwise
342      */
343     public int lookupInteger( final int n ) {
344         for (int i = 1; i < index; i++) {
345             if (constants[i] instanceof ConstantInteger) {
346                 final ConstantInteger./../../org/apache/bcel/classfile/ConstantInteger.html#ConstantInteger">ConstantInteger c = (ConstantInteger) constants[i];
347                 if (c.getBytes() == n) {
348                     return i;
349                 }
350             }
351         }
352         return -1;
353     }
354 
355 
356     /**
357      * Add a new Integer constant to the ConstantPool, if it is not already in there.
358      *
359      * @param n integer number to add
360      * @return index of entry
361      */
362     public int addInteger( final int n ) {
363         int ret;
364         if ((ret = lookupInteger(n)) != -1) {
365             return ret; // Already in CP
366         }
367         adjustSize();
368         ret = index;
369         constants[index++] = new ConstantInteger(n);
370         return ret;
371     }
372 
373 
374     /**
375      * Look for ConstantFloat in ConstantPool.
376      *
377      * @param n Float number to look for
378      * @return index on success, -1 otherwise
379      */
380     public int lookupFloat( final float n ) {
381         final int bits = Float.floatToIntBits(n);
382         for (int i = 1; i < index; i++) {
383             if (constants[i] instanceof ConstantFloat) {
384                 final ConstantFloat/../../../org/apache/bcel/classfile/ConstantFloat.html#ConstantFloat">ConstantFloat c = (ConstantFloat) constants[i];
385                 if (Float.floatToIntBits(c.getBytes()) == bits) {
386                     return i;
387                 }
388             }
389         }
390         return -1;
391     }
392 
393 
394     /**
395      * Add a new Float constant to the ConstantPool, if it is not already in there.
396      *
397      * @param n Float number to add
398      * @return index of entry
399      */
400     public int addFloat( final float n ) {
401         int ret;
402         if ((ret = lookupFloat(n)) != -1) {
403             return ret; // Already in CP
404         }
405         adjustSize();
406         ret = index;
407         constants[index++] = new ConstantFloat(n);
408         return ret;
409     }
410 
411     private final Map<String, Index> utf8Table = new HashMap<>();
412 
413 
414     /**
415      * Look for ConstantUtf8 in ConstantPool.
416      *
417      * @param n Utf8 string to look for
418      * @return index on success, -1 otherwise
419      */
420     public int lookupUtf8( final String n ) {
421         final Index index = utf8Table.get(n);
422         return (index != null) ? index.index : -1;
423     }
424 
425 
426     /**
427      * Add a new Utf8 constant to the ConstantPool, if it is not already in there.
428      *
429      * @param n Utf8 string to add
430      * @return index of entry
431      */
432     public int addUtf8( final String n ) {
433         int ret;
434         if ((ret = lookupUtf8(n)) != -1) {
435             return ret; // Already in CP
436         }
437         adjustSize();
438         ret = index;
439         constants[index++] = new ConstantUtf8(n);
440         if (!utf8Table.containsKey(n)) {
441             utf8Table.put(n, new Index(ret));
442         }
443         return ret;
444     }
445 
446 
447     /**
448      * Look for ConstantLong in ConstantPool.
449      *
450      * @param n Long number to look for
451      * @return index on success, -1 otherwise
452      */
453     public int lookupLong( final long n ) {
454         for (int i = 1; i < index; i++) {
455             if (constants[i] instanceof ConstantLong) {
456                 final ConstantLong./../../../org/apache/bcel/classfile/ConstantLong.html#ConstantLong">ConstantLong c = (ConstantLong) constants[i];
457                 if (c.getBytes() == n) {
458                     return i;
459                 }
460             }
461         }
462         return -1;
463     }
464 
465 
466     /**
467      * Add a new long constant to the ConstantPool, if it is not already in there.
468      *
469      * @param n Long number to add
470      * @return index of entry
471      */
472     public int addLong( final long n ) {
473         int ret;
474         if ((ret = lookupLong(n)) != -1) {
475             return ret; // Already in CP
476         }
477         adjustSize();
478         ret = index;
479         constants[index] = new ConstantLong(n);
480         index += 2; // Wastes one entry according to spec
481         return ret;
482     }
483 
484 
485     /**
486      * Look for ConstantDouble in ConstantPool.
487      *
488      * @param n Double number to look for
489      * @return index on success, -1 otherwise
490      */
491     public int lookupDouble( final double n ) {
492         final long bits = Double.doubleToLongBits(n);
493         for (int i = 1; i < index; i++) {
494             if (constants[i] instanceof ConstantDouble) {
495                 final ConstantDouble../../../org/apache/bcel/classfile/ConstantDouble.html#ConstantDouble">ConstantDouble c = (ConstantDouble) constants[i];
496                 if (Double.doubleToLongBits(c.getBytes()) == bits) {
497                     return i;
498                 }
499             }
500         }
501         return -1;
502     }
503 
504 
505     /**
506      * Add a new double constant to the ConstantPool, if it is not already in there.
507      *
508      * @param n Double number to add
509      * @return index of entry
510      */
511     public int addDouble( final double n ) {
512         int ret;
513         if ((ret = lookupDouble(n)) != -1) {
514             return ret; // Already in CP
515         }
516         adjustSize();
517         ret = index;
518         constants[index] = new ConstantDouble(n);
519         index += 2; // Wastes one entry according to spec
520         return ret;
521     }
522 
523     private final Map<String, Index> natTable = new HashMap<>();
524 
525 
526     /**
527      * Look for ConstantNameAndType in ConstantPool.
528      *
529      * @param name of variable/method
530      * @param signature of variable/method
531      * @return index on success, -1 otherwise
532      */
533     public int lookupNameAndType( final String name, final String signature ) {
534         final Index _index = natTable.get(name + NAT_DELIM + signature);
535         return (_index != null) ? _index.index : -1;
536     }
537 
538 
539     /**
540      * Add a new NameAndType constant to the ConstantPool if it is not already
541      * in there.
542      *
543      * @param name Name string to add
544      * @param signature signature string to add
545      * @return index of entry
546      */
547     public int addNameAndType( final String name, final String signature ) {
548         int ret;
549         int name_index;
550         int signature_index;
551         if ((ret = lookupNameAndType(name, signature)) != -1) {
552             return ret; // Already in CP
553         }
554         adjustSize();
555         name_index = addUtf8(name);
556         signature_index = addUtf8(signature);
557         ret = index;
558         constants[index++] = new ConstantNameAndType(name_index, signature_index);
559         final String key = name + NAT_DELIM + signature;
560         if (!natTable.containsKey(key)) {
561             natTable.put(key, new Index(ret));
562         }
563         return ret;
564     }
565 
566     private final Map<String, Index> cpTable = new HashMap<>();
567 
568 
569     /**
570      * Look for ConstantMethodref in ConstantPool.
571      *
572      * @param class_name Where to find method
573      * @param method_name Guess what
574      * @param signature return and argument types
575      * @return index on success, -1 otherwise
576      */
577     public int lookupMethodref( final String class_name, final String method_name, final String signature ) {
578         final Index index = cpTable.get(class_name + METHODREF_DELIM + method_name
579                 + METHODREF_DELIM + signature);
580         return (index != null) ? index.index : -1;
581     }
582 
583 
584     public int lookupMethodref( final MethodGen method ) {
585         return lookupMethodref(method.getClassName(), method.getName(), method.getSignature());
586     }
587 
588 
589     /**
590      * Add a new Methodref constant to the ConstantPool, if it is not already
591      * in there.
592      *
593      * @param class_name class name string to add
594      * @param method_name method name string to add
595      * @param signature method signature string to add
596      * @return index of entry
597      */
598     public int addMethodref( final String class_name, final String method_name, final String signature ) {
599         int ret;
600         int class_index;
601         int name_and_type_index;
602         if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) {
603             return ret; // Already in CP
604         }
605         adjustSize();
606         name_and_type_index = addNameAndType(method_name, signature);
607         class_index = addClass(class_name);
608         ret = index;
609         constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
610         final String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature;
611         if (!cpTable.containsKey(key)) {
612             cpTable.put(key, new Index(ret));
613         }
614         return ret;
615     }
616 
617 
618     public int addMethodref( final MethodGen method ) {
619         return addMethodref(method.getClassName(), method.getName(), method.getSignature());
620     }
621 
622 
623     /**
624      * Look for ConstantInterfaceMethodref in ConstantPool.
625      *
626      * @param class_name Where to find method
627      * @param method_name Guess what
628      * @param signature return and argument types
629      * @return index on success, -1 otherwise
630      */
631     public int lookupInterfaceMethodref( final String class_name, final String method_name, final String signature ) {
632         final Index index = cpTable.get(class_name + IMETHODREF_DELIM + method_name
633                 + IMETHODREF_DELIM + signature);
634         return (index != null) ? index.index : -1;
635     }
636 
637 
638     public int lookupInterfaceMethodref( final MethodGen method ) {
639         return lookupInterfaceMethodref(method.getClassName(), method.getName(), method
640                 .getSignature());
641     }
642 
643 
644     /**
645      * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already
646      * in there.
647      *
648      * @param class_name class name string to add
649      * @param method_name method name string to add
650      * @param signature signature string to add
651      * @return index of entry
652      */
653     public int addInterfaceMethodref( final String class_name, final String method_name, final String signature ) {
654         int ret;
655         int class_index;
656         int name_and_type_index;
657         if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) {
658             return ret; // Already in CP
659         }
660         adjustSize();
661         class_index = addClass(class_name);
662         name_and_type_index = addNameAndType(method_name, signature);
663         ret = index;
664         constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
665         final String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature;
666         if (!cpTable.containsKey(key)) {
667             cpTable.put(key, new Index(ret));
668         }
669         return ret;
670     }
671 
672 
673     public int addInterfaceMethodref( final MethodGen method ) {
674         return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature());
675     }
676 
677 
678     /**
679      * Look for ConstantFieldref in ConstantPool.
680      *
681      * @param class_name Where to find method
682      * @param field_name Guess what
683      * @param signature return and argument types
684      * @return index on success, -1 otherwise
685      */
686     public int lookupFieldref( final String class_name, final String field_name, final String signature ) {
687         final Index index = cpTable.get(class_name + FIELDREF_DELIM + field_name
688                 + FIELDREF_DELIM + signature);
689         return (index != null) ? index.index : -1;
690     }
691 
692 
693     /**
694      * Add a new Fieldref constant to the ConstantPool, if it is not already
695      * in there.
696      *
697      * @param class_name class name string to add
698      * @param field_name field name string to add
699      * @param signature signature string to add
700      * @return index of entry
701      */
702     public int addFieldref( final String class_name, final String field_name, final String signature ) {
703         int ret;
704         int class_index;
705         int name_and_type_index;
706         if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) {
707             return ret; // Already in CP
708         }
709         adjustSize();
710         class_index = addClass(class_name);
711         name_and_type_index = addNameAndType(field_name, signature);
712         ret = index;
713         constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
714         final String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature;
715         if (!cpTable.containsKey(key)) {
716             cpTable.put(key, new Index(ret));
717         }
718         return ret;
719     }
720 
721 
722     /**
723      * @param i index in constant pool
724      * @return constant pool entry at index i
725      */
726     public Constant getConstant( final int i ) {
727         return constants[i];
728     }
729 
730 
731     /**
732      * Use with care!
733      *
734      * @param i index in constant pool
735      * @param c new constant pool entry at index i
736      */
737     public void setConstant( final int i, final Constant c ) {
738         constants[i] = c;
739     }
740 
741 
742     /**
743      * @return intermediate constant pool
744      */
745     public ConstantPool getConstantPool() {
746         return new ConstantPool(constants);
747     }
748 
749 
750     /**
751      * @return current size of constant pool
752      */
753     public int getSize() {
754         return index;
755     }
756 
757 
758     /**
759      * @return constant pool with proper length
760      */
761     public ConstantPool getFinalConstantPool() {
762         final Constantnstant.html#Constant">Constant[] cs = new Constant[index];
763         System.arraycopy(constants, 0, cs, 0, index);
764         return new ConstantPool(cs);
765     }
766 
767 
768     /**
769      * @return String representation.
770      */
771     @Override
772     public String toString() {
773         final StringBuilder buf = new StringBuilder();
774         for (int i = 1; i < index; i++) {
775             buf.append(i).append(")").append(constants[i]).append("\n");
776         }
777         return buf.toString();
778     }
779 
780 
781     /** Import constant from another ConstantPool and return new index.
782      */
783     public int addConstant( final Constant c, final ConstantPoolGen cp ) {
784         final Constant[] constants = cp.getConstantPool().getConstantPool();
785         switch (c.getTag()) {
786             case Const.CONSTANT_String: {
787                 final ConstantString../../../org/apache/bcel/classfile/ConstantString.html#ConstantString">ConstantString s = (ConstantString) c;
788                 final ConstantUtf8/../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
789                 return addString(u8.getBytes());
790             }
791             case Const.CONSTANT_Class: {
792                 final ConstantClass/../../../org/apache/bcel/classfile/ConstantClass.html#ConstantClass">ConstantClass s = (ConstantClass) c;
793                 final ConstantUtf8/../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
794                 return addClass(u8.getBytes());
795             }
796             case Const.CONSTANT_NameAndType: {
797                 final ConstantNameAndType/../org/apache/bcel/classfile/ConstantNameAndType.html#ConstantNameAndType">ConstantNameAndType n = (ConstantNameAndType) c;
798                 final ConstantUtf8/../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
799                 final ConstantUtf8./../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
800                 return addNameAndType(u8.getBytes(), u8_2.getBytes());
801             }
802             case Const.CONSTANT_Utf8:
803                 return addUtf8(((ConstantUtf8) c).getBytes());
804             case Const.CONSTANT_Double:
805                 return addDouble(((ConstantDouble) c).getBytes());
806             case Const.CONSTANT_Float:
807                 return addFloat(((ConstantFloat) c).getBytes());
808             case Const.CONSTANT_Long:
809                 return addLong(((ConstantLong) c).getBytes());
810             case Const.CONSTANT_Integer:
811                 return addInteger(((ConstantInteger) c).getBytes());
812             case Const.CONSTANT_InterfaceMethodref:
813             case Const.CONSTANT_Methodref:
814             case Const.CONSTANT_Fieldref: {
815                 final ConstantCP"../../../../org/apache/bcel/classfile/ConstantCP.html#ConstantCP">ConstantCP m = (ConstantCP) c;
816                 final ConstantClass../../org/apache/bcel/classfile/ConstantClass.html#ConstantClass">ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
817                 final ConstantNameAndType/../org/apache/bcel/classfile/ConstantNameAndType.html#ConstantNameAndType">ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
818                 ConstantUtf8/../../../org/apache/bcel/classfile/ConstantUtf8.html#ConstantUtf8">ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
819                 final String class_name = u8.getBytes().replace('/', '.');
820                 u8 = (ConstantUtf8) constants[n.getNameIndex()];
821                 final String name = u8.getBytes();
822                 u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
823                 final String signature = u8.getBytes();
824                 switch (c.getTag()) {
825                     case Const.CONSTANT_InterfaceMethodref:
826                         return addInterfaceMethodref(class_name, name, signature);
827                     case Const.CONSTANT_Methodref:
828                         return addMethodref(class_name, name, signature);
829                     case Const.CONSTANT_Fieldref:
830                         return addFieldref(class_name, name, signature);
831                     default: // Never reached
832                         throw new IllegalArgumentException("Unknown constant type " + c);
833                 }
834             }
835             default: // Never reached
836                 throw new IllegalArgumentException("Unknown constant type " + c);
837         }
838     }
839 }