MappingKeeper.java revision 9f606f95f03a75961498803e24bee6799a7c0885
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2009 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 */
21package proguard.obfuscate;
22
23import proguard.classfile.*;
24import proguard.classfile.util.*;
25import proguard.util.ListUtil;
26
27
28/**
29 * This MappingKeeper applies the mappings that it receives to its class pool,
30 * so these mappings are ensured in a subsequent obfuscation step.
31 *
32 * @author Eric Lafortune
33 */
34public class MappingKeeper implements MappingProcessor
35{
36    private final ClassPool      classPool;
37    private final WarningPrinter warningPrinter;
38
39    // A field acting as a parameter.
40    private Clazz clazz;
41
42
43    /**
44     * Creates a new MappingKeeper.
45     * @param classPool      the class pool in which class names and class
46     *                       member names have to be mapped.
47     * @param warningPrinter the optional warning printer to which warnings
48     *                       can be printed.
49     */
50    public MappingKeeper(ClassPool      classPool,
51                         WarningPrinter warningPrinter)
52    {
53        this.classPool      = classPool;
54        this.warningPrinter = warningPrinter;
55    }
56
57
58    // Implementations for MappingProcessor.
59
60    public boolean processClassMapping(String className,
61                                       String newClassName)
62    {
63        // Find the class.
64        String name = ClassUtil.internalClassName(className);
65
66        clazz = classPool.getClass(name);
67        if (clazz != null)
68        {
69            String newName = ClassUtil.internalClassName(newClassName);
70
71            // Print out a warning if the mapping conflicts with a name that
72            // was set before.
73            if (warningPrinter != null)
74            {
75                String currentNewName = ClassObfuscator.newClassName(clazz);
76                if (currentNewName != null &&
77                    !currentNewName.equals(newName))
78                {
79                    warningPrinter.print(name,
80                                         currentNewName,
81                                         "Warning: " +
82                                         className +
83                                         " is not being kept as '" +
84                                         ClassUtil.externalClassName(currentNewName) +
85                                         "', but remapped to '" +
86                                         newClassName + "'");
87                }
88            }
89
90            ClassObfuscator.setNewClassName(clazz, newName);
91
92            // The class members have to be kept as well.
93            return true;
94        }
95
96        return false;
97    }
98
99
100    public void processFieldMapping(String className,
101                                    String fieldType,
102                                    String fieldName,
103                                    String newFieldName)
104    {
105        if (clazz != null)
106        {
107            // Find the field.
108            String name       = fieldName;
109            String descriptor = ClassUtil.internalType(fieldType);
110
111            Field field = clazz.findField(name, descriptor);
112            if (field != null)
113            {
114                // Print out a warning if the mapping conflicts with a name that
115                // was set before.
116                if (warningPrinter != null)
117                {
118                    String currentNewName = MemberObfuscator.newMemberName(field);
119                    if (currentNewName != null &&
120                        !currentNewName.equals(newFieldName))
121                    {
122                        warningPrinter.print(ClassUtil.internalClassName(className),
123                                             "Warning: " +
124                                             className +
125                                             ": field '" + fieldType + " " + fieldName +
126                                             "' is not being kept as '" + currentNewName +
127                                             "', but remapped to '" + newFieldName + "'");
128                    }
129                }
130
131                // Make sure the mapping name will be kept.
132                MemberObfuscator.setFixedNewMemberName(field, newFieldName);
133            }
134        }
135    }
136
137
138    public void processMethodMapping(String className,
139                                     int    firstLineNumber,
140                                     int    lastLineNumber,
141                                     String methodReturnType,
142                                     String methodName,
143                                     String methodArguments,
144                                     String newMethodName)
145    {
146        if (clazz != null)
147        {
148            // Find the method.
149            String descriptor = ClassUtil.internalMethodDescriptor(methodReturnType,
150                                                                   ListUtil.commaSeparatedList(methodArguments));
151
152            Method method = clazz.findMethod(methodName, descriptor);
153            if (method != null)
154            {
155                // Print out a warning if the mapping conflicts with a name that
156                // was set before.
157                if (warningPrinter != null)
158                {
159                    String currentNewName = MemberObfuscator.newMemberName(method);
160                    if (currentNewName != null &&
161                        !currentNewName.equals(newMethodName))
162                    {
163                        warningPrinter.print(ClassUtil.internalClassName(className),
164                                             "Warning: " +
165                                             className +
166                                             ": method '" + methodReturnType + " " + methodName + ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN + methodArguments + ClassConstants.EXTERNAL_METHOD_ARGUMENTS_CLOSE +
167                                             "' is not being kept as '" + currentNewName +
168                                             "', but remapped to '" + newMethodName + "'");
169                    }
170                }
171
172                // Make sure the mapping name will be kept.
173                MemberObfuscator.setFixedNewMemberName(method, newMethodName);
174            }
175        }
176    }
177}
178