Home | History | Annotate | Download | only in editor
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2009 Eric Lafortune (eric (at) 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.attribute.*;
     25 import proguard.classfile.attribute.annotation.*;
     26 import proguard.classfile.attribute.preverification.*;
     27 import proguard.classfile.attribute.visitor.AttributeVisitor;
     28 import proguard.classfile.util.SimplifiedVisitor;
     29 
     30 /**
     31  * This AttributeVisitor adds all attributes that it visits to the given
     32  * target class, class member, or attribute.
     33  *
     34  * @author Eric Lafortune
     35  */
     36 public class AttributeAdder
     37 extends      SimplifiedVisitor
     38 implements   AttributeVisitor
     39 {
     40     private static final byte[]          EMPTY_BYTES       = new byte[0];
     41     private static final int[]           EMPTY_INTS        = new int[0];
     42     private static final Attribute[]     EMPTY_ATTRIBUTES  = new Attribute[0];
     43     private static final ExceptionInfo[] EMPTY_EXCEPTIONS  = new ExceptionInfo[0];
     44 
     45 
     46     private final ProgramClass  targetClass;
     47     private final ProgramMember targetMember;
     48     private final CodeAttribute targetCodeAttribute;
     49     private final boolean       replaceAttributes;
     50 
     51     private final ConstantAdder    constantAdder;
     52     private final AttributesEditor attributesEditor;
     53 
     54 
     55     /**
     56      * Creates a new AttributeAdder that will copy attributes into the given
     57      * target class.
     58      */
     59     public AttributeAdder(ProgramClass targetClass,
     60                           boolean      replaceAttributes)
     61     {
     62         this(targetClass, null, null, replaceAttributes);
     63     }
     64 
     65 
     66     /**
     67      * Creates a new AttributeAdder that will copy attributes into the given
     68      * target class member.
     69      */
     70     public AttributeAdder(ProgramClass  targetClass,
     71                           ProgramMember targetMember,
     72                           boolean       replaceAttributes)
     73     {
     74         this(targetClass, targetMember, null, replaceAttributes);
     75     }
     76 
     77 
     78     /**
     79      * Creates a new AttributeAdder that will copy attributes into the given
     80      * target attribute.
     81      */
     82     public AttributeAdder(ProgramClass  targetClass,
     83                           ProgramMember targetMember,
     84                           CodeAttribute targetCodeAttribute,
     85                           boolean       replaceAttributes)
     86     {
     87         this.targetClass         = targetClass;
     88         this.targetMember        = targetMember;
     89         this.targetCodeAttribute = targetCodeAttribute;
     90         this.replaceAttributes   = replaceAttributes;
     91 
     92         constantAdder    = new ConstantAdder(targetClass);
     93         attributesEditor = new AttributesEditor(targetClass,
     94                                                 targetMember,
     95                                                 targetCodeAttribute,
     96                                                 replaceAttributes);
     97     }
     98 
     99 
    100     // Implementations for AttributeVisitor.
    101 
    102     public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
    103     {
    104         // Create a copy of the attribute.
    105         UnknownAttribute newUnknownAttribute =
    106             new UnknownAttribute(constantAdder.addConstant(clazz, unknownAttribute.u2attributeNameIndex),
    107                                  unknownAttribute.u4attributeLength,
    108                                  unknownAttribute.info);
    109 
    110         // Add it to the target class.
    111         attributesEditor.addAttribute(newUnknownAttribute);
    112     }
    113 
    114 
    115     public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
    116     {
    117         // Create a copy of the attribute.
    118         SourceFileAttribute newSourceFileAttribute =
    119             new SourceFileAttribute(constantAdder.addConstant(clazz, sourceFileAttribute.u2attributeNameIndex),
    120                                     constantAdder.addConstant(clazz, sourceFileAttribute.u2sourceFileIndex));
    121 
    122         // Add it to the target class.
    123         attributesEditor.addAttribute(newSourceFileAttribute);
    124     }
    125 
    126 
    127     public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
    128     {
    129         // Create a copy of the attribute.
    130         SourceDirAttribute newSourceDirAttribute =
    131             new SourceDirAttribute(constantAdder.addConstant(clazz, sourceDirAttribute.u2attributeNameIndex),
    132                                    constantAdder.addConstant(clazz, sourceDirAttribute.u2sourceDirIndex));
    133 
    134         // Add it to the target class.
    135         attributesEditor.addAttribute(newSourceDirAttribute);
    136     }
    137 
    138 
    139     public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
    140     {
    141         // TODO: Implement method.
    142         // Note that the attribute may already be present.
    143 //        // Create a copy of the attribute.
    144 //        InnerClassesAttribute newInnerClassesAttribute =
    145 //            new InnerClassesAttribute(constantAdder.addConstant(clazz, innerClassesAttribute.u2attributeNameIndex),
    146 //                                      0,
    147 //                                      null);
    148 //
    149 //        // Add it to the target class.
    150 //        attributesEditor.addClassAttribute(newInnerClassesAttribute);
    151     }
    152 
    153 
    154     public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
    155     {
    156         // Create a copy of the attribute.
    157         EnclosingMethodAttribute newEnclosingMethodAttribute =
    158             new EnclosingMethodAttribute(constantAdder.addConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex),
    159                                          constantAdder.addConstant(clazz, enclosingMethodAttribute.u2classIndex),
    160                                          enclosingMethodAttribute.u2nameAndTypeIndex == 0 ? 0 :
    161                                          constantAdder.addConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex));
    162 
    163         newEnclosingMethodAttribute.referencedClass  = enclosingMethodAttribute.referencedClass;
    164         newEnclosingMethodAttribute.referencedMethod = enclosingMethodAttribute.referencedMethod;
    165 
    166         // Add it to the target class.
    167         attributesEditor.addAttribute(newEnclosingMethodAttribute);
    168     }
    169 
    170 
    171     public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
    172     {
    173         // Create a copy of the attribute.
    174         DeprecatedAttribute newDeprecatedAttribute =
    175             new DeprecatedAttribute(constantAdder.addConstant(clazz, deprecatedAttribute.u2attributeNameIndex));
    176 
    177         // Add it to the target.
    178         attributesEditor.addAttribute(newDeprecatedAttribute);
    179     }
    180 
    181 
    182     public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
    183     {
    184         // Create a copy of the attribute.
    185         SyntheticAttribute newSyntheticAttribute =
    186             new SyntheticAttribute(constantAdder.addConstant(clazz, syntheticAttribute.u2attributeNameIndex));
    187 
    188         // Add it to the target.
    189         attributesEditor.addAttribute(newSyntheticAttribute);
    190     }
    191 
    192 
    193     public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
    194     {
    195         // Create a copy of the attribute.
    196         SignatureAttribute newSignatureAttribute =
    197             new SignatureAttribute(constantAdder.addConstant(clazz, signatureAttribute.u2attributeNameIndex),
    198                                    constantAdder.addConstant(clazz, signatureAttribute.u2signatureIndex));
    199 
    200         newSignatureAttribute.referencedClasses = signatureAttribute.referencedClasses;
    201 
    202         // Add it to the target.
    203         attributesEditor.addAttribute(newSignatureAttribute);
    204     }
    205 
    206 
    207     public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
    208     {
    209         // Create a copy of the attribute.
    210         ConstantValueAttribute newConstantValueAttribute =
    211             new ConstantValueAttribute(constantAdder.addConstant(clazz, constantValueAttribute.u2attributeNameIndex),
    212                                        constantAdder.addConstant(clazz, constantValueAttribute.u2constantValueIndex));
    213 
    214         // Add it to the target field.
    215         attributesEditor.addAttribute(newConstantValueAttribute);
    216     }
    217 
    218 
    219     public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
    220     {
    221         // Create a new exceptions attribute.
    222         ExceptionsAttribute newExceptionsAttribute =
    223             new ExceptionsAttribute(constantAdder.addConstant(clazz, exceptionsAttribute.u2attributeNameIndex),
    224                                     0,
    225                                     exceptionsAttribute.u2exceptionIndexTableLength > 0 ?
    226                                         new int[exceptionsAttribute.u2exceptionIndexTableLength] :
    227                                         EMPTY_INTS);
    228 
    229         // Add the exceptions.
    230         exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz,
    231                                                    new ExceptionAdder(targetClass,
    232                                                                       newExceptionsAttribute));
    233 
    234         // Add it to the target method.
    235         attributesEditor.addAttribute(newExceptionsAttribute);
    236     }
    237 
    238 
    239     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
    240     {
    241         // Create a new code attribute.
    242         CodeAttribute newCodeAttribute =
    243             new CodeAttribute(constantAdder.addConstant(clazz, codeAttribute.u2attributeNameIndex),
    244                               codeAttribute.u2maxStack,
    245                               codeAttribute.u2maxLocals,
    246                               0,
    247                               EMPTY_BYTES,
    248                               0,
    249                               codeAttribute.u2exceptionTableLength > 0 ?
    250                                   new ExceptionInfo[codeAttribute.u2exceptionTableLength] :
    251                                   EMPTY_EXCEPTIONS,
    252                               0,
    253                               codeAttribute.u2attributesCount > 0 ?
    254                                   new Attribute[codeAttribute.u2attributesCount] :
    255                                   EMPTY_ATTRIBUTES);
    256 
    257         CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
    258 
    259         codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
    260 
    261         // Add the instructions.
    262         codeAttribute.instructionsAccept(clazz,
    263                                          method,
    264                                          new InstructionAdder(targetClass,
    265                                                               codeAttributeComposer));
    266 
    267         // Append a label just after the code.
    268         codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
    269 
    270         // Add the exceptions.
    271         codeAttribute.exceptionsAccept(clazz,
    272                                        method,
    273                                        new ExceptionInfoAdder(targetClass,
    274                                                               codeAttributeComposer));
    275 
    276         codeAttributeComposer.endCodeFragment();
    277 
    278         // Add the attributes.
    279         codeAttribute.attributesAccept(clazz,
    280                                        method,
    281                                        new AttributeAdder(targetClass,
    282                                                           targetMember,
    283                                                           newCodeAttribute,
    284                                                           replaceAttributes));
    285 
    286         // Apply these changes to the new code attribute.
    287         codeAttributeComposer.visitCodeAttribute(targetClass,
    288                                                  (Method)targetMember,
    289                                                  newCodeAttribute);
    290 
    291         // Add the completed code attribute to the target method.
    292         attributesEditor.addAttribute(newCodeAttribute);
    293     }
    294 
    295 
    296     public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
    297     {
    298         // TODO: Implement method.
    299     }
    300 
    301 
    302     public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
    303     {
    304         // TODO: Implement method.
    305     }
    306 
    307 
    308     public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
    309     {
    310         // Create a new line number table attribute.
    311         LineNumberTableAttribute newLineNumberTableAttribute =
    312             new LineNumberTableAttribute(constantAdder.addConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex),
    313                                          0,
    314                                          new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]);
    315 
    316         // Add the line numbers.
    317         lineNumberTableAttribute.lineNumbersAccept(clazz,
    318                                                    method,
    319                                                    codeAttribute,
    320                                                    new LineNumberInfoAdder(newLineNumberTableAttribute));
    321 
    322         // Add it to the target.
    323         attributesEditor.addAttribute(newLineNumberTableAttribute);
    324     }
    325 
    326 
    327     public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
    328     {
    329         // Create a new local variable table attribute.
    330         LocalVariableTableAttribute newLocalVariableTableAttribute =
    331             new LocalVariableTableAttribute(constantAdder.addConstant(clazz, localVariableTableAttribute.u2attributeNameIndex),
    332                                             0,
    333                                             new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]);
    334 
    335         // Add the local variables.
    336         localVariableTableAttribute.localVariablesAccept(clazz,
    337                                                          method,
    338                                                          codeAttribute,
    339                                                          new LocalVariableInfoAdder(targetClass, newLocalVariableTableAttribute));
    340 
    341         // Add it to the target.
    342         attributesEditor.addAttribute(newLocalVariableTableAttribute);
    343     }
    344 
    345 
    346     public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
    347     {
    348         // Create a new local variable type table attribute.
    349         LocalVariableTypeTableAttribute newLocalVariableTypeTableAttribute =
    350             new LocalVariableTypeTableAttribute(constantAdder.addConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex),
    351                                             0,
    352                                             new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]);
    353 
    354         // Add the local variable types.
    355         localVariableTypeTableAttribute.localVariablesAccept(clazz,
    356                                                              method,
    357                                                              codeAttribute,
    358                                                              new LocalVariableTypeInfoAdder(targetClass, newLocalVariableTypeTableAttribute));
    359 
    360         // Add it to the target.
    361         attributesEditor.addAttribute(newLocalVariableTypeTableAttribute);
    362     }
    363 
    364 
    365     public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
    366     {
    367         // Create a new annotations attribute.
    368         RuntimeVisibleAnnotationsAttribute newAnnotationsAttribute =
    369             new RuntimeVisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleAnnotationsAttribute.u2attributeNameIndex),
    370                                                    0,
    371                                                    new Annotation[runtimeVisibleAnnotationsAttribute.u2annotationsCount]);
    372 
    373         // Add the annotations.
    374         runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz,
    375                                                              new AnnotationAdder(targetClass,
    376                                                                                  newAnnotationsAttribute));
    377 
    378         // Add it to the target.
    379         attributesEditor.addAttribute(newAnnotationsAttribute);
    380     }
    381 
    382 
    383     public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
    384     {
    385         // Create a new annotations attribute.
    386         RuntimeInvisibleAnnotationsAttribute newAnnotationsAttribute =
    387             new RuntimeInvisibleAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleAnnotationsAttribute.u2attributeNameIndex),
    388                                                      0,
    389                                                      new Annotation[runtimeInvisibleAnnotationsAttribute.u2annotationsCount]);
    390 
    391         // Add the annotations.
    392         runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz,
    393                                                                new AnnotationAdder(targetClass,
    394                                                                                    newAnnotationsAttribute));
    395 
    396         // Add it to the target.
    397         attributesEditor.addAttribute(newAnnotationsAttribute);
    398     }
    399 
    400 
    401     public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
    402     {
    403         // Create a new annotations attribute.
    404         RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute =
    405             new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex),
    406                                                             0,
    407                                                             new int[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount],
    408                                                             new Annotation[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount][]);
    409 
    410         // Add the annotations.
    411         runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz,
    412                                                                       method,
    413                                                                       new AnnotationAdder(targetClass,
    414                                                                                           newParameterAnnotationsAttribute));
    415 
    416         // Add it to the target.
    417         attributesEditor.addAttribute(newParameterAnnotationsAttribute);
    418     }
    419 
    420 
    421     public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
    422     {
    423         // Create a new annotations attribute.
    424         RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute =
    425             new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex),
    426                                                               0,
    427                                                               new int[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount],
    428                                                               new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount][]);
    429 
    430         // Add the annotations.
    431         runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz,
    432                                                                         method,
    433                                                                         new AnnotationAdder(targetClass,
    434                                                                                             newParameterAnnotationsAttribute));
    435 
    436         // Add it to the target.
    437         attributesEditor.addAttribute(newParameterAnnotationsAttribute);
    438     }
    439 
    440 
    441     public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
    442     {
    443         // Create a new annotation default attribute.
    444         AnnotationDefaultAttribute newAnnotationDefaultAttribute =
    445             new AnnotationDefaultAttribute(constantAdder.addConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex),
    446                                            null);
    447 
    448         // Add the annotations.
    449         annotationDefaultAttribute.defaultValueAccept(clazz,
    450                                                       new ElementValueAdder(targetClass,
    451                                                                             newAnnotationDefaultAttribute,
    452                                                                             false));
    453 
    454         // Add it to the target.
    455         attributesEditor.addAttribute(newAnnotationDefaultAttribute);
    456     }
    457 }
    458