summaryrefslogtreecommitdiff
path: root/src/proguard/gradle/ProGuardTask.java
diff options
context:
space:
mode:
authorYing Wang <wangying@google.com>2013-09-20 16:17:43 -0700
committerYing Wang <wangying@google.com>2013-09-20 16:32:42 -0700
commitb9cc48a43ed984587c939d02fba5316bf5c0df6e (patch)
tree7d42e31a97264803b1147ef6001e8a5e6968a122 /src/proguard/gradle/ProGuardTask.java
parent54f59ac04f3e21d5aecdd46bb1e7f4577924ab92 (diff)
downloadproguard-b9cc48a43ed984587c939d02fba5316bf5c0df6e.tar.gz
Upgrade Proguard to 4.10.
Downloaded from: http://sourceforge.net/projects/proguard/files/proguard/4.10/ Bug: 8992787 Change-Id: Ia07cc5b3feed443982b7e8f2a1f361479e735b18
Diffstat (limited to 'src/proguard/gradle/ProGuardTask.java')
-rw-r--r--src/proguard/gradle/ProGuardTask.java1532
1 files changed, 1532 insertions, 0 deletions
diff --git a/src/proguard/gradle/ProGuardTask.java b/src/proguard/gradle/ProGuardTask.java
new file mode 100644
index 0000000..f5f96e8
--- /dev/null
+++ b/src/proguard/gradle/ProGuardTask.java
@@ -0,0 +1,1532 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * 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.gradle;
+
+import groovy.lang.Closure;
+import org.gradle.api.*;
+import org.gradle.api.file.*;
+import org.gradle.api.logging.*;
+import org.gradle.api.tasks.*;
+import proguard.*;
+import proguard.classfile.*;
+import proguard.classfile.util.ClassUtil;
+import proguard.util.ListUtil;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This Task allows to configure and run ProGuard from Gradle.
+ *
+ * @author Eric Lafortune
+ */
+public class ProGuardTask extends DefaultTask
+{
+ // Accumulated input and output, for the sake of Gradle's lazy file
+ // resolution and lazy task execution.
+ private final List inJarFiles = new ArrayList();
+ private final List inJarFilters = new ArrayList();
+ private final List outJarFiles = new ArrayList();
+ private final List outJarFilters = new ArrayList();
+ private final List inJarCounts = new ArrayList();
+ private final List libraryJarFiles = new ArrayList();
+ private final List libraryJarFilters = new ArrayList();
+ private final List configurationFiles = new ArrayList();
+
+ // Accumulated configuration.
+ private final Configuration configuration = new Configuration();
+
+ // Field acting as a parameter for the class member specification methods.
+ private ClassSpecification classSpecification;
+
+
+ // Gradle task inputs and outputs, because annotations on the List fields
+ // (private or not) don't seem to work. Private methods don't work either,
+ // but package visible or protected methods are ok.
+
+ @InputFiles
+ protected FileCollection getInJarFiles() throws ParseException
+ {
+ return getProject().files(inJarFiles);
+ }
+
+ @Optional @OutputFiles
+ protected FileCollection getOutJarFiles() throws ParseException
+ {
+ return getProject().files(outJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getLibraryJarFiles() throws ParseException
+ {
+ return getProject().files(libraryJarFiles);
+ }
+
+ @InputFiles
+ protected FileCollection getConfigurationFiles() throws ParseException
+ {
+ return getProject().files(configurationFiles);
+ }
+
+
+ // Gradle task settings corresponding to all ProGuard options.
+
+ public void configuration(Object configurationFiles)
+ throws ParseException, IOException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.configurationFiles.add(configurationFiles);
+ }
+
+ public void injars(Object inJarFiles)
+ throws ParseException
+ {
+ injars(null, inJarFiles);
+ }
+
+ public void injars(Map filterArgs, Object inJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.inJarFiles.add(inJarFiles);
+ this.inJarFilters.add(filterArgs);
+ }
+
+ public void outjars(Object outJarFiles)
+ throws ParseException
+ {
+ outjars(null, outJarFiles);
+ }
+
+ public void outjars(Map filterArgs, Object outJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.outJarFiles.add(getProject().file(outJarFiles));
+ this.outJarFilters.add(filterArgs);
+ this.inJarCounts.add(Integer.valueOf(inJarFiles.size()));
+ }
+
+ public void libraryjars(Object libraryJarFiles)
+ throws ParseException
+ {
+ libraryjars(null, libraryJarFiles);
+ }
+
+ public void libraryjars(Map filterArgs, Object libraryJarFiles)
+ throws ParseException
+ {
+ // Just collect the arguments, so they can be resolved lazily.
+ this.libraryJarFiles.add(libraryJarFiles);
+ this.libraryJarFilters.add(filterArgs);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getskipnonpubliclibraryclasses()
+ {
+ skipnonpubliclibraryclasses();
+ return null;
+ }
+
+ public void skipnonpubliclibraryclasses()
+ {
+ configuration.skipNonPublicLibraryClasses = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontskipnonpubliclibraryclassmembers()
+ {
+ dontskipnonpubliclibraryclassmembers();
+ return null;
+ }
+
+ public void dontskipnonpubliclibraryclassmembers()
+ {
+ configuration.skipNonPublicLibraryClassMembers = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepdirectories()
+ {
+ keepdirectories();
+ return null;
+ }
+
+ public void keepdirectories()
+ {
+ keepdirectories(null);
+ }
+
+ public void keepdirectories(String filter)
+ {
+ configuration.keepDirectories =
+ extendFilter(configuration.keepDirectories, filter);
+ }
+
+ public void target(String targetClassVersion)
+ {
+ configuration.targetClassVersion =
+ ClassUtil.internalClassVersion(targetClassVersion);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getforceprocessing()
+ {
+ forceprocessing();
+ return null;
+ }
+
+ public void forceprocessing()
+ {
+ configuration.lastModified = Long.MAX_VALUE;
+ }
+
+ public void keep(String classSpecificationString)
+ throws ParseException
+ {
+ keep(null, classSpecificationString);
+ }
+
+ public void keep(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keep(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keep(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keep(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembers(null, classSpecificationString);
+ }
+
+ public void keepclassmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembers(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembers(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembers(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembers(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembers(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(false,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepnames(String classSpecificationString)
+ throws ParseException
+ {
+ keepnames(null, classSpecificationString);
+ }
+
+ public void keepnames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepnames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepnames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ true,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclassmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclassmembernames(null, classSpecificationString);
+ }
+
+ public void keepclassmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclassmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclassmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ false,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ public void keepclasseswithmembernames(String classSpecificationString)
+ throws ParseException
+ {
+ keepclasseswithmembernames(null, classSpecificationString);
+ }
+
+ public void keepclasseswithmembernames(Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepArgs,
+ classSpecificationString));
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs)
+ throws ParseException
+ {
+ keepclasseswithmembernames(keepClassSpecificationArgs, (Closure)null);
+ }
+
+ public void keepclasseswithmembernames(Map keepClassSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.keep =
+ extendClassSpecifications(configuration.keep,
+ createKeepClassSpecification(true,
+ false,
+ true,
+ keepClassSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintseeds()
+ {
+ printseeds();
+ return null;
+ }
+
+ public void printseeds()
+ {
+ configuration.printSeeds = Configuration.STD_OUT;
+ }
+
+ public void printseeds(Object printSeeds)
+ throws ParseException
+ {
+ configuration.printSeeds = getProject().file(printSeeds);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontshrink()
+ {
+ dontshrink();
+ return null;
+ }
+
+ public void dontshrink()
+ {
+ configuration.shrink = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintusage()
+ {
+ printusage();
+ return null;
+ }
+
+ public void printusage()
+ {
+ configuration.printUsage = Configuration.STD_OUT;
+ }
+
+ public void printusage(Object printUsage)
+ throws ParseException
+ {
+ configuration.printUsage = getProject().file(printUsage);
+ }
+
+ public void whyareyoukeeping(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs)
+ throws ParseException
+ {
+ whyareyoukeeping(classSpecificationArgs, null);
+ }
+
+ public void whyareyoukeeping(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.whyAreYouKeeping =
+ extendClassSpecifications(configuration.whyAreYouKeeping,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontoptimize()
+ {
+ dontoptimize();
+ return null;
+ }
+
+ public void dontoptimize()
+ {
+ configuration.optimize = false;
+ }
+
+ public void optimizations(String filter)
+ {
+ configuration.optimizations =
+ extendFilter(configuration.optimizations, filter);
+ }
+
+
+ public void optimizationpasses(int optimizationPasses)
+ {
+ configuration.optimizationPasses = optimizationPasses;
+ }
+
+ public void assumenosideeffects(String classSpecificationString)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationString));
+ }
+
+ public void assumenosideeffects(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ configuration.assumeNoSideEffects =
+ extendClassSpecifications(configuration.assumeNoSideEffects,
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure));
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getallowaccessmodification()
+ {
+ allowaccessmodification();
+ return null;
+ }
+
+ public void allowaccessmodification()
+ {
+ configuration.allowAccessModification = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmergeinterfacesaggressively()
+ {
+ mergeinterfacesaggressively();
+ return null;
+ }
+
+ public void mergeinterfacesaggressively()
+ {
+ configuration.mergeInterfacesAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontobfuscate()
+ {
+ dontobfuscate();
+ return null;
+ }
+
+ public void dontobfuscate()
+ {
+ configuration.obfuscate = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintmapping()
+ {
+ printmapping();
+ return null;
+ }
+
+ public void printmapping()
+ {
+ configuration.printMapping = Configuration.STD_OUT;
+ }
+
+ public void printmapping(Object printMapping)
+ throws ParseException
+ {
+ configuration.printMapping = getProject().file(printMapping);
+ }
+
+ public void applymapping(Object applyMapping)
+ throws ParseException
+ {
+ configuration.applyMapping = getProject().file(applyMapping);
+ }
+
+ public void obfuscationdictionary(Object obfuscationDictionary)
+ throws ParseException
+ {
+ configuration.obfuscationDictionary =
+ getProject().file(obfuscationDictionary);
+ }
+
+ public void classobfuscationdictionary(Object classObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.classObfuscationDictionary =
+ getProject().file(classObfuscationDictionary);
+ }
+
+ public void packageobfuscationdictionary(Object packageObfuscationDictionary)
+ throws ParseException
+ {
+ configuration.packageObfuscationDictionary =
+ getProject().file(packageObfuscationDictionary);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getoverloadaggressively()
+ {
+ overloadaggressively();
+ return null;
+ }
+
+ public void overloadaggressively()
+ {
+ configuration.overloadAggressively = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getuseuniqueclassmembernames()
+ {
+ useuniqueclassmembernames();
+ return null;
+ }
+
+ public void useuniqueclassmembernames()
+ {
+ configuration.useUniqueClassMemberNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontusemixedcaseclassnames()
+ {
+ dontusemixedcaseclassnames();
+ return null;
+ }
+
+ public void dontusemixedcaseclassnames()
+ {
+ configuration.useMixedCaseClassNames = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeeppackagenames()
+ {
+ keeppackagenames();
+ return null;
+ }
+
+ public void keeppackagenames()
+ {
+ keeppackagenames(null);
+ }
+
+ public void keeppackagenames(String filter)
+ {
+ configuration.keepPackageNames =
+ extendFilter(configuration.keepPackageNames, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getflattenpackagehierarchy()
+ {
+ flattenpackagehierarchy();
+ return null;
+ }
+
+ public void flattenpackagehierarchy()
+ {
+ flattenpackagehierarchy("");
+ }
+
+ public void flattenpackagehierarchy(String flattenPackageHierarchy)
+ {
+ configuration.flattenPackageHierarchy =
+ ClassUtil.internalClassName(flattenPackageHierarchy);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrepackageclasses()
+ {
+ repackageclasses();
+ return null;
+ }
+
+ public void repackageclasses()
+ {
+ repackageclasses("");
+ }
+
+ public void repackageclasses(String repackageClasses)
+ {
+ configuration.repackageClasses =
+ ClassUtil.internalClassName(repackageClasses);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepattributes()
+ {
+ keepattributes();
+ return null;
+ }
+
+ public void keepattributes()
+ {
+ keepattributes(null);
+ }
+
+ public void keepattributes(String filter)
+ {
+ configuration.keepAttributes =
+ extendFilter(configuration.keepAttributes, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getkeepparameternames()
+ {
+ keepparameternames();
+ return null;
+ }
+
+ public void keepparameternames()
+ {
+ configuration.keepParameterNames = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getrenamesourcefileattribute()
+ {
+ renamesourcefileattribute();
+ return null;
+ }
+
+ public void renamesourcefileattribute()
+ {
+ renamesourcefileattribute("");
+ }
+
+ public void renamesourcefileattribute(String newSourceFileAttribute)
+ {
+ configuration.newSourceFileAttribute = newSourceFileAttribute;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptclassstrings()
+ {
+ adaptclassstrings();
+ return null;
+ }
+
+ public void adaptclassstrings()
+ {
+ adaptclassstrings(null);
+ }
+
+ public void adaptclassstrings(String filter)
+ {
+ configuration.adaptClassStrings =
+ extendFilter(configuration.adaptClassStrings, filter, true);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilenames()
+ {
+ adaptresourcefilenames();
+ return null;
+ }
+
+ public void adaptresourcefilenames()
+ {
+ adaptresourcefilenames(null);
+ }
+
+ public void adaptresourcefilenames(String filter)
+ {
+ configuration.adaptResourceFileNames =
+ extendFilter(configuration.adaptResourceFileNames, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getadaptresourcefilecontents()
+ {
+ adaptresourcefilecontents();
+ return null;
+ }
+
+ public void adaptresourcefilecontents()
+ {
+ adaptresourcefilecontents(null);
+ }
+
+ public void adaptresourcefilecontents(String filter)
+ {
+ configuration.adaptResourceFileContents =
+ extendFilter(configuration.adaptResourceFileContents, filter);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontpreverify()
+ {
+ dontpreverify();
+ return null;
+ }
+
+ public void dontpreverify()
+ {
+ configuration.preverify = false;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getmicroedition()
+ {
+ microedition();
+ return null;
+ }
+
+ public void microedition()
+ {
+ configuration.microEdition = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getverbose()
+ {
+ verbose();
+ return null;
+ }
+
+ public void verbose()
+ {
+ configuration.verbose = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontnote()
+ {
+ dontnote();
+ return null;
+ }
+
+ public void dontnote()
+ {
+ dontnote(null);
+ }
+
+ public void dontnote(String filter)
+ {
+ configuration.note = extendFilter(configuration.note, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdontwarn()
+ {
+ dontwarn();
+ return null;
+ }
+
+ public void dontwarn()
+ {
+ dontwarn(null);
+ }
+
+ public void dontwarn(String filter)
+ {
+ configuration.warn = extendFilter(configuration.warn, filter, true);
+ }
+
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getignorewarnings()
+ {
+ ignorewarnings();
+ return null;
+ }
+
+ public void ignorewarnings()
+ {
+ configuration.ignoreWarnings = true;
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getprintconfiguration()
+ {
+ printconfiguration();
+ return null;
+ }
+
+ public void printconfiguration()
+ {
+ configuration.printConfiguration = Configuration.STD_OUT;
+ }
+
+ public void printconfiguration(Object printConfiguration)
+ throws ParseException
+ {
+ configuration.printConfiguration =
+ getProject().file(printConfiguration);
+ }
+
+ // Hack: support the keyword without parentheses in Groovy.
+ public Object getdump()
+ {
+ dump();
+ return null;
+ }
+
+ public void dump()
+ {
+ configuration.dump = Configuration.STD_OUT;
+ }
+
+ public void dump(Object dump)
+ throws ParseException
+ {
+ configuration.dump = getProject().file(dump);
+ }
+
+
+ // Class member methods.
+
+ public void field(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'field' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addField(createMemberSpecification(false,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ public void constructor(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'constructor' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ true,
+ memberSpecificationArgs));
+ }
+
+
+ public void method(Map memberSpecificationArgs)
+ throws ParseException
+ {
+ if (classSpecification == null)
+ {
+ throw new IllegalArgumentException("The 'method' method can only be used nested inside a class specification.");
+ }
+
+ classSpecification.addMethod(createMemberSpecification(true,
+ false,
+ memberSpecificationArgs));
+ }
+
+
+ // Gradle task execution.
+
+ @TaskAction
+ public void proguard()
+ throws ParseException, IOException
+ {
+ // Weave the input jars and the output jars into a single class path,
+ // with lazy resolution of the files.
+ configuration.programJars = new ClassPath();
+
+ int outJarIndex = 0;
+
+ int inJarCount = inJarCounts.size() == 0 ? -1 :
+ ((Integer)inJarCounts.get(0)).intValue();
+
+ for (int inJarIndex = 0; inJarIndex < inJarFiles.size(); inJarIndex++)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ inJarFiles.get(inJarIndex),
+ (Map)inJarFilters.get(inJarIndex),
+ false);
+
+ while (inJarIndex == inJarCount - 1)
+ {
+ configuration.programJars =
+ extendClassPath(configuration.programJars,
+ outJarFiles.get(outJarIndex),
+ (Map)outJarFilters.get(outJarIndex),
+ true);
+
+ outJarIndex++;
+
+ inJarCount = inJarCounts.size() == outJarIndex ? -1 :
+ ((Integer)inJarCounts.get(outJarIndex)).intValue();
+ }
+ }
+
+ // Copy the library jars into a single class path, with lazy resolution
+ // of the files.
+ configuration.libraryJars = new ClassPath();
+
+ for (int libraryJarIndex = 0; libraryJarIndex < libraryJarFiles.size(); libraryJarIndex++)
+ {
+ configuration.libraryJars =
+ extendClassPath(configuration.libraryJars,
+ libraryJarFiles.get(libraryJarIndex),
+ (Map)libraryJarFilters.get(libraryJarIndex),
+ false);
+ }
+
+ // Lazily apply the external configuration files.
+ ConfigurableFileCollection fileCollection =
+ getProject().files(configurationFiles);
+
+ Iterator<File> files = fileCollection.iterator();
+ while (files.hasNext())
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(files.next(), System.getProperties());
+
+ try
+ {
+ parser.parse(configuration);
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+
+ // Make sure the code is processed. Gradle has already checked that it
+ // was necessary.
+ configuration.lastModified = Long.MAX_VALUE;
+
+ // Let the logging manager capture the standard output and errors from
+ // ProGuard.
+ LoggingManager loggingManager = getLogging();
+ loggingManager.captureStandardOutput(LogLevel.INFO);
+ loggingManager.captureStandardError(LogLevel.WARN);
+
+ // Run ProGuard with the collected configuration.
+ new ProGuard(configuration).execute();
+
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Extends the given class path with the given filtered input or output
+ * files.
+ */
+ private ClassPath extendClassPath(ClassPath classPath,
+ Object files,
+ Map filterArgs,
+ boolean output)
+ {
+ ConfigurableFileCollection fileCollection = getProject().files(files);
+
+ if (classPath == null)
+ {
+ classPath = new ClassPath();
+ }
+
+ Iterator fileIterator = fileCollection.iterator();
+ while (fileIterator.hasNext())
+ {
+ File file = (File)fileIterator.next();
+ if (output || file.exists())
+ {
+ // Create the class path entry.
+ ClassPathEntry classPathEntry = new ClassPathEntry(file, output);
+
+ // Add any filters to the class path entry.
+ if (filterArgs != null)
+ {
+ classPathEntry.setFilter(ListUtil.commaSeparatedList((String)filterArgs.get("filter")));
+ classPathEntry.setJarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("jarfilter")));
+ classPathEntry.setWarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("warfilter")));
+ classPathEntry.setEarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("earfilter")));
+ classPathEntry.setZipFilter(ListUtil.commaSeparatedList((String)filterArgs.get("zipfilter")));
+ }
+
+ classPath.add(classPathEntry);
+ }
+ }
+
+ return classPath;
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ String classSpecificationString)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationString);
+
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ keepArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ ClassSpecification classSpecification =
+ createClassSpecification(classSpecificationArgs,
+ classMembersClosure);
+ return
+ createKeepClassSpecification(allowShrinking,
+ markClasses,
+ markConditionally,
+ classSpecificationArgs,
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given parameters.
+ */
+ private KeepClassSpecification createKeepClassSpecification(boolean allowShrinking,
+ boolean markClasses,
+ boolean markConditionally,
+ Map keepArgs,
+ ClassSpecification classSpecification)
+ {
+ return
+ new KeepClassSpecification(markClasses,
+ markConditionally,
+ retrieveBoolean(keepArgs, "allowshrinking", allowShrinking),
+ retrieveBoolean(keepArgs, "allowoptimization", false),
+ retrieveBoolean(keepArgs, "allowobfuscation", false),
+ classSpecification);
+ }
+
+
+ /**
+ * Creates specifications to keep classes and class members, based on the
+ * given ProGuard-style class specification.
+ */
+ private ClassSpecification createClassSpecification(String classSpecificationString)
+ throws ParseException
+ {
+ try
+ {
+ ConfigurationParser parser =
+ new ConfigurationParser(new String[] { classSpecificationString }, null);
+
+ try
+ {
+ return parser.parseClassSpecificationArguments();
+ }
+ finally
+ {
+ parser.close();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ParseException(e.getMessage());
+ }
+ }
+
+
+ /**
+ * Creates a specification of classes and class members, based on the
+ * given parameters.
+ */
+ private ClassSpecification createClassSpecification(Map classSpecificationArgs,
+ Closure classMembersClosure)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String type = (String)classSpecificationArgs.get("type");
+ String name = (String)classSpecificationArgs.get("name");
+ String extendsAnnotation = (String)classSpecificationArgs.get("extendsannotation");
+ String extends_ = (String)classSpecificationArgs.get("extends");
+ if (extends_ == null)
+ {
+ extends_ = (String)classSpecificationArgs.get("implements");
+ }
+
+ // Create the class specification.
+ ClassSpecification classSpecification =
+ new ClassSpecification(null,
+ requiredClassAccessFlags(true, access, type),
+ requiredClassAccessFlags(false, access, type),
+ annotation != null ? ClassUtil.internalType(annotation) : null,
+ name != null ? ClassUtil.internalClassName(name) : null,
+ extendsAnnotation != null ? ClassUtil.internalType(extendsAnnotation) : null,
+ extends_ != null ? ClassUtil.internalClassName(extends_) : null);
+
+ // Initialize the class specification with its closure.
+ if (classMembersClosure != null)
+ {
+ // Temporarily remember the class specification, so we can add
+ // class member specifications.
+ this.classSpecification = classSpecification;
+ classMembersClosure.call(classSpecification);
+ this.classSpecification = null;
+ }
+
+ return classSpecification;
+ }
+
+
+ /**
+ * Parses the class access flags that must be set (or not), based on the
+ * given ProGuard-style flag specification.
+ */
+ private int requiredClassAccessFlags(boolean set,
+ String access,
+ String type)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ if (type != null && (type.startsWith("!") ^ set))
+ {
+ int accessFlag =
+ type.equals("class") ? 0 :
+ type.equals( ClassConstants.EXTERNAL_ACC_INTERFACE) ||
+ type.equals("!" + ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE :
+ type.equals( ClassConstants.EXTERNAL_ACC_ENUM) ||
+ type.equals("!" + ClassConstants.EXTERNAL_ACC_ENUM) ? ClassConstants.INTERNAL_ACC_ENUM :
+ -1;
+ if (accessFlag == -1)
+ {
+ throw new ParseException("Incorrect class type ["+type+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Creates a specification of class members, based on the given parameters.
+ */
+ private MemberSpecification createMemberSpecification(boolean isMethod,
+ boolean isConstructor,
+ Map classSpecificationArgs)
+ throws ParseException
+ {
+ // Extract the arguments.
+ String access = (String)classSpecificationArgs.get("access");
+ String type = (String)classSpecificationArgs.get("type");
+ String annotation = (String)classSpecificationArgs.get("annotation");
+ String name = (String)classSpecificationArgs.get("name");
+ String parameters = (String)classSpecificationArgs.get("parameters");
+
+ // Perform some basic conversions and checks on the attributes.
+ if (annotation != null)
+ {
+ annotation = ClassUtil.internalType(annotation);
+ }
+
+ if (isMethod)
+ {
+ if (isConstructor)
+ {
+ if (type != null)
+ {
+ throw new ParseException("Type attribute not allowed in constructor specification ["+type+"]");
+ }
+
+ if (parameters != null)
+ {
+ type = ClassConstants.EXTERNAL_TYPE_VOID;
+ }
+
+ name = ClassConstants.INTERNAL_METHOD_NAME_INIT;
+ }
+ else if ((type != null) ^ (parameters != null))
+ {
+ throw new ParseException("Type and parameters attributes must always be present in combination in method specification");
+ }
+ }
+ else
+ {
+ if (parameters != null)
+ {
+ throw new ParseException("Parameters attribute not allowed in field specification ["+parameters+"]");
+ }
+ }
+
+ List parameterList = ListUtil.commaSeparatedList(parameters);
+
+ String descriptor =
+ parameters != null ? ClassUtil.internalMethodDescriptor(type, parameterList) :
+ type != null ? ClassUtil.internalType(type) :
+ null;
+
+ return new MemberSpecification(requiredMemberAccessFlags(true, access),
+ requiredMemberAccessFlags(false, access),
+ annotation,
+ name,
+ descriptor);
+ }
+
+
+ /**
+ * Parses the class member access flags that must be set (or not), based on
+ * the given ProGuard-style flag specification.
+ */
+ private int requiredMemberAccessFlags(boolean set,
+ String access)
+ throws ParseException
+ {
+ int accessFlags = 0;
+
+ if (access != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(access, " ,");
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken();
+
+ if (token.startsWith("!") ^ set)
+ {
+ String strippedToken = token.startsWith("!") ?
+ token.substring(1) :
+ token;
+
+ int accessFlag =
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PRIVATE) ? ClassConstants.INTERNAL_ACC_PRIVATE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_PROTECTED) ? ClassConstants.INTERNAL_ACC_PROTECTED :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_STATIC) ? ClassConstants.INTERNAL_ACC_STATIC :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT :
+ strippedToken.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC :
+ 0;
+
+ if (accessFlag == 0)
+ {
+ throw new ParseException("Incorrect class member access modifier ["+strippedToken+"]");
+ }
+
+ accessFlags |= accessFlag;
+ }
+ }
+ }
+
+ return accessFlags;
+ }
+
+
+ /**
+ * Retrieves a specified boolean flag from the given map.
+ */
+ private boolean retrieveBoolean(Map args, String name, boolean defaultValue)
+ {
+ if (args == null)
+ {
+ return defaultValue;
+ }
+
+ Object arg = args.get(name);
+
+ return arg == null ? defaultValue : ((Boolean)arg).booleanValue();
+ }
+
+
+ /**
+ * Adds the given class specification to the given list, creating a new list
+ * if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ ClassSpecification classSpecification)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.add(classSpecification);
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given class specifications to the given list, creating a new
+ * list if necessary.
+ */
+ private List extendClassSpecifications(List classSpecifications,
+ List additionalClassSpecifications)
+ {
+ if (additionalClassSpecifications != null)
+ {
+ if (classSpecifications == null)
+ {
+ classSpecifications = new ArrayList();
+ }
+
+ classSpecifications.addAll(additionalClassSpecifications);
+ }
+
+ return classSpecifications;
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary.
+ */
+ private List extendFilter(List filter,
+ String filterString)
+ {
+ return extendFilter(filter, filterString, false);
+ }
+
+
+ /**
+ * Adds the given filter to the given list, creating a new list if
+ * necessary. External class names are converted to internal class names,
+ * if requested.
+ */
+ private List extendFilter(List filter,
+ String filterString,
+ boolean convertExternalClassNames)
+ {
+ if (filter == null)
+ {
+ filter = new ArrayList();
+ }
+
+ if (filterString == null)
+ {
+ // Clear the filter to keep all names.
+ filter.clear();
+ }
+ else
+ {
+ if (convertExternalClassNames)
+ {
+ filterString = ClassUtil.internalClassName(filterString);
+ }
+
+ // Append the filter.
+ filter.addAll(ListUtil.commaSeparatedList(filterString));
+ }
+
+ return filter;
+ }
+}