diff options
Diffstat (limited to 'src/proguard/ConfigurationParser.java')
-rw-r--r-- | src/proguard/ConfigurationParser.java | 172 |
1 files changed, 100 insertions, 72 deletions
diff --git a/src/proguard/ConfigurationParser.java b/src/proguard/ConfigurationParser.java index e01809e..0a6e296 100644 --- a/src/proguard/ConfigurationParser.java +++ b/src/proguard/ConfigurationParser.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2011 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 @@ -58,9 +58,21 @@ public class ConfigurationParser public ConfigurationParser(String[] args, File baseDir) throws IOException { - reader = new ArgumentWordReader(args, baseDir); + this(new ArgumentWordReader(args, baseDir)); + } - readNextWord(); + + /** + * Creates a new ConfigurationParser for the given lines, + * with the given base directory. + */ + public ConfigurationParser(String lines, + String description, + File baseDir) throws IOException + { + this(new LineWordReader(new LineNumberReader(new StringReader(lines)), + description, + baseDir)); } @@ -69,9 +81,7 @@ public class ConfigurationParser */ public ConfigurationParser(File file) throws IOException { - reader = new FileWordReader(file); - - readNextWord(); + this(new FileWordReader(file)); } @@ -80,7 +90,16 @@ public class ConfigurationParser */ public ConfigurationParser(URL url) throws IOException { - reader = new FileWordReader(url); + this(new FileWordReader(url)); + } + + + /** + * Creates a new ConfigurationParser for the given word reader. + */ + public ConfigurationParser(WordReader reader) throws IOException + { + this.reader = reader; readNextWord(); } @@ -110,6 +129,7 @@ public class ConfigurationParser else if (ConfigurationConstants.OUTJARS_OPTION .startsWith(nextWord)) configuration.programJars = parseClassPathArgument(configuration.programJars, true); else if (ConfigurationConstants.LIBRARYJARS_OPTION .startsWith(nextWord)) configuration.libraryJars = parseClassPathArgument(configuration.libraryJars, false); else if (ConfigurationConstants.RESOURCEJARS_OPTION .startsWith(nextWord)) throw new ParseException("The '-resourcejars' option is no longer supported. Please use the '-injars' option for all input"); + else if (ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(true); else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses = parseNoArgument(false); else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION.startsWith(nextWord)) configuration.skipNonPublicLibraryClassMembers = parseNoArgument(false); else if (ConfigurationConstants.TARGET_OPTION .startsWith(nextWord)) configuration.targetClassVersion = parseClassVersion(); @@ -124,7 +144,7 @@ public class ConfigurationParser else if (ConfigurationConstants.PRINT_SEEDS_OPTION .startsWith(nextWord)) configuration.printSeeds = parseOptionalFile(); // After '-keep'. - else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION .startsWith(nextWord)) configuration.keepDirectories = parseCommaSeparatedList("directory name", true, true, false, false, true, false, false, configuration.keepDirectories); + else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION .startsWith(nextWord)) configuration.keepDirectories = parseCommaSeparatedList("directory name", true, true, false, true, false, true, false, false, configuration.keepDirectories); else if (ConfigurationConstants.DONT_SHRINK_OPTION .startsWith(nextWord)) configuration.shrink = parseNoArgument(false); else if (ConfigurationConstants.PRINT_USAGE_OPTION .startsWith(nextWord)) configuration.printUsage = parseOptionalFile(); @@ -132,7 +152,7 @@ public class ConfigurationParser else if (ConfigurationConstants.DONT_OPTIMIZE_OPTION .startsWith(nextWord)) configuration.optimize = parseNoArgument(false); else if (ConfigurationConstants.OPTIMIZATION_PASSES .startsWith(nextWord)) configuration.optimizationPasses = parseIntegerArgument(); - else if (ConfigurationConstants.OPTIMIZATIONS .startsWith(nextWord)) configuration.optimizations = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, configuration.optimizations); + else if (ConfigurationConstants.OPTIMIZATIONS .startsWith(nextWord)) configuration.optimizations = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, false, configuration.optimizations); else if (ConfigurationConstants.ASSUME_NO_SIDE_EFFECTS_OPTION .startsWith(nextWord)) configuration.assumeNoSideEffects = parseClassSpecificationArguments(configuration.assumeNoSideEffects); else if (ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION .startsWith(nextWord)) configuration.allowAccessModification = parseNoArgument(true); else if (ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.mergeInterfacesAggressively = parseNoArgument(true); @@ -146,22 +166,23 @@ public class ConfigurationParser else if (ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION .startsWith(nextWord)) configuration.overloadAggressively = parseNoArgument(true); else if (ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION .startsWith(nextWord)) configuration.useUniqueClassMemberNames = parseNoArgument(true); else if (ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION .startsWith(nextWord)) configuration.useMixedCaseClassNames = parseNoArgument(false); - else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION .startsWith(nextWord)) configuration.keepPackageNames = parseCommaSeparatedList("package name", true, true, false, true, false, true, false, configuration.keepPackageNames); + else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION .startsWith(nextWord)) configuration.keepPackageNames = parseCommaSeparatedList("package name", true, true, false, false, true, false, true, false, configuration.keepPackageNames); else if (ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION .startsWith(nextWord)) configuration.flattenPackageHierarchy = ClassUtil.internalClassName(parseOptionalArgument()); else if (ConfigurationConstants.REPACKAGE_CLASSES_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument()); else if (ConfigurationConstants.DEFAULT_PACKAGE_OPTION .startsWith(nextWord)) configuration.repackageClasses = ClassUtil.internalClassName(parseOptionalArgument()); - else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION .startsWith(nextWord)) configuration.keepAttributes = parseCommaSeparatedList("attribute name", true, true, false, true, false, false, false, configuration.keepAttributes); + else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION .startsWith(nextWord)) configuration.keepAttributes = parseCommaSeparatedList("attribute name", true, true, false, false, true, false, false, false, configuration.keepAttributes); + else if (ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION .startsWith(nextWord)) configuration.keepParameterNames = parseNoArgument(true); else if (ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION .startsWith(nextWord)) configuration.newSourceFileAttribute = parseOptionalArgument(); - else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION .startsWith(nextWord)) configuration.adaptClassStrings = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.adaptClassStrings); - else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, false, false, false, false, false, configuration.adaptResourceFileNames); - else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION .startsWith(nextWord)) configuration.adaptResourceFileContents = parseCommaSeparatedList("resource file name", true, true, false, false, false, false, false, configuration.adaptResourceFileContents); + else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION .startsWith(nextWord)) configuration.adaptClassStrings = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.adaptClassStrings); + else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_NAMES_OPTION .startsWith(nextWord)) configuration.adaptResourceFileNames = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileNames); + else if (ConfigurationConstants.ADAPT_RESOURCE_FILE_CONTENTS_OPTION .startsWith(nextWord)) configuration.adaptResourceFileContents = parseCommaSeparatedList("resource file name", true, true, false, true, false, false, false, false, configuration.adaptResourceFileContents); else if (ConfigurationConstants.DONT_PREVERIFY_OPTION .startsWith(nextWord)) configuration.preverify = parseNoArgument(false); else if (ConfigurationConstants.MICRO_EDITION_OPTION .startsWith(nextWord)) configuration.microEdition = parseNoArgument(true); else if (ConfigurationConstants.VERBOSE_OPTION .startsWith(nextWord)) configuration.verbose = parseNoArgument(true); - else if (ConfigurationConstants.DONT_NOTE_OPTION .startsWith(nextWord)) configuration.note = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.note); - else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseCommaSeparatedList("class name", true, true, false, true, false, true, false, configuration.warn); + else if (ConfigurationConstants.DONT_NOTE_OPTION .startsWith(nextWord)) configuration.note = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.note); + else if (ConfigurationConstants.DONT_WARN_OPTION .startsWith(nextWord)) configuration.warn = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.warn); else if (ConfigurationConstants.IGNORE_WARNINGS_OPTION .startsWith(nextWord)) configuration.ignoreWarnings = parseNoArgument(true); else if (ConfigurationConstants.PRINT_CONFIGURATION_OPTION .startsWith(nextWord)) configuration.printConfiguration = parseOptionalFile(); else if (ConfigurationConstants.DUMP_OPTION .startsWith(nextWord)) configuration.dump = parseOptionalFile(); @@ -190,7 +211,7 @@ public class ConfigurationParser private long parseIncludeArgument(long lastModified) throws ParseException, IOException { // Read the configuation file name. - readNextWord("configuration file name"); + readNextWord("configuration file name", true, false); File file = file(nextWord); reader.includeWordReader(new FileWordReader(file)); @@ -204,7 +225,7 @@ public class ConfigurationParser private void parseBaseDirectoryArgument() throws ParseException, IOException { // Read the base directory name. - readNextWord("base directory name"); + readNextWord("base directory name", true, false); reader.setBaseDir(file(nextWord)); @@ -225,7 +246,7 @@ public class ConfigurationParser while (true) { // Read the next jar name. - readNextWord("jar or directory name"); + readNextWord("jar or directory name", true, false); // Create a new class path entry. ClassPathEntry entry = new ClassPathEntry(file(nextWord), isOutput); @@ -245,7 +266,7 @@ public class ConfigurationParser { // Read the filter. filters[counter++] = - parseCommaSeparatedList("filter", true, false, true, false, true, false, false, null); + parseCommaSeparatedList("filter", true, false, true, true, false, true, false, false, null); } while (counter < filters.length && ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord)); @@ -343,7 +364,7 @@ public class ConfigurationParser throws ParseException, IOException { // Read the obligatory file name. - readNextWord("file name"); + readNextWord("file name", true, false); // Make sure the file is properly resolved. File file = file(nextWord); @@ -358,7 +379,7 @@ public class ConfigurationParser throws ParseException, IOException { // Read the optional file name. - readNextWord(); + readNextWord(true); // Didn't the user specify a file name? if (configurationEnd()) @@ -386,11 +407,11 @@ public class ConfigurationParser return ""; } - String fileName = nextWord; + String argument = nextWord; readNextWord(); - return fileName; + return argument; } @@ -431,7 +452,8 @@ public class ConfigurationParser { readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD + "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE + - "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true); + "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", + false, true); if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord)) { @@ -491,7 +513,8 @@ public class ConfigurationParser // Read and add the class configuration. readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD + "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE + - "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true); + "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", + false, true); classSpecifications.add(parseClassSpecificationArguments()); @@ -512,30 +535,21 @@ public class ConfigurationParser // Parse the class annotations and access modifiers until the class keyword. while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord)) { - // Parse the annotation type, if any. -// if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord)) -// { -// annotationType = -// ClassUtil.internalType( -// ListUtil.commaSeparatedString( -// parseCommaSeparatedList("annotation type", -// true, false, false, true, false, null))); -// -// continue; -// } - // Strip the negating sign, if any. - String strippedWord = nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD) ? + boolean negated = + nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD); + + String strippedWord = negated ? nextWord.substring(1) : nextWord; // Parse the class access modifiers. - // TODO: Distinguish annotation from annotation modifier. int accessFlag = strippedWord.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC : strippedWord.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL : strippedWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) ? ClassConstants.INTERNAL_ACC_INTERFACE : strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT : + strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC : strippedWord.equals(ClassConstants.EXTERNAL_ACC_ANNOTATION) ? ClassConstants.INTERNAL_ACC_ANNOTATTION : strippedWord.equals(ClassConstants.EXTERNAL_ACC_ENUM) ? ClassConstants.INTERNAL_ACC_ENUM : unknownAccessFlag(); @@ -543,9 +557,11 @@ public class ConfigurationParser // Is it an annotation modifier? if (accessFlag == ClassConstants.INTERNAL_ACC_ANNOTATTION) { - // Is the next word actually an annotation type? - readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", false); + // Already read the next word. + readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", + false, false); + // Is the next word actually an annotation type? if (!nextWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) && !nextWord.equals(ClassConstants.EXTERNAL_ACC_ENUM) && !nextWord.equals(ConfigurationConstants.CLASS_KEYWORD)) @@ -554,13 +570,17 @@ public class ConfigurationParser annotationType = ListUtil.commaSeparatedString( parseCommaSeparatedList("annotation type", - false, false, false, true, false, false, true, null)); + false, false, false, false, true, false, false, true, null), false); + // Continue parsing the access modifier that we just read + // in the next cycle. continue; } + + // Otherwise just handle the annotation modifier. } - if (strippedWord.equals(nextWord)) + if (!negated) { requiredSetClassAccessFlags |= accessFlag; } @@ -569,7 +589,6 @@ public class ConfigurationParser requiredUnsetClassAccessFlags |= accessFlag; } - if ((requiredSetClassAccessFlags & requiredUnsetClassAccessFlags) != 0) { @@ -585,16 +604,21 @@ public class ConfigurationParser break; } - readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD + - "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE + - "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", true); + // Should we read the next word? + if (accessFlag != ClassConstants.INTERNAL_ACC_ANNOTATTION) + { + readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD + + "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE + + "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", + false, true); + } } // Parse the class name part. String externalClassName = ListUtil.commaSeparatedString( parseCommaSeparatedList("class name or interface name", - true, false, false, true, false, false, false, null)); + true, false, false, false, true, false, false, false, null), false); // For backward compatibility, allow a single "*" wildcard to match any // class. @@ -612,7 +636,7 @@ public class ConfigurationParser if (ConfigurationConstants.IMPLEMENTS_KEYWORD.equals(nextWord) || ConfigurationConstants.EXTENDS_KEYWORD.equals(nextWord)) { - readNextWord("class name or interface name", true); + readNextWord("class name or interface name", false, true); // Parse the annotation type, if any. if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord)) @@ -620,13 +644,13 @@ public class ConfigurationParser extendsAnnotationType = ListUtil.commaSeparatedString( parseCommaSeparatedList("annotation type", - true, false, false, true, false, false, true, null)); + true, false, false, false, true, false, false, true, null), false); } String externalExtendsClassName = ListUtil.commaSeparatedString( parseCommaSeparatedList("class name or interface name", - false, false, false, true, false, false, false, null)); + false, false, false, false, true, false, false, false, null), false); extendsClassName = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalExtendsClassName) ? null : @@ -659,7 +683,8 @@ public class ConfigurationParser while (true) { readNextWord("class member description" + - " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'", true); + " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'", + false, true); if (nextWord.equals(ConfigurationConstants.CLOSE_KEYWORD)) { @@ -697,8 +722,7 @@ public class ConfigurationParser annotationType = ListUtil.commaSeparatedString( parseCommaSeparatedList("annotation type", - true, false, false, true, false, false, true, null)); - + true, false, false, false, true, false, false, true, null), false); continue; } @@ -716,9 +740,12 @@ public class ConfigurationParser strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED) ? ClassConstants.INTERNAL_ACC_SYNCHRONIZED : strippedWord.equals(ClassConstants.EXTERNAL_ACC_VOLATILE) ? ClassConstants.INTERNAL_ACC_VOLATILE : strippedWord.equals(ClassConstants.EXTERNAL_ACC_TRANSIENT) ? ClassConstants.INTERNAL_ACC_TRANSIENT : + strippedWord.equals(ClassConstants.EXTERNAL_ACC_BRIDGE) ? ClassConstants.INTERNAL_ACC_BRIDGE : + strippedWord.equals(ClassConstants.EXTERNAL_ACC_VARARGS) ? ClassConstants.INTERNAL_ACC_VARARGS : strippedWord.equals(ClassConstants.EXTERNAL_ACC_NATIVE) ? ClassConstants.INTERNAL_ACC_NATIVE : strippedWord.equals(ClassConstants.EXTERNAL_ACC_ABSTRACT) ? ClassConstants.INTERNAL_ACC_ABSTRACT : strippedWord.equals(ClassConstants.EXTERNAL_ACC_STRICT) ? ClassConstants.INTERNAL_ACC_STRICT : + strippedWord.equals(ClassConstants.EXTERNAL_ACC_SYNTHETIC) ? ClassConstants.INTERNAL_ACC_SYNTHETIC : 0; if (accessFlag == 0) { @@ -875,7 +902,7 @@ public class ConfigurationParser // Parse the method arguments. String descriptor = ClassUtil.internalMethodDescriptor(type, - parseCommaSeparatedList("argument", true, true, true, true, false, false, false, null)); + parseCommaSeparatedList("argument", true, true, true, false, true, false, false, false, null)); if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord)) { @@ -921,6 +948,7 @@ public class ConfigurationParser boolean readFirstWord, boolean allowEmptyList, boolean expectClosingParenthesis, + boolean isFileName, boolean checkJavaIdentifiers, boolean replaceSystemProperties, boolean replaceExternalClassNames, @@ -938,12 +966,12 @@ public class ConfigurationParser if (expectClosingParenthesis || !allowEmptyList) { // Read the first list entry. - readNextWord(expectedDescription); + readNextWord(expectedDescription, isFileName, false); } else { // Read the first list entry, if there is any. - readNextWord(); + readNextWord(isFileName); // Check if the list is empty. if (configurationEnd() || @@ -1005,7 +1033,7 @@ public class ConfigurationParser } // Read the next list entry. - readNextWord(expectedDescription); + readNextWord(expectedDescription, isFileName, false); } return list; @@ -1035,16 +1063,6 @@ public class ConfigurationParser file = new File(reader.getBaseDir(), fileName); } - // Try to get a canonical representation. - try - { - file = file.getCanonicalFile(); - } - catch (IOException ex) - { - // Just keep the original representation. - } - return file; } @@ -1096,7 +1114,7 @@ public class ConfigurationParser private void readNextWord(String expectedDescription) throws ParseException, IOException { - readNextWord(expectedDescription, false); + readNextWord(expectedDescription, false, false); } @@ -1105,10 +1123,11 @@ public class ConfigurationParser * throwing an exception if there is no next word. */ private void readNextWord(String expectedDescription, + boolean isFileName, boolean expectingAtCharacter) throws ParseException, IOException { - readNextWord(); + readNextWord(isFileName); if (configurationEnd(expectingAtCharacter)) { throw new ParseException("Expecting " + expectedDescription + @@ -1122,7 +1141,16 @@ public class ConfigurationParser */ private void readNextWord() throws IOException { - nextWord = reader.nextWord(); + readNextWord(false); + } + + + /** + * Reads the next word of the configuration in the 'nextWord' field. + */ + private void readNextWord(boolean isFileName) throws IOException + { + nextWord = reader.nextWord(isFileName); } |