• 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.attribute.annotation.*;
25 import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor;
26 
27 /**
28  * This AnnotationVisitor adds all element values that it visits to the given
29  * target annotation default attribute, annotation, or element value.
30  *
31  * @author Eric Lafortune
32  */
33 public class ElementValueAdder
34 implements   ElementValueVisitor
35 {
36     private static final ElementValue[] EMPTY_ELEMENT_VALUES = new ElementValue[0];
37 
38 
39     private final ProgramClass               targetClass;
40     private final AnnotationDefaultAttribute targetAnnotationDefaultAttribute;
41 
42     private final ConstantAdder       constantAdder;
43     private final ElementValuesEditor elementValuesEditor;
44 
45 
46     /**
47      * Creates a new ElementValueAdder that will copy element values into the
48      * given target annotation default attribute value.
49      */
ElementValueAdder(ProgramClass targetClass, AnnotationDefaultAttribute targetAnnotationDefaultAttribute, boolean replaceElementValues)50     public ElementValueAdder(ProgramClass               targetClass,
51                              AnnotationDefaultAttribute targetAnnotationDefaultAttribute,
52                              boolean                    replaceElementValues)
53     {
54         this.targetClass                      = targetClass;
55         this.targetAnnotationDefaultAttribute = targetAnnotationDefaultAttribute;
56 
57         constantAdder       = new ConstantAdder(targetClass);
58         elementValuesEditor = null;
59     }
60 
61 
62     /**
63      * Creates a new ElementValueAdder that will copy element values into the
64      * given target annotation.
65      */
ElementValueAdder(ProgramClass targetClass, Annotation targetAnnotation, boolean replaceElementValues)66     public ElementValueAdder(ProgramClass targetClass,
67                              Annotation   targetAnnotation,
68                              boolean      replaceElementValues)
69     {
70         this.targetClass                      = targetClass;
71         this.targetAnnotationDefaultAttribute = null;
72 
73         constantAdder       = new ConstantAdder(targetClass);
74         elementValuesEditor = new ElementValuesEditor(targetClass,
75                                                       targetAnnotation,
76                                                       replaceElementValues);
77     }
78 
79 
80     /**
81      * Creates a new ElementValueAdder that will copy element values into the
82      * given target element value.
83      */
ElementValueAdder(ProgramClass targetClass, ArrayElementValue targetArrayElementValue, boolean replaceElementValues)84     public ElementValueAdder(ProgramClass      targetClass,
85                              ArrayElementValue targetArrayElementValue,
86                              boolean           replaceElementValues)
87     {
88         this.targetClass                      = targetClass;
89         this.targetAnnotationDefaultAttribute = null;
90 
91         constantAdder       = new ConstantAdder(targetClass);
92         elementValuesEditor = new ElementValuesEditor(targetClass,
93                                                       targetArrayElementValue,
94                                                       replaceElementValues);
95     }
96 
97 
98     // Implementations for ElementValueVisitor.
99 
visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)100     public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
101     {
102         // Create a copy of the element value.
103         ConstantElementValue newConstantElementValue =
104             new ConstantElementValue(constantElementValue.u1tag,
105                                      constantElementValue.u2elementNameIndex == 0 ? 0 :
106                                      constantAdder.addConstant(clazz, constantElementValue.u2elementNameIndex),
107                                      constantAdder.addConstant(clazz, constantElementValue.u2constantValueIndex));
108 
109         newConstantElementValue.referencedClass  = constantElementValue.referencedClass;
110         newConstantElementValue.referencedMethod = constantElementValue.referencedMethod;
111 
112         // Add it to the target.
113         addElementValue(newConstantElementValue);
114     }
115 
116 
visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)117     public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
118     {
119         // Create a copy of the element value.
120         EnumConstantElementValue newEnumConstantElementValue =
121             new EnumConstantElementValue(enumConstantElementValue.u2elementNameIndex == 0 ? 0 :
122                                          constantAdder.addConstant(clazz, enumConstantElementValue.u2elementNameIndex),
123                                          constantAdder.addConstant(clazz, enumConstantElementValue.u2typeNameIndex),
124                                          constantAdder.addConstant(clazz, enumConstantElementValue.u2constantNameIndex));
125 
126         newEnumConstantElementValue.referencedClass  = enumConstantElementValue.referencedClass;
127         newEnumConstantElementValue.referencedMethod = enumConstantElementValue.referencedMethod;
128 
129         // TODO: Clone array.
130         newEnumConstantElementValue.referencedClasses = enumConstantElementValue.referencedClasses;
131 
132         // Add it to the target.
133         addElementValue(newEnumConstantElementValue);
134     }
135 
136 
visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)137     public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
138     {
139         // Create a copy of the element value.
140         ClassElementValue newClassElementValue =
141             new ClassElementValue(classElementValue.u2elementNameIndex == 0 ? 0 :
142                                   constantAdder.addConstant(clazz, classElementValue.u2elementNameIndex),
143                                   constantAdder.addConstant(clazz, classElementValue.u2classInfoIndex));
144 
145         newClassElementValue.referencedClass  = classElementValue.referencedClass;
146         newClassElementValue.referencedMethod = classElementValue.referencedMethod;
147 
148         // TODO: Clone array.
149         newClassElementValue.referencedClasses = classElementValue.referencedClasses;
150 
151         // Add it to the target.
152         addElementValue(newClassElementValue);
153     }
154 
155 
visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)156     public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
157     {
158         // Create a copy of the element value.
159         AnnotationElementValue newAnnotationElementValue =
160             new AnnotationElementValue(annotationElementValue.u2elementNameIndex == 0 ? 0 :
161                                        constantAdder.addConstant(clazz, annotationElementValue.u2elementNameIndex),
162                                        new Annotation());
163 
164         newAnnotationElementValue.referencedClass  = annotationElementValue.referencedClass;
165         newAnnotationElementValue.referencedMethod = annotationElementValue.referencedMethod;
166 
167         annotationElementValue.annotationAccept(clazz,
168                                                 new AnnotationAdder(targetClass,
169                                                                     newAnnotationElementValue));
170 
171         // Add it to the target.
172         addElementValue(newAnnotationElementValue);
173     }
174 
175 
visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)176     public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
177     {
178         // Create a copy of the element value.
179         ArrayElementValue newArrayElementValue =
180             new ArrayElementValue(arrayElementValue.u2elementNameIndex == 0 ? 0 :
181                                   constantAdder.addConstant(clazz, arrayElementValue.u2elementNameIndex),
182                                   0,
183                                   arrayElementValue.u2elementValuesCount > 0 ?
184                                       new ElementValue[arrayElementValue.u2elementValuesCount] :
185                                       EMPTY_ELEMENT_VALUES);
186 
187         newArrayElementValue.referencedClass  = arrayElementValue.referencedClass;
188         newArrayElementValue.referencedMethod = arrayElementValue.referencedMethod;
189 
190         arrayElementValue.elementValuesAccept(clazz,
191                                               annotation,
192                                               new ElementValueAdder(targetClass,
193                                                                     newArrayElementValue,
194                                                                     false));
195 
196         // Add it to the target.
197         addElementValue(newArrayElementValue);
198     }
199 
200 
201     // Small utility methods.
202 
addElementValue(ElementValue newElementValue)203     private void addElementValue(ElementValue newElementValue)
204     {
205         // What's the target?
206         if (targetAnnotationDefaultAttribute != null)
207         {
208             // Simply set the completed element value.
209             targetAnnotationDefaultAttribute.defaultValue = newElementValue;
210         }
211         else
212         {
213             // Add it to the target.
214             elementValuesEditor.addElementValue(newElementValue);
215         }
216     }
217 }