Arguments.java revision 2846:072008f47620
152419Sjulian/*
252419Sjulian * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
352419Sjulian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
452419Sjulian *
552419Sjulian * This code is free software; you can redistribute it and/or modify it
670700Sjulian * under the terms of the GNU General Public License version 2 only, as
752419Sjulian * published by the Free Software Foundation.  Oracle designates this
852419Sjulian * particular file as subject to the "Classpath" exception as provided
952419Sjulian * by Oracle in the LICENSE file that accompanied this code.
1052419Sjulian *
1152419Sjulian * This code is distributed in the hope that it will be useful, but WITHOUT
1252419Sjulian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1352419Sjulian * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1452419Sjulian * version 2 for more details (a copy is included in the LICENSE file that
1552419Sjulian * accompanied this code).
1652419Sjulian *
1770700Sjulian * You should have received a copy of the GNU General Public License version
1852419Sjulian * 2 along with this work; if not, write to the Free Software Foundation,
1952419Sjulian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2052419Sjulian *
2152419Sjulian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2252419Sjulian * or visit www.oracle.com if you need additional information or have any
2352419Sjulian * questions.
2452419Sjulian */
2552419Sjulianpackage com.sun.tools.javac.main;
2652419Sjulian
2752419Sjulianimport java.io.File;
2852419Sjulianimport java.util.Collections;
2952419Sjulianimport java.util.Iterator;
3052419Sjulianimport java.util.LinkedHashMap;
3152419Sjulianimport java.util.LinkedHashSet;
3252419Sjulianimport java.util.Map;
3352419Sjulianimport java.util.Set;
3452419Sjulian
3552419Sjulianimport javax.tools.JavaFileManager;
3667506Sjulianimport javax.tools.JavaFileObject;
3767506Sjulian
3852419Sjulianimport com.sun.tools.doclint.DocLint;
3952419Sjulianimport com.sun.tools.javac.code.Lint.LintCategory;
4052419Sjulianimport com.sun.tools.javac.code.Source;
4152419Sjulianimport com.sun.tools.javac.file.JavacFileManager;
4252419Sjulianimport com.sun.tools.javac.jvm.Profile;
4352419Sjulianimport com.sun.tools.javac.jvm.Target;
4452419Sjulianimport com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
4552419Sjulianimport com.sun.tools.javac.util.BaseFileManager;
4652419Sjulianimport com.sun.tools.javac.util.Context;
4752419Sjulianimport com.sun.tools.javac.util.List;
4852419Sjulianimport com.sun.tools.javac.util.ListBuffer;
4952419Sjulianimport com.sun.tools.javac.util.Log;
50131933Smarcelimport com.sun.tools.javac.util.Log.PrefixKind;
5152419Sjulianimport com.sun.tools.javac.util.Options;
52114216Skanimport com.sun.tools.javac.util.PropagatedException;
5352419Sjulian
5452419Sjulian/**
5570700Sjulian * Shared option and argument handling for command line and API usage of javac.
5652419Sjulian */
5752419Sjulianpublic class Arguments {
5852419Sjulian
5952843Sphk    /**
6072946Sjulian     * The context key for the arguments.
6152419Sjulian     */
6252419Sjulian    protected static final Context.Key<Arguments> argsKey = new Context.Key<>();
6352419Sjulian
6452419Sjulian    private String ownName;
6552419Sjulian    private Set<String> classNames;
6653913Sarchie    private Set<File> files;
6752419Sjulian    private Map<Option, String> deferredFileManagerOptions;
6872053Sjulian    private Set<JavaFileObject> fileObjects;
6959756Speter    private final Options options;
7070784Sjulian
7170700Sjulian    private JavaFileManager fileManager;
7270700Sjulian    private final Log log;
7352419Sjulian    private final Context context;
74122110Sharti
75122110Sharti    private enum ErrorMode { ILLEGAL_ARGUMENT, ILLEGAL_STATE, LOG };
76122110Sharti    private ErrorMode errorMode;
7770784Sjulian    private boolean errors;
7870784Sjulian
7970784Sjulian    /**
8070784Sjulian     * Gets the Arguments instance for this context.
8170784Sjulian     *
8270784Sjulian     * @param context the content
8370784Sjulian     * @return the Arguments instance for this context.
8470784Sjulian     */
8570784Sjulian    public static Arguments instance(Context context) {
8670784Sjulian        Arguments instance = context.get(argsKey);
8770784Sjulian        if (instance == null) {
8870784Sjulian            instance = new Arguments(context);
8970935Sjulian        }
9070935Sjulian        return instance;
9170935Sjulian    }
9270935Sjulian
9370935Sjulian    protected Arguments(Context context) {
9470935Sjulian        context.put(argsKey, this);
9570935Sjulian        options = Options.instance(context);
9670935Sjulian        log = Log.instance(context);
9770935Sjulian        this.context = context;
9870935Sjulian
9970935Sjulian        // Ideally, we could init this here and update/configure it as
10070935Sjulian        // needed, but right now, initializing a file manager triggers
10170935Sjulian        // initialization of other items in the context, such as Lint
10270935Sjulian        // and FSInfo, which should not be initialized until after
10370935Sjulian        // processArgs
10470935Sjulian        //        fileManager = context.get(JavaFileManager.class);
10570935Sjulian    }
10670935Sjulian
10770935Sjulian    private final OptionHelper cmdLineHelper = new OptionHelper() {
10870935Sjulian        @Override
10970784Sjulian        public String get(Option option) {
11070935Sjulian            return options.get(option);
11170935Sjulian        }
11270935Sjulian
113132464Sjulian        @Override
11470935Sjulian        public void put(String name, String value) {
11570935Sjulian            options.put(name, value);
11670935Sjulian        }
11770935Sjulian
11870935Sjulian        @Override
11970935Sjulian        public void remove(String name) {
12070935Sjulian            options.remove(name);
12170935Sjulian        }
12270935Sjulian
12370935Sjulian        @Override
12470935Sjulian        public boolean handleFileManagerOption(Option option, String value) {
12570935Sjulian            options.put(option.getText(), value);
12670935Sjulian            deferredFileManagerOptions.put(option, value);
12770935Sjulian            return true;
12870935Sjulian        }
12970935Sjulian
13070935Sjulian        @Override
13170935Sjulian        public Log getLog() {
13270935Sjulian            return log;
13370935Sjulian        }
13470935Sjulian
13570935Sjulian        @Override
13670935Sjulian        public String getOwnName() {
13770935Sjulian            return ownName;
13870935Sjulian        }
13970935Sjulian
14070935Sjulian        @Override
14170935Sjulian        public void error(String key, Object... args) {
14270935Sjulian            Arguments.this.error(key, args);
14370935Sjulian        }
14471885Sjulian
14571885Sjulian        @Override
14670935Sjulian        public void addFile(File f) {
14770935Sjulian            files.add(f);
14870935Sjulian        }
14970935Sjulian
15070935Sjulian        @Override
15170935Sjulian        public void addClassName(String s) {
15270935Sjulian            classNames.add(s);
15370935Sjulian        }
15470935Sjulian
15570935Sjulian    };
15670935Sjulian
15770700Sjulian    /**
15870700Sjulian     * Initializes this Args instance with a set of command line args.
15971902Sjulian     * The args will be processed in conjunction with the full set of
16070700Sjulian     * command line options, including -help, -version etc.
16152419Sjulian     * The args may also contain class names and filenames.
16270700Sjulian     * Any errors during this call, and later during validate, will be reported
16370700Sjulian     * to the log.
16452419Sjulian     * @param ownName the name of this tool; used to prefix messages
16570700Sjulian     * @param args the args to be processed
16671354Sjulian     */
16771354Sjulian    public void init(String ownName, String... args) {
16871354Sjulian        this.ownName = ownName;
16970700Sjulian        errorMode = ErrorMode.LOG;
17071354Sjulian        files = new LinkedHashSet<>();
17171354Sjulian        deferredFileManagerOptions = new LinkedHashMap<>();
17271354Sjulian        fileObjects = null;
17371354Sjulian        classNames = new LinkedHashSet<>();
174131008Srwatson        processArgs(List.from(args), Option.getJavaCompilerOptions(), cmdLineHelper, true, false);
17571354Sjulian    }
17671354Sjulian
17771354Sjulian    private final OptionHelper apiHelper = new GrumpyHelper(null) {
17871354Sjulian        @Override
17971354Sjulian        public String get(Option option) {
18071354Sjulian            return options.get(option.getText());
18171354Sjulian        }
18271354Sjulian
18352722Sjulian        @Override
18470700Sjulian        public void put(String name, String value) {
18552419Sjulian            options.put(name, value);
18652419Sjulian        }
18770700Sjulian
18852722Sjulian        @Override
18952419Sjulian        public void remove(String name) {
19070700Sjulian            options.remove(name);
19152419Sjulian        }
19274078Sjulian
19370700Sjulian        @Override
19470700Sjulian        public void error(String key, Object... args) {
19570700Sjulian            Arguments.this.error(key, args);
19671047Sjulian        }
19771047Sjulian
19871849Sjulian        @Override
19971849Sjulian        public Log getLog() {
20071047Sjulian            return Arguments.this.log;
20171047Sjulian        }
20252419Sjulian    };
20370784Sjulian
20470700Sjulian    /**
20570700Sjulian     * Initializes this Args instance with the parameters for a JavacTask.
20670700Sjulian     * The options will be processed in conjunction with the restricted set
20770700Sjulian     * of tool options, which does not include -help, -version, etc,
20870700Sjulian     * nor does it include classes and filenames, which should be specified
20970700Sjulian     * separately.
21070700Sjulian     * File manager options are handled directly by the file manager.
21171849Sjulian     * Any errors found while processing individual args will be reported
21270784Sjulian     * via IllegalArgumentException.
21370700Sjulian     * Any subsequent errors during validate will be reported via IllegalStateException.
21470700Sjulian     * @param ownName the name of this tool; used to prefix messages
21552419Sjulian     * @param options the options to be processed
21652419Sjulian     * @param classNames the classes to be subject to annotation processing
21770700Sjulian     * @param files the files to be compiled
21870700Sjulian     */
21970700Sjulian    public void init(String ownName,
22070700Sjulian            Iterable<String> options,
22152419Sjulian            Iterable<String> classNames,
22270700Sjulian            Iterable<? extends JavaFileObject> files) {
22370784Sjulian        this.ownName = ownName;
22470784Sjulian        this.classNames = toSet(classNames);
22570784Sjulian        this.fileObjects = toSet(files);
22670784Sjulian        this.files = null;
22770784Sjulian        errorMode = ErrorMode.ILLEGAL_ARGUMENT;
22870784Sjulian        if (options != null) {
22970784Sjulian            processArgs(toList(options), Option.getJavacToolOptions(), apiHelper, false, true);
23070784Sjulian        }
23170784Sjulian        errorMode = ErrorMode.ILLEGAL_STATE;
23270784Sjulian    }
23370784Sjulian
23470784Sjulian    /**
23570784Sjulian     * Gets the files to be compiled.
23670784Sjulian     * @return the files to be compiled
23770784Sjulian     */
23870784Sjulian    public Set<JavaFileObject> getFileObjects() {
23970784Sjulian        if (fileObjects == null) {
24070784Sjulian            if (files == null) {
24170784Sjulian                fileObjects = Collections.emptySet();
24270784Sjulian            } else {
24372200Sbmilekic                fileObjects = new LinkedHashSet<>();
24470784Sjulian                JavacFileManager jfm = (JavacFileManager) getFileManager();
24570784Sjulian                for (JavaFileObject fo: jfm.getJavaFileObjectsFromFiles(files))
24670784Sjulian                    fileObjects.add(fo);
24770784Sjulian            }
24870784Sjulian        }
24970784Sjulian        return fileObjects;
25072200Sbmilekic    }
25170784Sjulian
25270784Sjulian    /**
25372200Sbmilekic     * Gets the classes to be subject to annotation processing.
25470784Sjulian     * @return the classes to be subject to annotation processing
25570784Sjulian     */
25670784Sjulian    public Set<String> getClassNames() {
25772200Sbmilekic        return classNames;
25870784Sjulian    }
25972200Sbmilekic
26070784Sjulian    /**
26170784Sjulian     * Processes strings containing options and operands.
26270784Sjulian     * @param args the strings to be processed
26370784Sjulian     * @param allowableOpts the set of option declarations that are applicable
26470784Sjulian     * @param helper a help for use by Option.process
26570784Sjulian     * @param allowOperands whether or not to check for files and classes
26670784Sjulian     * @param checkFileManager whether or not to check if the file manager can handle
26770784Sjulian     *      options which are not recognized by any of allowableOpts
26870784Sjulian     * @return true if all the strings were successfully processed; false otherwise
26970784Sjulian     * @throws IllegalArgumentException if a problem occurs and errorMode is set to
27072200Sbmilekic     *      ILLEGAL_ARGUMENT
27170784Sjulian     */
27270784Sjulian    private boolean processArgs(Iterable<String> args,
27370784Sjulian            Set<Option> allowableOpts, OptionHelper helper,
27470784Sjulian            boolean allowOperands, boolean checkFileManager) {
27570784Sjulian        JavaFileManager fm = checkFileManager ? getFileManager() : null;
27670784Sjulian        Iterator<String> argIter = args.iterator();
27772200Sbmilekic        while (argIter.hasNext()) {
27870784Sjulian            String arg = argIter.next();
27970784Sjulian            if (arg.isEmpty()) {
28072200Sbmilekic                error("err.invalid.flag", arg);
28170784Sjulian                return false;
28270784Sjulian            }
28370784Sjulian
28472200Sbmilekic            Option option = null;
28570784Sjulian            if (arg.startsWith("-")) {
28672200Sbmilekic                for (Option o : allowableOpts) {
28770784Sjulian                    if (o.matches(arg)) {
28870784Sjulian                        option = o;
28970784Sjulian                        break;
29070784Sjulian                    }
29170784Sjulian                }
29270784Sjulian            } else if (allowOperands && Option.SOURCEFILE.matches(arg)) {
29370784Sjulian                option = Option.SOURCEFILE;
29470784Sjulian            }
29570784Sjulian
29670784Sjulian            if (option == null) {
29770784Sjulian                if (fm != null && fm.handleOption(arg, argIter)) {
29872200Sbmilekic                    continue;
29970784Sjulian                }
30070784Sjulian                error("err.invalid.flag", arg);
30172200Sbmilekic                return false;
30270784Sjulian            }
30370784Sjulian
30470784Sjulian            if (option.hasArg()) {
30570784Sjulian                if (!argIter.hasNext()) {
30672200Sbmilekic                    error("err.req.arg", arg);
30770784Sjulian                    return false;
30870784Sjulian                }
30972200Sbmilekic                String operand = argIter.next();
31070784Sjulian                if (option.process(helper, arg, operand)) {
31170784Sjulian                    return false;
31270784Sjulian                }
31370784Sjulian            } else {
31470784Sjulian                if (option.process(helper, arg)) {
31570784Sjulian                    return false;
31670784Sjulian                }
31770700Sjulian            }
31870700Sjulian
31970784Sjulian        }
32070784Sjulian
32170784Sjulian        options.notifyListeners();
32270700Sjulian
32370700Sjulian        return true;
32470700Sjulian    }
32570700Sjulian
326131933Smarcel    /**
32752419Sjulian     * Validates the overall consistency of the options and operands
32871047Sjulian     * processed by processOptions.
32952419Sjulian     * @return true if all args are successfully validating; false otherwise.
33052419Sjulian     * @throws IllegalStateException if a problem is found and errorMode is set to
33152722Sjulian     *      ILLEGAL_STATE
33252722Sjulian     */
33353403Sarchie    public boolean validate() {
33453403Sarchie        if (isEmpty()) {
33553403Sarchie            // It is allowed to compile nothing if just asking for help or version info.
33653403Sarchie            // But also note that none of these options are supported in API mode.
33753403Sarchie            if (options.isSet(Option.HELP)
338113255Sdes                || options.isSet(Option.X)
33953403Sarchie                || options.isSet(Option.VERSION)
34053403Sarchie                || options.isSet(Option.FULLVERSION))
34153403Sarchie                return true;
34253403Sarchie
34387599Sobrien            if (JavaCompiler.explicitAnnotationProcessingRequested(options)) {
34453403Sarchie                error("err.no.source.files.classes");
34553403Sarchie            } else {
34653403Sarchie                error("err.no.source.files");
34753403Sarchie            }
34853403Sarchie            return false;
34952722Sjulian        }
35053403Sarchie
35152419Sjulian        if (!checkDirectory(Option.D)) {
35253913Sarchie            return false;
35353913Sarchie        }
35453913Sarchie        if (!checkDirectory(Option.S)) {
35553913Sarchie            return false;
35653913Sarchie        }
35797685Sarchie
35897685Sarchie        String sourceString = options.get(Option.SOURCE);
35953913Sarchie        Source source = (sourceString != null)
36053913Sarchie                ? Source.lookup(sourceString)
36197685Sarchie                : Source.DEFAULT;
36253913Sarchie        String targetString = options.get(Option.TARGET);
36353913Sarchie        Target target = (targetString != null)
36453913Sarchie                ? Target.lookup(targetString)
36553913Sarchie                : Target.DEFAULT;
36653913Sarchie
36753913Sarchie        // We don't check source/target consistency for CLDC, as J2ME
36853913Sarchie        // profiles are not aligned with J2SE targets; moreover, a
36953913Sarchie        // single CLDC target may have many profiles.  In addition,
37053913Sarchie        // this is needed for the continued functioning of the JSR14
37153913Sarchie        // prototype.
37253913Sarchie        if (Character.isDigit(target.name.charAt(0))) {
37372645Sasmodai            if (target.compareTo(source.requiredTarget()) < 0) {
37453913Sarchie                if (targetString != null) {
37553913Sarchie                    if (sourceString == null) {
37653913Sarchie                        error("warn.target.default.source.conflict",
37753913Sarchie                                targetString,
37853913Sarchie                                source.requiredTarget().name);
37953913Sarchie                    } else {
38053913Sarchie                        error("warn.source.target.conflict",
38153913Sarchie                                sourceString,
38253913Sarchie                                source.requiredTarget().name);
38353913Sarchie                    }
38453913Sarchie                    return false;
38553913Sarchie                } else {
38653913Sarchie                    target = source.requiredTarget();
38753913Sarchie                    options.put("-target", target.name);
38853913Sarchie                }
38953913Sarchie            }
39053913Sarchie        }
39153913Sarchie
39253913Sarchie        String profileString = options.get(Option.PROFILE);
39353913Sarchie        if (profileString != null) {
39453913Sarchie            Profile profile = Profile.lookup(profileString);
39553913Sarchie            if (!profile.isValid(target)) {
39653913Sarchie                error("warn.profile.target.conflict", profileString, target.name);
39753913Sarchie            }
39853913Sarchie
39953913Sarchie            // This check is only effective in command line mode,
40053913Sarchie            // where the file manager options are added to options
40153913Sarchie            if (options.get(Option.BOOTCLASSPATH) != null) {
40253913Sarchie                error("err.profile.bootclasspath.conflict");
40353913Sarchie            }
40453913Sarchie        }
40553913Sarchie
40653913Sarchie        boolean lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
40753913Sarchie
40853913Sarchie        if (lintOptions && source.compareTo(Source.DEFAULT) < 0) {
40953913Sarchie            JavaFileManager fm = getFileManager();
41053913Sarchie            if (fm instanceof BaseFileManager) {
41153913Sarchie                if (((BaseFileManager) fm).isDefaultBootClassPath())
41253913Sarchie                    log.warning(LintCategory.OPTIONS, "source.no.bootclasspath", source.name);
41353913Sarchie            }
41453913Sarchie        }
41553913Sarchie
41653913Sarchie        boolean obsoleteOptionFound = false;
41753913Sarchie
41853913Sarchie        if (source.compareTo(Source.MIN) < 0) {
41953913Sarchie            log.error("option.removed.source", source.name, Source.MIN.name);
42053913Sarchie        } else if (source == Source.MIN && lintOptions) {
42153913Sarchie            log.warning(LintCategory.OPTIONS, "option.obsolete.source", source.name);
42253913Sarchie            obsoleteOptionFound = true;
42353913Sarchie        }
42453913Sarchie
42553913Sarchie        if (target.compareTo(Target.MIN) < 0) {
42653913Sarchie            log.error("option.removed.target", target.name, Target.MIN.name);
42753913Sarchie        } else if (target == Target.MIN && lintOptions) {
42853913Sarchie            log.warning(LintCategory.OPTIONS, "option.obsolete.target", target.name);
42953913Sarchie            obsoleteOptionFound = true;
43053913Sarchie        }
43153913Sarchie
43253913Sarchie        if (obsoleteOptionFound)
43353913Sarchie            log.warning(LintCategory.OPTIONS, "option.obsolete.suppression");
43453913Sarchie
43553913Sarchie        return !errors;
43653913Sarchie    }
43753913Sarchie
43853913Sarchie    /**
43953913Sarchie     * Returns true if there are no files or classes specified for use.
44053913Sarchie     * @return true if there are no files or classes specified for use
44153913Sarchie     */
44253913Sarchie    public boolean isEmpty() {
44353913Sarchie        return ((files == null) || files.isEmpty())
44453913Sarchie                && ((fileObjects == null) || fileObjects.isEmpty())
44553913Sarchie                && classNames.isEmpty();
44653913Sarchie    }
44753913Sarchie
44853913Sarchie    /**
44953913Sarchie     * Gets the file manager options which may have been deferred
45053913Sarchie     * during processArgs.
45153913Sarchie     * @return the deferred file manager options
45253913Sarchie     */
45353913Sarchie    public Map<Option, String> getDeferredFileManagerOptions() {
45453913Sarchie        return deferredFileManagerOptions;
45553913Sarchie    }
45653913Sarchie
45753913Sarchie    /**
45853913Sarchie     * Gets any options specifying plugins to be run.
45953913Sarchie     * @return options for plugins
46053913Sarchie     */
46153913Sarchie    public Set<List<String>> getPluginOpts() {
46253913Sarchie        String plugins = options.get(Option.PLUGIN);
46353913Sarchie        if (plugins == null)
46453913Sarchie            return Collections.emptySet();
46553913Sarchie
46653913Sarchie        Set<List<String>> pluginOpts = new LinkedHashSet<>();
46753913Sarchie        for (String plugin: plugins.split("\\x00")) {
46853913Sarchie            pluginOpts.add(List.from(plugin.split("\\s+")));
46953913Sarchie        }
47053913Sarchie        return Collections.unmodifiableSet(pluginOpts);
47153913Sarchie    }
47253913Sarchie
47353913Sarchie    /**
47453913Sarchie     * Gets any options specifying how doclint should be run.
47553913Sarchie     * An empty list is returned if no doclint options are specified
47653913Sarchie     * or if the only doclint option is -Xdoclint:none.
47753913Sarchie     * @return options for doclint
47853913Sarchie     */
47953913Sarchie    public List<String> getDocLintOpts() {
48053913Sarchie        String xdoclint = options.get(Option.XDOCLINT);
48153913Sarchie        String xdoclintCustom = options.get(Option.XDOCLINT_CUSTOM);
48253913Sarchie        if (xdoclint == null && xdoclintCustom == null)
48353913Sarchie            return List.nil();
48453913Sarchie
48553913Sarchie        Set<String> doclintOpts = new LinkedHashSet<>();
48653913Sarchie        if (xdoclint != null)
48753913Sarchie            doclintOpts.add(DocLint.XMSGS_OPTION);
48853913Sarchie        if (xdoclintCustom != null) {
48953913Sarchie            for (String s: xdoclintCustom.split("\\s+")) {
49053913Sarchie                if (s.isEmpty())
49153913Sarchie                    continue;
49253913Sarchie                doclintOpts.add(s.replace(Option.XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX));
49353913Sarchie            }
49453913Sarchie        }
49553913Sarchie
49653913Sarchie        if (doclintOpts.equals(Collections.singleton(DocLint.XMSGS_CUSTOM_PREFIX + "none")))
49753913Sarchie            return List.nil();
49853913Sarchie
49953913Sarchie        String checkPackages = options.get(Option.XDOCLINT_PACKAGE);
50053913Sarchie
50153913Sarchie        if (checkPackages != null) {
50262471Sphk            for (String s : checkPackages.split("\\s+")) {
50362471Sphk                doclintOpts.add(s.replace(Option.XDOCLINT_PACKAGE.text, DocLint.XCHECK_PACKAGE));
50462471Sphk            }
50562471Sphk        }
50662471Sphk
50762471Sphk        // standard doclet normally generates H1, H2,
50862471Sphk        // so for now, allow user comments to assume that
50953913Sarchie        doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");
51053913Sarchie
51153913Sarchie        return List.from(doclintOpts.toArray(new String[doclintOpts.size()]));
51253913Sarchie    }
51353913Sarchie
51453913Sarchie    private boolean checkDirectory(Option option) {
51553913Sarchie        String value = options.get(option);
51653913Sarchie        if (value == null) {
51753913Sarchie            return true;
51853913Sarchie        }
51953913Sarchie        File file = new File(value);
52053913Sarchie        if (!file.exists()) {
52153913Sarchie            error("err.dir.not.found", value);
52253913Sarchie            return false;
52353913Sarchie        }
52453913Sarchie        if (!file.isDirectory()) {
52553913Sarchie            error("err.file.not.directory", value);
52653913Sarchie            return false;
52753913Sarchie        }
52853913Sarchie        return true;
52953913Sarchie    }
53053913Sarchie
53153913Sarchie    void error(String key, Object... args) {
53252419Sjulian        errors = true;
53352419Sjulian        switch (errorMode) {
53452419Sjulian            case ILLEGAL_ARGUMENT: {
53552419Sjulian                String msg = log.localize(PrefixKind.JAVAC, key, args);
53652419Sjulian                throw new PropagatedException(new IllegalArgumentException(msg));
53752419Sjulian            }
53852419Sjulian            case ILLEGAL_STATE: {
53952419Sjulian                String msg = log.localize(PrefixKind.JAVAC, key, args);
54052419Sjulian                throw new PropagatedException(new IllegalStateException(msg));
54152419Sjulian            }
54270700Sjulian            case LOG:
54352419Sjulian                report(key, args);
54452419Sjulian                log.printLines(PrefixKind.JAVAC, "msg.usage", ownName);
54552419Sjulian        }
54671047Sjulian    }
54752419Sjulian
54852419Sjulian    void warning(String key, Object... args) {
54952419Sjulian        report(key, args);
55052419Sjulian    }
55152419Sjulian
552125028Sharti    private void report(String key, Object... args) {
55352419Sjulian        log.printRawLines(ownName + ": " + log.localize(PrefixKind.JAVAC, key, args));
55452419Sjulian    }
55552419Sjulian
55652419Sjulian    private JavaFileManager getFileManager() {
55769923Sjulian        if (fileManager == null)
558101241Smux            fileManager = context.get(JavaFileManager.class);
55952419Sjulian        return fileManager;
56052419Sjulian    }
56152419Sjulian
56252419Sjulian    <T> ListBuffer<T> toList(Iterable<? extends T> items) {
56352419Sjulian        ListBuffer<T> list = new ListBuffer<>();
56452419Sjulian        if (items != null) {
56552419Sjulian            for (T item : items) {
56652419Sjulian                list.add(item);
56752419Sjulian            }
56870700Sjulian        }
56970700Sjulian        return list;
57070700Sjulian    }
57170700Sjulian
57270700Sjulian    <T> Set<T> toSet(Iterable<? extends T> items) {
57370700Sjulian        Set<T> set = new LinkedHashSet<>();
57470700Sjulian        if (items != null) {
57570784Sjulian            for (T item : items) {
57670700Sjulian                set.add(item);
57770700Sjulian            }
57870700Sjulian        }
57970700Sjulian        return set;
58070700Sjulian    }
58170700Sjulian}
58270935Sjulian