1 21 package proguard; 22 23 import proguard.classfile.*; 24 import proguard.classfile.util.*; 25 import proguard.util.*; 26 27 import java.io.*; 28 import java.util.*; 29 30 31 36 public class ConfigurationWriter 37 { 38 private static final String [] KEEP_OPTIONS = new String [] 39 { 40 ConfigurationConstants.KEEP_OPTION, 41 ConfigurationConstants.KEEP_CLASS_MEMBERS_OPTION, 42 ConfigurationConstants.KEEP_CLASSES_WITH_MEMBERS_OPTION 43 }; 44 45 46 private PrintWriter writer; 47 private File baseDir; 48 49 50 53 public ConfigurationWriter(File configurationFile) throws IOException 54 { 55 this(new PrintWriter(new FileWriter(configurationFile))); 56 57 baseDir = configurationFile.getParentFile(); 58 } 59 60 61 64 public ConfigurationWriter(OutputStream outputStream) throws IOException 65 { 66 this(new PrintWriter(outputStream)); 67 } 68 69 70 73 public ConfigurationWriter(PrintWriter writer) throws IOException 74 { 75 this.writer = writer; 76 } 77 78 79 82 public void close() throws IOException 83 { 84 writer.close(); 85 } 86 87 88 93 public void write(Configuration configuration) throws IOException 94 { 95 writeJarOptions(ConfigurationConstants.INJARS_OPTION, 97 ConfigurationConstants.OUTJARS_OPTION, 98 configuration.programJars); 99 writer.println(); 100 101 writeJarOptions(ConfigurationConstants.LIBRARYJARS_OPTION, 103 ConfigurationConstants.LIBRARYJARS_OPTION, 104 configuration.libraryJars); 105 writer.println(); 106 107 writeOption(ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION, !configuration.skipNonPublicLibraryClasses); 109 writeOption(ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION, !configuration.skipNonPublicLibraryClassMembers); 110 writeOption(ConfigurationConstants.TARGET_OPTION, ClassUtil.externalClassVersion(configuration.targetClassVersion)); 111 writeOption(ConfigurationConstants.FORCE_PROCESSING_OPTION, configuration.lastModified == Long.MAX_VALUE); 112 113 writeOption(ConfigurationConstants.DONT_SHRINK_OPTION, !configuration.shrink); 114 writeOption(ConfigurationConstants.PRINT_USAGE_OPTION, configuration.printUsage); 115 116 writeOption(ConfigurationConstants.DONT_OPTIMIZE_OPTION, !configuration.optimize); 117 writeOption(ConfigurationConstants.OPTIMIZATION_PASSES, configuration.optimizationPasses); 118 writeOption(ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION, configuration.allowAccessModification); 119 120 writeOption(ConfigurationConstants.DONT_OBFUSCATE_OPTION, !configuration.obfuscate); 121 writeOption(ConfigurationConstants.PRINT_MAPPING_OPTION, configuration.printMapping); 122 writeOption(ConfigurationConstants.APPLY_MAPPING_OPTION, configuration.applyMapping); 123 writeOption(ConfigurationConstants.OBFUSCATION_DICTIONARY_OPTION, configuration.obfuscationDictionary); 124 writeOption(ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION, configuration.overloadAggressively); 125 writeOption(ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION, configuration.useUniqueClassMemberNames); 126 writeOption(ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION, !configuration.useMixedCaseClassNames); 127 writeOption(ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION, configuration.flattenPackageHierarchy == null ? null : ClassUtil.externalClassName(configuration.flattenPackageHierarchy)); 128 writeOption(ConfigurationConstants.REPACKAGE_CLASSES_OPTION, configuration.repackageClasses == null ? null : ClassUtil.externalClassName(configuration.repackageClasses)); 129 writeOption(ConfigurationConstants.KEEP_ATTRIBUTES_OPTION, ListUtil.commaSeparatedString(configuration.keepAttributes)); 130 writeOption(ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION, configuration.newSourceFileAttribute); 131 writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION, ListUtil.commaSeparatedString(configuration.adaptResourceFileNames)); 132 writeOption(ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION, ListUtil.commaSeparatedString(configuration.adaptResourceFileContents)); 133 134 writeOption(ConfigurationConstants.DONT_PREVERIFY_OPTION, !configuration.preverify); 135 writeOption(ConfigurationConstants.MICRO_EDITION_OPTION, configuration.microEdition); 136 137 writeOption(ConfigurationConstants.VERBOSE_OPTION, configuration.verbose); 138 writeOption(ConfigurationConstants.DONT_NOTE_OPTION, !configuration.note); 139 writeOption(ConfigurationConstants.DONT_WARN_OPTION, !configuration.warn); 140 writeOption(ConfigurationConstants.IGNORE_WARNINGS_OPTION, configuration.ignoreWarnings); 141 writeOption(ConfigurationConstants.PRINT_CONFIGURATION_OPTION, configuration.printConfiguration); 142 writeOption(ConfigurationConstants.DUMP_OPTION, configuration.dump); 143 144 writeOption(ConfigurationConstants.PRINT_SEEDS_OPTION, configuration.printSeeds); 145 writer.println(); 146 147 writeOptions(ConfigurationConstants.WHY_ARE_YOU_KEEPING_OPTION, configuration.whyAreYouKeeping); 149 150 writeOptions(KEEP_OPTIONS, configuration.keep); 152 153 writeOptions(ConfigurationConstants.ASSUME_NO_SIDE_EFFECTS_OPTION, configuration.assumeNoSideEffects); 155 156 writer.flush(); 157 } 158 159 160 private void writeJarOptions(String inputEntryOptionName, 161 String outputEntryOptionName, 162 ClassPath classPath) 163 { 164 if (classPath != null) 165 { 166 for (int index = 0; index < classPath.size(); index++) 167 { 168 ClassPathEntry entry = classPath.get(index); 169 String optionName = entry.isOutput() ? 170 outputEntryOptionName : 171 inputEntryOptionName; 172 173 writer.print(optionName); 174 writer.print(' '); 175 writer.print(relativeFileName(entry.getFile())); 176 177 boolean filtered = false; 179 180 filtered = writeFilter(filtered, entry.getZipFilter()); 181 filtered = writeFilter(filtered, entry.getEarFilter()); 182 filtered = writeFilter(filtered, entry.getWarFilter()); 183 filtered = writeFilter(filtered, entry.getJarFilter()); 184 filtered = writeFilter(filtered, entry.getFilter()); 185 186 if (filtered) 187 { 188 writer.print(ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD); 189 } 190 191 writer.println(); 192 } 193 } 194 } 195 196 197 private boolean writeFilter(boolean filtered, String filter) 198 { 199 if (filtered) 200 { 201 writer.print(ConfigurationConstants.SEPARATOR_KEYWORD); 202 } 203 204 if (filter != null) 205 { 206 if (!filtered) 207 { 208 writer.print(ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD); 209 } 210 211 writer.print(quotedString(filter)); 212 213 filtered = true; 214 } 215 216 return filtered; 217 } 218 219 220 private void writeOption(String optionName, boolean flag) 221 { 222 if (flag) 223 { 224 writer.println(optionName); 225 } 226 } 227 228 229 private void writeOption(String optionName, int argument) 230 { 231 if (argument != 1) 232 { 233 writer.print(optionName); 234 writer.print(' '); 235 writer.println(argument); 236 } 237 } 238 239 240 private void writeOption(String optionName, String arguments) 241 { 242 if (arguments != null) 243 { 244 writer.print(optionName); 245 writer.print(' '); 246 writer.println(quotedString(arguments)); 247 } 248 } 249 250 251 private void writeOption(String optionName, File file) 252 { 253 if (file != null) 254 { 255 if (file.getPath().length() > 0) 256 { 257 writer.print(optionName); 258 writer.print(' '); 259 writer.println(relativeFileName(file)); 260 } 261 else 262 { 263 writer.println(optionName); 264 } 265 } 266 } 267 268 269 private void writeOptions(String [] optionNames, 270 List keepSpecifications) 271 { 272 if (keepSpecifications != null) 273 { 274 for (int index = 0; index < keepSpecifications.size(); index++) 275 { 276 writeOption(optionNames, (KeepSpecification)keepSpecifications.get(index)); 277 } 278 } 279 } 280 281 282 private void writeOption(String [] optionNames, 283 KeepSpecification keepSpecification) 284 { 285 String optionName = optionNames[keepSpecification.markConditionally ? 2 : 287 keepSpecification.markClasses ? 0 : 288 1]; 289 290 if (keepSpecification.allowShrinking) 291 { 292 optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD + 293 ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION; 294 } 295 296 if (keepSpecification.allowOptimization) 297 { 298 optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD + 299 ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION; 300 } 301 302 if (keepSpecification.allowObfuscation) 303 { 304 optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD + 305 ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION; 306 } 307 308 writeOption(optionName, keepSpecification); 310 } 311 312 313 private void writeOptions(String optionName, 314 List classSpecifications) 315 { 316 if (classSpecifications != null) 317 { 318 for (int index = 0; index < classSpecifications.size(); index++) 319 { 320 writeOption(optionName, (ClassSpecification)classSpecifications.get(index)); 321 } 322 } 323 } 324 325 326 private void writeOption(String optionName, 327 ClassSpecification classSpecification) 328 { 329 writer.println(); 330 331 writeComments(classSpecification.comments); 333 334 writer.print(optionName); 335 writer.print(' '); 336 337 if (classSpecification.annotationType != null) 339 { 340 writer.print(ConfigurationConstants.ANNOTATION_KEYWORD); 341 writer.print(ClassUtil.externalType(classSpecification.annotationType)); 342 writer.print(' '); 343 } 344 345 writer.print(ClassUtil.externalClassAccessFlags(classSpecification.requiredUnsetAccessFlags, 347 ConfigurationConstants.NEGATOR_KEYWORD)); 348 349 writer.print(ClassUtil.externalClassAccessFlags(classSpecification.requiredSetAccessFlags)); 350 351 if (((classSpecification.requiredSetAccessFlags | 354 classSpecification.requiredUnsetAccessFlags) & 355 ClassConstants.INTERNAL_ACC_INTERFACE) == 0) 356 { 357 writer.print(ConfigurationConstants.CLASS_KEYWORD); 358 } 359 360 writer.print(' '); 361 362 writer.print(classSpecification.className != null ? 364 ClassUtil.externalClassName(classSpecification.className) : 365 ConfigurationConstants.ANY_CLASS_KEYWORD); 366 367 if (classSpecification.extendsAnnotationType != null || 369 classSpecification.extendsClassName != null) 370 { 371 writer.print(' '); 372 writer.print(ConfigurationConstants.EXTENDS_KEYWORD); 373 writer.print(' '); 374 375 if (classSpecification.extendsAnnotationType != null) 377 { 378 writer.print(ConfigurationConstants.ANNOTATION_KEYWORD); 379 writer.print(ClassUtil.externalType(classSpecification.extendsAnnotationType)); 380 writer.print(' '); 381 } 382 383 writer.print(classSpecification.extendsClassName != null ? 385 ClassUtil.externalClassName(classSpecification.extendsClassName) : 386 ConfigurationConstants.ANY_CLASS_KEYWORD); 387 } 388 389 if (classSpecification.fieldSpecifications != null || 391 classSpecification.methodSpecifications != null) 392 { 393 writer.print(' '); 394 writer.println(ConfigurationConstants.OPEN_KEYWORD); 395 396 writeFieldSpecification( classSpecification.fieldSpecifications); 397 writeMethodSpecification(classSpecification.methodSpecifications); 398 399 writer.println(ConfigurationConstants.CLOSE_KEYWORD); 400 } 401 else 402 { 403 writer.println(); 404 } 405 } 406 407 408 409 private void writeComments(String comments) 410 { 411 if (comments != null) 412 { 413 int index = 0; 414 while (index < comments.length()) 415 { 416 int breakIndex = comments.indexOf('\n', index); 417 if (breakIndex < 0) 418 { 419 breakIndex = comments.length(); 420 } 421 422 writer.print('#'); 423 424 if (comments.charAt(index) != ' ') 425 { 426 writer.print(' '); 427 } 428 429 writer.println(comments.substring(index, breakIndex)); 430 431 index = breakIndex + 1; 432 } 433 } 434 } 435 436 437 private void writeFieldSpecification(List memberSpecifications) 438 { 439 if (memberSpecifications != null) 440 { 441 for (int index = 0; index < memberSpecifications.size(); index++) 442 { 443 MemberSpecification memberSpecification = 444 (MemberSpecification)memberSpecifications.get(index); 445 446 writer.print(" "); 447 448 if (memberSpecification.annotationType != null) 450 { 451 writer.print(ConfigurationConstants.ANNOTATION_KEYWORD); 452 writer.println(ClassUtil.externalType(memberSpecification.annotationType)); 453 writer.print(" "); 454 } 455 456 writer.print(ClassUtil.externalFieldAccessFlags(memberSpecification.requiredUnsetAccessFlags, 458 ConfigurationConstants.NEGATOR_KEYWORD)); 459 460 writer.print(ClassUtil.externalFieldAccessFlags(memberSpecification.requiredSetAccessFlags)); 461 462 String name = memberSpecification.name; 464 String descriptor = memberSpecification.descriptor; 465 466 if (name == null) 467 { 468 name = ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD; 469 } 470 471 writer.print(descriptor != null ? 472 ClassUtil.externalFullFieldDescription(0, 473 name, 474 descriptor) : 475 ConfigurationConstants.ANY_FIELD_KEYWORD); 476 477 writer.println(ConfigurationConstants.SEPARATOR_KEYWORD); 478 } 479 } 480 } 481 482 483 private void writeMethodSpecification(List memberSpecifications) 484 { 485 if (memberSpecifications != null) 486 { 487 for (int index = 0; index < memberSpecifications.size(); index++) 488 { 489 MemberSpecification memberSpecification = 490 (MemberSpecification)memberSpecifications.get(index); 491 492 writer.print(" "); 493 494 if (memberSpecification.annotationType != null) 496 { 497 writer.print(ConfigurationConstants.ANNOTATION_KEYWORD); 498 writer.println(ClassUtil.externalType(memberSpecification.annotationType)); 499 writer.print(" "); 500 } 501 502 writer.print(ClassUtil.externalMethodAccessFlags(memberSpecification.requiredUnsetAccessFlags, 504 ConfigurationConstants.NEGATOR_KEYWORD)); 505 506 writer.print(ClassUtil.externalMethodAccessFlags(memberSpecification.requiredSetAccessFlags)); 507 508 String name = memberSpecification.name; 510 String descriptor = memberSpecification.descriptor; 511 512 if (name == null) 513 { 514 name = ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD; 515 } 516 517 writer.print(descriptor != null ? 518 ClassUtil.externalFullMethodDescription(ClassConstants.INTERNAL_METHOD_NAME_INIT, 519 0, 520 name, 521 descriptor) : 522 ConfigurationConstants.ANY_METHOD_KEYWORD); 523 524 writer.println(ConfigurationConstants.SEPARATOR_KEYWORD); 525 } 526 } 527 } 528 529 530 534 private String relativeFileName(File file) 535 { 536 String fileName = file.getAbsolutePath(); 537 538 if (baseDir != null) 540 { 541 String baseDirName = baseDir.getAbsolutePath() + File.separator; 542 if (fileName.startsWith(baseDirName)) 543 { 544 fileName = fileName.substring(baseDirName.length()); 545 } 546 } 547 548 return quotedString(fileName); 549 } 550 551 552 555 private String quotedString(String string) 556 { 557 return string.length() == 0 || 558 string.indexOf(' ') >= 0 || 559 string.indexOf('@') >= 0 || 560 string.indexOf('{') >= 0 || 561 string.indexOf('}') >= 0 || 562 string.indexOf('(') >= 0 || 563 string.indexOf(')') >= 0 || 564 string.indexOf(':') >= 0 || 565 string.indexOf(';') >= 0 ? ("'" + string + "'") : 566 ( string ); 567 } 568 569 570 573 public static void main(String [] args) { 574 try 575 { 576 ConfigurationWriter writer = new ConfigurationWriter(new File(args[0])); 577 578 writer.write(new Configuration()); 579 } 580 catch (Exception ex) 581 { 582 ex.printStackTrace(); 583 } 584 } 585 } 586 | Popular Tags |