Home | History | Annotate | Download | only in obfuscate
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2009 Eric Lafortune (eric (at) 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.*;
     24 import proguard.classfile.util.*;
     25 import 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  */
     34 public 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