• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2009 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.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      */
AttributeAdder(ProgramClass targetClass, boolean replaceAttributes)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      */
AttributeAdder(ProgramClass targetClass, ProgramMember targetMember, boolean replaceAttributes)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      */
AttributeAdder(ProgramClass targetClass, ProgramMember targetMember, CodeAttribute targetCodeAttribute, boolean replaceAttributes)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 
visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)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 
visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)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 
visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)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 
visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)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 
visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)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 
visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)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 
visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)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 
visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)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 
visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)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 
visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)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 
visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)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 
visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)296     public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
297     {
298         // TODO: Implement method.
299     }
300 
301 
visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)302     public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
303     {
304         // TODO: Implement method.
305     }
306 
307 
visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)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 
visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)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 
visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)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 
visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)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 
visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)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 
visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)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 
visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)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 
visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)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