KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > obfuscate > MemberNameConflictFixer


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.obfuscate;
22
23 import proguard.classfile.util.*;
24 import proguard.classfile.*;
25 import proguard.classfile.visitor.MemberVisitor;
26
27 import java.util.Map JavaDoc;
28
29 /**
30  * This MemberInfoVisitor solves obfuscation naming conflicts in all class
31  * members that it visits. It avoids names from the given descriptor map,
32  * delegating to the given obfuscator in order to get a new name if necessary.
33  *
34  * @author Eric Lafortune
35  */

36 public class MemberNameConflictFixer implements MemberVisitor
37 {
38     private boolean allowAggressiveOverloading;
39     private Map JavaDoc descriptorMap;
40     private WarningPrinter warningPrinter;
41     private MemberObfuscator memberObfuscator;
42
43
44     /**
45      * Creates a new MemberNameConflictFixer.
46      * @param allowAggressiveOverloading a flag that specifies whether class
47      * members can be overloaded aggressively.
48      * @param descriptorMap the map of descriptors to
49      * [new name - old name] maps.
50      * @param warningPrinter an optional warning printer to which
51      * warnings about conflicting name
52      * mappings can be printed.
53      * @param memberObfuscator the obfuscator that can assign new
54      * names to members with conflicting
55      * names.
56      */

57     public MemberNameConflictFixer(boolean allowAggressiveOverloading,
58                                    Map JavaDoc descriptorMap,
59                                    WarningPrinter warningPrinter,
60                                    MemberObfuscator memberObfuscator)
61     {
62         this.allowAggressiveOverloading = allowAggressiveOverloading;
63         this.descriptorMap = descriptorMap;
64         this.warningPrinter = warningPrinter;
65         this.memberObfuscator = memberObfuscator;
66     }
67
68
69
70
71     // Implementations for MemberVisitor.
72

73     public void visitProgramField(ProgramClass programClass, ProgramField programField)
74     {
75         visitMember(programClass, programField, true);
76     }
77
78
79     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
80     {
81         // Special cases: <clinit> and <init> are always kept unchanged.
82
// We can ignore them here.
83
String JavaDoc name = programMethod.getName(programClass);
84         if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ||
85             name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
86         {
87             return;
88         }
89
90         visitMember(programClass, programMethod, false);
91     }
92
93
94     public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) {}
95     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {}
96
97
98     /**
99      * Obfuscates the given class member.
100      * @param clazz the class of the given member.
101      * @param member the class member to be obfuscated.
102      * @param isField specifies whether the class member is a field.
103      */

104     private void visitMember(Clazz clazz,
105                              Member member,
106                              boolean isField)
107     {
108         // Get the member's name and descriptor.
109
String JavaDoc name = member.getName(clazz);
110         String JavaDoc descriptor = member.getDescriptor(clazz);
111
112         // Check whether we're allowed to overload aggressively.
113
if (!allowAggressiveOverloading)
114         {
115             // Trim the return argument from the descriptor if not.
116
// Works for fields and methods alike.
117
descriptor = descriptor.substring(0, descriptor.indexOf(')')+1);
118         }
119
120         // Get the name map, creating a new one if necessary.
121
Map JavaDoc nameMap = MemberObfuscator.retrieveNameMap(descriptorMap, descriptor);
122
123         // Get the member's new name.
124
String JavaDoc newName = MemberObfuscator.newMemberName(member);
125
126         String JavaDoc previousName = (String JavaDoc)nameMap.get(newName);
127         if (!name.equals(previousName))
128         {
129             // There's a conflict! A member (with a given old name) in a
130
// first namespace has received the same new name as this
131
// member (with a different old name) in a second name space,
132
// and now these two have to live together in this name space.
133
if (MemberObfuscator.hasFixedNewMemberName(member) &&
134                 warningPrinter != null)
135             {
136                 descriptor = member.getDescriptor(clazz);
137                 warningPrinter.print("Warning: " + ClassUtil.externalClassName(clazz.getName()) +
138                                                    (isField ?
139                                                        ": field '" + ClassUtil.externalFullFieldDescription(0, name, descriptor) :
140                                                        ": method '" + ClassUtil.externalFullMethodDescription(clazz.getName(), 0, name, descriptor)) +
141                                      "' can't be mapped to '" + newName +
142                                      "' because it would conflict with " +
143                                      (isField ?
144                                          "field '" :
145                                          "method '" ) + previousName +
146                                      "', which is already being mapped to '" + newName + "'");
147             }
148
149             // Clear the conflicting name.
150
MemberObfuscator.setNewMemberName(member, null);
151
152             // Assign a new name.
153
member.accept(clazz, memberObfuscator);
154         }
155     }
156 }
157
Popular Tags