AnnotationAdder.java revision cfead78069f3dc32998dc118ee08cab3867acea2
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2011 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.annotation.*;
25import proguard.classfile.attribute.annotation.visitor.AnnotationVisitor;
26import proguard.classfile.util.SimplifiedVisitor;
27
28/**
29 * This AnnotationVisitor adds all annotations that it visits to the given
30 * target annotation element value, target annotation attribute, or target
31 * parameter annotation attribute.
32 *
33 * @author Eric Lafortune
34 */
35public class AnnotationAdder
36extends      SimplifiedVisitor
37implements   AnnotationVisitor
38{
39    private static final ElementValue[] EMPTY_ELEMENT_VALUES = new ElementValue[0];
40
41
42    private final ProgramClass                        targetClass;
43    private final AnnotationElementValue              targetAnnotationElementValue;
44    private final AnnotationsAttributeEditor          annotationsAttributeEditor;
45    private final ParameterAnnotationsAttributeEditor parameterAnnotationsAttributeEditor;
46
47    private final ConstantAdder constantAdder;
48
49
50    /**
51     * Creates a new AnnotationAdder that will copy annotations into the given
52     * target annotation element value.
53     */
54    public AnnotationAdder(ProgramClass           targetClass,
55                           AnnotationElementValue targetAnnotationElementValue)
56    {
57        this.targetClass                         = targetClass;
58        this.targetAnnotationElementValue        = targetAnnotationElementValue;
59        this.annotationsAttributeEditor          = null;
60        this.parameterAnnotationsAttributeEditor = null;
61
62        constantAdder = new ConstantAdder(targetClass);
63    }
64
65
66    /**
67     * Creates a new AnnotationAdder that will copy annotations into the given
68     * target annotations attribute.
69     */
70    public AnnotationAdder(ProgramClass         targetClass,
71                           AnnotationsAttribute targetAnnotationsAttribute)
72    {
73        this.targetClass                         = targetClass;
74        this.targetAnnotationElementValue        = null;
75        this.annotationsAttributeEditor          = new AnnotationsAttributeEditor(targetAnnotationsAttribute);
76        this.parameterAnnotationsAttributeEditor = null;
77
78        constantAdder = new ConstantAdder(targetClass);
79    }
80
81
82    /**
83     * Creates a new AnnotationAdder that will copy annotations into the given
84     * target parameter annotations attribute.
85     */
86    public AnnotationAdder(ProgramClass                  targetClass,
87                           ParameterAnnotationsAttribute targetParameterAnnotationsAttribute)
88    {
89        this.targetClass                         = targetClass;
90        this.targetAnnotationElementValue        = null;
91        this.annotationsAttributeEditor          = null;
92        this.parameterAnnotationsAttributeEditor = new ParameterAnnotationsAttributeEditor(targetParameterAnnotationsAttribute);
93
94        constantAdder = new ConstantAdder(targetClass);
95    }
96
97
98    // Implementations for AnnotationVisitor.
99
100    public void visitAnnotation(Clazz clazz, Annotation annotation)
101    {
102        Annotation newAnnotation =
103            new Annotation(constantAdder.addConstant(clazz, annotation.u2typeIndex),
104                           0,
105                           annotation.u2elementValuesCount > 0 ?
106                               new ElementValue[annotation.u2elementValuesCount] :
107                               EMPTY_ELEMENT_VALUES);
108
109        // TODO: Clone array.
110        newAnnotation.referencedClasses = annotation.referencedClasses;
111
112        // Add the element values.
113        annotation.elementValuesAccept(clazz,
114                                       new ElementValueAdder(targetClass,
115                                                             newAnnotation,
116                                                             false));
117
118        // What's the target?
119        if (targetAnnotationElementValue != null)
120        {
121            // Simply set the completed annotation.
122            targetAnnotationElementValue.annotationValue = newAnnotation;
123        }
124        else
125        {
126            // Add the completed annotation.
127            annotationsAttributeEditor.addAnnotation(newAnnotation);
128        }
129    }
130
131
132    public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation)
133    {
134        Annotation newAnnotation =
135            new Annotation(constantAdder.addConstant(clazz, annotation.u2typeIndex),
136                           0,
137                           annotation.u2elementValuesCount > 0 ?
138                               new ElementValue[annotation.u2elementValuesCount] :
139                               EMPTY_ELEMENT_VALUES);
140
141        // TODO: Clone array.
142        newAnnotation.referencedClasses = annotation.referencedClasses;
143
144        // Add the element values.
145        annotation.elementValuesAccept(clazz,
146                                       new ElementValueAdder(targetClass,
147                                                             newAnnotation,
148                                                             false));
149
150        // Add the completed annotation.
151        parameterAnnotationsAttributeEditor.addAnnotation(parameterIndex, newAnnotation);
152    }
153}