KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > optimize > peephole > SingleImplementationInliner


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 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.optimize.peephole;
22
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.*;
25 import proguard.classfile.attribute.visitor.*;
26 import proguard.classfile.attribute.annotation.*;
27 import proguard.classfile.attribute.annotation.visitor.*;
28 import proguard.classfile.constant.*;
29 import proguard.classfile.constant.visitor.ConstantVisitor;
30 import proguard.classfile.editor.ClassReferenceFixer;
31 import proguard.classfile.visitor.*;
32 import proguard.classfile.util.SimplifiedVisitor;
33 import proguard.optimize.info.SingleImplementationMarker;
34
35 /**
36  * This ClassVisitor replaces all references to interfaces that have single
37  * implementations by references to those implementations. The names will then
38  * have to be fixed, based on the new references.
39  *
40  * @see SingleImplementationMarker
41  * @see SingleImplementationFixer
42  * @see ClassReferenceFixer
43  * @author Eric Lafortune
44  */

45 public class SingleImplementationInliner
46 extends SimplifiedVisitor
47 implements ClassVisitor,
48              ConstantVisitor,
49              MemberVisitor,
50              AttributeVisitor,
51              LocalVariableInfoVisitor,
52              LocalVariableTypeInfoVisitor,
53              AnnotationVisitor,
54              ElementValueVisitor
55 {
56     // Implementations for ClassVisitor.
57

58     public void visitProgramClass(ProgramClass programClass)
59     {
60         // Update the constant pool.
61
programClass.constantPoolEntriesAccept(this);
62
63         // Update the class members.
64
programClass.fieldsAccept(this);
65         programClass.methodsAccept(this);
66
67         // Update the attributes.
68
programClass.attributesAccept(this);
69     }
70
71
72     // Implementations for ConstantVisitor.
73

74     public void visitAnyConstant(Clazz clazz, Constant constant) {}
75
76
77     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
78     {
79         if (stringConstant.referencedMember == null)
80         {
81             // Update the referenced class if it is an interface with a single
82
// implementation.
83
Clazz singleImplementationClass =
84                 SingleImplementationMarker.singleImplementation(stringConstant.referencedClass);
85
86             if (singleImplementationClass != null)
87             {
88                 stringConstant.referencedClass = singleImplementationClass;
89             }
90         }
91     }
92
93
94     public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
95     {
96         // Update the referenced interface if it has a single implementation.
97
Clazz singleImplementationClass =
98             SingleImplementationMarker.singleImplementation(interfaceMethodrefConstant.referencedClass);
99
100         if (singleImplementationClass != null)
101         {
102             // We know the single implementation contains the method.
103
String JavaDoc name = interfaceMethodrefConstant.getName(clazz);
104             String JavaDoc type = interfaceMethodrefConstant.getType(clazz);
105
106             interfaceMethodrefConstant.referencedClass = singleImplementationClass;
107             interfaceMethodrefConstant.referencedMember = singleImplementationClass.findMethod(name, type);
108         }
109     }
110
111
112     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
113     {
114         // Update the referenced class if it is an interface with a single
115
// implementation.
116
Clazz singleImplementationClass =
117             SingleImplementationMarker.singleImplementation(classConstant.referencedClass);
118
119         if (singleImplementationClass != null)
120         {
121             classConstant.referencedClass = singleImplementationClass;
122         }
123     }
124
125
126     // Implementations for MemberVisitor.
127

128     public void visitProgramField(ProgramClass programClass, ProgramField programField)
129     {
130         // Update the referenced class if the type is an interface with a
131
// single implementation.
132
Clazz singleImplementationClass =
133             SingleImplementationMarker.singleImplementation(programField.referencedClass);
134
135         if (singleImplementationClass != null)
136         {
137             programField.referencedClass = singleImplementationClass;
138         }
139
140         // Update the attributes.
141
programField.attributesAccept(programClass, this);
142     }
143
144
145     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
146     {
147         // Update the referenced classes if the descriptor contains
148
// interfaces with single implementations.
149
updateReferencedClasses(programMethod.referencedClasses);
150
151         // Update the attributes.
152
programMethod.attributesAccept(programClass, this);
153     }
154
155
156     // Implementations for AttributeVisitor.
157

158     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
159
160
161     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
162     {
163         // Update the referenced classes of the local variables.
164
codeAttribute.attributesAccept(clazz, method, this);
165     }
166
167
168     public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
169     {
170         // Update the referenced classes of the local variables.
171
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
172     }
173
174
175     public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
176     {
177         // Update the referenced classes of the local variable types.
178
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
179     }
180
181
182     public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
183     {
184         // Update the referenced classes.
185
updateReferencedClasses(signatureAttribute.referencedClasses);
186     }
187
188
189     public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
190     {
191         // Update the annotations.
192
annotationsAttribute.annotationsAccept(clazz, this);
193     }
194
195
196     public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
197     {
198         // Update the annotations.
199
parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
200     }
201
202
203     public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
204     {
205         // Update the annotation.
206
annotationDefaultAttribute.defaultValueAccept(clazz, this);
207     }
208
209
210     // Implementations for LocalVariableInfoVisitor.
211

212     public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
213     {
214         // Update the referenced class if it is an interface with a single
215
// implementation.
216
Clazz singleImplementationClass =
217             SingleImplementationMarker.singleImplementation(localVariableInfo.referencedClass);
218
219         if (singleImplementationClass != null)
220         {
221             localVariableInfo.referencedClass = singleImplementationClass;
222         }
223     }
224
225
226     // Implementations for LocalVariableTypeInfoVisitor.
227

228     public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
229     {
230         // Update the referenced classes.
231
updateReferencedClasses(localVariableTypeInfo.referencedClasses);
232     }
233
234
235     // Implementations for AnnotationVisitor.
236

237     public void visitAnnotation(Clazz clazz, Annotation annotation)
238     {
239         // Update the referenced classes.
240
updateReferencedClasses(annotation.referencedClasses);
241
242         // Update the element values.
243
annotation.elementValuesAccept(clazz, this);
244     }
245
246
247     // Implementations for ElementValueVisitor.
248

249     public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
250     {
251     }
252
253
254     public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
255     {
256         // Update the referenced classes.
257
updateReferencedClasses(enumConstantElementValue.referencedClasses);
258     }
259
260
261     public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
262     {
263         // Update the referenced classes.
264
updateReferencedClasses(classElementValue.referencedClasses);
265     }
266
267
268     public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
269     {
270         // Update the annotation.
271
annotationElementValue.annotationAccept(clazz, this);
272     }
273
274
275     public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
276     {
277         // Update the element values.
278
arrayElementValue.elementValuesAccept(clazz, annotation, this);
279     }
280
281
282     // Small utility methods.
283

284     /**
285      * Updates the given array of referenced classes, replacing references
286      * to a interfaces with single implementations by these implementations.
287      */

288     private void updateReferencedClasses(Clazz[] referencedClasses)
289     {
290         // Update all referenced classes.
291
if (referencedClasses != null)
292         {
293             for (int index = 0; index < referencedClasses.length; index++)
294             {
295                 // See if we have is an interface with a single implementation.
296
Clazz singleImplementationClass =
297                     SingleImplementationMarker.singleImplementation(referencedClasses[index]);
298
299                 // Update or copy the referenced class.
300
if (singleImplementationClass != null)
301                 {
302                     referencedClasses[index] = singleImplementationClass;
303                 }
304             }
305         }
306     }
307 }
308
Popular Tags