KickJava   Java API By Example, From Geeks To Geeks.

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


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.constant.*;
25 import proguard.classfile.constant.visitor.ConstantVisitor;
26 import proguard.classfile.editor.*;
27 import proguard.classfile.util.SimplifiedVisitor;
28 import proguard.classfile.visitor.ClassVisitor;
29 import proguard.optimize.info.SingleImplementationMarker;
30
31 /**
32  * This ClassVisitor cleans up after the SingleImplementationInliner.
33  * It fixes the names of interfaces that have single implementations, lets
34  * the implementations and fields references point to them again. This is
35  * necessary after the SingleImplementationInliner has overzealously renamed
36  * the interfaces to the single implementations, let the single implementations
37  * point to themselves as interfaces, and let the field references point to the
38  * single implementations.
39  *
40  * @see SingleImplementationInliner
41  * @see ClassReferenceFixer
42  * @author Eric Lafortune
43  */

44 public class SingleImplementationFixer
45 extends SimplifiedVisitor
46 implements ClassVisitor,
47              ConstantVisitor
48 {
49     private ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor();
50
51
52     // Implementations for ClassVisitor.
53

54     public void visitProgramClass(ProgramClass programClass)
55     {
56         // Is this an interface with a single implementation?
57
Clazz singleImplementationClass =
58             SingleImplementationMarker.singleImplementation(programClass);
59
60         if (singleImplementationClass != null)
61         {
62             // Fix the reference to its own name.
63
fixThisClassReference(programClass);
64
65             // Fix the reference from its single interface or implementation.
66
fixInterfaceReference((ProgramClass)programClass.subClasses[0],
67                                   programClass);
68         }
69
70         // Fix the field references in the constant pool.
71
programClass.constantPoolEntriesAccept(this);
72     }
73
74
75     // Implementations for ConstantVisitor.
76

77     public void visitAnyConstant(Clazz clazz, Constant constant) {}
78
79
80     public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
81     {
82         // Update the referenced class if it is an interface with a single
83
// implementation.
84
Clazz singleImplementationClass =
85             SingleImplementationMarker.singleImplementation(fieldrefConstant.referencedClass);
86
87         if (singleImplementationClass != null)
88         {
89             // Fix the reference to the interface.
90
fixFieldrefClassReference((ProgramClass)clazz,
91                                       fieldrefConstant);
92         }
93     }
94
95
96     // Small utility methods.
97

98     /**
99      * Fixes the given class, so its name points to itself again.
100      */

101     private void fixThisClassReference(ProgramClass programClass)
102     {
103         // We have to add a new class entry to avoid an existing entry with the
104
// same name being reused. The names have to be fixed later, based on
105
// their referenced classes.
106
int nameIndex =
107             constantPoolEditor.addUtf8Constant(programClass,
108                                                programClass.getName());
109         programClass.u2thisClass =
110             constantPoolEditor.addConstant(programClass,
111                                            new ClassConstant(nameIndex,
112                                                              programClass));
113     }
114
115
116     /**
117      * Fixes the given class, so it points to the given interface again.
118      */

119     private void fixInterfaceReference(ProgramClass programClass,
120                                        ProgramClass interfaceClass)
121     {
122         // Make sure the class refers to the given interface again.
123
String JavaDoc interfaceName = interfaceClass.getName();
124
125         int interfacesCount = programClass.u2interfacesCount;
126         for (int index = 0; index < interfacesCount; index++)
127         {
128             if (interfaceName.equals(programClass.getInterfaceName(index)))
129             {
130                 // Update the class index.
131
// We have to add a new class entry to avoid an existing entry
132
// with the same name being reused. The names have to be fixed
133
// later, based on their referenced classes.
134
int nameIndex =
135                     constantPoolEditor.addUtf8Constant(programClass,
136                                                        interfaceName);
137                 programClass.u2interfaces[index] =
138                     constantPoolEditor.addConstant(programClass,
139                                                    new ClassConstant(nameIndex,
140                                                                      interfaceClass));
141                 break;
142
143             }
144         }
145     }
146
147
148     /**
149      * Fixes the given field reference, so its class index points to its
150      * class again. Note that this could be a different class than the one
151      * in the original class.
152      */

153     private void fixFieldrefClassReference(ProgramClass programClass,
154                                            FieldrefConstant fieldrefConstant)
155     {
156         Clazz referencedClass = fieldrefConstant.referencedClass;
157
158         // We have to add a new class entry to avoid an existing entry with the
159
// same name being reused. The names have to be fixed later, based on
160
// their referenced classes.
161
int nameIndex =
162             constantPoolEditor.addUtf8Constant(programClass,
163                                                fieldrefConstant.getClassName(programClass));
164         fieldrefConstant.u2classIndex =
165             constantPoolEditor.addConstant(programClass,
166                                            new ClassConstant(nameIndex,
167                                                              referencedClass));
168     }
169 }
170
Popular Tags