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 */ 21package proguard.ant; 22 23import org.apache.tools.ant.*; 24import proguard.*; 25 26import java.io.IOException; 27import java.util.*; 28 29/** 30 * This Task allows to define a ProGuard configuration from Ant. 31 * 32 * @author Eric Lafortune 33 */ 34public class ConfigurationTask extends Task 35{ 36 protected final Configuration configuration = new Configuration(); 37 38 39 /** 40 * Adds the contents of this configuration task to the given configuration. 41 * @param configuration the configuration to be extended. 42 */ 43 public void appendTo(Configuration configuration) 44 { 45 // Append all of these configuration entries to the given configuration. 46 configuration.programJars = extendClassPath(configuration.programJars, 47 this.configuration.programJars); 48 49 configuration.libraryJars = extendClassPath(configuration.libraryJars, 50 this.configuration.libraryJars); 51 52 configuration.keep = extendClassSpecifications(configuration.keep, 53 this.configuration.keep); 54 55 configuration.keepDirectories = extendList(configuration.keepDirectories, 56 this.configuration.keepDirectories); 57 58 configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping, 59 this.configuration.whyAreYouKeeping); 60 61 configuration.optimizations = extendClassSpecifications(configuration.optimizations, 62 this.configuration.optimizations); 63 64 configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects, 65 this.configuration.assumeNoSideEffects); 66 67 configuration.keepPackageNames = extendList(configuration.keepPackageNames, 68 this.configuration.keepPackageNames); 69 70 configuration.keepAttributes = extendList(configuration.keepAttributes, 71 this.configuration.keepAttributes); 72 73 configuration.adaptClassStrings = extendList(configuration.adaptClassStrings, 74 this.configuration.adaptClassStrings); 75 76 configuration.adaptResourceFileNames = extendList(configuration.adaptResourceFileNames, 77 this.configuration.adaptResourceFileNames); 78 79 configuration.adaptResourceFileContents = extendList(configuration.adaptResourceFileContents, 80 this.configuration.adaptResourceFileContents); 81 82 configuration.note = extendList(configuration.note, 83 this.configuration.note); 84 85 configuration.warn = extendList(configuration.warn, 86 this.configuration.warn); 87 } 88 89 90 // Ant task nested elements. 91 92 public void addConfiguredInjar(ClassPathElement classPathElement) 93 { 94 configuration.programJars = extendClassPath(configuration.programJars, 95 classPathElement, 96 false); 97 } 98 99 100 public void addConfiguredOutjar(ClassPathElement classPathElement) 101 { 102 configuration.programJars = extendClassPath(configuration.programJars, 103 classPathElement, 104 true); 105 } 106 107 108 public void addConfiguredLibraryjar(ClassPathElement classPathElement) 109 { 110 configuration.libraryJars = extendClassPath(configuration.libraryJars, 111 classPathElement, 112 false); 113 } 114 115 116 public void addConfiguredKeepdirectory(FilterElement filterElement) 117 { 118 configuration.keepDirectories = extendFilter(configuration.keepDirectories, 119 filterElement); 120 } 121 122 123 public void addConfiguredKeepdirectories(FilterElement filterElement) 124 { 125 configuration.keepDirectories = extendFilter(configuration.keepDirectories, 126 filterElement); 127 } 128 129 130 public void addConfiguredKeep(KeepSpecificationElement keepSpecificationElement) 131 { 132 configuration.keep = extendKeepSpecifications(configuration.keep, 133 keepSpecificationElement, 134 true, 135 false); 136 } 137 138 139 public void addConfiguredKeepclassmembers(KeepSpecificationElement keepSpecificationElement) 140 { 141 configuration.keep = extendKeepSpecifications(configuration.keep, 142 keepSpecificationElement, 143 false, 144 false); 145 } 146 147 148 public void addConfiguredKeepclasseswithmembers(KeepSpecificationElement keepSpecificationElement) 149 { 150 configuration.keep = extendKeepSpecifications(configuration.keep, 151 keepSpecificationElement, 152 true, 153 true); 154 } 155 156 157 public void addConfiguredKeepnames(KeepSpecificationElement keepSpecificationElement) 158 { 159 // Set the shrinking flag, based on the name (backward compatibility). 160 keepSpecificationElement.setAllowshrinking(true); 161 162 configuration.keep = extendKeepSpecifications(configuration.keep, 163 keepSpecificationElement, 164 true, 165 false); 166 } 167 168 169 public void addConfiguredKeepclassmembernames(KeepSpecificationElement keepSpecificationElement) 170 { 171 // Set the shrinking flag, based on the name (backward compatibility). 172 keepSpecificationElement.setAllowshrinking(true); 173 174 configuration.keep = extendKeepSpecifications(configuration.keep, 175 keepSpecificationElement, 176 false, 177 false); 178 } 179 180 181 public void addConfiguredKeepclasseswithmembernames(KeepSpecificationElement keepSpecificationElement) 182 { 183 // Set the shrinking flag, based on the name (backward compatibility). 184 keepSpecificationElement.setAllowshrinking(true); 185 186 configuration.keep = extendKeepSpecifications(configuration.keep, 187 keepSpecificationElement, 188 true, 189 true); 190 } 191 192 193 public void addConfiguredWhyareyoukeeping(ClassSpecificationElement classSpecificationElement) 194 { 195 configuration.whyAreYouKeeping = extendClassSpecifications(configuration.whyAreYouKeeping, 196 classSpecificationElement); 197 } 198 199 200 public void addConfiguredAssumenosideeffects(ClassSpecificationElement classSpecificationElement) 201 { 202 configuration.assumeNoSideEffects = extendClassSpecifications(configuration.assumeNoSideEffects, 203 classSpecificationElement); 204 } 205 206 207 public void addConfiguredOptimizations(FilterElement filterElement) 208 { 209 addConfiguredOptimization(filterElement); 210 } 211 212 213 public void addConfiguredOptimization(FilterElement filterElement) 214 { 215 configuration.optimizations = extendFilter(configuration.optimizations, 216 filterElement); 217 } 218 219 220 public void addConfiguredKeeppackagename(FilterElement filterElement) 221 { 222 configuration.keepPackageNames = extendFilter(configuration.keepPackageNames, 223 filterElement, 224 true); 225 } 226 227 228 public void addConfiguredKeeppackagenames(FilterElement filterElement) 229 { 230 configuration.keepPackageNames = extendFilter(configuration.keepPackageNames, 231 filterElement, 232 true); 233 } 234 235 236 public void addConfiguredKeepattributes(FilterElement filterElement) 237 { 238 addConfiguredKeepattribute(filterElement); 239 } 240 241 242 public void addConfiguredKeepattribute(FilterElement filterElement) 243 { 244 configuration.keepAttributes = extendFilter(configuration.keepAttributes, 245 filterElement); 246 } 247 248 249 public void addConfiguredAdaptclassstrings(FilterElement filterElement) 250 { 251 configuration.adaptClassStrings = extendFilter(configuration.adaptClassStrings, 252 filterElement, true); 253 } 254 255 256 public void addConfiguredAdaptresourcefilenames(FilterElement filterElement) 257 { 258 configuration.adaptResourceFileNames = extendFilter(configuration.adaptResourceFileNames, 259 filterElement); 260 } 261 262 263 public void addConfiguredAdaptresourcefilecontents(FilterElement filterElement) 264 { 265 configuration.adaptResourceFileContents = extendFilter(configuration.adaptResourceFileContents, 266 filterElement); 267 } 268 269 270 public void addConfiguredDontnote(FilterElement filterElement) 271 { 272 configuration.note = extendFilter(configuration.note, filterElement, true); 273 } 274 275 276 public void addConfiguredDontwarn(FilterElement filterElement) 277 { 278 configuration.warn = extendFilter(configuration.warn, filterElement, true); 279 } 280 281 282 public void addConfiguredConfiguration(ConfigurationElement configurationElement) 283 { 284 configurationElement.appendTo(configuration); 285 } 286 287 288 // Implementations for Task. 289 290 public void addText(String text) throws BuildException 291 { 292 try 293 { 294 Project project = getProject(); 295 296 // Replace Ant-style properties ('${...}'). 297 String arg = project.replaceProperties(text); 298 299 // Get the combined system properties and Ant properties, for 300 // replacing ProGuard-style properties ('<...>'). 301 Properties properties = new Properties(); 302 properties.putAll(project.getProperties()); 303 304 ConfigurationParser parser = new ConfigurationParser(arg, 305 "embedded configuration", 306 project.getBaseDir(), 307 properties); 308 309 try 310 { 311 parser.parse(configuration); 312 } 313 catch (ParseException ex) 314 { 315 throw new BuildException(ex.getMessage()); 316 } 317 finally 318 { 319 parser.close(); 320 } 321 } 322 catch (IOException ex) 323 { 324 throw new BuildException(ex.getMessage()); 325 } 326 } 327 328 329 // Small utility methods. 330 331 private ClassPath extendClassPath(ClassPath classPath, 332 ClassPathElement classPathElement, 333 boolean output) 334 { 335 if (classPath == null) 336 { 337 classPath = new ClassPath(); 338 } 339 340 classPathElement.appendClassPathEntriesTo(classPath, 341 output); 342 343 return classPath; 344 } 345 346 347 private ClassPath extendClassPath(ClassPath classPath, 348 ClassPath additionalClassPath) 349 { 350 if (additionalClassPath != null) 351 { 352 if (classPath == null) 353 { 354 classPath = new ClassPath(); 355 } 356 357 classPath.addAll(additionalClassPath); 358 } 359 360 return classPath; 361 } 362 363 364 private List extendKeepSpecifications(List keepSpecifications, 365 KeepSpecificationElement keepSpecificationElement, 366 boolean markClasses, 367 boolean markClassesConditionally) 368 { 369 if (keepSpecifications == null) 370 { 371 keepSpecifications = new ArrayList(); 372 } 373 374 keepSpecificationElement.appendTo(keepSpecifications, 375 markClasses, 376 markClassesConditionally); 377 378 return keepSpecifications; 379 } 380 381 382 private List extendClassSpecifications(List classSpecifications, 383 ClassSpecificationElement classSpecificationElement) 384 { 385 if (classSpecifications == null) 386 { 387 classSpecifications = new ArrayList(); 388 } 389 390 classSpecificationElement.appendTo(classSpecifications); 391 392 return classSpecifications; 393 } 394 395 396 private List extendClassSpecifications(List classSpecifications, 397 List additionalClassSpecifications) 398 { 399 if (additionalClassSpecifications != null) 400 { 401 if (classSpecifications == null) 402 { 403 classSpecifications = new ArrayList(); 404 } 405 406 classSpecifications.addAll(additionalClassSpecifications); 407 } 408 409 return classSpecifications; 410 } 411 412 413 private List extendFilter(List filter, 414 FilterElement filterElement) 415 { 416 return extendFilter(filter, filterElement, false); 417 } 418 419 420 private List extendFilter(List filter, 421 FilterElement filterElement, 422 boolean internal) 423 { 424 if (filter == null) 425 { 426 filter = new ArrayList(); 427 } 428 429 filterElement.appendTo(filter, internal); 430 431 return filter; 432 } 433 434 435 private List extendList(List list, 436 List additionalList) 437 { 438 if (additionalList != null) 439 { 440 if (list == null) 441 { 442 list = new ArrayList(); 443 } 444 445 list.addAll(additionalList); 446 } 447 448 return list; 449 } 450} 451