1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.ant; 22 23import org.apache.tools.ant.BuildException; 24import proguard.*; 25import proguard.classfile.util.ClassUtil; 26 27import java.io.*; 28import java.util.ArrayList; 29 30/** 31 * This Task allows to configure and run ProGuard from Ant. 32 * 33 * @author Eric Lafortune 34 */ 35public class ProGuardTask extends ConfigurationTask 36{ 37 // Ant task attributes. 38 39 public void setConfiguration(File configurationFile) throws BuildException 40 { 41 try 42 { 43 ConfigurationParser parser = new ConfigurationParser(configurationFile); 44 45 try 46 { 47 parser.parse(configuration); 48 } 49 catch (ParseException ex) 50 { 51 throw new BuildException(ex.getMessage()); 52 } 53 finally 54 { 55 parser.close(); 56 } 57 } 58 catch (IOException ex) 59 { 60 throw new BuildException(ex.getMessage()); 61 } 62 } 63 64 65 /** 66 * @deprecated Use the nested outjar element instead. 67 */ 68 public void setOutjar(String parameters) 69 { 70 throw new BuildException("Use the <outjar> nested element instead of the 'outjar' attribute"); 71 } 72 73 74 public void setSkipnonpubliclibraryclasses(boolean skipNonPublicLibraryClasses) 75 { 76 configuration.skipNonPublicLibraryClasses = skipNonPublicLibraryClasses; 77 } 78 79 80 public void setSkipnonpubliclibraryclassmembers(boolean skipNonPublicLibraryClassMembers) 81 { 82 configuration.skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembers; 83 } 84 85 86 public void setTarget(String target) 87 { 88 configuration.targetClassVersion = ClassUtil.internalClassVersion(target); 89 if (configuration.targetClassVersion == 0) 90 { 91 throw new BuildException("Unsupported target '"+target+"'"); 92 } 93 } 94 95 96 public void setForceprocessing(boolean forceProcessing) 97 { 98 configuration.lastModified = forceProcessing ? Long.MAX_VALUE : 0; 99 } 100 101 102 public void setPrintseeds(File printSeeds) 103 { 104 configuration.printSeeds = optionalFile(printSeeds); 105 } 106 107 108 public void setShrink(boolean shrink) 109 { 110 configuration.shrink = shrink; 111 } 112 113 114 public void setPrintusage(File printUsage) 115 { 116 configuration.printUsage = optionalFile(printUsage); 117 } 118 119 120 public void setOptimize(boolean optimize) 121 { 122 configuration.optimize = optimize; 123 } 124 125 126 public void setOptimizationpasses(int optimizationPasses) 127 { 128 configuration.optimizationPasses = optimizationPasses; 129 } 130 131 132 public void setAllowaccessmodification(boolean allowAccessModification) 133 { 134 configuration.allowAccessModification = allowAccessModification; 135 } 136 137 138 public void setMergeinterfacesaggressively(boolean mergeinterfacesaggressively) 139 { 140 configuration.mergeInterfacesAggressively = mergeinterfacesaggressively; 141 } 142 143 144 public void setObfuscate(boolean obfuscate) 145 { 146 configuration.obfuscate = obfuscate; 147 } 148 149 150 public void setPrintmapping(File printMapping) 151 { 152 configuration.printMapping = optionalFile(printMapping); 153 } 154 155 156 public void setApplymapping(File applyMapping) 157 { 158 configuration.applyMapping = resolvedFile(applyMapping); 159 } 160 161 162 public void setObfuscationdictionary(File obfuscationDictionary) 163 { 164 configuration.obfuscationDictionary = resolvedFile(obfuscationDictionary); 165 } 166 167 168 public void setClassobfuscationdictionary(File classObfuscationDictionary) 169 { 170 configuration.classObfuscationDictionary = resolvedFile(classObfuscationDictionary); 171 } 172 173 174 public void setPackageobfuscationdictionary(File packageObfuscationDictionary) 175 { 176 configuration.packageObfuscationDictionary = resolvedFile(packageObfuscationDictionary); 177 } 178 179 180 public void setOverloadaggressively(boolean overloadAggressively) 181 { 182 configuration.overloadAggressively = overloadAggressively; 183 } 184 185 186 public void setUseuniqueclassmembernames(boolean useUniqueClassMemberNames) 187 { 188 configuration.useUniqueClassMemberNames = useUniqueClassMemberNames; 189 } 190 191 192 public void setUsemixedcaseclassnames(boolean useMixedCaseClassNames) 193 { 194 configuration.useMixedCaseClassNames = useMixedCaseClassNames; 195 } 196 197 198 public void setFlattenpackagehierarchy(String flattenPackageHierarchy) 199 { 200 configuration.flattenPackageHierarchy = ClassUtil.internalClassName(flattenPackageHierarchy); 201 } 202 203 204 public void setRepackageclasses(String repackageClasses) 205 { 206 configuration.repackageClasses = ClassUtil.internalClassName(repackageClasses); 207 } 208 209 /** 210 * @deprecated Use the repackageclasses attribute instead. 211 */ 212 public void setDefaultpackage(String defaultPackage) 213 { 214 configuration.repackageClasses = ClassUtil.internalClassName(defaultPackage); 215 } 216 217 218 public void setRenamesourcefileattribute(String newSourceFileAttribute) 219 { 220 configuration.newSourceFileAttribute = newSourceFileAttribute; 221 } 222 223 224 public void setPreverify(boolean preverify) 225 { 226 configuration.preverify = preverify; 227 } 228 229 230 public void setMicroedition(boolean microEdition) 231 { 232 configuration.microEdition = microEdition; 233 } 234 235 236 public void setVerbose(boolean verbose) 237 { 238 configuration.verbose = verbose; 239 } 240 241 242 public void setNote(boolean note) 243 { 244 configuration.note = note ? null : new ArrayList(); 245 } 246 247 248 public void setWarn(boolean warn) 249 { 250 configuration.warn = warn ? null : new ArrayList(); 251 } 252 253 254 public void setIgnorewarnings(boolean ignoreWarnings) 255 { 256 configuration.ignoreWarnings = ignoreWarnings; 257 } 258 259 260 public void setPrintconfiguration(File printConfiguration) 261 { 262 configuration.printConfiguration = optionalFile(printConfiguration); 263 } 264 265 266 public void setDump(File dump) 267 { 268 configuration.dump = optionalFile(dump); 269 } 270 271 272 // Implementations for Task. 273 274 public void execute() throws BuildException 275 { 276 try 277 { 278 ProGuard proGuard = new ProGuard(configuration); 279 proGuard.execute(); 280 } 281 catch (IOException ex) 282 { 283 throw new BuildException(ex.getMessage()); 284 } 285 } 286 287 288 // Small utility methods. 289 290 /** 291 * Returns a file that is properly resolved with respect to the project 292 * directory, or <code>null</code> or empty if its name is actually a 293 * boolean flag. 294 */ 295 private File optionalFile(File file) 296 { 297 String fileName = file.getName(); 298 299 return 300 fileName.equalsIgnoreCase("false") || 301 fileName.equalsIgnoreCase("no") || 302 fileName.equalsIgnoreCase("off") ? null : 303 fileName.equalsIgnoreCase("true") || 304 fileName.equalsIgnoreCase("yes") || 305 fileName.equalsIgnoreCase("on") ? new File("") : 306 resolvedFile(file); 307 } 308 309 310 /** 311 * Returns a file that is properly resolved with respect to the project 312 * directory. 313 */ 314 private File resolvedFile(File file) 315 { 316 return file.isAbsolute() ? file : 317 new File(getProject().getBaseDir(), 318 file.getName()); 319 } 320} 321