KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > shrink > AnnotationUsageMarker


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This library 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 library 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 Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21 package proguard.shrink;
22
23 import proguard.classfile.util.SimplifiedVisitor;
24 import proguard.classfile.attribute.visitor.*;
25 import proguard.classfile.attribute.*;
26 import proguard.classfile.attribute.annotation.visitor.*;
27 import proguard.classfile.attribute.annotation.*;
28 import proguard.classfile.constant.visitor.ConstantVisitor;
29 import proguard.classfile.constant.*;
30 import proguard.classfile.visitor.*;
31 import proguard.classfile.*;
32
33 /**
34  * This AttributeVisitor recursively marks all necessary annotation information
35  * in the attributes that it visits.
36  *
37  * @see UsageMarker
38  *
39  * @author Eric Lafortune
40  */

41 public class AnnotationUsageMarker
42 extends SimplifiedVisitor
43 implements AttributeVisitor,
44              AnnotationVisitor,
45              ElementValueVisitor,
46              ConstantVisitor,
47              ClassVisitor,
48              MemberVisitor
49 {
50     private UsageMarker usageMarker;
51
52     // Fields acting as a return parameters for several methods.
53
private boolean attributeUsed;
54     private boolean annotationUsed;
55     private boolean elementValueUsed;
56     private boolean classUsed;
57     private boolean methodUsed;
58
59
60     /**
61      * Creates a new InnerUsageMarker.
62      * @param usageMarker the usage marker that is used to mark the classes
63      * and class members.
64      */

65     public AnnotationUsageMarker(UsageMarker usageMarker)
66     {
67         this.usageMarker = usageMarker;
68     }
69
70
71     // Implementations for AttributeVisitor.
72

73     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
74
75
76     public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
77     {
78         // Mark the necessary annotation information.
79
attributeUsed = false;
80         annotationsAttribute.annotationsAccept(clazz, this);
81
82         if (attributeUsed)
83         {
84             // We got a positive used flag, so some annotation is being used.
85
// Mark this attribute as being used as well.
86
usageMarker.markAsUsed(annotationsAttribute);
87
88             markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
89         }
90     }
91
92
93     public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
94     {
95         // Mark the necessary annotation information.
96
attributeUsed = false;
97         parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
98
99         if (attributeUsed)
100         {
101             // We got a positive used flag, so some annotation is being used.
102
// Mark this attribute as being used as well.
103
usageMarker.markAsUsed(parameterAnnotationsAttribute);
104
105             markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
106         }
107     }
108
109
110     public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
111     {
112         // Mark the necessary annotation information.
113
attributeUsed = false;
114         annotationDefaultAttribute.defaultValueAccept(clazz, this);
115
116         if (attributeUsed)
117         {
118             // We got a positive used flag, so some annotation is being used.
119
// Mark this attribute as being used as well.
120
usageMarker.markAsUsed(annotationDefaultAttribute);
121
122             markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
123         }
124     }
125
126
127     // Implementations for AnnotationVisitor.
128

129     public void visitAnnotation(Clazz clazz, Annotation annotation)
130     {
131         if (isReferencedClassUsed(annotation))
132         {
133             // Mark the annotation as being used.
134
usageMarker.markAsUsed(annotation);
135
136             markConstant(clazz, annotation.u2typeIndex);
137
138             // Mark the necessary element values.
139
annotation.elementValuesAccept(clazz, this);
140
141             // The return values.
142
annotationUsed = true;
143             attributeUsed = true;
144         }
145     }
146
147
148     // Implementations for ElementValueVisitor.
149

150     public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
151     {
152         if (isReferencedMethodUsed(constantElementValue))
153         {
154             // Mark the element value as being used.
155
usageMarker.markAsUsed(constantElementValue);
156
157             markConstant(clazz, constantElementValue.u2elementNameIndex);
158             markConstant(clazz, constantElementValue.u2constantValueIndex);
159
160             // The return value.
161
elementValueUsed = true;
162         }
163     }
164
165
166     public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
167     {
168         if (isReferencedMethodUsed(enumConstantElementValue))
169         {
170             // Check the referenced classes.
171
classUsed = true;
172             enumConstantElementValue.referencedClassesAccept(usageMarker);
173
174             if (classUsed)
175             {
176                 // Mark the element value as being used.
177
usageMarker.markAsUsed(enumConstantElementValue);
178
179                 markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
180                 markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
181                 markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
182
183                 // The return value.
184
elementValueUsed = true;
185             }
186         }
187     }
188
189
190     public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
191     {
192         if (isReferencedMethodUsed(classElementValue))
193         {
194             // Check the referenced classes.
195
classUsed = true;
196             classElementValue.referencedClassesAccept(usageMarker);
197
198             if (classUsed)
199             {
200                 // Mark the element value as being used.
201
usageMarker.markAsUsed(classElementValue);
202
203                 markConstant(clazz, classElementValue.u2elementNameIndex);
204                 markConstant(clazz, classElementValue.u2classInfoIndex);
205
206                 // The return value.
207
elementValueUsed = true;
208             }
209         }
210     }
211
212
213     public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
214     {
215         if (isReferencedMethodUsed(annotationElementValue))
216         {
217             boolean oldAnnotationUsed = annotationUsed;
218
219             // Check and mark the contained annotation.
220
annotationUsed = false;
221             annotationElementValue.annotationAccept(clazz, this);
222
223             if (annotationUsed)
224             {
225                 // Mark the element value as being used.
226
usageMarker.markAsUsed(annotationElementValue);
227
228                 markConstant(clazz, annotationElementValue.u2elementNameIndex);
229
230                 // The return value.
231
elementValueUsed = true;
232             }
233
234             annotationUsed = oldAnnotationUsed;
235         }
236     }
237
238
239     public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
240     {
241         if (isReferencedMethodUsed(arrayElementValue))
242         {
243             boolean oldelementValueUsed = elementValueUsed;
244
245             // Check and mark the contained element values.
246
elementValueUsed = false;
247             arrayElementValue.elementValuesAccept(clazz, annotation, this);
248
249             if (elementValueUsed)
250             {
251                 // Mark the element value as being used.
252
usageMarker.markAsUsed(arrayElementValue);
253
254                 markConstant(clazz, arrayElementValue.u2elementNameIndex);
255
256                 // The return value.
257
//elementValueUsed = true;
258
}
259             else
260             {
261                 elementValueUsed = oldelementValueUsed;
262             }
263         }
264     }
265
266
267     // Implementations for ConstantVisitor.
268

269     public void visitAnyConstant(Clazz clazz, Constant constant)
270     {
271         usageMarker.markAsUsed(constant);
272     }
273
274
275     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
276     {
277         classUsed = usageMarker.isUsed(classConstant);
278
279         // Is the class constant marked as being used?
280
if (!classUsed)
281         {
282             // Check the referenced class.
283
classUsed = true;
284             classConstant.referencedClassAccept(this);
285
286             // Is the referenced class marked as being used?
287
if (classUsed)
288             {
289                 // Mark the class constant and its Utf8 constant.
290
usageMarker.markAsUsed(classConstant);
291
292                 markConstant(clazz, classConstant.u2nameIndex);
293             }
294         }
295     }
296
297
298     // Implementations for ClassVisitor.
299

300     public void visitProgramClass(ProgramClass programClass)
301     {
302         classUsed = usageMarker.isUsed(programClass);
303     }
304
305
306     public void visitLibraryClass(LibraryClass libraryClass)
307     {
308         classUsed = true;
309     }
310
311
312     // Implementations for MemberVisitor.
313

314     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
315     {
316         methodUsed = usageMarker.isUsed(programMethod);
317     }
318
319
320     public void visitLibraryMethod(LibraryClass LibraryClass, LibraryMethod libraryMethod)
321     {
322         classUsed = true;
323     }
324
325
326     // Small utility methods.
327

328     /**
329      * Returns whether the annotation class has been marked as being used.
330      */

331     private boolean isReferencedClassUsed(Annotation annotation)
332     {
333         // Check if the referenced class is being used.
334
classUsed = true;
335         annotation.referencedClassAccept(this);
336
337         return classUsed;
338     }
339
340
341     /**
342      * Returns whether the annotation method has been marked as being used.
343      */

344     private boolean isReferencedMethodUsed(ElementValue elementValue)
345     {
346         // Check if the referenced method is being used.
347
methodUsed = true;
348         elementValue.referencedMethodAccept(this);
349
350         return methodUsed;
351     }
352
353
354     /**
355      * Marks the specified constant pool entry.
356      */

357     private void markConstant(Clazz clazz, int index)
358     {
359         if (index > 0)
360         {
361             clazz.constantPoolEntryAccept(index, this);
362         }
363     }
364 }
365
Popular Tags