• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard.classfile.editor;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.constant.*;
25 
26 /**
27  * This class can add constant pool entries to a given class.
28  *
29  * @author Eric Lafortune
30  */
31 public class ConstantPoolEditor
32 {
33     private static final boolean DEBUG = false;
34 
35     private ProgramClass targetClass;
36 
37 
38     /**
39      * Creates a new ConstantPoolEditor that will edit constants in the given
40      * target class.
41      */
ConstantPoolEditor(ProgramClass targetClass)42     public ConstantPoolEditor(ProgramClass targetClass)
43     {
44         this.targetClass = targetClass;
45     }
46 
47 
48     /**
49      * Finds or creates a IntegerConstant constant pool entry with the given
50      * value.
51      * @return the constant pool index of the Utf8Constant.
52      */
addIntegerConstant(int value)53     public int addIntegerConstant(int value)
54     {
55         int        constantPoolCount = targetClass.u2constantPoolCount;
56         Constant[] constantPool      = targetClass.constantPool;
57 
58         // Check if the entry already exists.
59         for (int index = 1; index < constantPoolCount; index++)
60         {
61             Constant constant = constantPool[index];
62 
63             if (constant != null &&
64                 constant.getTag() == ClassConstants.CONSTANT_Integer)
65             {
66                 IntegerConstant integerConstant = (IntegerConstant)constant;
67                 if (integerConstant.getValue() == value)
68                 {
69                     return index;
70                 }
71             }
72         }
73 
74         return addConstant(new IntegerConstant(value));
75     }
76 
77 
78     /**
79      * Finds or creates a LongConstant constant pool entry with the given value.
80      * @return the constant pool index of the LongConstant.
81      */
addLongConstant(long value)82     public int addLongConstant(long value)
83     {
84         int        constantPoolCount = targetClass.u2constantPoolCount;
85         Constant[] constantPool      = targetClass.constantPool;
86 
87         // Check if the entry already exists.
88         for (int index = 1; index < constantPoolCount; index++)
89         {
90             Constant constant = constantPool[index];
91 
92             if (constant != null &&
93                 constant.getTag() == ClassConstants.CONSTANT_Long)
94             {
95                 LongConstant longConstant = (LongConstant)constant;
96                 if (longConstant.getValue() == value)
97                 {
98                     return index;
99                 }
100             }
101         }
102 
103         return addConstant(new LongConstant(value));
104     }
105 
106 
107     /**
108      * Finds or creates a FloatConstant constant pool entry with the given
109      * value.
110      * @return the constant pool index of the FloatConstant.
111      */
addFloatConstant(float value)112     public int addFloatConstant(float value)
113     {
114         int        constantPoolCount = targetClass.u2constantPoolCount;
115         Constant[] constantPool      = targetClass.constantPool;
116 
117         // Check if the entry already exists.
118         for (int index = 1; index < constantPoolCount; index++)
119         {
120             Constant constant = constantPool[index];
121 
122             if (constant != null &&
123                 constant.getTag() == ClassConstants.CONSTANT_Float)
124             {
125                 FloatConstant floatConstant = (FloatConstant)constant;
126                 if (floatConstant.getValue() == value)
127                 {
128                     return index;
129                 }
130             }
131         }
132 
133         return addConstant(new FloatConstant(value));
134     }
135 
136 
137     /**
138      * Finds or creates a DoubleConstant constant pool entry with the given
139      * value.
140      * @return the constant pool index of the DoubleConstant.
141      */
addDoubleConstant(double value)142     public int addDoubleConstant(double value)
143     {
144         int        constantPoolCount = targetClass.u2constantPoolCount;
145         Constant[] constantPool      = targetClass.constantPool;
146 
147         // Check if the entry already exists.
148         for (int index = 1; index < constantPoolCount; index++)
149         {
150             Constant constant = constantPool[index];
151 
152             if (constant != null &&
153                 constant.getTag() == ClassConstants.CONSTANT_Double)
154             {
155                 DoubleConstant doubleConstant = (DoubleConstant)constant;
156                 if (doubleConstant.getValue() == value)
157                 {
158                     return index;
159                 }
160             }
161         }
162 
163         return addConstant(new DoubleConstant(value));
164     }
165 
166 
167     /**
168      * Finds or creates a StringConstant constant pool entry with the given
169      * value.
170      * @return the constant pool index of the StringConstant.
171      */
addStringConstant(String string, Clazz referencedClass, Member referencedMember)172     public int addStringConstant(String string,
173                                  Clazz  referencedClass,
174                                  Member referencedMember)
175     {
176         int        constantPoolCount = targetClass.u2constantPoolCount;
177         Constant[] constantPool      = targetClass.constantPool;
178 
179         // Check if the entry already exists.
180         for (int index = 1; index < constantPoolCount; index++)
181         {
182             Constant constant = constantPool[index];
183 
184             if (constant != null &&
185                 constant.getTag() == ClassConstants.CONSTANT_String)
186             {
187                 StringConstant stringConstant = (StringConstant)constant;
188                 if (stringConstant.getString(targetClass).equals(string))
189                 {
190                     return index;
191                 }
192             }
193         }
194 
195         return addConstant(new StringConstant(addUtf8Constant(string),
196                                               referencedClass,
197                                               referencedMember));
198     }
199 
200 
201     /**
202      * Finds or creates a InvokeDynamicConstant constant pool entry with the
203      * given bootstrap method constant pool entry index, method name, and
204      * descriptor.
205      * @return the constant pool index of the InvokeDynamicConstant.
206      */
addInvokeDynamicConstant(int bootstrapMethodIndex, String name, String descriptor, Clazz[] referencedClasses)207     public int addInvokeDynamicConstant(int     bootstrapMethodIndex,
208                                         String  name,
209                                         String  descriptor,
210                                         Clazz[] referencedClasses)
211     {
212         return addInvokeDynamicConstant(bootstrapMethodIndex,
213                                         addNameAndTypeConstant(name, descriptor),
214                                         referencedClasses);
215     }
216 
217 
218     /**
219      * Finds or creates a InvokeDynamicConstant constant pool entry with the given
220      * class constant pool entry index and name and type constant pool entry
221      * index.
222      * @return the constant pool index of the InvokeDynamicConstant.
223      */
addInvokeDynamicConstant(int bootstrapMethodIndex, int nameAndTypeIndex, Clazz[] referencedClasses)224     public int addInvokeDynamicConstant(int     bootstrapMethodIndex,
225                                         int     nameAndTypeIndex,
226                                         Clazz[] referencedClasses)
227     {
228         int        constantPoolCount = targetClass.u2constantPoolCount;
229         Constant[] constantPool      = targetClass.constantPool;
230 
231         // Check if the entry already exists.
232         for (int index = 1; index < constantPoolCount; index++)
233         {
234             Constant constant = constantPool[index];
235 
236             if (constant != null &&
237                 constant.getTag() == ClassConstants.CONSTANT_InvokeDynamic)
238             {
239                 InvokeDynamicConstant invokeDynamicConstant = (InvokeDynamicConstant)constant;
240                 if (invokeDynamicConstant.u2bootstrapMethodAttributeIndex == bootstrapMethodIndex &&
241                     invokeDynamicConstant.u2nameAndTypeIndex     == nameAndTypeIndex)
242                 {
243                     return index;
244                 }
245             }
246         }
247 
248         return addConstant(new InvokeDynamicConstant(bootstrapMethodIndex,
249                                                      nameAndTypeIndex,
250                                                      referencedClasses));
251     }
252 
253 
254     /**
255      * Finds or creates a MethodHandleConstant constant pool entry of the
256      * specified kind and with the given field ref, interface method ref,
257      * or method ref constant pool entry index.
258      * @return the constant pool index of the MethodHandleConstant.
259      */
addMethodHandleConstant(int referenceKind, int referenceIndex)260     public int addMethodHandleConstant(int referenceKind,
261                                        int referenceIndex)
262     {
263         int        constantPoolCount = targetClass.u2constantPoolCount;
264         Constant[] constantPool      = targetClass.constantPool;
265 
266         // Check if the entry already exists.
267         for (int index = 1; index < constantPoolCount; index++)
268         {
269             Constant constant = constantPool[index];
270 
271             if (constant != null &&
272                 constant.getTag() == ClassConstants.CONSTANT_MethodHandle)
273             {
274                 MethodHandleConstant methodHandleConstant = (MethodHandleConstant)constant;
275                 if (methodHandleConstant.u1referenceKind  == referenceKind &&
276                     methodHandleConstant.u2referenceIndex == referenceIndex)
277                 {
278                     return index;
279                 }
280             }
281         }
282 
283         return addConstant(new MethodHandleConstant(referenceKind,
284                                                     referenceIndex));
285     }
286 
287 
288     /**
289      * Finds or creates a FieldrefConstant constant pool entry for the given
290      * class and field.
291      * @return the constant pool index of the FieldrefConstant.
292      */
addFieldrefConstant(Clazz referencedClass, Member referencedMember)293     public int addFieldrefConstant(Clazz  referencedClass,
294                                    Member referencedMember)
295     {
296         return addFieldrefConstant(referencedClass.getName(),
297                                    referencedMember.getName(referencedClass),
298                                    referencedMember.getDescriptor(referencedClass),
299                                    referencedClass,
300                                    referencedMember);
301     }
302 
303 
304     /**
305      * Finds or creates a FieldrefConstant constant pool entry with the given
306      * class name, field name, and descriptor.
307      * @return the constant pool index of the FieldrefConstant.
308      */
addFieldrefConstant(String className, String name, String descriptor, Clazz referencedClass, Member referencedMember)309     public int addFieldrefConstant(String className,
310                                    String name,
311                                    String descriptor,
312                                    Clazz  referencedClass,
313                                    Member referencedMember)
314     {
315         return addFieldrefConstant(className,
316                                    addNameAndTypeConstant(name, descriptor),
317                                    referencedClass,
318                                    referencedMember);
319     }
320 
321 
322     /**
323      * Finds or creates a FieldrefConstant constant pool entry with the given
324      * class name, field name, and descriptor.
325      * @return the constant pool index of the FieldrefConstant.
326      */
addFieldrefConstant(String className, int nameAndTypeIndex, Clazz referencedClass, Member referencedMember)327     public int addFieldrefConstant(String className,
328                                    int    nameAndTypeIndex,
329                                    Clazz  referencedClass,
330                                    Member referencedMember)
331     {
332         return addFieldrefConstant(addClassConstant(className, referencedClass),
333                                    nameAndTypeIndex,
334                                    referencedClass,
335                                    referencedMember);
336     }
337 
338 
339     /**
340      * Finds or creates a FieldrefConstant constant pool entry with the given
341      * class constant pool entry index, field name, and descriptor.
342      * @return the constant pool index of the FieldrefConstant.
343      */
addFieldrefConstant(int classIndex, String name, String descriptor, Clazz referencedClass, Member referencedMember)344     public int addFieldrefConstant(int    classIndex,
345                                    String name,
346                                    String descriptor,
347                                    Clazz  referencedClass,
348                                    Member referencedMember)
349     {
350         return addFieldrefConstant(classIndex,
351                                    addNameAndTypeConstant(name, descriptor),
352                                    referencedClass,
353                                    referencedMember);
354     }
355 
356 
357     /**
358      * Finds or creates a FieldrefConstant constant pool entry with the given
359      * class constant pool entry index and name and type constant pool entry
360      * index.
361      * @return the constant pool index of the FieldrefConstant.
362      */
addFieldrefConstant(int classIndex, int nameAndTypeIndex, Clazz referencedClass, Member referencedMember)363     public int addFieldrefConstant(int    classIndex,
364                                    int    nameAndTypeIndex,
365                                    Clazz  referencedClass,
366                                    Member referencedMember)
367     {
368         int        constantPoolCount = targetClass.u2constantPoolCount;
369         Constant[] constantPool      = targetClass.constantPool;
370 
371         // Check if the entry already exists.
372         for (int index = 1; index < constantPoolCount; index++)
373         {
374             Constant constant = constantPool[index];
375 
376             if (constant != null &&
377                 constant.getTag() == ClassConstants.CONSTANT_Fieldref)
378             {
379                 FieldrefConstant fieldrefConstant = (FieldrefConstant)constant;
380                 if (fieldrefConstant.u2classIndex         == classIndex &&
381                     fieldrefConstant.u2nameAndTypeIndex   == nameAndTypeIndex)
382                 {
383                     return index;
384                 }
385             }
386         }
387 
388         return addConstant(new FieldrefConstant(classIndex,
389                                                 nameAndTypeIndex,
390                                                 referencedClass,
391                                                 referencedMember));
392     }
393 
394 
395     /**
396      * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
397      * given class name, method name, and descriptor.
398      * @return the constant pool index of the InterfaceMethodrefConstant.
399      */
addInterfaceMethodrefConstant(String className, String name, String descriptor, Clazz referencedClass, Member referencedMember)400     public int addInterfaceMethodrefConstant(String className,
401                                              String name,
402                                              String descriptor,
403                                              Clazz  referencedClass,
404                                              Member referencedMember)
405     {
406         return addInterfaceMethodrefConstant(className,
407                                              addNameAndTypeConstant(name, descriptor),
408                                              referencedClass,
409                                              referencedMember);
410     }
411 
412 
413     /**
414      * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
415      * given class name, method name, and descriptor.
416      * @return the constant pool index of the InterfaceMethodrefConstant.
417      */
addInterfaceMethodrefConstant(String className, int nameAndTypeIndex, Clazz referencedClass, Member referencedMember)418     public int addInterfaceMethodrefConstant(String className,
419                                              int    nameAndTypeIndex,
420                                              Clazz  referencedClass,
421                                              Member referencedMember)
422     {
423         return addInterfaceMethodrefConstant(addClassConstant(className, referencedClass),
424                                              nameAndTypeIndex,
425                                              referencedClass,
426                                              referencedMember);
427     }
428 
429 
430     /**
431      * Finds or creates a InterfaceMethodrefConstant constant pool entry for the
432      * given class and method.
433      * @return the constant pool index of the InterfaceMethodrefConstant.
434      */
addInterfaceMethodrefConstant(Clazz referencedClass, Member referencedMember)435     public int addInterfaceMethodrefConstant(Clazz  referencedClass,
436                                              Member referencedMember)
437     {
438         return addInterfaceMethodrefConstant(referencedClass.getName(),
439                                              referencedMember.getName(referencedClass),
440                                              referencedMember.getDescriptor(referencedClass),
441                                              referencedClass,
442                                              referencedMember);
443     }
444 
445 
446     /**
447      * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
448      * given class constant pool entry index, method name, and descriptor.
449      * @return the constant pool index of the InterfaceMethodrefConstant.
450      */
addInterfaceMethodrefConstant(int classIndex, String name, String descriptor, Clazz referencedClass, Member referencedMember)451     public int addInterfaceMethodrefConstant(int    classIndex,
452                                              String name,
453                                              String descriptor,
454                                              Clazz  referencedClass,
455                                              Member referencedMember)
456     {
457         return addInterfaceMethodrefConstant(classIndex,
458                                              addNameAndTypeConstant(name, descriptor),
459                                              referencedClass,
460                                              referencedMember);
461     }
462 
463 
464     /**
465      * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
466      * given class constant pool entry index and name and type constant pool
467      * entry index.
468      * @return the constant pool index of the InterfaceMethodrefConstant.
469      */
addInterfaceMethodrefConstant(int classIndex, int nameAndTypeIndex, Clazz referencedClass, Member referencedMember)470     public int addInterfaceMethodrefConstant(int    classIndex,
471                                              int    nameAndTypeIndex,
472                                              Clazz  referencedClass,
473                                              Member referencedMember)
474     {
475         int        constantPoolCount = targetClass.u2constantPoolCount;
476         Constant[] constantPool      = targetClass.constantPool;
477 
478         // Check if the entry already exists.
479         for (int index = 1; index < constantPoolCount; index++)
480         {
481             Constant constant = constantPool[index];
482 
483             if (constant != null &&
484                             constant.getTag() == ClassConstants.CONSTANT_InterfaceMethodref)
485             {
486                 InterfaceMethodrefConstant methodrefConstant = (InterfaceMethodrefConstant)constant;
487                 if (methodrefConstant.u2classIndex       == classIndex &&
488                     methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
489                 {
490                     return index;
491                 }
492             }
493         }
494 
495         return addConstant(new InterfaceMethodrefConstant(classIndex,
496                                                           nameAndTypeIndex,
497                                                           referencedClass,
498                                                           referencedMember));
499     }
500 
501 
502     /**
503      * Finds or creates a MethodrefConstant constant pool entry for the given
504      * class and method.
505      * @return the constant pool index of the MethodrefConstant.
506      */
addMethodrefConstant(Clazz referencedClass, Member referencedMember)507     public int addMethodrefConstant(Clazz  referencedClass,
508                                     Member referencedMember)
509     {
510         return addMethodrefConstant(referencedClass.getName(),
511                                     referencedMember.getName(referencedClass),
512                                     referencedMember.getDescriptor(referencedClass),
513                                     referencedClass,
514                                     referencedMember);
515     }
516 
517 
518     /**
519      * Finds or creates a MethodrefConstant constant pool entry with the given
520      * class name, method name, and descriptor.
521      * @return the constant pool index of the MethodrefConstant.
522      */
addMethodrefConstant(String className, String name, String descriptor, Clazz referencedClass, Member referencedMember)523     public int addMethodrefConstant(String className,
524                                     String name,
525                                     String descriptor,
526                                     Clazz  referencedClass,
527                                     Member referencedMember)
528     {
529         return addMethodrefConstant(className,
530                                     addNameAndTypeConstant(name, descriptor),
531                                     referencedClass,
532                                     referencedMember);
533     }
534 
535 
536     /**
537      * Finds or creates a MethodrefConstant constant pool entry with the given
538      * class name, method name, and descriptor.
539      * @return the constant pool index of the MethodrefConstant.
540      */
addMethodrefConstant(String className, int nameAndTypeIndex, Clazz referencedClass, Member referencedMember)541     public int addMethodrefConstant(String className,
542                                     int    nameAndTypeIndex,
543                                     Clazz  referencedClass,
544                                     Member referencedMember)
545     {
546         return addMethodrefConstant(addClassConstant(className, referencedClass),
547                                     nameAndTypeIndex,
548                                     referencedClass,
549                                     referencedMember);
550     }
551 
552 
553     /**
554      * Finds or creates a MethodrefConstant constant pool entry with the given
555      * class constant pool entry index, method name, and descriptor.
556      * @return the constant pool index of the MethodrefConstant.
557      */
addMethodrefConstant(int classIndex, String name, String descriptor, Clazz referencedClass, Member referencedMember)558     public int addMethodrefConstant(int    classIndex,
559                                     String name,
560                                     String descriptor,
561                                     Clazz  referencedClass,
562                                     Member referencedMember)
563     {
564         return addMethodrefConstant(classIndex,
565                                     addNameAndTypeConstant(name, descriptor),
566                                     referencedClass,
567                                     referencedMember);
568     }
569 
570 
571     /**
572      * Finds or creates a MethodrefConstant constant pool entry with the given
573      * class constant pool entry index and name and type constant pool entry
574      * index.
575      * @return the constant pool index of the MethodrefConstant.
576      */
addMethodrefConstant(int classIndex, int nameAndTypeIndex, Clazz referencedClass, Member referencedMember)577     public int addMethodrefConstant(int    classIndex,
578                                     int    nameAndTypeIndex,
579                                     Clazz  referencedClass,
580                                     Member referencedMember)
581     {
582         int        constantPoolCount = targetClass.u2constantPoolCount;
583         Constant[] constantPool      = targetClass.constantPool;
584 
585         // Check if the entry already exists.
586         for (int index = 1; index < constantPoolCount; index++)
587         {
588             Constant constant = constantPool[index];
589 
590             if (constant != null &&
591                 constant.getTag() == ClassConstants.CONSTANT_Methodref)
592             {
593                 MethodrefConstant methodrefConstant = (MethodrefConstant)constant;
594                 if (methodrefConstant.u2classIndex       == classIndex &&
595                     methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
596                 {
597                     return index;
598                 }
599             }
600         }
601 
602         return addConstant(new MethodrefConstant(classIndex,
603                                                  nameAndTypeIndex,
604                                                  referencedClass,
605                                                  referencedMember));
606     }
607 
608 
609     /**
610      * Finds or creates a ClassConstant constant pool entry for the given class.
611      * @return the constant pool index of the ClassConstant.
612      */
addClassConstant(Clazz referencedClass)613     public int addClassConstant(Clazz referencedClass)
614     {
615         return addClassConstant(referencedClass.getName(),
616                                 referencedClass);
617     }
618 
619 
620     /**
621      * Finds or creates a ClassConstant constant pool entry with the given name.
622      * @return the constant pool index of the ClassConstant.
623      */
addClassConstant(String name, Clazz referencedClass)624     public int addClassConstant(String name,
625                                 Clazz  referencedClass)
626     {
627         int        constantPoolCount = targetClass.u2constantPoolCount;
628         Constant[] constantPool      = targetClass.constantPool;
629 
630         // Check if the entry already exists.
631         for (int index = 1; index < constantPoolCount; index++)
632         {
633             Constant constant = constantPool[index];
634 
635             if (constant != null &&
636                 constant.getTag() == ClassConstants.CONSTANT_Class)
637             {
638                 ClassConstant classConstant = (ClassConstant)constant;
639                 if (classConstant.getName(targetClass).equals(name))
640                 {
641                     return index;
642                 }
643             }
644         }
645 
646         int nameIndex = addUtf8Constant(name);
647 
648         return addConstant(new ClassConstant(nameIndex, referencedClass));
649     }
650 
651 
652     /**
653      * Finds or creates a MethodTypeConstant constant pool entry with the given
654      * type.
655      * @return the constant pool index of the MethodTypeConstant.
656      */
addMethodTypeConstant(String type)657     public int addMethodTypeConstant(String type)
658     {
659         int        constantPoolCount = targetClass.u2constantPoolCount;
660         Constant[] constantPool      = targetClass.constantPool;
661 
662         // Check if the entry already exists.
663         for (int index = 1; index < constantPoolCount; index++)
664         {
665             Constant constant = constantPool[index];
666 
667             if (constant != null &&
668                 constant.getTag() == ClassConstants.CONSTANT_MethodType)
669             {
670                 MethodTypeConstant methodTypeConstant = (MethodTypeConstant)constant;
671                 if (methodTypeConstant.getType(targetClass).equals(type))
672                 {
673                     return index;
674                 }
675             }
676         }
677 
678         return addConstant(new MethodTypeConstant(addUtf8Constant(type)));
679     }
680 
681 
682     /**
683      * Finds or creates a NameAndTypeConstant constant pool entry with the given
684      * name and type.
685      * @return the constant pool index of the NameAndTypeConstant.
686      */
addNameAndTypeConstant(String name, String type)687     public int addNameAndTypeConstant(String name,
688                                       String type)
689     {
690         int        constantPoolCount = targetClass.u2constantPoolCount;
691         Constant[] constantPool      = targetClass.constantPool;
692 
693         // Check if the entry already exists.
694         for (int index = 1; index < constantPoolCount; index++)
695         {
696             Constant constant = constantPool[index];
697 
698             if (constant != null &&
699                 constant.getTag() == ClassConstants.CONSTANT_NameAndType)
700             {
701                 NameAndTypeConstant nameAndTypeConstant = (NameAndTypeConstant)constant;
702                 if (nameAndTypeConstant.getName(targetClass).equals(name) &&
703                     nameAndTypeConstant.getType(targetClass).equals(type))
704                 {
705                     return index;
706                 }
707             }
708         }
709 
710         return addConstant(new NameAndTypeConstant(addUtf8Constant(name),
711                                                    addUtf8Constant(type)));
712     }
713 
714 
715     /**
716      * Finds or creates a Utf8Constant constant pool entry for the given string.
717      * @return the constant pool index of the Utf8Constant.
718      */
addUtf8Constant(String string)719     public int addUtf8Constant(String string)
720     {
721         int        constantPoolCount = targetClass.u2constantPoolCount;
722         Constant[] constantPool      = targetClass.constantPool;
723 
724         // Check if the entry already exists.
725         for (int index = 1; index < constantPoolCount; index++)
726         {
727             Constant constant = constantPool[index];
728 
729             if (constant != null &&
730                 constant.getTag() == ClassConstants.CONSTANT_Utf8)
731             {
732                 Utf8Constant utf8Constant = (Utf8Constant)constant;
733                 if (utf8Constant.getString().equals(string))
734                 {
735                     return index;
736                 }
737             }
738         }
739 
740         return addConstant(new Utf8Constant(string));
741     }
742 
743 
744     /**
745      * Adds a given constant pool entry to the end of the constant pool/
746      * @return the constant pool index for the added entry.
747      */
addConstant(Constant constant)748     public int addConstant(Constant constant)
749     {
750         int        constantPoolCount = targetClass.u2constantPoolCount;
751         Constant[] constantPool      = targetClass.constantPool;
752 
753         // Make sure there is enough space for another constant pool entry.
754         if (constantPool.length < constantPoolCount+2)
755         {
756             targetClass.constantPool = new Constant[constantPoolCount+2];
757             System.arraycopy(constantPool, 0,
758                              targetClass.constantPool, 0,
759                              constantPoolCount);
760             constantPool = targetClass.constantPool;
761         }
762 
763         if (DEBUG)
764         {
765             System.out.println(targetClass.getName()+": adding ["+constant.getClass().getName()+"] at index "+targetClass.u2constantPoolCount);
766         }
767 
768         // Create a new Utf8Constant for the given string.
769         constantPool[targetClass.u2constantPoolCount++] = constant;
770 
771         // Long constants and double constants take up two entries in the
772         // constant pool.
773         int tag = constant.getTag();
774         if (tag == ClassConstants.CONSTANT_Long ||
775             tag == ClassConstants.CONSTANT_Double)
776         {
777             constantPool[targetClass.u2constantPoolCount++] = null;
778         }
779 
780         return constantPoolCount;
781     }
782 }
783