diff options
Diffstat (limited to 'src/proguard/ant')
-rw-r--r-- | src/proguard/ant/ClassPathElement.java | 191 | ||||
-rw-r--r-- | src/proguard/ant/ClassSpecificationElement.java | 257 | ||||
-rw-r--r-- | src/proguard/ant/ConfigurationElement.java | 53 | ||||
-rw-r--r-- | src/proguard/ant/ConfigurationTask.java | 440 | ||||
-rw-r--r-- | src/proguard/ant/FilterElement.java | 85 | ||||
-rw-r--r-- | src/proguard/ant/KeepSpecificationElement.java | 87 | ||||
-rw-r--r-- | src/proguard/ant/MemberSpecificationElement.java | 215 | ||||
-rw-r--r-- | src/proguard/ant/ProGuardTask.java | 320 | ||||
-rw-r--r-- | src/proguard/ant/package.html | 3 | ||||
-rw-r--r-- | src/proguard/ant/task.properties | 2 |
10 files changed, 1653 insertions, 0 deletions
diff --git a/src/proguard/ant/ClassPathElement.java b/src/proguard/ant/ClassPathElement.java new file mode 100644 index 0000000..b5c2df4 --- /dev/null +++ b/src/proguard/ant/ClassPathElement.java @@ -0,0 +1,191 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.*; +import proguard.*; +import proguard.util.ListUtil; + +import java.io.File; + +/** + * This FileSet represents a class path entry (or a set of class path entries) + * in Ant. + * + * @author Eric Lafortune + */ +public class ClassPathElement extends Path +{ + private String filter; + private String jarFilter; + private String warFilter; + private String earFilter; + private String zipFilter; + + + /** + * @see Path#Path(Project) + */ + public ClassPathElement(Project project) + { + super(project); + } + + + /** + * Adds the contents of this class path element to the given class path. + * @param classPath the class path to be extended. + * @param output specifies whether this is an output entry or not. + */ + public void appendClassPathEntriesTo(ClassPath classPath, boolean output) + { + File baseDir = getProject().getBaseDir(); + String[] fileNames; + + if (isReference()) + { + // Get the referenced path or file set. + Object referencedObject = getCheckedRef(DataType.class, + DataType.class.getName()); + + if (referencedObject instanceof Path) + { + Path path = (Path)referencedObject; + + // Get the names of the files in the referenced path. + fileNames = path.list(); + } + else if (referencedObject instanceof AbstractFileSet) + { + AbstractFileSet fileSet = (AbstractFileSet)referencedObject; + + // Get the names of the existing input files in the referenced file set. + DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject()); + baseDir = scanner.getBasedir(); + fileNames = scanner.getIncludedFiles(); + } + else + { + throw new BuildException("The refid attribute doesn't point to a <path> element or a <fileset> element"); + } + } + else + { + // Get the names of the files in this path. + fileNames = list(); + } + + if (output) + { + if (fileNames.length != 1) + { + throw new BuildException("The <outjar> element must specify exactly one file or directory ["+fileNames.length+"]"); + } + } + //else + //{ + // if (fileNames.length < 1) + // { + // throw new BuildException("The <injar> element must specify at least one file or directory"); + // } + //} + + for (int index = 0; index < fileNames.length; index++) + { + // Create a new class path entry, with the proper file name and + // any filters. + String fileName = fileNames[index]; + File file = new File(fileName); + + ClassPathEntry entry = + new ClassPathEntry(file.isAbsolute() ? file : new File(baseDir, fileName), + output); + entry.setFilter(ListUtil.commaSeparatedList(filter)); + entry.setJarFilter(ListUtil.commaSeparatedList(jarFilter)); + entry.setWarFilter(ListUtil.commaSeparatedList(warFilter)); + entry.setEarFilter(ListUtil.commaSeparatedList(earFilter)); + entry.setZipFilter(ListUtil.commaSeparatedList(zipFilter)); + + // Add it to the class path. + classPath.add(entry); + } + } + + + // Ant task attributes. + + /** + * @deprecated Use {@link #setLocation(File)} instead. + */ + public void setFile(File file) + { + setLocation(file); + } + + + /** + * @deprecated Use {@link #setLocation(File)} instead. + */ + public void setDir(File file) + { + setLocation(file); + } + + + /** + * @deprecated Use {@link #setLocation(File)} instead. + */ + public void setName(File file) + { + setLocation(file); + } + + + public void setFilter(String filter) + { + this.filter = filter; + } + + + public void setJarfilter(String jarFilter) + { + this.jarFilter = jarFilter; + } + + + public void setWarfilter(String warFilter) + { + this.warFilter = warFilter; + } + + + public void setEarfilter(String earFilter) + { + this.earFilter = earFilter; + } + + + public void setZipfilter(String zipFilter) + { + this.zipFilter = zipFilter; + } +} diff --git a/src/proguard/ant/ClassSpecificationElement.java b/src/proguard/ant/ClassSpecificationElement.java new file mode 100644 index 0000000..f4ea2ff --- /dev/null +++ b/src/proguard/ant/ClassSpecificationElement.java @@ -0,0 +1,257 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.DataType; +import proguard.*; +import proguard.classfile.ClassConstants; +import proguard.classfile.util.ClassUtil; + +import java.util.*; + +/** + * This DataType represents a class specification in Ant. + * + * @author Eric Lafortune + */ +public class ClassSpecificationElement extends DataType +{ + private static final String ANY_CLASS_KEYWORD = "*"; + + private String access; + private String annotation; + private String type; + private String name; + private String extendsAnnotation; + private String extends_; + private List fieldSpecifications = new ArrayList(); + private List methodSpecifications = new ArrayList(); + + + /** + * Adds the contents of this class specification element to the given list. + * @param classSpecifications the class specifications to be extended. + */ + public void appendTo(List classSpecifications) + { + // Get the referenced file set, or else this one. + ClassSpecificationElement classSpecificationElement = isReference() ? + (ClassSpecificationElement)getCheckedRef(this.getClass(), + this.getClass().getName()) : + this; + + ClassSpecification classSpecification = + createClassSpecification(classSpecificationElement); + + // Add it to the list. + classSpecifications.add(classSpecification); + } + + + /** + * Creates a new class specification corresponding to the contents of this + * class specification element. + */ + protected ClassSpecification createClassSpecification(ClassSpecificationElement classSpecificationElement) + { + String access = classSpecificationElement.access; + String annotation = classSpecificationElement.annotation; + String type = classSpecificationElement.type; + String name = classSpecificationElement.name; + String extendsAnnotation = classSpecificationElement.extendsAnnotation; + String extends_ = classSpecificationElement.extends_; + + // For backward compatibility, allow a single "*" wildcard to match + // any class. + if (name != null && + name.equals(ANY_CLASS_KEYWORD)) + { + name = null; + } + + ClassSpecification classSpecification = + new ClassSpecification(null, + requiredAccessFlags(true, access, type), + requiredAccessFlags(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); + + for (int index = 0; index < fieldSpecifications.size(); index++) + { + classSpecification.addField((MemberSpecification)fieldSpecifications.get(index)); + } + + for (int index = 0; index < methodSpecifications.size(); index++) + { + classSpecification.addMethod((MemberSpecification)methodSpecifications.get(index)); + } + + return classSpecification; + } + + + // Ant task attributes. + + public void setAccess(String access) + { + this.access = access; + } + + + public void setAnnotation(String annotation) + { + this.annotation = annotation; + } + + + public void setType(String type) + { + this.type = type; + } + + + public void setName(String name) + { + this.name = name; + } + + + public void setExtendsannotation(String extendsAnnotation) + { + this.extendsAnnotation = extendsAnnotation; + } + + + public void setExtends(String extends_) + { + this.extends_ = extends_; + } + + + public void setImplements(String implements_) + { + this.extends_ = implements_; + } + + + // Ant task nested elements. + + public void addConfiguredField(MemberSpecificationElement memberSpecificationElement) + { + if (fieldSpecifications == null) + { + fieldSpecifications = new ArrayList(); + } + + memberSpecificationElement.appendTo(fieldSpecifications, + false, + false); + } + + + public void addConfiguredMethod(MemberSpecificationElement memberSpecificationElement) + { + if (methodSpecifications == null) + { + methodSpecifications = new ArrayList(); + } + + memberSpecificationElement.appendTo(methodSpecifications, + true, + false); + } + + + public void addConfiguredConstructor(MemberSpecificationElement memberSpecificationElement) + { + if (methodSpecifications == null) + { + methodSpecifications = new ArrayList(); + } + + memberSpecificationElement.appendTo(methodSpecifications, + true, + true); + } + + + // Small utility methods. + + private int requiredAccessFlags(boolean set, + String access, + String type) + throws BuildException + { + 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_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION : + 0; + + if (accessFlag == 0) + { + throw new BuildException("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 BuildException("Incorrect class type ["+type+"]"); + } + + accessFlags |= accessFlag; + } + + return accessFlags; + } +} diff --git a/src/proguard/ant/ConfigurationElement.java b/src/proguard/ant/ConfigurationElement.java new file mode 100644 index 0000000..76e9418 --- /dev/null +++ b/src/proguard/ant/ConfigurationElement.java @@ -0,0 +1,53 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.DataType; +import proguard.Configuration; + +/** + * This DataType represents a reference to a ProGuard configuration in Ant. + * + * @author Eric Lafortune + */ +public class ConfigurationElement extends DataType +{ + /** + * Adds the contents of this configuration task to the given configuration. + * @param configuration the configuration to be extended. + */ + public void appendTo(Configuration configuration) + { + // Get the referenced element. + if (!isReference()) + { + throw new BuildException("Nested element <configuration> must have a refid attribute"); + } + + ConfigurationTask configurationTask = + (ConfigurationTask)getCheckedRef(ConfigurationTask.class, + ConfigurationTask.class.getName()); + + // Append the referenced configuration entries to the given configuration. + configurationTask.appendTo(configuration); + } +} diff --git a/src/proguard/ant/ConfigurationTask.java b/src/proguard/ant/ConfigurationTask.java new file mode 100644 index 0000000..0d2f04f --- /dev/null +++ b/src/proguard/ant/ConfigurationTask.java @@ -0,0 +1,440 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import org.apache.tools.ant.*; +import proguard.*; + +import java.io.IOException; +import java.util.*; + +/** + * This Task allows to define a ProGuard configuration from Ant. + * + * @author Eric Lafortune + */ +public class ConfigurationTask extends Task +{ + protected final Configuration configuration = new Configuration(); + + + /** + * Adds the contents of this configuration task to the given configuration. + * @param configuration the configuration to be extended. + */ + public void appendTo(Configuration configuration) + { + // Append all of these configuration entries to the given configuration. + configuration.programJars = extendClassPath(configuration.programJars, + this.configuration.programJars); + + configuration.libraryJars = extendClassPath(configuration.libraryJars, + this.configuration.libraryJars); + + configuration.keep = extendClassSpecifications(configuration.keep, + this.configuration.keep); + + configuration.keepDirectories = extendList(configuration.keepDirectories, + this.configuration.keepDirectories); + + configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping, + this.configuration.whyAreYouKeeping); + + configuration.optimizations = extendClassSpecifications(configuration.optimizations, + this.configuration.optimizations); + + configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects, + this.configuration.assumeNoSideEffects); + + configuration.keepPackageNames = extendList(configuration.keepPackageNames, + this.configuration.keepPackageNames); + + configuration.keepAttributes = extendList(configuration.keepAttributes, + this.configuration.keepAttributes); + + configuration.adaptClassStrings = extendList(configuration.adaptClassStrings, + this.configuration.adaptClassStrings); + + configuration.adaptResourceFileNames = extendList(configuration.adaptResourceFileNames, + this.configuration.adaptResourceFileNames); + + configuration.adaptResourceFileContents = extendList(configuration.adaptResourceFileContents, + this.configuration.adaptResourceFileContents); + + configuration.note = extendList(configuration.note, + this.configuration.note); + + configuration.warn = extendList(configuration.warn, + this.configuration.warn); + } + + + // Ant task nested elements. + + public void addConfiguredInjar(ClassPathElement classPathElement) + { + configuration.programJars = extendClassPath(configuration.programJars, + classPathElement, + false); + } + + + public void addConfiguredOutjar(ClassPathElement classPathElement) + { + configuration.programJars = extendClassPath(configuration.programJars, + classPathElement, + true); + } + + + public void addConfiguredLibraryjar(ClassPathElement classPathElement) + { + configuration.libraryJars = extendClassPath(configuration.libraryJars, + classPathElement, + false); + } + + + public void addConfiguredKeepdirectory(FilterElement filterElement) + { + configuration.keepDirectories = extendFilter(configuration.keepDirectories, + filterElement); + } + + + public void addConfiguredKeepdirectories(FilterElement filterElement) + { + configuration.keepDirectories = extendFilter(configuration.keepDirectories, + filterElement); + } + + + public void addConfiguredKeep(KeepSpecificationElement keepSpecificationElement) + { + configuration.keep = extendKeepSpecifications(configuration.keep, + keepSpecificationElement, + true, + false); + } + + + public void addConfiguredKeepclassmembers(KeepSpecificationElement keepSpecificationElement) + { + configuration.keep = extendKeepSpecifications(configuration.keep, + keepSpecificationElement, + false, + false); + } + + + public void addConfiguredKeepclasseswithmembers(KeepSpecificationElement keepSpecificationElement) + { + configuration.keep = extendKeepSpecifications(configuration.keep, + keepSpecificationElement, + true, + true); + } + + + public void addConfiguredKeepnames(KeepSpecificationElement keepSpecificationElement) + { + // Set the shrinking flag, based on the name (backward compatibility). + keepSpecificationElement.setAllowshrinking(true); + + configuration.keep = extendKeepSpecifications(configuration.keep, + keepSpecificationElement, + true, + false); + } + + + public void addConfiguredKeepclassmembernames(KeepSpecificationElement keepSpecificationElement) + { + // Set the shrinking flag, based on the name (backward compatibility). + keepSpecificationElement.setAllowshrinking(true); + + configuration.keep = extendKeepSpecifications(configuration.keep, + keepSpecificationElement, + false, + false); + } + + + public void addConfiguredKeepclasseswithmembernames(KeepSpecificationElement keepSpecificationElement) + { + // Set the shrinking flag, based on the name (backward compatibility). + keepSpecificationElement.setAllowshrinking(true); + + configuration.keep = extendKeepSpecifications(configuration.keep, + keepSpecificationElement, + true, + true); + } + + + public void addConfiguredWhyareyoukeeping(ClassSpecificationElement classSpecificationElement) + { + configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping, + classSpecificationElement); + } + + + public void addConfiguredAssumenosideeffects(ClassSpecificationElement classSpecificationElement) + { + configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects, + classSpecificationElement); + } + + + public void addConfiguredOptimizations(FilterElement filterElement) + { + addConfiguredOptimization(filterElement); + } + + + public void addConfiguredOptimization(FilterElement filterElement) + { + configuration.optimizations = extendFilter(configuration.optimizations, + filterElement); + } + + + public void addConfiguredKeeppackagename(FilterElement filterElement) + { + configuration.keepPackageNames = extendFilter(configuration.keepPackageNames, + filterElement, + true); + } + + + public void addConfiguredKeeppackagenames(FilterElement filterElement) + { + configuration.keepPackageNames = extendFilter(configuration.keepPackageNames, + filterElement, + true); + } + + + public void addConfiguredKeepattributes(FilterElement filterElement) + { + addConfiguredKeepattribute(filterElement); + } + + + public void addConfiguredKeepattribute(FilterElement filterElement) + { + configuration.keepAttributes = extendFilter(configuration.keepAttributes, + filterElement); + } + + + public void addConfiguredAdaptclassstrings(FilterElement filterElement) + { + configuration.adaptClassStrings = extendFilter(configuration.adaptClassStrings, + filterElement, true); + } + + + public void addConfiguredAdaptresourcefilenames(FilterElement filterElement) + { + configuration.adaptResourceFileNames = extendFilter(configuration.adaptResourceFileNames, + filterElement); + } + + + public void addConfiguredAdaptresourcefilecontents(FilterElement filterElement) + { + configuration.adaptResourceFileContents = extendFilter(configuration.adaptResourceFileContents, + filterElement); + } + + + public void addConfiguredDontnote(FilterElement filterElement) + { + configuration.note = extendFilter(configuration.note, filterElement, true); + } + + + public void addConfiguredDontwarn(FilterElement filterElement) + { + configuration.warn = extendFilter(configuration.warn, filterElement, true); + } + + + public void addConfiguredConfiguration(ConfigurationElement configurationElement) + { + configurationElement.appendTo(configuration); + } + + + // Implementations for Task. + + public void addText(String text) throws BuildException + { + try + { + String arg = getProject().replaceProperties(text); + + ConfigurationParser parser = new ConfigurationParser(new String[] { arg }, + getProject().getBaseDir()); + + try + { + parser.parse(configuration); + } + catch (ParseException ex) + { + throw new BuildException(ex.getMessage()); + } + finally + { + parser.close(); + } + } + catch (IOException ex) + { + throw new BuildException(ex.getMessage()); + } + } + + + // Small utility methods. + + private ClassPath extendClassPath(ClassPath classPath, + ClassPathElement classPathElement, + boolean output) + { + if (classPath == null) + { + classPath = new ClassPath(); + } + + classPathElement.appendClassPathEntriesTo(classPath, + output); + + return classPath; + } + + + private ClassPath extendClassPath(ClassPath classPath, + ClassPath additionalClassPath) + { + if (additionalClassPath != null) + { + if (classPath == null) + { + classPath = new ClassPath(); + } + + classPath.addAll(additionalClassPath); + } + + return classPath; + } + + + private List extendKeepSpecifications(List keepSpecifications, + KeepSpecificationElement keepSpecificationElement, + boolean markClasses, + boolean markClassesConditionally) + { + if (keepSpecifications == null) + { + keepSpecifications = new ArrayList(); + } + + keepSpecificationElement.appendTo(keepSpecifications, + markClasses, + markClassesConditionally); + + return keepSpecifications; + } + + + private List extendClassSpecifications(List classSpecifications, + ClassSpecificationElement classSpecificationElement) + { + if (classSpecifications == null) + { + classSpecifications = new ArrayList(); + } + + classSpecificationElement.appendTo(classSpecifications); + + return classSpecifications; + } + + + private List extendClassSpecifications(List classSpecifications, + List additionalClassSpecifications) + { + if (additionalClassSpecifications != null) + { + if (classSpecifications == null) + { + classSpecifications = new ArrayList(); + } + + classSpecifications.addAll(additionalClassSpecifications); + } + + return classSpecifications; + } + + + private List extendFilter(List filter, + FilterElement filterElement) + { + return extendFilter(filter, filterElement, false); + } + + + private List extendFilter(List filter, + FilterElement filterElement, + boolean internal) + { + if (filter == null) + { + filter = new ArrayList(); + } + + filterElement.appendTo(filter, internal); + + return filter; + } + + + private List extendList(List list, + List additionalList) + { + if (additionalList != null) + { + if (list == null) + { + list = new ArrayList(); + } + + list.addAll(additionalList); + } + + return list; + } +} diff --git a/src/proguard/ant/FilterElement.java b/src/proguard/ant/FilterElement.java new file mode 100644 index 0000000..d792c5d --- /dev/null +++ b/src/proguard/ant/FilterElement.java @@ -0,0 +1,85 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import org.apache.tools.ant.types.DataType; +import proguard.classfile.util.ClassUtil; +import proguard.util.ListUtil; + +import java.util.List; + +/** + * This DataType represents a name filter in Ant. + * + * @author Eric Lafortune + */ +public class FilterElement extends DataType +{ + private String filter; + + + /** + * Adds the contents of this element to the given name filter. + * @param filter the list of attributes to be extended. + * @param internal specifies whether the filter string should be converted + * to internal types. + */ + public void appendTo(List filter, boolean internal) + { + // Get the referenced element, or else this one. + FilterElement filterElement = isReference() ? + (FilterElement)getCheckedRef(this.getClass(), + this.getClass().getName()) : + this; + + String filterString = filterElement.filter; + + if (filterString == null) + { + // Clear the filter to keep all names. + filter.clear(); + } + else + { + if (internal) + { + filterString = ClassUtil.internalClassName(filterString); + } + + // Append the filter. + filter.addAll(ListUtil.commaSeparatedList(filterString)); + } + } + + + // Ant task attributes. + + public void setName(String name) + { + this.filter = name; + } + + + public void setFilter(String filter) + { + this.filter = filter; + } +} diff --git a/src/proguard/ant/KeepSpecificationElement.java b/src/proguard/ant/KeepSpecificationElement.java new file mode 100644 index 0000000..e36b744 --- /dev/null +++ b/src/proguard/ant/KeepSpecificationElement.java @@ -0,0 +1,87 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import proguard.KeepClassSpecification; + +import java.util.List; + +/** + * This DataType represents a class specification in Ant. + * + * @author Eric Lafortune + */ +public class KeepSpecificationElement extends ClassSpecificationElement +{ + private boolean allowShrinking; + private boolean allowOptimization; + private boolean allowObfuscation; + + + /** + * Adds the contents of this class specification element to the given list. + * @param keepSpecifications the class specifications to be extended. + * @param markClasses specifies whether to mark the classes. + * @param markConditionally specifies whether to mark the classes + * and class members conditionally. + */ + public void appendTo(List keepSpecifications, + boolean markClasses, + boolean markConditionally) + { + // Get the referenced file set, or else this one. + KeepSpecificationElement keepSpecificationElement = isReference() ? + (KeepSpecificationElement)getCheckedRef(this.getClass(), + this.getClass().getName()) : + this; + + KeepClassSpecification keepClassSpecification = + new KeepClassSpecification(markClasses, + markConditionally, + allowShrinking, + allowOptimization, + allowObfuscation, + createClassSpecification(keepSpecificationElement)); + + // Add it to the list. + keepSpecifications.add(keepClassSpecification); + } + + + // Ant task attributes. + + public void setAllowshrinking(boolean allowShrinking) + { + this.allowShrinking = allowShrinking; + } + + + public void setAllowoptimization(boolean allowOptimization) + { + this.allowOptimization = allowOptimization; + } + + + public void setAllowobfuscation(boolean allowObfuscation) + { + this.allowObfuscation = allowObfuscation; + } +} diff --git a/src/proguard/ant/MemberSpecificationElement.java b/src/proguard/ant/MemberSpecificationElement.java new file mode 100644 index 0000000..d4bb4a9 --- /dev/null +++ b/src/proguard/ant/MemberSpecificationElement.java @@ -0,0 +1,215 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.DataType; +import proguard.MemberSpecification; +import proguard.classfile.ClassConstants; +import proguard.classfile.util.ClassUtil; +import proguard.util.ListUtil; + +import java.util.*; + +/** + * This DataType represents a class member specification in Ant. + * + * @author Eric Lafortune + */ +public class MemberSpecificationElement extends DataType +{ + private String access; + private String annotation; + private String type; + private String name; + private String parameters; + + + /** + * Adds the contents of this class member specification element to the given + * list. + * @param memberSpecifications the class member specifications to be + * extended. + * @param isMethod specifies whether this specification + * refers to a method. + * @param isConstructor specifies whether this specification + * refers to a constructor. + */ + public void appendTo(List memberSpecifications, + boolean isMethod, + boolean isConstructor) + { + // Get the referenced file set, or else this one. + MemberSpecificationElement memberSpecificationElement = isReference() ? + (MemberSpecificationElement)getCheckedRef(this.getClass(), + this.getClass().getName()) : + this; + + // Create a new class specification. + String access = memberSpecificationElement.access; + String type = memberSpecificationElement.type; + String annotation = memberSpecificationElement.annotation; + String name = memberSpecificationElement.name; + String parameters = memberSpecificationElement.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 BuildException("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 BuildException("Type and parameters attributes must always be present in combination in method specification"); + } + } + else + { + if (parameters != null) + { + throw new BuildException("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; + + MemberSpecification memberSpecification = + new MemberSpecification(requiredAccessFlags(true, access), + requiredAccessFlags(false, access), + annotation, + name, + descriptor); + + // Add it to the list. + memberSpecifications.add(memberSpecification); + } + + + // Ant task attributes. + + public void setAccess(String access) + { + this.access = access; + } + + + public void setAnnotation(String annotation) + { + this.annotation = annotation; + } + + + public void setType(String type) + { + this.type = type; + } + + + public void setName(String name) + { + this.name = name; + } + + + public void setParameters(String parameters) + { + this.parameters = parameters; + } + + + /** + * @deprecated Use {@link #setParameters(String)} instead. + */ + public void setParam(String parameters) + { + this.parameters = parameters; + } + + + // Small utility methods. + + private int requiredAccessFlags(boolean set, + String access) + throws BuildException + { + 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_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 : + 0; + + if (accessFlag == 0) + { + throw new BuildException("Incorrect class member access modifier ["+strippedToken+"]"); + } + + accessFlags |= accessFlag; + } + } + } + + return accessFlags; + } +} diff --git a/src/proguard/ant/ProGuardTask.java b/src/proguard/ant/ProGuardTask.java new file mode 100644 index 0000000..b7fc361 --- /dev/null +++ b/src/proguard/ant/ProGuardTask.java @@ -0,0 +1,320 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2009 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.ant; + +import org.apache.tools.ant.BuildException; +import proguard.*; +import proguard.classfile.util.ClassUtil; + +import java.io.*; +import java.util.ArrayList; + +/** + * This Task allows to configure and run ProGuard from Ant. + * + * @author Eric Lafortune + */ +public class ProGuardTask extends ConfigurationTask +{ + // Ant task attributes. + + public void setConfiguration(File configurationFile) throws BuildException + { + try + { + ConfigurationParser parser = new ConfigurationParser(configurationFile); + + try + { + parser.parse(configuration); + } + catch (ParseException ex) + { + throw new BuildException(ex.getMessage()); + } + finally + { + parser.close(); + } + } + catch (IOException ex) + { + throw new BuildException(ex.getMessage()); + } + } + + + /** + * @deprecated Use the nested outjar element instead. + */ + public void setOutjar(String parameters) + { + throw new BuildException("Use the <outjar> nested element instead of the 'outjar' attribute"); + } + + + public void setSkipnonpubliclibraryclasses(boolean skipNonPublicLibraryClasses) + { + configuration.skipNonPublicLibraryClasses = skipNonPublicLibraryClasses; + } + + + public void setSkipnonpubliclibraryclassmembers(boolean skipNonPublicLibraryClassMembers) + { + configuration.skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembers; + } + + + public void setTarget(String target) + { + configuration.targetClassVersion = ClassUtil.internalClassVersion(target); + if (configuration.targetClassVersion == 0) + { + throw new BuildException("Unsupported target '"+target+"'"); + } + } + + + public void setForceprocessing(boolean forceProcessing) + { + configuration.lastModified = forceProcessing ? Long.MAX_VALUE : 0; + } + + + public void setPrintseeds(File printSeeds) + { + configuration.printSeeds = optionalFile(printSeeds); + } + + + public void setShrink(boolean shrink) + { + configuration.shrink = shrink; + } + + + public void setPrintusage(File printUsage) + { + configuration.printUsage = optionalFile(printUsage); + } + + + public void setOptimize(boolean optimize) + { + configuration.optimize = optimize; + } + + + public void setOptimizationpasses(int optimizationPasses) + { + configuration.optimizationPasses = optimizationPasses; + } + + + public void setAllowaccessmodification(boolean allowAccessModification) + { + configuration.allowAccessModification = allowAccessModification; + } + + + public void setMergeinterfacesaggressively(boolean mergeinterfacesaggressively) + { + configuration.mergeInterfacesAggressively = mergeinterfacesaggressively; + } + + + public void setObfuscate(boolean obfuscate) + { + configuration.obfuscate = obfuscate; + } + + + public void setPrintmapping(File printMapping) + { + configuration.printMapping = optionalFile(printMapping); + } + + + public void setApplymapping(File applyMapping) + { + configuration.applyMapping = resolvedFile(applyMapping); + } + + + public void setObfuscationdictionary(File obfuscationDictionary) + { + configuration.obfuscationDictionary = resolvedFile(obfuscationDictionary); + } + + + public void setClassobfuscationdictionary(File classObfuscationDictionary) + { + configuration.classObfuscationDictionary = resolvedFile(classObfuscationDictionary); + } + + + public void setPackageobfuscationdictionary(File packageObfuscationDictionary) + { + configuration.packageObfuscationDictionary = resolvedFile(packageObfuscationDictionary); + } + + + public void setOverloadaggressively(boolean overloadAggressively) + { + configuration.overloadAggressively = overloadAggressively; + } + + + public void setUseuniqueclassmembernames(boolean useUniqueClassMemberNames) + { + configuration.useUniqueClassMemberNames = useUniqueClassMemberNames; + } + + + public void setUsemixedcaseclassnames(boolean useMixedCaseClassNames) + { + configuration.useMixedCaseClassNames = useMixedCaseClassNames; + } + + + public void setFlattenpackagehierarchy(String flattenPackageHierarchy) + { + configuration.flattenPackageHierarchy = ClassUtil.internalClassName(flattenPackageHierarchy); + } + + + public void setRepackageclasses(String repackageClasses) + { + configuration.repackageClasses = ClassUtil.internalClassName(repackageClasses); + } + + /** + * @deprecated Use the repackageclasses attribute instead. + */ + public void setDefaultpackage(String defaultPackage) + { + configuration.repackageClasses = ClassUtil.internalClassName(defaultPackage); + } + + + public void setRenamesourcefileattribute(String newSourceFileAttribute) + { + configuration.newSourceFileAttribute = newSourceFileAttribute; + } + + + public void setPreverify(boolean preverify) + { + configuration.preverify = preverify; + } + + + public void setMicroedition(boolean microEdition) + { + configuration.microEdition = microEdition; + } + + + public void setVerbose(boolean verbose) + { + configuration.verbose = verbose; + } + + + public void setNote(boolean note) + { + configuration.note = note ? null : new ArrayList(); + } + + + public void setWarn(boolean warn) + { + configuration.warn = warn ? null : new ArrayList(); + } + + + public void setIgnorewarnings(boolean ignoreWarnings) + { + configuration.ignoreWarnings = ignoreWarnings; + } + + + public void setPrintconfiguration(File printConfiguration) + { + configuration.printConfiguration = optionalFile(printConfiguration); + } + + + public void setDump(File dump) + { + configuration.dump = optionalFile(dump); + } + + + // Implementations for Task. + + public void execute() throws BuildException + { + try + { + ProGuard proGuard = new ProGuard(configuration); + proGuard.execute(); + } + catch (IOException ex) + { + throw new BuildException(ex.getMessage()); + } + } + + + // Small utility methods. + + /** + * Returns a file that is properly resolved with respect to the project + * directory, or <code>null</code> or empty if its name is actually a + * boolean flag. + */ + private File optionalFile(File file) + { + String fileName = file.getName(); + + return + fileName.equalsIgnoreCase("false") || + fileName.equalsIgnoreCase("no") || + fileName.equalsIgnoreCase("off") ? null : + fileName.equalsIgnoreCase("true") || + fileName.equalsIgnoreCase("yes") || + fileName.equalsIgnoreCase("on") ? new File("") : + resolvedFile(file); + } + + + /** + * Returns a file that is properly resolved with respect to the project + * directory. + */ + private File resolvedFile(File file) + { + return file.isAbsolute() ? file : + new File(getProject().getBaseDir(), + file.getName()); + } +} diff --git a/src/proguard/ant/package.html b/src/proguard/ant/package.html new file mode 100644 index 0000000..75e0466 --- /dev/null +++ b/src/proguard/ant/package.html @@ -0,0 +1,3 @@ +<body> +This package contains the Ant task for ProGuard. +</body> diff --git a/src/proguard/ant/task.properties b/src/proguard/ant/task.properties new file mode 100644 index 0000000..b676db7 --- /dev/null +++ b/src/proguard/ant/task.properties @@ -0,0 +1,2 @@ +proguard = proguard.ant.ProGuardTask
+proguardconfiguration = proguard.ant.ConfigurationTask
|