1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
59f606f95f03a75961498803e24bee6799a7c0885Ying Wang * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it
8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free
9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option)
10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version.
11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT
13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details.
16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along
18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc.,
19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.obfuscate;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.*;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.*;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.ClassConstant;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.ConstantVisitor;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.ClassVisitor;
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.util.*;
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.*;
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This <code>ClassVisitor</code> comes up with obfuscated names for the
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes it visits, and for their class members. The actual renaming is
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * done afterward.
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see ClassRenamer
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class ClassObfuscator
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends      SimplifiedVisitor
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   ClassVisitor,
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             AttributeVisitor,
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             InnerClassesInfoVisitor,
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             ConstantVisitor
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final DictionaryNameFactory classNameFactory;
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final DictionaryNameFactory packageNameFactory;
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean               useMixedCaseClassNames;
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final StringMatcher         keepPackageNamesMatcher;
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final String                flattenPackageHierarchy;
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final String                repackageClasses;
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean               allowAccessModification;
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final Set classNamesToAvoid                       = new HashSet();
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Map: [package prefix - new package prefix]
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final Map packagePrefixMap                        = new HashMap();
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Map: [package prefix - package name factory]
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final Map packagePrefixPackageNameFactoryMap      = new HashMap();
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Map: [package prefix - numeric class name factory]
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final Map packagePrefixClassNameFactoryMap        = new HashMap();
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Map: [package prefix - numeric class name factory]
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final Map packagePrefixNumericClassNameFactoryMap = new HashMap();
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Field acting as temporary variables and as return values for names
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // of outer classes and types of inner classes.
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String  newClassName;
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean numericClassName;
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new ClassObfuscator.
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param programClassPool        the class pool in which class names
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                have to be unique.
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param classNameFactory        the optional class obfuscation dictionary.
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param packageNameFactory      the optional package obfuscation
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                dictionary.
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param useMixedCaseClassNames  specifies whether obfuscated packages and
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                classes can get mixed-case names.
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param keepPackageNames        the optional filter for which matching
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                package names are kept.
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param flattenPackageHierarchy the base package if the obfuscated package
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                hierarchy is to be flattened.
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param repackageClasses        the base package if the obfuscated classes
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                are to be repackaged.
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param allowAccessModification specifies whether obfuscated classes can
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                be freely moved between packages.
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public ClassObfuscator(ClassPool             programClassPool,
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           DictionaryNameFactory classNameFactory,
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           DictionaryNameFactory packageNameFactory,
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           boolean               useMixedCaseClassNames,
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           List                  keepPackageNames,
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           String                flattenPackageHierarchy,
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           String                repackageClasses,
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           boolean               allowAccessModification)
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.classNameFactory   = classNameFactory;
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.packageNameFactory = packageNameFactory;
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // First append the package separator if necessary.
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (flattenPackageHierarchy != null &&
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            flattenPackageHierarchy.length() > 0)
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            flattenPackageHierarchy += ClassConstants.INTERNAL_PACKAGE_SEPARATOR;
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // First append the package separator if necessary.
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (repackageClasses != null &&
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            repackageClasses.length() > 0)
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            repackageClasses += ClassConstants.INTERNAL_PACKAGE_SEPARATOR;
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.useMixedCaseClassNames  = useMixedCaseClassNames;
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.keepPackageNamesMatcher = keepPackageNames == null ? null :
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new ListParser(new FileNameParser()).parse(keepPackageNames);
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.flattenPackageHierarchy = flattenPackageHierarchy;
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.repackageClasses        = repackageClasses;
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.allowAccessModification = allowAccessModification;
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Map the root package onto the root package.
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        packagePrefixMap.put("", "");
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Collect all names that have been taken already.
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(new MyKeepCollector());
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for ClassVisitor.
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramClass(ProgramClass programClass)
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Does this class still need a new name?
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        newClassName = newClassName(programClass);
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (newClassName == null)
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Make sure the outer class has a name, if it exists. The name will
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // be stored as the new class name, as a side effect, so we'll be
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // able to use it as a prefix.
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClass.attributesAccept(this);
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Figure out a package prefix. The package prefix may actually be
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // the an outer class prefix, if any, or it may be the fixed base
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // package, if classes are to be repackaged.
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String newPackagePrefix = newClassName != null ?
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                newClassName + ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR :
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                newPackagePrefix(ClassUtil.internalPackagePrefix(programClass.getName()));
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Come up with a new class name, numeric or ordinary.
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            newClassName = newClassName != null && numericClassName ?
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                generateUniqueNumericClassName(newPackagePrefix) :
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                generateUniqueClassName(newPackagePrefix);
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            setNewClassName(programClass, newClassName);
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for AttributeVisitor.
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make sure the outer classes have a name, if they exist.
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        innerClassesAttribute.innerClassEntriesAccept(clazz, this);
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make sure the enclosing class has a name.
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        enclosingMethodAttribute.referencedClassAccept(this);
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String innerClassName = clazz.getName();
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String outerClassName = clazz.getClassName(enclosingMethodAttribute.u2classIndex);
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        numericClassName = isNumericClassName(innerClassName,
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              outerClassName);
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for InnerClassesInfoVisitor.
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make sure the outer class has a name, if it exists.
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int innerClassIndex = innerClassesInfo.u2innerClassIndex;
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int outerClassIndex = innerClassesInfo.u2outerClassIndex;
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (innerClassIndex != 0 &&
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            outerClassIndex != 0)
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String innerClassName = clazz.getClassName(innerClassIndex);
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (innerClassName.equals(clazz.getName()))
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                clazz.constantPoolEntryAccept(outerClassIndex, this);
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                String outerClassName = clazz.getClassName(outerClassIndex);
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                numericClassName = isNumericClassName(innerClassName,
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      outerClassName);
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether the given inner class name is a numeric name.
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean isNumericClassName(String innerClassName,
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       String outerClassName)
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int innerClassNameStart  = outerClassName.length() + 1;
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int innerClassNameLength = innerClassName.length();
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (innerClassNameStart >= innerClassNameLength)
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return false;
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        for (int index = innerClassNameStart; index < innerClassNameLength; index++)
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!Character.isDigit(innerClassName.charAt(index)))
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                return false;
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return true;
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for ConstantVisitor.
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make sure the outer class has a name.
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        classConstant.referencedClassAccept(this);
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * This ClassVisitor collects package names and class names that have to
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * be kept.
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private class MyKeepCollector implements ClassVisitor
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        public void visitProgramClass(ProgramClass programClass)
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Does the class already have a new name?
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String newClassName = newClassName(programClass);
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (newClassName != null)
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Remember not to use this name.
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classNamesToAvoid.add(mixedCaseClassName(newClassName));
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Are we not aggressively repackaging all obfuscated classes?
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (repackageClasses == null ||
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    !allowAccessModification)
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    String className = programClass.getName();
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Keep the package name for all other classes in the same
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // package. Do this recursively if we're not doing any
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // repackaging.
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    mapPackageName(className,
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   newClassName,
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   repackageClasses        == null &&
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   flattenPackageHierarchy == null);
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        public void visitLibraryClass(LibraryClass libraryClass)
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        /**
290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato         * Makes sure the package name of the given class will always be mapped
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato         * consistently with its new name.
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato         */
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        private void mapPackageName(String  className,
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    String  newClassName,
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    boolean recursively)
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String packagePrefix    = ClassUtil.internalPackagePrefix(className);
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String newPackagePrefix = ClassUtil.internalPackagePrefix(newClassName);
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Put the mapping of this package prefix, and possibly of its
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // entire hierarchy, into the package prefix map.
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            do
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                packagePrefixMap.put(packagePrefix, newPackagePrefix);
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (!recursively)
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                packagePrefix    = ClassUtil.internalPackagePrefix(packagePrefix);
312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                newPackagePrefix = ClassUtil.internalPackagePrefix(newPackagePrefix);
313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            while (packagePrefix.length()    > 0 &&
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                   newPackagePrefix.length() > 0);
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Small utility methods.
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Finds or creates the new package prefix for the given package.
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String newPackagePrefix(String packagePrefix)
326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Doesn't the package prefix have a new package prefix yet?
328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String newPackagePrefix = (String)packagePrefixMap.get(packagePrefix);
329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (newPackagePrefix == null)
330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Are we keeping the package name?
332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (keepPackageNamesMatcher != null &&
333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                keepPackageNamesMatcher.matches(packagePrefix.length() > 0 ?
334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    packagePrefix.substring(0, packagePrefix.length()-1) :
335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    packagePrefix))
336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                return packagePrefix;
338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Are we forcing a new package prefix?
341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (repackageClasses != null)
342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                return repackageClasses;
344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Are we forcing a new superpackage prefix?
347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Otherwise figure out the new superpackage prefix, recursively.
348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String newSuperPackagePrefix = flattenPackageHierarchy != null ?
349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                flattenPackageHierarchy :
350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                newPackagePrefix(ClassUtil.internalPackagePrefix(packagePrefix));
351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Come up with a new package prefix.
353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            newPackagePrefix = generateUniquePackagePrefix(newSuperPackagePrefix);
354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Remember to use this mapping in the future.
356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            packagePrefixMap.put(packagePrefix, newPackagePrefix);
357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return newPackagePrefix;
360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new package prefix in the given new superpackage.
365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String generateUniquePackagePrefix(String newSuperPackagePrefix)
367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Find the right name factory for this package.
369b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        NameFactory packageNameFactory =
370b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (NameFactory)packagePrefixPackageNameFactoryMap.get(newSuperPackagePrefix);
371b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (packageNameFactory == null)
372b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
373b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // We haven't seen packages in this superpackage before. Create
374b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // a new name factory for them.
375b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            packageNameFactory = new SimpleNameFactory(useMixedCaseClassNames);
376b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (this.packageNameFactory != null)
377b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                packageNameFactory =
379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new DictionaryNameFactory(this.packageNameFactory,
380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              packageNameFactory);
381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            packagePrefixPackageNameFactoryMap.put(newSuperPackagePrefix,
384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   packageNameFactory);
385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return generateUniquePackagePrefix(newSuperPackagePrefix, packageNameFactory);
388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new package prefix in the given new superpackage, with the
393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * given package name factory.
394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String generateUniquePackagePrefix(String      newSuperPackagePrefix,
396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               NameFactory packageNameFactory)
397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Come up with package names until we get an original one.
399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String newPackagePrefix;
400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        do
401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Let the factory produce a package name.
403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            newPackagePrefix = newSuperPackagePrefix +
404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                               packageNameFactory.nextName() +
405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                               ClassConstants.INTERNAL_PACKAGE_SEPARATOR;
406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (packagePrefixMap.containsValue(newPackagePrefix));
408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return newPackagePrefix;
410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new class name in the given new package.
415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String generateUniqueClassName(String newPackagePrefix)
417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Find the right name factory for this package.
419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        NameFactory classNameFactory =
420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (NameFactory)packagePrefixClassNameFactoryMap.get(newPackagePrefix);
421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (classNameFactory == null)
422b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // We haven't seen classes in this package before.
424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Create a new name factory for them.
425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            classNameFactory = new SimpleNameFactory(useMixedCaseClassNames);
426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (this.classNameFactory != null)
427b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classNameFactory =
429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new DictionaryNameFactory(this.classNameFactory,
430b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              classNameFactory);
431b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            packagePrefixClassNameFactoryMap.put(newPackagePrefix,
434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                 classNameFactory);
435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return generateUniqueClassName(newPackagePrefix, classNameFactory);
438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
441b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
442b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new class name in the given new package.
443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String generateUniqueNumericClassName(String newPackagePrefix)
445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Find the right name factory for this package.
447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        NameFactory classNameFactory =
448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (NameFactory)packagePrefixNumericClassNameFactoryMap.get(newPackagePrefix);
449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (classNameFactory == null)
450b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // We haven't seen classes in this package before.
452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Create a new name factory for them.
453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            classNameFactory = new NumericNameFactory();
454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            packagePrefixNumericClassNameFactoryMap.put(newPackagePrefix,
456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                        classNameFactory);
457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return generateUniqueClassName(newPackagePrefix, classNameFactory);
460b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new class name in the given new package, with the given
465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * class name factory.
466b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String generateUniqueClassName(String      newPackagePrefix,
468b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                           NameFactory classNameFactory)
469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Come up with class names until we get an original one.
471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String newClassName;
472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        do
473b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Let the factory produce a class name.
475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            newClassName = newPackagePrefix +
476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           classNameFactory.nextName();
477b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
4789f606f95f03a75961498803e24bee6799a7c0885Ying Wang        while (classNamesToAvoid.contains(mixedCaseClassName(newClassName)));
479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return newClassName;
481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
483b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the given class name, unchanged if mixed-case class names are
486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * allowed, or the lower-case version otherwise.
487b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String mixedCaseClassName(String className)
489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
490b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return useMixedCaseClassNames ?
491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            className :
492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            className.toLowerCase();
493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
495b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
496b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
497b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Assigns a new name to the given class.
498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param clazz the given class.
499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param name  the new name.
500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
501b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    static void setNewClassName(Clazz clazz, String name)
502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        clazz.setVisitorInfo(name);
504b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Retrieves the new name of the given class.
509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param clazz the given class.
510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return the class's new name, or <code>null</code> if it doesn't
511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *         have one yet.
512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
513b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    static String newClassName(Clazz clazz)
514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
515b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Object visitorInfo = clazz.getVisitorInfo();
516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
517b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return visitorInfo instanceof String ?
518b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (String)visitorInfo :
519b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            null;
520b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
521b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
522