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.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.*;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.AllConstantVisitor;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.*;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.*;
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.util.*;
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.io.*;
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.*;
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This class can perform obfuscation of class pools according to a given
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * specification.
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class Obfuscator
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final Configuration configuration;
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new Obfuscator.
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public Obfuscator(Configuration configuration)
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.configuration = configuration;
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Performs obfuscation of the given program class pool.
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void execute(ClassPool programClassPool,
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        ClassPool libraryClassPool) throws IOException
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Check if we have at least some keep commands.
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configuration.keep         == null &&
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            configuration.applyMapping == null &&
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            configuration.printMapping == null)
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new IOException("You have to specify '-keep' options for the obfuscation step.");
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Clean up any old visitor info.
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(new ClassCleaner());
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.classesAccept(new ClassCleaner());
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // If the class member names have to correspond globally,
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // link all class members in all classes, otherwise
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // link all non-private methods in all class hierarchies.
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ClassVisitor memberInfoLinker =
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            configuration.useUniqueClassMemberNames ?
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (ClassVisitor)new AllMemberVisitor(new MethodLinker()) :
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (ClassVisitor)new BottomClassFilter(new MethodLinker());
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(memberInfoLinker);
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.classesAccept(memberInfoLinker);
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Create a visitor for marking the seeds.
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        NameMarker nameMarker = new NameMarker();
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ClassPoolVisitor classPoolvisitor =
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep,
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                    nameMarker,
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                    nameMarker,
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                    false,
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                    false,
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                    true);
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Mark the seeds.
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.accept(classPoolvisitor);
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.accept(classPoolvisitor);
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // All library classes and library class members keep their names.
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.classesAccept(nameMarker);
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker));
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Mark attributes that have to be kept.
1029f606f95f03a75961498803e24bee6799a7c0885Ying Wang        AttributeUsageMarker requiredAttributeUsageMarker =
1039f606f95f03a75961498803e24bee6799a7c0885Ying Wang            new AttributeUsageMarker();
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        AttributeVisitor optionalAttributeUsageMarker =
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            configuration.keepAttributes == null ? null :
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes),
1089f606f95f03a75961498803e24bee6799a7c0885Ying Wang                                        requiredAttributeUsageMarker);
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new AllAttributeVisitor(true,
1129f606f95f03a75961498803e24bee6799a7c0885Ying Wang            new RequiredAttributeFilter(requiredAttributeUsageMarker,
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        optionalAttributeUsageMarker)));
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Remove the attributes that can be discarded. Note that the attributes
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // may only be discarded after the seeds have been marked, since the
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // configuration may rely on annotations.
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(new AttributeShrinker());
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Apply the mapping, if one has been specified. The mapping can
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // override the names of library classes and of library class members.
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configuration.applyMapping != null)
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            MappingReader reader = new MappingReader(configuration.applyMapping);
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            MappingProcessor keeper =
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MultiMappingProcessor(new MappingProcessor[]
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MappingKeeper(programClassPool, warningPrinter),
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MappingKeeper(libraryClassPool, null),
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                });
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            reader.pump(keeper);
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Print out a summary of the warnings if necessary.
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int mappingWarningCount = warningPrinter.getWarningCount();
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (mappingWarningCount > 0)
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.err.println("Warning: there were " + mappingWarningCount +
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                            " kept classes and class members that were remapped anyway.");
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.err.println("         You should adapt your configuration or edit the mapping file.");
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (!configuration.ignoreWarnings)
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    System.err.println("         If you are sure this remapping won't hurt,");
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    System.err.println("         you could try your luck using the '-ignorewarnings' option.");
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    throw new IOException("Please correct the above warnings first.");
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Come up with new names for all classes.
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        DictionaryNameFactory classNameFactory = configuration.classObfuscationDictionary != null ?
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new DictionaryNameFactory(configuration.classObfuscationDictionary, null) :
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            null;
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        DictionaryNameFactory packageNameFactory = configuration.packageObfuscationDictionary != null ?
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new DictionaryNameFactory(configuration.packageObfuscationDictionary, null) :
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            null;
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new ClassObfuscator(programClassPool,
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                classNameFactory,
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                packageNameFactory,
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                configuration.useMixedCaseClassNames,
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                configuration.keepPackageNames,
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                configuration.flattenPackageHierarchy,
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                configuration.repackageClasses,
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                configuration.allowAccessModification));
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Come up with new names for all class members.
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        NameFactory nameFactory = new SimpleNameFactory();
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configuration.obfuscationDictionary != null)
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            nameFactory = new DictionaryNameFactory(configuration.obfuscationDictionary,
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                    nameFactory);
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Maintain a map of names to avoid [descriptor - new name - old name].
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Map descriptorMap = new HashMap();
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Do the class member names have to be globally unique?
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configuration.useUniqueClassMemberNames)
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Collect all member names in all classes.
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClassPool.classesAccept(
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberNameCollector(configuration.overloadAggressively,
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        descriptorMap)));
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Assign new names to all members in all classes.
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClassPool.classesAccept(
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberObfuscator(configuration.overloadAggressively,
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     nameFactory,
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     descriptorMap)));
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Come up with new names for all non-private class members.
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClassPool.classesAccept(
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MultiClassVisitor(new ClassVisitor[]
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Collect all private member names in this class and down
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // the hierarchy.
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ClassHierarchyTraveler(true, false, false, true,
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new AllMemberVisitor(
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0,
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberNameCollector(configuration.overloadAggressively,
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptorMap)))),
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Collect all non-private member names anywhere in the hierarchy.
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ClassHierarchyTraveler(true, true, true, true,
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new AllMemberVisitor(
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberNameCollector(configuration.overloadAggressively,
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptorMap)))),
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Assign new names to all non-private members in this class.
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new AllMemberVisitor(
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberObfuscator(configuration.overloadAggressively,
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         nameFactory,
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         descriptorMap))),
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Clear the collected names.
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MapCleaner(descriptorMap)
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }));
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Come up with new names for all private class members.
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClassPool.classesAccept(
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MultiClassVisitor(new ClassVisitor[]
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Collect all member names in this class.
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new AllMemberVisitor(
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberNameCollector(configuration.overloadAggressively,
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptorMap)),
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Collect all non-private member names higher up the hierarchy.
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ClassHierarchyTraveler(false, true, true, false,
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new AllMemberVisitor(
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberNameCollector(configuration.overloadAggressively,
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptorMap)))),
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Assign new names to all private members in this class.
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new AllMemberVisitor(
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0,
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberObfuscator(configuration.overloadAggressively,
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         nameFactory,
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         descriptorMap))),
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Clear the collected names.
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MapCleaner(descriptorMap)
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }));
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Some class members may have ended up with conflicting names.
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Come up with new, globally unique names for them.
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        NameFactory specialNameFactory =
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new SpecialNameFactory(new SimpleNameFactory());
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Collect a map of special names to avoid
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // [descriptor - new name - old name].
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Map specialDescriptorMap = new HashMap();
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new AllMemberVisitor(
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new MemberSpecialNameFilter(
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new MemberNameCollector(configuration.overloadAggressively,
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    specialDescriptorMap))));
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.classesAccept(
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new AllMemberVisitor(
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new MemberSpecialNameFilter(
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new MemberNameCollector(configuration.overloadAggressively,
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    specialDescriptorMap))));
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace conflicting non-private member names with special names.
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new MultiClassVisitor(new ClassVisitor[]
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Collect all private member names in this class and down
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // the hierarchy.
290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new ClassHierarchyTraveler(true, false, false, true,
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0,
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberNameCollector(configuration.overloadAggressively,
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        descriptorMap)))),
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Collect all non-private member names in this class and
297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // higher up the hierarchy.
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new ClassHierarchyTraveler(true, true, true, false,
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberNameCollector(configuration.overloadAggressively,
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        descriptorMap)))),
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Assign new names to all conflicting non-private members
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // in this class and higher up the hierarchy.
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new ClassHierarchyTraveler(true, true, true, false,
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberNameConflictFixer(configuration.overloadAggressively,
310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptorMap,
311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            warningPrinter,
312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberObfuscator(configuration.overloadAggressively,
313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     specialNameFactory,
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     specialDescriptorMap))))),
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Clear the collected names.
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MapCleaner(descriptorMap)
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }));
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace conflicting private member names with special names.
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // This is only possible if those names were kept or mapped.
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new MultiClassVisitor(new ClassVisitor[]
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Collect all member names in this class.
326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberNameCollector(configuration.overloadAggressively,
328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        descriptorMap)),
329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Collect all non-private member names higher up the hierarchy.
331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new ClassHierarchyTraveler(false, true, true, false,
332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberNameCollector(configuration.overloadAggressively,
335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        descriptorMap)))),
336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Assign new names to all conflicting private members in this
338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // class.
339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllMemberVisitor(
340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0,
341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberNameConflictFixer(configuration.overloadAggressively,
342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptorMap,
343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            warningPrinter,
344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MemberObfuscator(configuration.overloadAggressively,
345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     specialNameFactory,
346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     specialDescriptorMap)))),
347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Clear the collected names.
349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new MapCleaner(descriptorMap)
350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }));
351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print out any warnings about member name conflicts.
353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int warningCount = warningPrinter.getWarningCount();
354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (warningCount > 0)
355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("Warning: there were " + warningCount +
357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                               " conflicting class member name mappings.");
358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("         Your configuration may be inconsistent.");
359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!configuration.ignoreWarnings)
361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.err.println("         If you are sure the conflicts are harmless,");
363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.err.println("         you could try your luck using the '-ignorewarnings' option.");
364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new IOException("Please correct the above warnings first.");
365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Print out the mapping, if requested.
369b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configuration.printMapping != null)
370b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
371b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            PrintStream ps = isFile(configuration.printMapping) ?
372b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new PrintStream(new BufferedOutputStream(new FileOutputStream(configuration.printMapping))) :
373b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.out;
374b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
375b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Print out items that will be removed.
376b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClassPool.classesAcceptAlphabetically(new MappingPrinter(ps));
377b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (ps != System.out)
379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ps.close();
381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Actually apply the new names.
385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(new ClassRenamer());
386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.classesAccept(new ClassRenamer());
387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Update all references to these new names.
389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(new ClassReferenceFixer(false));
390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        libraryClassPool.classesAccept(new ClassReferenceFixer(false));
391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        programClassPool.classesAccept(new MemberReferenceFixer());
392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make package visible elements public or protected, if obfuscated
394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // classes are being repackaged aggressively.
395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configuration.repackageClasses != null &&
396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            configuration.allowAccessModification)
397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClassPool.classesAccept(
399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AllConstantVisitor(
400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new AccessFixer()));
401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Rename the source file attributes, if requested.
404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configuration.newSourceFileAttribute != null)
405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programClassPool.classesAccept(new SourceFileRenamer(configuration.newSourceFileAttribute));
407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
4099f606f95f03a75961498803e24bee6799a7c0885Ying Wang        // Mark NameAndType constant pool entries that have to be kept
4109f606f95f03a75961498803e24bee6799a7c0885Ying Wang        // and remove the other ones.
4119f606f95f03a75961498803e24bee6799a7c0885Ying Wang        programClassPool.classesAccept(new NameAndTypeUsageMarker());
4129f606f95f03a75961498803e24bee6799a7c0885Ying Wang        programClassPool.classesAccept(new NameAndTypeShrinker());
4139f606f95f03a75961498803e24bee6799a7c0885Ying Wang
4149f606f95f03a75961498803e24bee6799a7c0885Ying Wang        // Mark Utf8 constant pool entries that have to be kept
4159f606f95f03a75961498803e24bee6799a7c0885Ying Wang        // and remove the other ones.
4169f606f95f03a75961498803e24bee6799a7c0885Ying Wang        programClassPool.classesAccept(new Utf8UsageMarker());
4179f606f95f03a75961498803e24bee6799a7c0885Ying Wang        programClassPool.classesAccept(new Utf8Shrinker());
418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
422b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether the given file is actually a file, or just a placeholder
423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * for the standard output.
424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean isFile(File file)
426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
427b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return file.getPath().length() > 0;
428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
430