1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it
8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free
9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option)
10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version.
11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT
13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details.
16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along
18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc.,
19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.ClassUtil;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.util.ListUtil;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.io.*;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.net.URL;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.*;
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This class parses ProGuard configurations. Configurations can be read from an
34b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * array of arguments or from a configuration file or URL. External references
35b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * in file names ('<...>') can be resolved against a given set of properties.
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class ConfigurationParser
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
41b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private final WordReader reader;
42b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private final Properties properties;
43b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String     nextWord;
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String     lastComments;
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
49b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Creates a new ConfigurationParser for the given String arguments and
50b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * the given Properties.
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
52b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public ConfigurationParser(String[]   args,
53b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               Properties properties) throws IOException
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
55b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this(args, null, properties);
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new ConfigurationParser for the given String arguments,
61b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * with the given base directory and the given Properties.
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
63b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public ConfigurationParser(String[]   args,
64b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               File       baseDir,
65b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               Properties properties) throws IOException
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
67b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this(new ArgumentWordReader(args, baseDir), properties);
68b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
69cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang
70b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
71b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
72b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Creates a new ConfigurationParser for the given lines,
73b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * with the given base directory and the given Properties.
74b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
75b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public ConfigurationParser(String     lines,
76b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               String     description,
77b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               File       baseDir,
78b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               Properties properties) throws IOException
79b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
80b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this(new LineWordReader(new LineNumberReader(new StringReader(lines)),
81b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                description,
82b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                baseDir),
83b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             properties);
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
88b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Creates a new ConfigurationParser for the given file, with the system
89b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Properties.
90b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * @deprecated Temporary code for backward compatibility in Obclipse.
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public ConfigurationParser(File file) throws IOException
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
94b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this(file, System.getProperties());
95b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
969f606f95f03a75961498803e24bee6799a7c0885Ying Wang
97b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
98b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
99b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Creates a new ConfigurationParser for the given file and the given
100b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Properties.
101b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
102b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public ConfigurationParser(File       file,
103b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               Properties properties) throws IOException
104b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
105b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this(new FileWordReader(file), properties);
106b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
107b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
108b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
109b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
110b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Creates a new ConfigurationParser for the given URL and the given
111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Properties.
112b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
113b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public ConfigurationParser(URL        url,
114b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               Properties properties) throws IOException
115b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
116b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this(new FileWordReader(url), properties);
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
121b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Creates a new ConfigurationParser for the given word reader and the
122b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * given Properties.
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
124b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public ConfigurationParser(WordReader reader,
125b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                               Properties properties) throws IOException
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
127b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this.reader     = reader;
128b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this.properties = properties;
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Parses and returns the configuration.
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param configuration the configuration that is updated as a side-effect.
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @throws ParseException if the any of the configuration settings contains
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                        a syntax error.
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @throws IOException if an IO error occurs while reading a configuration.
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void parse(Configuration configuration)
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (nextWord != null)
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            lastComments = reader.lastComments();
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // First include directives.
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if      (ConfigurationConstants.AT_DIRECTIVE                                     .startsWith(nextWord) ||
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                     ConfigurationConstants.INCLUDE_DIRECTIVE                                .startsWith(nextWord)) configuration.lastModified                     = parseIncludeArgument(configuration.lastModified);
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.BASE_DIRECTORY_DIRECTIVE                         .startsWith(nextWord)) parseBaseDirectoryArgument();
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Then configuration options with or without arguments.
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.INJARS_OPTION                                    .startsWith(nextWord)) configuration.programJars                      = parseClassPathArgument(configuration.programJars, false);
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.OUTJARS_OPTION                                   .startsWith(nextWord)) configuration.programJars                      = parseClassPathArgument(configuration.programJars, true);
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.LIBRARYJARS_OPTION                               .startsWith(nextWord)) configuration.libraryJars                      = parseClassPathArgument(configuration.libraryJars, false);
15745e52b5ab37a26149ce031caa44bb167da217667Paul Duffin            // Android-added: Parse -systemjars option.
15845e52b5ab37a26149ce031caa44bb167da217667Paul Duffin            else if (ConfigurationConstants.SYSTEMJARS_OPTION                                .startsWith(nextWord)) configuration.systemJars                       = parseClassPathArgument(configuration.systemJars, false);
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            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");
160b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION           .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses      = parseNoArgument(true);
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES_OPTION      .startsWith(nextWord)) configuration.skipNonPublicLibraryClasses      = parseNoArgument(false);
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS_OPTION.startsWith(nextWord)) configuration.skipNonPublicLibraryClassMembers = parseNoArgument(false);
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.TARGET_OPTION                                    .startsWith(nextWord)) configuration.targetClassVersion               = parseClassVersion();
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.FORCE_PROCESSING_OPTION                          .startsWith(nextWord)) configuration.lastModified                     = parseNoArgument(Long.MAX_VALUE);
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.KEEP_OPTION                                      .startsWith(nextWord)) configuration.keep                             = parseKeepClassSpecificationArguments(configuration.keep, true,  false, false);
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.KEEP_CLASS_MEMBERS_OPTION                        .startsWith(nextWord)) configuration.keep                             = parseKeepClassSpecificationArguments(configuration.keep, false, false, false);
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBERS_OPTION                 .startsWith(nextWord)) configuration.keep                             = parseKeepClassSpecificationArguments(configuration.keep, false, true,  false);
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.KEEP_NAMES_OPTION                                .startsWith(nextWord)) configuration.keep                             = parseKeepClassSpecificationArguments(configuration.keep, true,  false, true);
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.KEEP_CLASS_MEMBER_NAMES_OPTION                   .startsWith(nextWord)) configuration.keep                             = parseKeepClassSpecificationArguments(configuration.keep, false, false, true);
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.KEEP_CLASSES_WITH_MEMBER_NAMES_OPTION            .startsWith(nextWord)) configuration.keep                             = parseKeepClassSpecificationArguments(configuration.keep, false, true,  true);
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.PRINT_SEEDS_OPTION                               .startsWith(nextWord)) configuration.printSeeds                       = parseOptionalFile();
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // After '-keep'.
175b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.KEEP_DIRECTORIES_OPTION                          .startsWith(nextWord)) configuration.keepDirectories                  = parseCommaSeparatedList("directory name", true, true, false, true, false, true, false, false, configuration.keepDirectories);
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DONT_SHRINK_OPTION                               .startsWith(nextWord)) configuration.shrink                           = parseNoArgument(false);
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.PRINT_USAGE_OPTION                               .startsWith(nextWord)) configuration.printUsage                       = parseOptionalFile();
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.WHY_ARE_YOU_KEEPING_OPTION                       .startsWith(nextWord)) configuration.whyAreYouKeeping                 = parseClassSpecificationArguments(configuration.whyAreYouKeeping);
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DONT_OPTIMIZE_OPTION                             .startsWith(nextWord)) configuration.optimize                         = parseNoArgument(false);
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.OPTIMIZATION_PASSES                              .startsWith(nextWord)) configuration.optimizationPasses               = parseIntegerArgument();
183b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.OPTIMIZATIONS                                    .startsWith(nextWord)) configuration.optimizations                    = parseCommaSeparatedList("optimization name", true, false, false, false, false, false, false, false, configuration.optimizations);
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.ASSUME_NO_SIDE_EFFECTS_OPTION                    .startsWith(nextWord)) configuration.assumeNoSideEffects              = parseClassSpecificationArguments(configuration.assumeNoSideEffects);
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.ALLOW_ACCESS_MODIFICATION_OPTION                 .startsWith(nextWord)) configuration.allowAccessModification          = parseNoArgument(true);
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.MERGE_INTERFACES_AGGRESSIVELY_OPTION             .startsWith(nextWord)) configuration.mergeInterfacesAggressively      = parseNoArgument(true);
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DONT_OBFUSCATE_OPTION                            .startsWith(nextWord)) configuration.obfuscate                        = parseNoArgument(false);
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.PRINT_MAPPING_OPTION                             .startsWith(nextWord)) configuration.printMapping                     = parseOptionalFile();
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.APPLY_MAPPING_OPTION                             .startsWith(nextWord)) configuration.applyMapping                     = parseFile();
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.OBFUSCATION_DICTIONARY_OPTION                    .startsWith(nextWord)) configuration.obfuscationDictionary            = parseFile();
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.CLASS_OBFUSCATION_DICTIONARY_OPTION              .startsWith(nextWord)) configuration.classObfuscationDictionary       = parseFile();
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.PACKAGE_OBFUSCATION_DICTIONARY_OPTION            .startsWith(nextWord)) configuration.packageObfuscationDictionary     = parseFile();
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.OVERLOAD_AGGRESSIVELY_OPTION                     .startsWith(nextWord)) configuration.overloadAggressively             = parseNoArgument(true);
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.USE_UNIQUE_CLASS_MEMBER_NAMES_OPTION             .startsWith(nextWord)) configuration.useUniqueClassMemberNames        = parseNoArgument(true);
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DONT_USE_MIXED_CASE_CLASS_NAMES_OPTION           .startsWith(nextWord)) configuration.useMixedCaseClassNames           = parseNoArgument(false);
197b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.KEEP_PACKAGE_NAMES_OPTION                        .startsWith(nextWord)) configuration.keepPackageNames                 = parseCommaSeparatedList("package name", true, true, false, false, true, false, true, false, configuration.keepPackageNames);
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.FLATTEN_PACKAGE_HIERARCHY_OPTION                 .startsWith(nextWord)) configuration.flattenPackageHierarchy          = ClassUtil.internalClassName(parseOptionalArgument());
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.REPACKAGE_CLASSES_OPTION                         .startsWith(nextWord)) configuration.repackageClasses                 = ClassUtil.internalClassName(parseOptionalArgument());
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DEFAULT_PACKAGE_OPTION                           .startsWith(nextWord)) configuration.repackageClasses                 = ClassUtil.internalClassName(parseOptionalArgument());
201b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.KEEP_ATTRIBUTES_OPTION                           .startsWith(nextWord)) configuration.keepAttributes                   = parseCommaSeparatedList("attribute name", true, true, false, false, true, false, false, false, configuration.keepAttributes);
202b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.KEEP_PARAMETER_NAMES_OPTION                      .startsWith(nextWord)) configuration.keepParameterNames               = parseNoArgument(true);
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.RENAME_SOURCE_FILE_ATTRIBUTE_OPTION              .startsWith(nextWord)) configuration.newSourceFileAttribute           = parseOptionalArgument();
204b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.ADAPT_CLASS_STRINGS_OPTION                       .startsWith(nextWord)) configuration.adaptClassStrings                = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.adaptClassStrings);
205b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            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);
206b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            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);
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DONT_PREVERIFY_OPTION                            .startsWith(nextWord)) configuration.preverify                        = parseNoArgument(false);
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.MICRO_EDITION_OPTION                             .startsWith(nextWord)) configuration.microEdition                     = parseNoArgument(true);
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.VERBOSE_OPTION                                   .startsWith(nextWord)) configuration.verbose                          = parseNoArgument(true);
212b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.DONT_NOTE_OPTION                                 .startsWith(nextWord)) configuration.note                             = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.note);
213b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (ConfigurationConstants.DONT_WARN_OPTION                                 .startsWith(nextWord)) configuration.warn                             = parseCommaSeparatedList("class name", true, true, false, false, true, false, true, false, configuration.warn);
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.IGNORE_WARNINGS_OPTION                           .startsWith(nextWord)) configuration.ignoreWarnings                   = parseNoArgument(true);
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.PRINT_CONFIGURATION_OPTION                       .startsWith(nextWord)) configuration.printConfiguration               = parseOptionalFile();
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.DUMP_OPTION                                      .startsWith(nextWord)) configuration.dump                             = parseOptionalFile();
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Unknown option " + reader.locationDescription());
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Closes the configuration.
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @throws IOException if an IO error occurs while closing the configuration.
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void close() throws IOException
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (reader != null)
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            reader.close();
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private long parseIncludeArgument(long lastModified) throws ParseException, IOException
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
2412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Read the configuration file name.
242b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        readNextWord("configuration file name", true, false);
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        File file = file(nextWord);
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        reader.includeWordReader(new FileWordReader(file));
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return Math.max(lastModified, file.lastModified());
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void parseBaseDirectoryArgument() throws ParseException, IOException
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the base directory name.
256b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        readNextWord("base directory name", true, false);
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        reader.setBaseDir(file(nextWord));
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private ClassPath parseClassPathArgument(ClassPath classPath,
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             boolean   isOutput)
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Create a new List if necessary.
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (classPath == null)
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            classPath = new ClassPath();
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (true)
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Read the next jar name.
277b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            readNextWord("jar or directory name", true, false);
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Create a new class path entry.
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ClassPathEntry entry = new ClassPathEntry(file(nextWord), isOutput);
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Read the opening parenthesis or the separator, if any.
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord();
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Read the optional filters.
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!configurationEnd() &&
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(nextWord))
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read all filters in an array.
2902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                List[] filters = new List[7];
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                int counter = 0;
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                do
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Read the filter.
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    filters[counter++] =
297b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                        parseCommaSeparatedList("filter", true, true, true, true, false, true, false, false, null);
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                while (counter < filters.length &&
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                       ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord));
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Make sure there is a closing parenthesis.
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord))
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    throw new ParseException("Expecting separating '" + ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "' or '" + ConfigurationConstants.SEPARATOR_KEYWORD +
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "', or closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "' before " + reader.locationDescription());
309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Set all filters from the array on the entry.
312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                entry.setFilter(filters[--counter]);
313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (counter > 0)
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    entry.setJarFilter(filters[--counter]);
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    if (counter > 0)
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        entry.setWarFilter(filters[--counter]);
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        if (counter > 0)
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        {
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            entry.setEarFilter(filters[--counter]);
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            if (counter > 0)
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            {
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                entry.setZipFilter(filters[--counter]);
3252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                if (counter > 0)
3262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                {
3272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                    // For backward compatibility, the apk
3282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                    // filter comes second in the list.
3292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                    entry.setApkFilter(filters[--counter]);
3302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                    if (counter > 0)
3312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                    {
3322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                        // For backward compatibility, the aar
3332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                        // filter comes first in the list.
3342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                        entry.setAarFilter(filters[--counter]);
3352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                    }
3362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                }
337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            }
338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        }
339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read the separator, if any.
343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                readNextWord();
344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Add the entry to the list.
347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            classPath.add(entry);
348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (configurationEnd())
350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                return classPath;
352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!nextWord.equals(ConfigurationConstants.JAR_SEPARATOR_KEYWORD))
355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Expecting class path separator '" + ConfigurationConstants.JAR_SEPARATOR_KEYWORD +
357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' before " + reader.locationDescription());
358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int parseClassVersion()
364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the obligatory target.
367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord("java version");
368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
369b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int classVersion = ClassUtil.internalClassVersion(nextWord);
370b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (classVersion == 0)
371b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
372b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new ParseException("Unsupported java version " + reader.locationDescription());
373b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
374b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
375b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
376b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
377b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return classVersion;
378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int parseIntegerArgument()
382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Read the obligatory integer.
387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord("integer");
388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int integer = Integer.parseInt(nextWord);
390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord();
392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return integer;
394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (NumberFormatException e)
396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new ParseException("Expecting integer argument instead of '" + nextWord +
398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     "' before " + reader.locationDescription());
399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private File parseFile()
404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the obligatory file name.
407b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        readNextWord("file name", true, false);
408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make sure the file is properly resolved.
410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        File file = file(nextWord);
411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return file;
415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private File parseOptionalFile()
419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the optional file name.
422b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        readNextWord(true);
423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Didn't the user specify a file name?
425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configurationEnd())
426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
427b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            return Configuration.STD_OUT;
428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
430b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make sure the file is properly resolved.
431b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        File file = file(nextWord);
432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return file;
436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String parseOptionalArgument() throws IOException
440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
441b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the optional argument.
442b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Didn't the user specify an argument?
445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configurationEnd())
446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return "";
448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
450b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        String argument = nextWord;
451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
454b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        return argument;
455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean parseNoArgument(boolean value) throws IOException
459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
460b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return value;
463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
466b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private long parseNoArgument(long value) throws IOException
467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
468b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord();
469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return value;
471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
473b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private List parseKeepClassSpecificationArguments(List    keepClassSpecifications,
475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      boolean markClasses,
476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      boolean markConditionally,
477b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                      boolean allowShrinking)
478b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Create a new List if necessary.
481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (keepClassSpecifications == null)
482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
483b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            keepClassSpecifications = new ArrayList();
484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
4862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        boolean markDescriptorClasses = false;
4872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        //boolean allowShrinking        = false;
4882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        boolean allowOptimization     = false;
4892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        boolean allowObfuscation      = false;
490b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the keep modifiers.
492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (true)
493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
4952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                         "', '"      + JavaConstants.ACC_INTERFACE +
4962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                         "', or '"   + JavaConstants.ACC_ENUM + "'",
497b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                         false, true);
498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
501b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Not a comma. Stop parsing the keep modifiers.
502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
504b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord("keyword '" + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION +
506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                         "', '"      + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION +
507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                         "', or '"   + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION + "'");
508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
5092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if      (ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION.startsWith(nextWord))
510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
5112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                markDescriptorClasses = true;
512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
5132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            else if (ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION           .startsWith(nextWord))
514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
5152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                allowShrinking        = true;
516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
5172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            else if (ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION        .startsWith(nextWord))
518b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
5192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                allowOptimization     = true;
5202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
5212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            else if (ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION         .startsWith(nextWord))
5222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
5232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                allowObfuscation      = true;
524b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
525b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
526b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
5272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                throw new ParseException("Expecting keyword '" + ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION +
5282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                         "', '"                + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION +
529b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "', '"                + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION +
530b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "', or '"             + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION +
531b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' before " + reader.locationDescription());
532b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
533b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
534b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
535b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read the class configuration.
536b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ClassSpecification classSpecification =
537b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            parseClassSpecificationArguments();
538b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
539b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Create and add the keep configuration.
540b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        keepClassSpecifications.add(new KeepClassSpecification(markClasses,
541b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                               markConditionally,
5422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                               markDescriptorClasses,
543b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                               allowShrinking,
544b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                               allowOptimization,
545b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                               allowObfuscation,
546b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                               classSpecification));
547b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return keepClassSpecifications;
548b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
549b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
550b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
551b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private List parseClassSpecificationArguments(List classSpecifications)
552b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
553b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
554b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Create a new List if necessary.
555b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (classSpecifications == null)
556b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
557b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            classSpecifications = new ArrayList();
558b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
559b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
560b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Read and add the class configuration.
561b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
5622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                     "', '"      + JavaConstants.ACC_INTERFACE +
5632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                     "', or '"   + JavaConstants.ACC_ENUM + "'",
564b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                     false, true);
565b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
566b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        classSpecifications.add(parseClassSpecificationArguments());
567b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
568b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return classSpecifications;
569b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
570b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
571b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
572b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
573b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Parses and returns a class specification.
574b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * @throws ParseException if the class specification contains a syntax error.
575b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * @throws IOException    if an IO error occurs while reading the class
576b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     *                        specification.
577b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
578b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public ClassSpecification parseClassSpecificationArguments()
579b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
580b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
581b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Clear the annotation type.
582b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String annotationType = null;
583b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
584b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Clear the class access modifiers.
585b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int requiredSetClassAccessFlags   = 0;
586b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int requiredUnsetClassAccessFlags = 0;
587b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
588b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Parse the class annotations and access modifiers until the class keyword.
589b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord))
590b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
5919f606f95f03a75961498803e24bee6799a7c0885Ying Wang            // Strip the negating sign, if any.
592b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            boolean negated =
593b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                nextWord.startsWith(ConfigurationConstants.NEGATOR_KEYWORD);
594b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
595b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            String strippedWord = negated ?
596b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord.substring(1) :
597b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord;
598b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
599b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Parse the class access modifiers.
600b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int accessFlag =
6012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_PUBLIC)     ? ClassConstants.ACC_PUBLIC      :
6022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_FINAL)      ? ClassConstants.ACC_FINAL       :
6032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_INTERFACE)  ? ClassConstants.ACC_INTERFACE   :
6042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_ABSTRACT)   ? ClassConstants.ACC_ABSTRACT    :
6052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_SYNTHETIC)  ? ClassConstants.ACC_SYNTHETIC   :
6062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_ANNOTATION) ? ClassConstants.ACC_ANNOTATTION :
6072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_ENUM)       ? ClassConstants.ACC_ENUM        :
6082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                                    unknownAccessFlag();
609b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
610b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Is it an annotation modifier?
6112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (accessFlag == ClassConstants.ACC_ANNOTATTION)
612b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
613b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Already read the next word.
6142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                readNextWord("annotation type or keyword '" + JavaConstants.ACC_INTERFACE + "'",
615b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                             false, false);
6169f606f95f03a75961498803e24bee6799a7c0885Ying Wang
617b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Is the next word actually an annotation type?
6182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                if (!nextWord.equals(JavaConstants.ACC_INTERFACE) &&
6192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    !nextWord.equals(JavaConstants.ACC_ENUM)      &&
620b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    !nextWord.equals(ConfigurationConstants.CLASS_KEYWORD))
621b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
622b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Parse the annotation type.
623b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    annotationType =
624b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        ListUtil.commaSeparatedString(
625b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        parseCommaSeparatedList("annotation type",
626b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                                false, false, false, false, true, false, false, true, null), false);
627b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
628b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    // Continue parsing the access modifier that we just read
629b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    // in the next cycle.
630b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    continue;
631b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
632b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
633b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Otherwise just handle the annotation modifier.
634b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
635b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
636b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            if (!negated)
637b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
638b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                requiredSetClassAccessFlags   |= accessFlag;
639b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
640b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
641b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
642b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                requiredUnsetClassAccessFlags |= accessFlag;
643b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
644b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
645b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if ((requiredSetClassAccessFlags &
646b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                 requiredUnsetClassAccessFlags) != 0)
647b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
648b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Conflicting class access modifiers for '" + strippedWord +
649b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' before " + reader.locationDescription());
650b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
651b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
6522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (strippedWord.equals(JavaConstants.ACC_INTERFACE) ||
6532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_ENUM)      ||
654b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                strippedWord.equals(ConfigurationConstants.CLASS_KEYWORD))
655b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
656b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // The interface or enum keyword. Stop parsing the class flags.
657b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
658b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
659b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
660b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Should we read the next word?
6612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (accessFlag != ClassConstants.ACC_ANNOTATTION)
662b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            {
663b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD +
6642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                             "', '"      + JavaConstants.ACC_INTERFACE +
6652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                             "', or '"   + JavaConstants.ACC_ENUM + "'",
666b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                             false, true);
667b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            }
668b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
669b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
670b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato       // Parse the class name part.
671b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String externalClassName =
672b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ListUtil.commaSeparatedString(
673b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            parseCommaSeparatedList("class name or interface name",
674b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                    true, false, false, false, true, false, false, false, null), false);
675b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
676b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // For backward compatibility, allow a single "*" wildcard to match any
677b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // class.
678b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String className = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalClassName) ?
679b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            null :
680b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ClassUtil.internalClassName(externalClassName);
681b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
682b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Clear the annotation type and the class name of the extends part.
683b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String extendsAnnotationType = null;
684b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String extendsClassName      = null;
685b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
686b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!configurationEnd())
687b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
688b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Parse 'implements ...' or 'extends ...' part, if any.
689b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (ConfigurationConstants.IMPLEMENTS_KEYWORD.equals(nextWord) ||
690b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ConfigurationConstants.EXTENDS_KEYWORD.equals(nextWord))
691b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
692b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                readNextWord("class name or interface name", false, true);
693b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
694b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Parse the annotation type, if any.
695b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
696b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
697b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    extendsAnnotationType =
698b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        ListUtil.commaSeparatedString(
699b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        parseCommaSeparatedList("annotation type",
700b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                                true, false, false, false, true, false, false, true, null), false);
701b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
702b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
703b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                String externalExtendsClassName =
704b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    ListUtil.commaSeparatedString(
705b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    parseCommaSeparatedList("class name or interface name",
706b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                            false, false, false, false, true, false, false, false, null), false);
707b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
708b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                extendsClassName = ConfigurationConstants.ANY_CLASS_KEYWORD.equals(externalExtendsClassName) ?
709b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    null :
710b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    ClassUtil.internalClassName(externalExtendsClassName);
711b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
712b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
713b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
714b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Create the basic class specification.
715b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ClassSpecification classSpecification =
716b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new ClassSpecification(lastComments,
717b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   requiredSetClassAccessFlags,
718b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   requiredUnsetClassAccessFlags,
719b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   annotationType,
720b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   className,
721b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   extendsAnnotationType,
722b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   extendsClassName);
723b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
724b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
725b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Now add any class members to this class specification.
726b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!configurationEnd())
727b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
728b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Check the class member opening part.
729b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!ConfigurationConstants.OPEN_KEYWORD.equals(nextWord))
730b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
731b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Expecting opening '" + ConfigurationConstants.OPEN_KEYWORD +
732b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' at " + reader.locationDescription());
733b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
734b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
735b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Parse all class members.
736b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            while (true)
737b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
738b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                readNextWord("class member description" +
739b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                             " or closing '" + ConfigurationConstants.CLOSE_KEYWORD + "'",
740b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                             false, true);
741b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
742b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (nextWord.equals(ConfigurationConstants.CLOSE_KEYWORD))
743b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
744b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // The closing brace. Stop parsing the class members.
745b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    readNextWord();
746b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
747b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
748b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
749b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
750b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                parseMemberSpecificationArguments(externalClassName,
751b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                  classSpecification);
752b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
753b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
754b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
755b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return classSpecification;
756b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
757b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
758b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
759b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void parseMemberSpecificationArguments(String             externalClassName,
760b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   ClassSpecification classSpecification)
761b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
762b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
763b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Clear the annotation name.
764b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String annotationType = null;
765b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
766b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Parse the class member access modifiers, if any.
767b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int requiredSetMemberAccessFlags   = 0;
768b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int requiredUnsetMemberAccessFlags = 0;
769b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
770b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (!configurationEnd(true))
771b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
772b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Parse the annotation type, if any.
773b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (ConfigurationConstants.ANNOTATION_KEYWORD.equals(nextWord))
774b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
775b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                annotationType =
776b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    ListUtil.commaSeparatedString(
777b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    parseCommaSeparatedList("annotation type",
778b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                            true, false, false, false, true, false, false, true, null), false);
779b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                continue;
780b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
781b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
782b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String strippedWord = nextWord.startsWith("!") ?
783b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord.substring(1) :
784b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord;
785b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
786b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Parse the class member access modifiers.
787b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int accessFlag =
7882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_PUBLIC)       ? ClassConstants.ACC_PUBLIC       :
7892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_PRIVATE)      ? ClassConstants.ACC_PRIVATE      :
7902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_PROTECTED)    ? ClassConstants.ACC_PROTECTED    :
7912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_STATIC)       ? ClassConstants.ACC_STATIC       :
7922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_FINAL)        ? ClassConstants.ACC_FINAL        :
7932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_SYNCHRONIZED) ? ClassConstants.ACC_SYNCHRONIZED :
7942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_VOLATILE)     ? ClassConstants.ACC_VOLATILE     :
7952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_TRANSIENT)    ? ClassConstants.ACC_TRANSIENT    :
7962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_BRIDGE)       ? ClassConstants.ACC_BRIDGE       :
7972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_VARARGS)      ? ClassConstants.ACC_VARARGS      :
7982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_NATIVE)       ? ClassConstants.ACC_NATIVE       :
7992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_ABSTRACT)     ? ClassConstants.ACC_ABSTRACT     :
8002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_STRICT)       ? ClassConstants.ACC_STRICT       :
8012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                strippedWord.equals(JavaConstants.ACC_SYNTHETIC)    ? ClassConstants.ACC_SYNTHETIC    :
8022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                                      0;
803b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (accessFlag == 0)
804b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
805b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Not a class member access modifier. Stop parsing them.
806b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
807b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
808b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
809b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (strippedWord.equals(nextWord))
810b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
811b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                requiredSetMemberAccessFlags   |= accessFlag;
812b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
813b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
814b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
815b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                requiredUnsetMemberAccessFlags |= accessFlag;
816b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
817b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
818b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Make sure the user doesn't try to set and unset the same
819b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // access flags simultaneously.
820b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if ((requiredSetMemberAccessFlags &
821b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                 requiredUnsetMemberAccessFlags) != 0)
822b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
823b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Conflicting class member access modifiers for " +
824b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         reader.locationDescription());
825b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
826b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
827b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord("class member description");
828b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
829b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
830b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Parse the class member type and name part.
831b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
832b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Did we get a special wildcard?
833b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD.equals(nextWord) ||
834b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ConfigurationConstants.ANY_FIELD_KEYWORD       .equals(nextWord) ||
835b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ConfigurationConstants.ANY_METHOD_KEYWORD      .equals(nextWord))
836b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
837b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Act according to the type of wildcard..
838b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD.equals(nextWord))
839b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
840b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkFieldAccessFlags(requiredSetMemberAccessFlags,
841b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                      requiredUnsetMemberAccessFlags);
842b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkMethodAccessFlags(requiredSetMemberAccessFlags,
843b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       requiredUnsetMemberAccessFlags);
844b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
845b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classSpecification.addField(
846b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberSpecification(requiredSetMemberAccessFlags,
847b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            requiredUnsetMemberAccessFlags,
848b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            annotationType,
849b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null,
850b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null));
851b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classSpecification.addMethod(
852b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberSpecification(requiredSetMemberAccessFlags,
853b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            requiredUnsetMemberAccessFlags,
854b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            annotationType,
855b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null,
856b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null));
857b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
858b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.ANY_FIELD_KEYWORD.equals(nextWord))
859b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
860b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkFieldAccessFlags(requiredSetMemberAccessFlags,
861b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                      requiredUnsetMemberAccessFlags);
862b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
863b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classSpecification.addField(
864b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberSpecification(requiredSetMemberAccessFlags,
865b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            requiredUnsetMemberAccessFlags,
866b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            annotationType,
867b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null,
868b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null));
869b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
870b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.ANY_METHOD_KEYWORD.equals(nextWord))
871b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
872b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkMethodAccessFlags(requiredSetMemberAccessFlags,
873b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       requiredUnsetMemberAccessFlags);
874b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
875b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classSpecification.addMethod(
876b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberSpecification(requiredSetMemberAccessFlags,
877b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            requiredUnsetMemberAccessFlags,
878b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            annotationType,
879b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null,
880b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            null));
881b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
882b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
883b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // We still have to read the closing separator.
884b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord("separator '" + ConfigurationConstants.SEPARATOR_KEYWORD + "'");
885b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
886b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord))
887b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
888b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Expecting separator '" + ConfigurationConstants.SEPARATOR_KEYWORD +
889b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' before " + reader.locationDescription());
890b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
891b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
892b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
893b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
894b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Make sure we have a proper type.
895b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            checkJavaIdentifier("java type");
896b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String type = nextWord;
897b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
898b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            readNextWord("class member name");
899b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String name = nextWord;
900b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
901b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Did we get just one word before the opening parenthesis?
902b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(name))
903b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
904b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // This must be a constructor then.
905b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Make sure the type is a proper constructor name.
9062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                if (!(type.equals(ClassConstants.METHOD_NAME_INIT) ||
907b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                      type.equals(externalClassName) ||
908b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                      type.equals(ClassUtil.externalShortClassName(externalClassName))))
909b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
910b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    throw new ParseException("Expecting type and name " +
911b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "instead of just '" + type +
912b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "' before " + reader.locationDescription());
913b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
914b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
915b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Assign the fixed constructor type and name.
9162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                type = JavaConstants.TYPE_VOID;
9172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                name = ClassConstants.METHOD_NAME_INIT;
918b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
919b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
920b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
921b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // It's not a constructor.
922b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Make sure we have a proper name.
923b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkJavaIdentifier("class member name");
924b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
925b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read the opening parenthesis or the separating
926b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // semi-colon.
927b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                readNextWord("opening '" + ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
928b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                             "' or separator '" + ConfigurationConstants.SEPARATOR_KEYWORD + "'");
929b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
930b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
931b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Are we looking at a field, a method, or something else?
932b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord))
933b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
934b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // It's a field.
935b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkFieldAccessFlags(requiredSetMemberAccessFlags,
936b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                      requiredUnsetMemberAccessFlags);
937b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
938b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // We already have a field descriptor.
939b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                String descriptor = ClassUtil.internalType(type);
940b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
941b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Add the field.
942b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classSpecification.addField(
943b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberSpecification(requiredSetMemberAccessFlags,
944b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            requiredUnsetMemberAccessFlags,
945b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            annotationType,
946b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            name,
947b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptor));
948b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
949b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else if (ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(nextWord))
950b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
951b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // It's a method.
952b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkMethodAccessFlags(requiredSetMemberAccessFlags,
953b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       requiredUnsetMemberAccessFlags);
954b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
955b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Parse the method arguments.
956b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                String descriptor =
957b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    ClassUtil.internalMethodDescriptor(type,
958b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                                       parseCommaSeparatedList("argument", true, true, true, false, true, false, false, false, null));
959b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
960b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (!ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD.equals(nextWord))
961b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
962b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    throw new ParseException("Expecting separating '" + ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
963b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "' or closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
964b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "' before " + reader.locationDescription());
965b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
966b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
967b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read the separator after the closing parenthesis.
968b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                readNextWord("separator '" + ConfigurationConstants.SEPARATOR_KEYWORD + "'");
969b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
970b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (!ConfigurationConstants.SEPARATOR_KEYWORD.equals(nextWord))
971b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
972b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    throw new ParseException("Expecting separator '" + ConfigurationConstants.SEPARATOR_KEYWORD +
973b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             "' before " + reader.locationDescription());
974b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
975b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
976b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Add the method.
977b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                classSpecification.addMethod(
978b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new MemberSpecification(requiredSetMemberAccessFlags,
979b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            requiredUnsetMemberAccessFlags,
980b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            annotationType,
981b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            name,
982b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            descriptor));
983b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
984b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
985b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
986b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // It doesn't look like a field or a method.
987b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Expecting opening '" + ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
988b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' or separator '" + ConfigurationConstants.SEPARATOR_KEYWORD +
989b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' before " + reader.locationDescription());
990b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
991b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
992b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
993b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
994b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
995b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
996b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Reads a comma-separated list of java identifiers or of file names.
997b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Examples of invocation arguments:
9982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("directory name", true,  true,  false, true,  false, true,  false, false, ...)
9992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("optimization",   true,  false, false, false, false, false, false, false, ...)
10002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("package name",   true,  true,  false, false, true,  false, true,  false, ...)
10012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("attribute name", true,  true,  false, false, true,  false, false, false, ...)
10022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("class name",     true,  true,  false, false, true,  false, true,  false, ...)
10032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("resource file",  true,  true,  false, true,  false, false, false, false, ...)
10042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("resource file",  true,  true,  false, true,  false, false, false, false, ...)
10052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("class name",     true,  true,  false, false, true,  false, true,  false, ...)
10062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("class name",     true,  true,  false, false, true,  false, true,  false, ...)
10072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("filter",         true,  true,  true,  true,  false, true,  false, false, ...)
10082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("annotation ",    false, false, false, false, true,  false, false, true,  ...)
10092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("class name ",    true,  false, false, false, true,  false, false, false, ...)
10102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("annotation ",    true,  false, false, false, true,  false, false, true,  ...)
10112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("class name ",    false, false, false, false, true,  false, false, false, ...)
10122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("annotation ",    true,  false, false, false, true,  false, false, true,  ...)
10132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     *   ("argument",       true,  true,  true,  false, true,  false, false, false, ...)
1014b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1015b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private List parseCommaSeparatedList(String  expectedDescription,
1016b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         boolean readFirstWord,
1017b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         boolean allowEmptyList,
1018b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         boolean expectClosingParenthesis,
1019b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                         boolean isFileName,
1020b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         boolean checkJavaIdentifiers,
1021b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         boolean replaceSystemProperties,
1022b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         boolean replaceExternalClassNames,
1023b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         boolean replaceExternalTypes,
1024b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         List    list)
1025b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
1026b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1027b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (list == null)
1028b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1029b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            list = new ArrayList();
1030b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1031b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1032b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (readFirstWord)
1033b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1034b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            if (!allowEmptyList)
1035b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1036b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read the first list entry.
1037b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                readNextWord(expectedDescription, isFileName, false);
1038b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            }
1039b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            else if (expectClosingParenthesis)
1040b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            {
1041b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Read the first list entry.
1042b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                readNextWord(expectedDescription, isFileName, false);
1043b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
1044b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Return if the entry is actually empty (an empty file name or
1045b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // a closing parenthesis).
1046b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                if (nextWord.length() == 0)
1047b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                {
1048b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    // Read the closing parenthesis
1049b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    readNextWord("closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
1050b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                 "'");
1051b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
1052b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    return list;
1053b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                }
1054b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                else if (nextWord.equals(ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD))
1055b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                {
1056b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    return list;
1057b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                }
1058b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1059b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
1060b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1061b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read the first list entry, if there is any.
1062b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                readNextWord(isFileName);
1063b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1064b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Check if the list is empty.
1065b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                if (configurationEnd())
1066b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
1067b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    return list;
1068b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
1069b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1070b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1071b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1072b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (true)
1073b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1074b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (checkJavaIdentifiers)
1075b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1076b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                checkJavaIdentifier("java type");
1077b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1078b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1079b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (replaceSystemProperties)
1080b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1081b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord = replaceSystemProperties(nextWord);
1082b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1083b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1084b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (replaceExternalClassNames)
1085b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1086b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord = ClassUtil.internalClassName(nextWord);
1087b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1088b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1089b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (replaceExternalTypes)
1090b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1091b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord = ClassUtil.internalType(nextWord);
1092b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1093b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1094b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            list.add(nextWord);
1095b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1096b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (expectClosingParenthesis)
1097b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1098b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read a comma (or a closing parenthesis, or a different word).
1099b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                readNextWord("separating '" + ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD +
1100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                             "' or closing '" + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD +
1101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                             "'");
1102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
1104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Read a comma (or a different word).
1106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                readNextWord();
1107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord))
1110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                return list;
1112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Read the next list entry.
1115b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            readNextWord(expectedDescription, isFileName, false);
1116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Throws a ParseException for an unexpected keyword.
1122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int unknownAccessFlag() throws ParseException
1124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        throw new ParseException("Unexpected keyword " + reader.locationDescription());
1126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a properly resolved File, based on the given word.
1131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private File file(String word) throws ParseException
1133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String fileName = replaceSystemProperties(word);
1135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        File   file     = new File(fileName);
1136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Try to get an absolute file.
1138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!file.isAbsolute())
1139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            file = new File(reader.getBaseDir(), fileName);
1141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return file;
1144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1148b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Replaces any properties in the given word by their values.
1149b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * For instance, the substring "<java.home>" is replaced by its value.
1150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String replaceSystemProperties(String word) throws ParseException
1152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int fromIndex = 0;
1154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (true)
1155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            fromIndex = word.indexOf(ConfigurationConstants.OPEN_SYSTEM_PROPERTY, fromIndex);
1157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (fromIndex < 0)
1158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
1160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int toIndex = word.indexOf(ConfigurationConstants.CLOSE_SYSTEM_PROPERTY, fromIndex+1);
1163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (toIndex < 0)
1164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
11652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                break;
1166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String propertyName  = word.substring(fromIndex+1, toIndex);
1169b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            String propertyValue = properties.getProperty(propertyName);
1170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (propertyValue == null)
1171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw new ParseException("Value of system property '" + propertyName +
1173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                         "' is undefined in " + reader.locationDescription());
1174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
11762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            word = word.substring(0, fromIndex) + propertyValue + word.substring(toIndex+1);
11772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            fromIndex += propertyValue.length();
1179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return word;
1182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Reads the next word of the configuration in the 'nextWord' field,
1187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * throwing an exception if there is no next word.
1188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void readNextWord(String expectedDescription)
1190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
1191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1192b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        readNextWord(expectedDescription, false, false);
1193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Reads the next word of the configuration in the 'nextWord' field,
1198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * throwing an exception if there is no next word.
1199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void readNextWord(String  expectedDescription,
1201b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                              boolean isFileName,
1202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                              boolean expectingAtCharacter)
1203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException, IOException
1204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1205b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        readNextWord(isFileName);
1206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (configurationEnd(expectingAtCharacter))
1207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new ParseException("Expecting " + expectedDescription +
1209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     " before " + reader.locationDescription());
1210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Reads the next word of the configuration in the 'nextWord' field.
1216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void readNextWord() throws IOException
1218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1219b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        readNextWord(false);
1220b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
1221b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
1222b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
1223b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
1224b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Reads the next word of the configuration in the 'nextWord' field.
1225b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
1226b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private void readNextWord(boolean isFileName) throws IOException
1227b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
1228b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        nextWord = reader.nextWord(isFileName);
1229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether the end of the configuration has been reached.
1234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean configurationEnd()
1236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return configurationEnd(false);
1238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether the end of the configuration has been reached.
1243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean configurationEnd(boolean expectingAtCharacter)
1245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return nextWord == null ||
1247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               nextWord.startsWith(ConfigurationConstants.OPTION_PREFIX) ||
1248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               (!expectingAtCharacter &&
1249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                nextWord.equals(ConfigurationConstants.AT_DIRECTIVE));
1250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Checks whether the given word is a valid Java identifier and throws
1255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * a ParseException if it isn't. Wildcard characters are accepted.
1256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void checkJavaIdentifier(String expectedDescription)
1258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException
1259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!isJavaIdentifier(nextWord))
1261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new ParseException("Expecting " + expectedDescription +
1263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     " before " + reader.locationDescription());
1264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether the given word is a valid Java identifier.
1270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Wildcard characters are accepted.
1271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean isJavaIdentifier(String aWord)
1273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1274b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        if (aWord.length() == 0)
1275b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        {
1276b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            return false;
1277b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        }
1278b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
1279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        for (int index = 0; index < aWord.length(); index++)
1280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            char c = aWord.charAt(index);
1282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!(Character.isJavaIdentifierPart(c) ||
1283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '.' ||
1284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '[' ||
1285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == ']' ||
1286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '<' ||
1287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '>' ||
1288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '-' ||
1289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '!' ||
1290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '*' ||
1291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '?' ||
1292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                  c == '%'))
1293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                return false;
1295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return true;
1299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Checks whether the given access flags are valid field access flags,
1304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * throwing a ParseException if they aren't.
1305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void checkFieldAccessFlags(int requiredSetMemberAccessFlags,
1307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       int requiredUnsetMemberAccessFlags)
1308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException
1309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (((requiredSetMemberAccessFlags |
1311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato              requiredUnsetMemberAccessFlags) &
13122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            ~ClassConstants.VALID_ACC_FIELD) != 0)
1313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new ParseException("Invalid method access modifier for field before " +
1315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     reader.locationDescription());
1316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Checks whether the given access flags are valid method access flags,
1322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * throwing a ParseException if they aren't.
1323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void checkMethodAccessFlags(int requiredSetMemberAccessFlags,
1325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        int requiredUnsetMemberAccessFlags)
1326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    throws ParseException
1327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (((requiredSetMemberAccessFlags |
1329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato              requiredUnsetMemberAccessFlags) &
13302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            ~ClassConstants.VALID_ACC_METHOD) != 0)
1331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new ParseException("Invalid field access modifier for method before " +
1333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     reader.locationDescription());
1334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * A main method for testing configuration parsing.
1340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public static void main(String[] args)
1342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
1344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1345b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            ConfigurationParser parser =
1346b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                new ConfigurationParser(args, System.getProperties());
1347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            try
1349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                parser.parse(new Configuration());
1351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            catch (ParseException ex)
1353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ex.printStackTrace();
1355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            finally
1357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                parser.close();
1359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (IOException ex)
1362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            ex.printStackTrace();
1364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
1367