• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
21 package proguard.io;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.util.ClassUtil;
25 
26 import java.io.IOException;
27 import java.util.Map;
28 
29 /**
30  * This DataEntryReader delegates to another DataEntryReader, renaming the
31  * data entries based on the renamed classes in the given ClassPool.
32  *
33  * @author Eric Lafortune
34  */
35 public class DataEntryObfuscator implements DataEntryReader
36 {
37     private final ClassPool       classPool;
38     private final Map             packagePrefixMap;
39     private final DataEntryReader dataEntryReader;
40 
41 
42     /**
43      * Creates a new DataEntryObfuscator.
44      * @param classPool        the class pool that maps from old names to new
45      *                         names.
46      * @param packagePrefixMap the map from old package prefixes to new package
47      *                         prefixes.
48      * @param dataEntryReader  the DataEntryReader to which calls will be
49      *                         delegated.
50      */
DataEntryObfuscator(ClassPool classPool, Map packagePrefixMap, DataEntryReader dataEntryReader)51     public DataEntryObfuscator(ClassPool       classPool,
52                                Map             packagePrefixMap,
53                                DataEntryReader dataEntryReader)
54     {
55         this.classPool        = classPool;
56         this.packagePrefixMap = packagePrefixMap;
57         this.dataEntryReader  = dataEntryReader;
58     }
59 
60 
61     // Implementations for DataEntryReader.
62 
read(DataEntry dataEntry)63     public void read(DataEntry dataEntry) throws IOException
64     {
65         // Delegate to the actual data entry reader.
66         dataEntryReader.read(renamedDataEntry(dataEntry));
67     }
68 
69 
70     /**
71      * Create a renamed data entry, if possible.
72      */
renamedDataEntry(DataEntry dataEntry)73     private DataEntry renamedDataEntry(DataEntry dataEntry)
74     {
75         String dataEntryName = dataEntry.getName();
76 
77         // Try to find a corresponding class name by removing increasingly
78         // long suffixes,
79         for (int suffixIndex = dataEntryName.length() - 1;
80              suffixIndex > 0;
81              suffixIndex--)
82         {
83             char c = dataEntryName.charAt(suffixIndex);
84             if (!Character.isLetterOrDigit(c))
85             {
86                 // Chop off the suffix.
87                 String className = dataEntryName.substring(0, suffixIndex);
88 
89                 // Did we get to the package separator?
90                 if (c == ClassConstants.INTERNAL_PACKAGE_SEPARATOR)
91                 {
92                     break;
93                 }
94 
95                 // Is there a class corresponding to the data entry?
96                 Clazz clazz = classPool.getClass(className);
97                 if (clazz != null)
98                 {
99                     // Did the class get a new name?
100                     String newClassName = clazz.getName();
101                     if (!className.equals(newClassName))
102                     {
103                         // Return a renamed data entry.
104                         String newDataEntryName =
105                             newClassName + dataEntryName.substring(suffixIndex);
106 
107                         return new RenamedDataEntry(dataEntry, newDataEntryName);
108                     }
109 
110                     // Otherwise stop looking.
111                     break;
112                 }
113             }
114         }
115 
116         // Did the package get a new name?
117         String packagePrefix    = ClassUtil.internalPackagePrefix(dataEntryName);
118         String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
119         if (newPackagePrefix != null &&
120             !packagePrefix.equals(newPackagePrefix))
121         {
122             // Return a renamed data entry.
123             String newDataEntryName =
124                 newPackagePrefix + dataEntryName.substring(packagePrefix.length());
125 
126             return new RenamedDataEntry(dataEntry, newDataEntryName);
127         }
128 
129         return dataEntry;
130     }
131 }
132