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 */
21package proguard.classfile.editor;
22
23import proguard.classfile.*;
24import proguard.classfile.attribute.*;
25import proguard.classfile.attribute.annotation.*;
26import proguard.classfile.attribute.annotation.visitor.*;
27import proguard.classfile.attribute.preverification.*;
28import proguard.classfile.attribute.preverification.visitor.*;
29import proguard.classfile.attribute.visitor.*;
30import proguard.classfile.constant.*;
31import proguard.classfile.constant.visitor.ConstantVisitor;
32import proguard.classfile.instruction.*;
33import proguard.classfile.instruction.visitor.InstructionVisitor;
34import proguard.classfile.util.SimplifiedVisitor;
35import proguard.classfile.visitor.*;
36
37/**
38 * This ClassVisitor remaps all possible references to constant pool entries
39 * of the classes that it visits, based on a given index map. It is assumed that
40 * the constant pool entries themselves have already been remapped.
41 *
42 * @author Eric Lafortune
43 */
44public class ConstantPoolRemapper
45extends      SimplifiedVisitor
46implements   ClassVisitor,
47             ConstantVisitor,
48             MemberVisitor,
49             AttributeVisitor,
50             BootstrapMethodInfoVisitor,
51             InnerClassesInfoVisitor,
52             ExceptionInfoVisitor,
53             InstructionVisitor,
54             StackMapFrameVisitor,
55             VerificationTypeVisitor,
56             ParameterInfoVisitor,
57             LocalVariableInfoVisitor,
58             LocalVariableTypeInfoVisitor,
59             AnnotationVisitor,
60             ElementValueVisitor
61{
62    private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true);
63
64    private int[] constantIndexMap;
65
66
67    /**
68     * Sets the given mapping of old constant pool entry indexes to their new
69     * indexes.
70     */
71    public void setConstantIndexMap(int[] constantIndexMap)
72    {
73        this.constantIndexMap = constantIndexMap;
74    }
75
76
77    // Implementations for ClassVisitor.
78
79    public void visitProgramClass(ProgramClass programClass)
80    {
81        // Remap the local constant pool references.
82        programClass.u2thisClass  = remapConstantIndex(programClass.u2thisClass);
83        programClass.u2superClass = remapConstantIndex(programClass.u2superClass);
84
85        remapConstantIndexArray(programClass.u2interfaces,
86                                programClass.u2interfacesCount);
87
88        // Remap the references of the contant pool entries themselves.
89        programClass.constantPoolEntriesAccept(this);
90
91        // Remap the references in all fields, methods, and attributes.
92        programClass.fieldsAccept(this);
93        programClass.methodsAccept(this);
94        programClass.attributesAccept(this);
95    }
96
97
98    public void visitLibraryClass(LibraryClass libraryClass)
99    {
100    }
101
102
103    // Implementations for ConstantVisitor.
104
105    public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
106    {
107        // Nothing to do.
108    }
109
110
111    public void visitLongConstant(Clazz clazz, LongConstant longConstant)
112    {
113        // Nothing to do.
114    }
115
116
117    public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
118    {
119        // Nothing to do.
120    }
121
122
123    public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
124    {
125        // Nothing to do.
126    }
127
128
129    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
130    {
131        stringConstant.u2stringIndex =
132            remapConstantIndex(stringConstant.u2stringIndex);
133    }
134
135
136    public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
137    {
138        // Nothing to do.
139    }
140
141
142    public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
143    {
144        invokeDynamicConstant.u2nameAndTypeIndex =
145            remapConstantIndex(invokeDynamicConstant.u2nameAndTypeIndex);
146    }
147
148
149    public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
150    {
151        methodHandleConstant.u2referenceIndex =
152            remapConstantIndex(methodHandleConstant.u2referenceIndex);
153    }
154
155
156    public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
157    {
158        fieldrefConstant.u2classIndex =
159            remapConstantIndex(fieldrefConstant.u2classIndex);
160        fieldrefConstant.u2nameAndTypeIndex =
161            remapConstantIndex(fieldrefConstant.u2nameAndTypeIndex);
162    }
163
164
165    public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
166    {
167        interfaceMethodrefConstant.u2classIndex =
168            remapConstantIndex(interfaceMethodrefConstant.u2classIndex);
169        interfaceMethodrefConstant.u2nameAndTypeIndex =
170            remapConstantIndex(interfaceMethodrefConstant.u2nameAndTypeIndex);
171    }
172
173
174    public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
175    {
176        methodrefConstant.u2classIndex =
177            remapConstantIndex(methodrefConstant.u2classIndex);
178        methodrefConstant.u2nameAndTypeIndex =
179            remapConstantIndex(methodrefConstant.u2nameAndTypeIndex);
180    }
181
182
183    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
184    {
185        classConstant.u2nameIndex =
186            remapConstantIndex(classConstant.u2nameIndex);
187    }
188
189
190    public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
191    {
192        methodTypeConstant.u2descriptorIndex =
193            remapConstantIndex(methodTypeConstant.u2descriptorIndex);
194    }
195
196
197    public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
198    {
199        nameAndTypeConstant.u2nameIndex =
200            remapConstantIndex(nameAndTypeConstant.u2nameIndex);
201        nameAndTypeConstant.u2descriptorIndex =
202            remapConstantIndex(nameAndTypeConstant.u2descriptorIndex);
203    }
204
205
206    // Implementations for MemberVisitor.
207
208    public void visitProgramField(ProgramClass programClass, ProgramField programField)
209    {
210        visitMember(programClass, programField);
211    }
212
213
214    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
215    {
216        visitMember(programClass, programMethod);
217    }
218
219
220    private void visitMember(ProgramClass programClass, ProgramMember programMember)
221    {
222        // Remap the local constant pool references.
223        programMember.u2nameIndex =
224            remapConstantIndex(programMember.u2nameIndex);
225        programMember.u2descriptorIndex =
226            remapConstantIndex(programMember.u2descriptorIndex);
227
228        // Remap the constant pool references of the remaining attributes.
229        programMember.attributesAccept(programClass, this);
230    }
231
232
233    public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
234    {
235        // Library classes are left unchanged.
236    }
237
238
239    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
240    {
241        // Library classes are left unchanged.
242    }
243
244
245    // Implementations for AttributeVisitor.
246
247    public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
248    {
249        unknownAttribute.u2attributeNameIndex =
250            remapConstantIndex(unknownAttribute.u2attributeNameIndex);
251
252        // There's not much else we can do with unknown attributes.
253    }
254
255
256    public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
257    {
258        bootstrapMethodsAttribute.u2attributeNameIndex =
259            remapConstantIndex(bootstrapMethodsAttribute.u2attributeNameIndex);
260
261        // Remap the constant pool references of the bootstrap method entries.
262        bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
263    }
264
265
266    public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
267    {
268        sourceFileAttribute.u2attributeNameIndex =
269            remapConstantIndex(sourceFileAttribute.u2attributeNameIndex);
270        sourceFileAttribute.u2sourceFileIndex =
271            remapConstantIndex(sourceFileAttribute.u2sourceFileIndex);
272    }
273
274
275    public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
276    {
277        sourceDirAttribute.u2attributeNameIndex =
278            remapConstantIndex(sourceDirAttribute.u2attributeNameIndex);
279        sourceDirAttribute.u2sourceDirIndex       =
280            remapConstantIndex(sourceDirAttribute.u2sourceDirIndex);
281    }
282
283
284    public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
285    {
286        innerClassesAttribute.u2attributeNameIndex =
287            remapConstantIndex(innerClassesAttribute.u2attributeNameIndex);
288
289        // Remap the constant pool references of the inner classes.
290        innerClassesAttribute.innerClassEntriesAccept(clazz, this);
291    }
292
293
294    public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
295    {
296        enclosingMethodAttribute.u2attributeNameIndex =
297            remapConstantIndex(enclosingMethodAttribute.u2attributeNameIndex);
298        enclosingMethodAttribute.u2classIndex =
299            remapConstantIndex(enclosingMethodAttribute.u2classIndex);
300        enclosingMethodAttribute.u2nameAndTypeIndex =
301            remapConstantIndex(enclosingMethodAttribute.u2nameAndTypeIndex);
302    }
303
304
305    public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
306    {
307        deprecatedAttribute.u2attributeNameIndex =
308            remapConstantIndex(deprecatedAttribute.u2attributeNameIndex);
309    }
310
311
312    public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
313    {
314        syntheticAttribute.u2attributeNameIndex =
315            remapConstantIndex(syntheticAttribute.u2attributeNameIndex);
316    }
317
318
319    public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
320    {
321        signatureAttribute.u2attributeNameIndex =
322            remapConstantIndex(signatureAttribute.u2attributeNameIndex);
323        signatureAttribute.u2signatureIndex       =
324            remapConstantIndex(signatureAttribute.u2signatureIndex);
325    }
326
327
328    public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
329    {
330        constantValueAttribute.u2attributeNameIndex =
331            remapConstantIndex(constantValueAttribute.u2attributeNameIndex);
332        constantValueAttribute.u2constantValueIndex =
333            remapConstantIndex(constantValueAttribute.u2constantValueIndex);
334    }
335
336
337    public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
338    {
339        methodParametersAttribute.u2attributeNameIndex =
340            remapConstantIndex(methodParametersAttribute.u2attributeNameIndex);
341
342        // Remap the constant pool references of the parameter information.
343        methodParametersAttribute.parametersAccept(clazz, method, this);
344    }
345
346
347    public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
348    {
349        exceptionsAttribute.u2attributeNameIndex =
350            remapConstantIndex(exceptionsAttribute.u2attributeNameIndex);
351
352        // Remap the constant pool references of the exceptions.
353        remapConstantIndexArray(exceptionsAttribute.u2exceptionIndexTable,
354                                exceptionsAttribute.u2exceptionIndexTableLength);
355    }
356
357
358    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
359    {
360        codeAttribute.u2attributeNameIndex =
361            remapConstantIndex(codeAttribute.u2attributeNameIndex);
362
363        // Initially, the code attribute editor doesn't contain any changes.
364        codeAttributeEditor.reset(codeAttribute.u4codeLength);
365
366        // Remap the constant pool references of the instructions.
367        codeAttribute.instructionsAccept(clazz, method, this);
368
369        // Apply the code atribute editor. It will only contain any changes if
370        // the code length is changing at any point.
371        codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
372
373        // Remap the constant pool references of the exceptions and attributes.
374        codeAttribute.exceptionsAccept(clazz, method, this);
375        codeAttribute.attributesAccept(clazz, method, this);
376    }
377
378
379    public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
380    {
381        stackMapAttribute.u2attributeNameIndex =
382            remapConstantIndex(stackMapAttribute.u2attributeNameIndex);
383
384        // Remap the constant pool references of the stack map frames.
385        stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
386    }
387
388
389    public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
390    {
391        stackMapTableAttribute.u2attributeNameIndex =
392            remapConstantIndex(stackMapTableAttribute.u2attributeNameIndex);
393
394        // Remap the constant pool references of the stack map frames.
395        stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
396    }
397
398
399    public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
400    {
401        lineNumberTableAttribute.u2attributeNameIndex =
402            remapConstantIndex(lineNumberTableAttribute.u2attributeNameIndex);
403    }
404
405
406    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
407    {
408        localVariableTableAttribute.u2attributeNameIndex =
409            remapConstantIndex(localVariableTableAttribute.u2attributeNameIndex);
410
411        // Remap the constant pool references of the local variables.
412        localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
413    }
414
415
416    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
417    {
418        localVariableTypeTableAttribute.u2attributeNameIndex =
419            remapConstantIndex(localVariableTypeTableAttribute.u2attributeNameIndex);
420
421        // Remap the constant pool references of the local variables.
422        localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
423    }
424
425
426    public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
427    {
428        annotationsAttribute.u2attributeNameIndex =
429            remapConstantIndex(annotationsAttribute.u2attributeNameIndex);
430
431        // Remap the constant pool references of the annotations.
432        annotationsAttribute.annotationsAccept(clazz, this);
433    }
434
435
436    public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
437    {
438        parameterAnnotationsAttribute.u2attributeNameIndex =
439            remapConstantIndex(parameterAnnotationsAttribute.u2attributeNameIndex);
440
441        // Remap the constant pool references of the annotations.
442        parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
443    }
444
445
446    public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
447    {
448        annotationDefaultAttribute.u2attributeNameIndex =
449            remapConstantIndex(annotationDefaultAttribute.u2attributeNameIndex);
450
451        // Remap the constant pool references of the annotations.
452        annotationDefaultAttribute.defaultValueAccept(clazz, this);
453    }
454
455
456    // Implementations for BootstrapMethodInfoVisitor.
457
458    public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
459    {
460        bootstrapMethodInfo.u2methodHandleIndex =
461            remapConstantIndex(bootstrapMethodInfo.u2methodHandleIndex);
462
463        // Remap the constant pool references of the bootstrap methods..
464        remapConstantIndexArray(bootstrapMethodInfo.u2methodArguments,
465                                bootstrapMethodInfo.u2methodArgumentCount);
466    }
467
468
469    // Implementations for InnerClassesInfoVisitor.
470
471    public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
472    {
473        if (innerClassesInfo.u2innerClassIndex != 0)
474        {
475            innerClassesInfo.u2innerClassIndex =
476                remapConstantIndex(innerClassesInfo.u2innerClassIndex);
477        }
478
479        if (innerClassesInfo.u2outerClassIndex != 0)
480        {
481            innerClassesInfo.u2outerClassIndex =
482                remapConstantIndex(innerClassesInfo.u2outerClassIndex);
483        }
484
485        if (innerClassesInfo.u2innerNameIndex != 0)
486        {
487            innerClassesInfo.u2innerNameIndex =
488                remapConstantIndex(innerClassesInfo.u2innerNameIndex);
489        }
490    }
491
492
493    // Implementations for ExceptionInfoVisitor.
494
495    public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
496    {
497        if (exceptionInfo.u2catchType != 0)
498        {
499            exceptionInfo.u2catchType =
500                remapConstantIndex(exceptionInfo.u2catchType);
501        }
502    }
503
504
505    // Implementations for InstructionVisitor.
506
507    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
508
509
510    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
511    {
512        // Is the new constant pool index different from the original one?
513        int newConstantIndex = remapConstantIndex(constantInstruction.constantIndex);
514        if (newConstantIndex != constantInstruction.constantIndex)
515        {
516            // Replace the instruction.
517            Instruction replacementInstruction =
518                new ConstantInstruction(constantInstruction.opcode,
519                                        newConstantIndex,
520                                        constantInstruction.constant);
521
522            codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
523        }
524    }
525
526
527    // Implementations for StackMapFrameVisitor.
528
529    public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
530
531
532    public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
533    {
534        // Remap the constant pool references of the verification types.
535        sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
536    }
537
538
539    public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
540    {
541        // Remap the constant pool references of the verification types.
542        moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
543    }
544
545
546    public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
547    {
548        // Remap the constant pool references of the verification types.
549        fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
550        fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
551    }
552
553
554    // Implementations for VerificationTypeVisitor.
555
556    public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
557
558
559    public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
560    {
561        objectType.u2classIndex =
562            remapConstantIndex(objectType.u2classIndex);
563    }
564
565
566    // Implementations for ParameterInfoVisitor.
567
568    public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
569    {
570        parameterInfo.u2nameIndex =
571            remapConstantIndex(parameterInfo.u2nameIndex);
572    }
573
574
575    // Implementations for LocalVariableInfoVisitor.
576
577    public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
578    {
579        localVariableInfo.u2nameIndex =
580            remapConstantIndex(localVariableInfo.u2nameIndex);
581        localVariableInfo.u2descriptorIndex =
582            remapConstantIndex(localVariableInfo.u2descriptorIndex);
583    }
584
585
586    // Implementations for LocalVariableTypeInfoVisitor.
587
588    public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
589    {
590        localVariableTypeInfo.u2nameIndex =
591            remapConstantIndex(localVariableTypeInfo.u2nameIndex);
592        localVariableTypeInfo.u2signatureIndex =
593            remapConstantIndex(localVariableTypeInfo.u2signatureIndex);
594    }
595
596
597    // Implementations for AnnotationVisitor.
598
599    public void visitAnnotation(Clazz clazz, Annotation annotation)
600    {
601        annotation.u2typeIndex =
602            remapConstantIndex(annotation.u2typeIndex);
603
604        // Remap the constant pool references of the element values.
605        annotation.elementValuesAccept(clazz, this);
606    }
607
608
609    // Implementations for ElementValueVisitor.
610
611    public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
612    {
613        constantElementValue.u2elementNameIndex =
614            remapConstantIndex(constantElementValue.u2elementNameIndex);
615        constantElementValue.u2constantValueIndex =
616            remapConstantIndex(constantElementValue.u2constantValueIndex);
617    }
618
619
620    public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
621    {
622        enumConstantElementValue.u2elementNameIndex =
623            remapConstantIndex(enumConstantElementValue.u2elementNameIndex);
624        enumConstantElementValue.u2typeNameIndex =
625            remapConstantIndex(enumConstantElementValue.u2typeNameIndex);
626        enumConstantElementValue.u2constantNameIndex =
627            remapConstantIndex(enumConstantElementValue.u2constantNameIndex);
628    }
629
630
631    public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
632    {
633        classElementValue.u2elementNameIndex =
634            remapConstantIndex(classElementValue.u2elementNameIndex);
635        classElementValue.u2classInfoIndex       =
636            remapConstantIndex(classElementValue.u2classInfoIndex);
637    }
638
639
640    public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
641    {
642        annotationElementValue.u2elementNameIndex =
643            remapConstantIndex(annotationElementValue.u2elementNameIndex);
644
645        // Remap the constant pool references of the annotation.
646        annotationElementValue.annotationAccept(clazz, this);
647    }
648
649
650    public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
651    {
652        arrayElementValue.u2elementNameIndex =
653            remapConstantIndex(arrayElementValue.u2elementNameIndex);
654
655        // Remap the constant pool references of the element values.
656        arrayElementValue.elementValuesAccept(clazz, annotation, this);
657    }
658
659
660    /**
661     * Remaps all constant pool indices in the given array.
662     */
663    private void remapConstantIndexArray(int[] array, int length)
664    {
665        for (int index = 0; index < length; index++)
666        {
667            array[index] = remapConstantIndex(array[index]);
668        }
669    }
670
671    // Small utility methods.
672
673
674    /**
675     * Returns the new constant pool index of the entry at the
676     * given index.
677     */
678    private int remapConstantIndex(int constantIndex)
679    {
680        int remappedConstantIndex = constantIndexMap[constantIndex];
681        if (remappedConstantIndex < 0)
682        {
683            throw new IllegalArgumentException("Can't remap constant index ["+constantIndex+"]");
684        }
685
686        return remappedConstantIndex;
687    }
688}
689