diff options
Diffstat (limited to 'third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java')
-rw-r--r-- | third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java b/third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java new file mode 100644 index 0000000000..ed3b279306 --- /dev/null +++ b/third_party/java/proguard/proguard5.3.3/src/proguard/OutputWriter.java @@ -0,0 +1,219 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard; + +import proguard.classfile.ClassPool; +import proguard.classfile.util.ClassUtil; +import proguard.io.*; + +import java.io.IOException; +import java.util.*; + +/** + * This class writes the output class files. + * + * @author Eric Lafortune + */ +public class OutputWriter +{ + private final Configuration configuration; + + + /** + * Creates a new OutputWriter to write output class files as specified by + * the given configuration. + */ + public OutputWriter(Configuration configuration) + { + this.configuration = configuration; + } + + + /** + * Writes the given class pool to class files, based on the current + * configuration. + */ + public void execute(ClassPool programClassPool) throws IOException + { + ClassPath programJars = configuration.programJars; + + int firstInputIndex = 0; + int lastInputIndex = 0; + + // Go over all program class path entries. + for (int index = 0; index < programJars.size(); index++) + { + // Is it an input entry? + ClassPathEntry entry = programJars.get(index); + if (!entry.isOutput()) + { + // Remember the index of the last input entry. + lastInputIndex = index; + } + else + { + // Check if this the last output entry in a series. + int nextIndex = index + 1; + if (nextIndex == programJars.size() || + !programJars.get(nextIndex).isOutput()) + { + // Write the processed input entries to the output entries. + writeOutput(programClassPool, + programJars, + firstInputIndex, + lastInputIndex + 1, + nextIndex); + + // Start with the next series of input entries. + firstInputIndex = nextIndex; + } + } + } + } + + + /** + * Transfers the specified input jars to the specified output jars. + */ + private void writeOutput(ClassPool programClassPool, + ClassPath classPath, + int fromInputIndex, + int fromOutputIndex, + int toOutputIndex) + throws IOException + { + try + { + // Construct the writer that can write jars, wars, ears, zips, and + // directories, cascading over the specified output entries. + DataEntryWriter writer = + DataEntryWriterFactory.createDataEntryWriter(classPath, + fromOutputIndex, + toOutputIndex); + + // The writer will be used to write possibly obfuscated class files. + DataEntryReader classRewriter = + new ClassRewriter(programClassPool, writer); + + // The writer will also be used to write resource files. + DataEntryReader resourceCopier = + new DataEntryCopier(writer); + + DataEntryReader resourceRewriter = resourceCopier; + + // Adapt resource file contents and names, if necessary. + if (configuration.obfuscate) + { + // Wrap the resource writer with a filter and a data entry + // rewriter, if required. + if (configuration.adaptResourceFileContents != null) + { + resourceRewriter = + new NameFilter(configuration.adaptResourceFileContents, + new NameFilter("META-INF/MANIFEST.MF,META-INF/*.SF", + new ManifestRewriter(programClassPool, writer), + new DataEntryRewriter(programClassPool, writer)), + resourceRewriter); + } + + // Wrap the resource writer with a filter and a data entry + // renamer, if required. + if (configuration.adaptResourceFileNames != null) + { + Map packagePrefixMap = createPackagePrefixMap(programClassPool); + + resourceRewriter = + new NameFilter(configuration.adaptResourceFileNames, + new DataEntryObfuscator(programClassPool, + packagePrefixMap, + resourceRewriter), + resourceRewriter); + } + } + + DataEntryReader directoryRewriter = null; + + // Wrap the directory writer with a filter and a data entry renamer, + // if required. + if (configuration.keepDirectories != null) + { + Map packagePrefixMap = createPackagePrefixMap(programClassPool); + + directoryRewriter = + new NameFilter(configuration.keepDirectories, + new DataEntryRenamer(packagePrefixMap, + resourceCopier, + resourceCopier)); + } + + // Create the reader that can write class files and copy directories + // and resource files to the main writer. + DataEntryReader reader = + new ClassFilter( classRewriter, + new DirectoryFilter(directoryRewriter, + resourceRewriter)); + + // Go over the specified input entries and write their processed + // versions. + new InputReader(configuration).readInput(" Copying resources from program ", + classPath, + fromInputIndex, + fromOutputIndex, + reader); + + // Close all output entries. + writer.close(); + } + catch (IOException ex) + { + throw (IOException)new IOException("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")").initCause(ex); + } + } + + + /** + * Creates a map of old package prefixes to new package prefixes, based on + * the given class pool. + */ + private static Map createPackagePrefixMap(ClassPool classPool) + { + Map packagePrefixMap = new HashMap(); + + Iterator iterator = classPool.classNames(); + while (iterator.hasNext()) + { + String className = (String)iterator.next(); + String packagePrefix = ClassUtil.internalPackagePrefix(className); + + String mappedNewPackagePrefix = (String)packagePrefixMap.get(packagePrefix); + if (mappedNewPackagePrefix == null || + !mappedNewPackagePrefix.equals(packagePrefix)) + { + String newClassName = classPool.getClass(className).getName(); + String newPackagePrefix = ClassUtil.internalPackagePrefix(newClassName); + + packagePrefixMap.put(packagePrefix, newPackagePrefix); + } + } + + return packagePrefixMap; + } +} |