1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 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 */ 21 package proguard.ant; 22 23 import org.apache.tools.ant.BuildException; 24 import proguard.*; 25 import proguard.classfile.util.ClassUtil; 26 27 import java.io.*; 28 import java.util.*; 29 30 /** 31 * This Task allows to configure and run ProGuard from Ant. 32 * 33 * @author Eric Lafortune 34 */ 35 public class ProGuardTask extends ConfigurationTask 36 { 37 // Ant task attributes. 38 setConfiguration(File configurationFile)39 public void setConfiguration(File configurationFile) throws BuildException 40 { 41 try 42 { 43 // Get the combined system properties and Ant properties, for 44 // replacing ProGuard-style properties ('<...>'). 45 Properties properties = new Properties(); 46 properties.putAll(getProject().getProperties()); 47 48 ConfigurationParser parser = new ConfigurationParser(configurationFile, 49 properties); 50 try 51 { 52 parser.parse(configuration); 53 } 54 catch (ParseException e) 55 { 56 throw new BuildException(e.getMessage(), e); 57 } 58 finally 59 { 60 parser.close(); 61 } 62 } 63 catch (IOException e) 64 { 65 throw new BuildException(e.getMessage(), e); 66 } 67 } 68 69 70 /** 71 * @deprecated Use the nested outjar element instead. 72 */ setOutjar(String parameters)73 public void setOutjar(String parameters) 74 { 75 throw new BuildException("Use the <outjar> nested element instead of the 'outjar' attribute"); 76 } 77 78 setSkipnonpubliclibraryclasses(boolean skipNonPublicLibraryClasses)79 public void setSkipnonpubliclibraryclasses(boolean skipNonPublicLibraryClasses) 80 { 81 configuration.skipNonPublicLibraryClasses = skipNonPublicLibraryClasses; 82 } 83 84 setSkipnonpubliclibraryclassmembers(boolean skipNonPublicLibraryClassMembers)85 public void setSkipnonpubliclibraryclassmembers(boolean skipNonPublicLibraryClassMembers) 86 { 87 configuration.skipNonPublicLibraryClassMembers = skipNonPublicLibraryClassMembers; 88 } 89 90 setTarget(String target)91 public void setTarget(String target) 92 { 93 configuration.targetClassVersion = ClassUtil.internalClassVersion(target); 94 if (configuration.targetClassVersion == 0) 95 { 96 throw new BuildException("Unsupported target '"+target+"'"); 97 } 98 } 99 100 setForceprocessing(boolean forceProcessing)101 public void setForceprocessing(boolean forceProcessing) 102 { 103 configuration.lastModified = forceProcessing ? Long.MAX_VALUE : 0; 104 } 105 106 setPrintseeds(File printSeeds)107 public void setPrintseeds(File printSeeds) 108 { 109 configuration.printSeeds = optionalFile(printSeeds); 110 } 111 112 setShrink(boolean shrink)113 public void setShrink(boolean shrink) 114 { 115 configuration.shrink = shrink; 116 } 117 118 setPrintusage(File printUsage)119 public void setPrintusage(File printUsage) 120 { 121 configuration.printUsage = optionalFile(printUsage); 122 } 123 124 setOptimize(boolean optimize)125 public void setOptimize(boolean optimize) 126 { 127 configuration.optimize = optimize; 128 } 129 130 setOptimizationpasses(int optimizationPasses)131 public void setOptimizationpasses(int optimizationPasses) 132 { 133 configuration.optimizationPasses = optimizationPasses; 134 } 135 136 setAllowaccessmodification(boolean allowAccessModification)137 public void setAllowaccessmodification(boolean allowAccessModification) 138 { 139 configuration.allowAccessModification = allowAccessModification; 140 } 141 142 setMergeinterfacesaggressively(boolean mergeinterfacesaggressively)143 public void setMergeinterfacesaggressively(boolean mergeinterfacesaggressively) 144 { 145 configuration.mergeInterfacesAggressively = mergeinterfacesaggressively; 146 } 147 148 setObfuscate(boolean obfuscate)149 public void setObfuscate(boolean obfuscate) 150 { 151 configuration.obfuscate = obfuscate; 152 } 153 154 setPrintmapping(File printMapping)155 public void setPrintmapping(File printMapping) 156 { 157 configuration.printMapping = optionalFile(printMapping); 158 } 159 160 setApplymapping(File applyMapping)161 public void setApplymapping(File applyMapping) 162 { 163 configuration.applyMapping = resolvedFile(applyMapping); 164 } 165 166 setObfuscationdictionary(File obfuscationDictionary)167 public void setObfuscationdictionary(File obfuscationDictionary) 168 { 169 configuration.obfuscationDictionary = resolvedFile(obfuscationDictionary); 170 } 171 172 setClassobfuscationdictionary(File classObfuscationDictionary)173 public void setClassobfuscationdictionary(File classObfuscationDictionary) 174 { 175 configuration.classObfuscationDictionary = resolvedFile(classObfuscationDictionary); 176 } 177 178 setPackageobfuscationdictionary(File packageObfuscationDictionary)179 public void setPackageobfuscationdictionary(File packageObfuscationDictionary) 180 { 181 configuration.packageObfuscationDictionary = resolvedFile(packageObfuscationDictionary); 182 } 183 184 setOverloadaggressively(boolean overloadAggressively)185 public void setOverloadaggressively(boolean overloadAggressively) 186 { 187 configuration.overloadAggressively = overloadAggressively; 188 } 189 190 setUseuniqueclassmembernames(boolean useUniqueClassMemberNames)191 public void setUseuniqueclassmembernames(boolean useUniqueClassMemberNames) 192 { 193 configuration.useUniqueClassMemberNames = useUniqueClassMemberNames; 194 } 195 196 setUsemixedcaseclassnames(boolean useMixedCaseClassNames)197 public void setUsemixedcaseclassnames(boolean useMixedCaseClassNames) 198 { 199 configuration.useMixedCaseClassNames = useMixedCaseClassNames; 200 } 201 202 setFlattenpackagehierarchy(String flattenPackageHierarchy)203 public void setFlattenpackagehierarchy(String flattenPackageHierarchy) 204 { 205 configuration.flattenPackageHierarchy = ClassUtil.internalClassName(flattenPackageHierarchy); 206 } 207 208 setRepackageclasses(String repackageClasses)209 public void setRepackageclasses(String repackageClasses) 210 { 211 configuration.repackageClasses = ClassUtil.internalClassName(repackageClasses); 212 } 213 214 /** 215 * @deprecated Use the repackageclasses attribute instead. 216 */ setDefaultpackage(String defaultPackage)217 public void setDefaultpackage(String defaultPackage) 218 { 219 configuration.repackageClasses = ClassUtil.internalClassName(defaultPackage); 220 } 221 222 setKeepparameternames(boolean keepParameterNames)223 public void setKeepparameternames(boolean keepParameterNames) 224 { 225 configuration.keepParameterNames = keepParameterNames; 226 } 227 228 setRenamesourcefileattribute(String newSourceFileAttribute)229 public void setRenamesourcefileattribute(String newSourceFileAttribute) 230 { 231 configuration.newSourceFileAttribute = newSourceFileAttribute; 232 } 233 234 setPreverify(boolean preverify)235 public void setPreverify(boolean preverify) 236 { 237 configuration.preverify = preverify; 238 } 239 240 setMicroedition(boolean microEdition)241 public void setMicroedition(boolean microEdition) 242 { 243 configuration.microEdition = microEdition; 244 } 245 246 setVerbose(boolean verbose)247 public void setVerbose(boolean verbose) 248 { 249 configuration.verbose = verbose; 250 } 251 252 setNote(boolean note)253 public void setNote(boolean note) 254 { 255 if (note) 256 { 257 // Switch on notes if they were completely disabled. 258 if (configuration.note != null && 259 configuration.note.isEmpty()) 260 { 261 configuration.note = null; 262 } 263 } 264 else 265 { 266 // Switch off notes. 267 configuration.note = new ArrayList(); 268 } 269 } 270 271 setWarn(boolean warn)272 public void setWarn(boolean warn) 273 { 274 if (warn) 275 { 276 // Switch on warnings if they were completely disabled. 277 if (configuration.warn != null && 278 configuration.warn.isEmpty()) 279 { 280 configuration.warn = null; 281 } 282 } 283 else 284 { 285 // Switch off warnings. 286 configuration.warn = new ArrayList(); 287 } 288 } 289 290 setIgnorewarnings(boolean ignoreWarnings)291 public void setIgnorewarnings(boolean ignoreWarnings) 292 { 293 configuration.ignoreWarnings = ignoreWarnings; 294 } 295 296 setPrintconfiguration(File printConfiguration)297 public void setPrintconfiguration(File printConfiguration) 298 { 299 configuration.printConfiguration = optionalFile(printConfiguration); 300 } 301 302 setDump(File dump)303 public void setDump(File dump) 304 { 305 configuration.dump = optionalFile(dump); 306 } 307 308 309 // Implementations for Task. 310 execute()311 public void execute() throws BuildException 312 { 313 try 314 { 315 ProGuard proGuard = new ProGuard(configuration); 316 proGuard.execute(); 317 } 318 catch (IOException e) 319 { 320 throw new BuildException(e.getMessage(), e); 321 } 322 } 323 324 325 // Small utility methods. 326 327 /** 328 * Returns a file that is properly resolved with respect to the project 329 * directory, or <code>null</code> or empty if its name is actually a 330 * boolean flag. 331 */ optionalFile(File file)332 private File optionalFile(File file) 333 { 334 String fileName = file.getName(); 335 336 return 337 fileName.equalsIgnoreCase("false") || 338 fileName.equalsIgnoreCase("no") || 339 fileName.equalsIgnoreCase("off") ? null : 340 fileName.equalsIgnoreCase("true") || 341 fileName.equalsIgnoreCase("yes") || 342 fileName.equalsIgnoreCase("on") ? Configuration.STD_OUT : 343 resolvedFile(file); 344 } 345 346 347 /** 348 * Returns a file that is properly resolved with respect to the project 349 * directory. 350 */ resolvedFile(File file)351 private File resolvedFile(File file) 352 { 353 return file.isAbsolute() ? file : 354 new File(getProject().getBaseDir(), 355 file.getName()); 356 } 357 } 358