1
/* $Id: ClassFileObfuscator.java,v 1.23 2004/11/01 21:17:51 eric Exp $
3
* ProGuard -- shrinking, optimization, and obfuscation of Java class files.
5
* Copyright (c) 2002-2004 Eric Lafortune (eric@graphics.cornell.edu)
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)
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
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
21
package proguard.obfuscate;
23
import proguard.classfile.*;
24
import proguard.classfile.util.*;
25
import proguard.classfile.visitor.*;
31
* This <code>ClassFileVisitor</code> comes up with obfuscated names for the
32
* class files it visits, and for their class members. The actual renaming is
35
* @see ClassFileRenamer
37
* @author Eric Lafortune
39
public class ClassFileObfuscator
40
implements ClassFileVisitor
42
private boolean useMixedCaseClassNames;
43
private String defaultPackageName;
45
// Map: [package name - class name factory]
46
private final Map packageMap = new HashMap();
47
private final NameFactory defaultPackageClassNameFactory;
48
private final Set namesToAvoid = new HashSet();
52
* Creates a new ClassFileObfuscator.
53
* @param programClassPool the class pool in which class names have to be
55
* @param defaultPackageName the package in which all classes that don't
56
* have fixed names will be put, or <code>null</code>,
57
* if all classes can remain in their original
59
* @param allowAggressiveOverloading a flag that specifies whether class
60
* members can be overloaded aggressively.
62
public ClassFileObfuscator(ClassPool programClassPool,
63
String defaultPackageName,
64
boolean useMixedCaseClassNames)
66
this.defaultPackageName = defaultPackageName;
67
this.useMixedCaseClassNames = useMixedCaseClassNames;
68
this.defaultPackageClassNameFactory = new SimpleNameFactory(useMixedCaseClassNames);
70
// Collect all names that have been taken already.
71
programClassPool.classFilesAccept(new ClassFileVisitor()
73
public void visitProgramClassFile(ProgramClassFile programClassFile)
75
String newClassName = newClassName(programClassFile);
76
if (newClassName != null)
78
namesToAvoid.add(newClassName);
82
public void visitLibraryClassFile(LibraryClassFile libraryClassFile)
89
// Implementations for ClassFileVisitor.
91
public void visitProgramClassFile(ProgramClassFile programClassFile)
93
// Does this class file still need a new name?
94
if (newClassName(programClassFile) == null)
96
// Figure out a new name.
97
String className = programClassFile.getName();
98
String packageName = ClassUtil.internalPackageName(className);
100
String newPackageName = packageName;
102
// Find the right name factory for this package, or use the default.
103
NameFactory packageClassNameFactory = (NameFactory)packageMap.get(packageName);
104
if (packageClassNameFactory == null)
106
// Do we have a default package name?
107
if (defaultPackageName == null)
109
// We haven't seen this package before. Create a new name factory
111
packageClassNameFactory = new SimpleNameFactory(useMixedCaseClassNames);
112
packageMap.put(packageName, packageClassNameFactory);
116
// Fall back on the default package class name factory and name.
117
packageClassNameFactory = defaultPackageClassNameFactory;
118
newPackageName = defaultPackageName;
122
// Come up with class names until we get an original one.
126
// Let the factory produce a class name.
127
newClassName = packageClassNameFactory.nextName();
129
// We may have to add a package part to the class name.
130
if (newPackageName.length() > 0)
134
ClassConstants.INTERNAL_PACKAGE_SEPARATOR +
139
while (namesToAvoid.contains(newClassName));
141
setNewClassName(programClassFile, newClassName);
146
public void visitLibraryClassFile(LibraryClassFile libraryClassFile)
151
// Small utility methods.
154
* Assigns a new name to the given class file.
155
* @param classFile the given class file.
156
* @param name the new name.
158
static void setNewClassName(ClassFile classFile, String name)
160
classFile.setVisitorInfo(name);
166
* Retrieves the new name of the given class file.
167
* @param classFile the given class file.
168
* @return the class file's new name, or <code>null</code> if it doesn't
171
static String newClassName(ClassFile classFile)
173
Object visitorInfo = classFile.getVisitorInfo();
175
return visitorInfo instanceof String ?
176
(String)visitorInfo :