aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java')
-rw-r--r--third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java558
1 files changed, 558 insertions, 0 deletions
diff --git a/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java b/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java
new file mode 100644
index 0000000000..73dce7323b
--- /dev/null
+++ b/third_party/java/proguard/proguard5.3.3/src/proguard/ProGuard.java
@@ -0,0 +1,558 @@
+/*
+ * 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.*;
+import proguard.classfile.attribute.visitor.AllAttributeVisitor;
+import proguard.classfile.editor.*;
+import proguard.classfile.visitor.*;
+import proguard.obfuscate.Obfuscator;
+import proguard.optimize.Optimizer;
+import proguard.optimize.peephole.LineNumberLinearizer;
+import proguard.preverify.*;
+import proguard.shrink.Shrinker;
+
+import java.io.*;
+
+/**
+ * Tool for shrinking, optimizing, obfuscating, and preverifying Java classes.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuard
+{
+ public static final String VERSION = "ProGuard, version 5.3.3";
+
+ private final Configuration configuration;
+ private ClassPool programClassPool = new ClassPool();
+ private final ClassPool libraryClassPool = new ClassPool();
+
+
+ /**
+ * Creates a new ProGuard object to process jars as specified by the given
+ * configuration.
+ */
+ public ProGuard(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+
+ /**
+ * Performs all subsequent ProGuard operations.
+ */
+ public void execute() throws IOException
+ {
+ System.out.println(VERSION);
+
+ GPL.check();
+
+ if (configuration.printConfiguration != null)
+ {
+ printConfiguration();
+ }
+
+ new ConfigurationChecker(configuration).check();
+
+ if (configuration.programJars != null &&
+ configuration.programJars.hasOutput() &&
+ new UpToDateChecker(configuration).check())
+ {
+ return;
+ }
+
+ readInput();
+
+ if (configuration.shrink ||
+ configuration.optimize ||
+ configuration.obfuscate ||
+ configuration.preverify)
+ {
+ clearPreverification();
+ }
+
+ if (configuration.printSeeds != null ||
+ configuration.shrink ||
+ configuration.optimize ||
+ configuration.obfuscate ||
+ configuration.preverify)
+ {
+ initialize();
+ }
+
+ if (configuration.targetClassVersion != 0)
+ {
+ target();
+ }
+
+ if (configuration.printSeeds != null)
+ {
+ printSeeds();
+ }
+
+ if (configuration.shrink)
+ {
+ shrink();
+ }
+
+ if (configuration.preverify)
+ {
+ inlineSubroutines();
+ }
+
+ if (configuration.optimize)
+ {
+ for (int optimizationPass = 0;
+ optimizationPass < configuration.optimizationPasses;
+ optimizationPass++)
+ {
+ if (!optimize())
+ {
+ // Stop optimizing if the code doesn't improve any further.
+ break;
+ }
+
+ // Shrink again, if we may.
+ if (configuration.shrink)
+ {
+ // Don't print any usage this time around.
+ configuration.printUsage = null;
+ configuration.whyAreYouKeeping = null;
+
+ shrink();
+ }
+ }
+ }
+
+ if (configuration.optimize)
+ {
+ linearizeLineNumbers();
+ }
+
+ if (configuration.obfuscate)
+ {
+ obfuscate();
+ }
+
+ if (configuration.optimize)
+ {
+ trimLineNumbers();
+ }
+
+ if (configuration.preverify)
+ {
+ preverify();
+ }
+
+ if (configuration.shrink ||
+ configuration.optimize ||
+ configuration.obfuscate ||
+ configuration.preverify)
+ {
+ sortClassElements();
+ }
+
+ if (configuration.programJars.hasOutput())
+ {
+ writeOutput();
+ }
+
+ if (configuration.dump != null)
+ {
+ dump();
+ }
+ }
+
+
+ /**
+ * Prints out the configuration that ProGuard is using.
+ */
+ private void printConfiguration() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Printing configuration to [" + fileName(configuration.printConfiguration) + "]...");
+ }
+
+ PrintStream ps = createPrintStream(configuration.printConfiguration);
+ try
+ {
+ new ConfigurationWriter(ps).write(configuration);
+ }
+ finally
+ {
+ closePrintStream(ps);
+ }
+ }
+
+
+ /**
+ * Reads the input class files.
+ */
+ private void readInput() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Reading input...");
+ }
+
+ // Fill the program class pool and the library class pool.
+ new InputReader(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Initializes the cross-references between all classes, performs some
+ * basic checks, and shrinks the library class pool.
+ */
+ private void initialize() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Initializing...");
+ }
+
+ new Initializer(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Sets that target versions of the program classes.
+ */
+ private void target() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Setting target versions...");
+ }
+
+ new Targeter(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Prints out classes and class members that are used as seeds in the
+ * shrinking and obfuscation steps.
+ */
+ private void printSeeds() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Printing kept classes, fields, and methods...");
+ }
+
+ PrintStream ps = createPrintStream(configuration.printSeeds);
+ try
+ {
+ new SeedPrinter(ps).write(configuration, programClassPool, libraryClassPool);
+ }
+ finally
+ {
+ closePrintStream(ps);
+ }
+ }
+
+
+ /**
+ * Performs the shrinking step.
+ */
+ private void shrink() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Shrinking...");
+
+ // We'll print out some explanation, if requested.
+ if (configuration.whyAreYouKeeping != null)
+ {
+ System.out.println("Explaining why classes and class members are being kept...");
+ }
+
+ // We'll print out the usage, if requested.
+ if (configuration.printUsage != null)
+ {
+ System.out.println("Printing usage to [" + fileName(configuration.printUsage) + "]...");
+ }
+ }
+
+ // Perform the actual shrinking.
+ programClassPool =
+ new Shrinker(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Performs the subroutine inlining step.
+ */
+ private void inlineSubroutines()
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Inlining subroutines...");
+ }
+
+ // Perform the actual inlining.
+ new SubroutineInliner(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Performs the optimization step.
+ */
+ private boolean optimize() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Optimizing...");
+ }
+
+ // Perform the actual optimization.
+ return new Optimizer(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Performs the obfuscation step.
+ */
+ private void obfuscate() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Obfuscating...");
+
+ // We'll apply a mapping, if requested.
+ if (configuration.applyMapping != null)
+ {
+ System.out.println("Applying mapping [" + fileName(configuration.applyMapping) + "]");
+ }
+
+ // We'll print out the mapping, if requested.
+ if (configuration.printMapping != null)
+ {
+ System.out.println("Printing mapping to [" + fileName(configuration.printMapping) + "]...");
+ }
+ }
+
+ // Perform the actual obfuscation.
+ new Obfuscator(configuration).execute(programClassPool, libraryClassPool);
+ }
+
+
+ /**
+ * Disambiguates the line numbers of all program classes, after
+ * optimizations like method inlining and class merging.
+ */
+ private void linearizeLineNumbers()
+ {
+ programClassPool.classesAccept(new LineNumberLinearizer());
+ }
+
+
+ /**
+ * Trims the line number table attributes of all program classes.
+ */
+ private void trimLineNumbers()
+ {
+ programClassPool.classesAccept(new AllAttributeVisitor(true,
+ new LineNumberTableAttributeTrimmer()));
+ }
+
+
+ /**
+ * Clears any JSE preverification information from the program classes.
+ */
+ private void clearPreverification()
+ {
+ programClassPool.classesAccept(
+ new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_6,
+ new AllMethodVisitor(
+ new AllAttributeVisitor(
+ new NamedAttributeDeleter(ClassConstants.ATTR_StackMapTable)))));
+ }
+
+
+ /**
+ * Performs the preverification step.
+ */
+ private void preverify()
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Preverifying...");
+ }
+
+ // Perform the actual preverification.
+ new Preverifier(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Sorts the elements of all program classes.
+ */
+ private void sortClassElements()
+ {
+ programClassPool.classesAccept(new ClassElementSorter());
+ }
+
+
+ /**
+ * Writes the output class files.
+ */
+ private void writeOutput() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Writing output...");
+ }
+
+ // Write out the program class pool.
+ new OutputWriter(configuration).execute(programClassPool);
+ }
+
+
+ /**
+ * Prints out the contents of the program classes.
+ */
+ private void dump() throws IOException
+ {
+ if (configuration.verbose)
+ {
+ System.out.println("Printing classes to [" + fileName(configuration.dump) + "]...");
+ }
+
+ PrintStream ps = createPrintStream(configuration.dump);
+ try
+ {
+ programClassPool.classesAccept(new ClassPrinter(ps));
+ }
+ finally
+ {
+ closePrintStream(ps);
+ }
+ }
+
+
+ /**
+ * Returns a print stream for the given file, or the standard output if
+ * the file name is empty.
+ */
+ private PrintStream createPrintStream(File file)
+ throws FileNotFoundException
+ {
+ return file == Configuration.STD_OUT ? System.out :
+ new PrintStream(
+ new BufferedOutputStream(
+ new FileOutputStream(file)));
+ }
+
+
+ /**
+ * Closes the given print stream, or closes it if is the standard output.
+ * @param printStream
+ */
+ private void closePrintStream(PrintStream printStream)
+ {
+ if (printStream == System.out)
+ {
+ printStream.flush();
+ }
+ else
+ {
+ printStream.close();
+ }
+ }
+
+
+ /**
+ * Returns the canonical file name for the given file, or "standard output"
+ * if the file name is empty.
+ */
+ private String fileName(File file)
+ {
+ if (file == Configuration.STD_OUT)
+ {
+ return "standard output";
+ }
+ else
+ {
+ try
+ {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ex)
+ {
+ return file.getPath();
+ }
+ }
+ }
+
+
+ /**
+ * The main method for ProGuard.
+ */
+ public static void main(String[] args)
+ {
+ if (args.length == 0)
+ {
+ System.out.println(VERSION);
+ System.out.println("Usage: java proguard.ProGuard [options ...]");
+ System.exit(1);
+ }
+
+ // Create the default options.
+ Configuration configuration = new Configuration();
+
+ try
+ {
+ // Parse the options specified in the command line arguments.
+ ConfigurationParser parser = new ConfigurationParser(args,
+ System.getProperties());
+ try
+ {
+ parser.parse(configuration);
+ }
+ finally
+ {
+ parser.close();
+ }
+
+ // Execute ProGuard with these options.
+ new ProGuard(configuration).execute();
+ }
+ catch (Exception ex)
+ {
+ if (configuration.verbose)
+ {
+ // Print a verbose stack trace.
+ ex.printStackTrace();
+ }
+ else
+ {
+ // Print just the stack trace message.
+ System.err.println("Error: "+ex.getMessage());
+ }
+
+ System.exit(1);
+ }
+
+ System.exit(0);
+ }
+}