/*
 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.sjavac.options;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.sun.tools.sjavac.CopyFile;
import com.sun.tools.sjavac.Transformer;


Sjavac options can be classified as: (1) relevant only for sjavac, such as --server (2) relevant for sjavac and javac, such as -d, or (3) relevant only for javac, such as -g. This enum represents all options from (1) and (2). Note that instances of this enum only entail static information about the option. For storage of option values, refer to com.sun.tools.sjavac.options.Options.

This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice.

/** * Sjavac options can be classified as: * * (1) relevant only for sjavac, such as --server * (2) relevant for sjavac and javac, such as -d, or * (3) relevant only for javac, such as -g. * * This enum represents all options from (1) and (2). Note that instances of * this enum only entail static information about the option. For storage of * option values, refer to com.sun.tools.sjavac.options.Options. * * <p><b>This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */
public enum Option { SRC("-src", "Location of source files to be compiled") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { List<Path> paths = getFileListArg(iter, helper); if (paths != null) helper.sourceRoots(paths); } }, SOURCE_PATH("--source-path", "Specify search path for sources.") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { List<Path> paths = getFileListArg(iter, helper); if (paths != null) helper.sourcepath(paths); } }, SOURCEPATH("-sourcepath", "An alias for -sourcepath") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { SOURCE_PATH.processMatching(iter, helper); } }, MODULE_PATH("--module-path", "Specify search path for modules.") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { List<Path> paths = getFileListArg(iter, helper); if (paths != null) helper.modulepath(paths); } }, P("-p", "An alias for --module-path") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { MODULE_PATH.processMatching(iter, helper); } }, CLASS_PATH("--class-path", "Specify search path for classes.") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { List<Path> paths = getFileListArg(iter, helper); if (paths != null) helper.classpath(paths); } }, CLASSPATH("-classpath", "An alias for -classpath.") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { CLASS_PATH.processMatching(iter, helper); } }, CP("-cp", "An alias for -classpath") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { CLASS_PATH.processMatching(iter, helper); } }, X("-x", "Exclude files matching the given pattern") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { String pattern = getFilePatternArg(iter, helper); if (pattern != null) helper.exclude(pattern); } }, I("-i", "Include only files matching the given pattern") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { String pattern = getFilePatternArg(iter, helper); if (pattern != null) helper.include(pattern); } }, TR("-tr", "Translate resources") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { if (!iter.hasNext()) { helper.reportError(arg + " must be followed by a translation rule"); return; } String trArg = iter.next(); // Validate argument syntax. Examples: // .prop=com.sun.tools.javac.smart.CompileProperties // .idl=com.sun.corba.CompileIdl // .g3=antlr.CompileGrammar,debug=true String ident = "[a-zA-Z_][a-zA-Z0-9_]*"; Pattern p = Pattern.compile("(?<suffix>\\." + ident + ")=" + "(?<class>" + ident + "(\\." + ident + ")*)" + "(?<extra>,.*)?"); // Check syntax Matcher m = p.matcher(trArg); if (!m.matches()) { helper.reportError("The string \"" + trArg + "\" is not a " + "valid translate pattern"); return; } // Extract relevant parts String suffix = m.group("suffix"); String classname = m.group("class"); String extra = m.group("extra"); // Valid suffix? if (suffix.matches("\\.(class|java)")) { helper.reportError("You cannot have a translator for " + suffix + " files!"); return; } // Construct transformer try { Class<?> trCls = Class.forName(classname); Transformer transformer = (Transformer) trCls.getConstructor().newInstance(); transformer.setExtra(extra); helper.addTransformer(suffix, transformer); } catch (Exception e) { helper.reportError("Cannot use " + classname + " as a translator: " + e.getMessage()); } } }, COPY("-copy", "Copy resources") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { if (!iter.hasNext()) { helper.reportError(arg + " must be followed by a resource type"); return; } String copyArg = iter.next(); // Validate argument syntax. Examples: .gif, .html if (!copyArg.matches("\\.[a-zA-Z_][a-zA-Z0-9_]*")) { helper.reportError("The string \"" + copyArg + "\" is not a " + "valid resource type."); return; } helper.addTransformer(copyArg, new CopyFile()); } }, J("-j", "Number of cores") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { if (!iter.hasNext() || !iter.peek().matches("\\d+")) { helper.reportError(arg + " must be followed by an integer"); return; } helper.numCores(Integer.parseInt(iter.next())); } }, SERVER("--server:", "Specify server configuration file of running server") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.serverConf(iter.current().substring(arg.length())); } }, STARTSERVER("--startserver:", "Start server and use the given configuration file") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.startServerConf(iter.current().substring(arg.length())); } }, IMPLICIT("-implicit:", "Specify how to treat implicitly referenced source code") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.implicit(iter.current().substring(arg.length())); } }, LOG("--log=", "Specify logging level") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.logLevel(iter.current().substring(arg.length())); } }, VERBOSE("-verbose", "Set verbosity level to \"info\"") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.logLevel("info"); } }, PERMIT_ARTIFACT("--permit-artifact=", "Allow this artifact in destination directory") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { String a = iter.current().substring(arg.length()); helper.permitArtifact(Paths.get(a).toFile().getAbsolutePath()); } }, PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Allow unidentified artifacts in destination directory") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.permitUnidentifiedArtifacts(); } }, PERMIT_SOURCES_WITHOUT_PACKAGE("--permit-sources-without-package", "Permit sources in the default package") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.permitDefaultPackage(); } }, COMPARE_FOUND_SOURCES("--compare-found-sources", "Compare found sources with given sources") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { Path referenceSourceList = getFileArg(iter, helper, true, false); if (referenceSourceList != null) helper.compareFoundSources(referenceSourceList); } }, D("-d", "Output destination directory") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { Path dir = getFileArg(iter, helper, false, true); if (dir != null) helper.destDir(dir); } }, S("-s", "Directory for generated sources") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { Path dir = getFileArg(iter, helper, false, true); if (dir != null) helper.generatedSourcesDir(dir); } }, H("-h", "Directory for header files") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { Path dir = getFileArg(iter, helper, false, true); if (dir != null) helper.headerDir(dir); } }, STATE_DIR("--state-dir=", "Directory used to store sjavac state and log files.") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { String p = iter.current().substring(arg.length()); helper.stateDir(Paths.get(p)); } }; public final String arg; final String description; private Option(String arg, String description) { this.arg = arg; this.description = description; }
Retrieve and verify syntax of file list argument.
/** Retrieve and verify syntax of file list argument. */
List<Path> getFileListArg(ArgumentIterator iter, OptionHelper helper) { if (!iter.hasNext()) { helper.reportError(arg + " must be followed by a list of files " + "separated by " + File.pathSeparator); return null; } List<Path> result = new ArrayList<>(); for (String pathStr : iter.next().split(File.pathSeparator)) result.add(Paths.get(pathStr)); return result; }
Retrieve and verify syntax of file argument.
/** Retrieve and verify syntax of file argument. */
Path getFileArg(ArgumentIterator iter, OptionHelper helper, boolean fileAcceptable, boolean dirAcceptable) { if (!iter.hasNext()) { String errmsg = arg + " must be followed by "; if (fileAcceptable && dirAcceptable) errmsg += "a file or directory."; else if (fileAcceptable) errmsg += "a file."; else if (dirAcceptable) errmsg += "a directory."; else throw new IllegalArgumentException("File or directory must be acceptable."); helper.reportError(errmsg); return null; } return Paths.get(iter.next()); }
Retrieve the next file or package argument.
/** Retrieve the next file or package argument. */
String getFilePatternArg(ArgumentIterator iter, OptionHelper helper) { if (!iter.hasNext()) { helper.reportError(arg + " must be followed by a glob pattern."); return null; } return iter.next(); } // Future cleanup: Change the "=" syntax to ":" syntax to be consistent and // to follow the javac-option style. public boolean hasOption() { return arg.endsWith(":") || arg.endsWith("="); }
Process current argument of argIter. It's final, since the option customization is typically done in processMatching.
Params:
  • argIter – Iterator to read current and succeeding arguments from.
  • helper – The helper to report back to.
Returns:true iff the argument was processed by this option.
/** * Process current argument of argIter. * * It's final, since the option customization is typically done in * processMatching. * * @param argIter Iterator to read current and succeeding arguments from. * @param helper The helper to report back to. * @return true iff the argument was processed by this option. */
public final boolean processCurrent(ArgumentIterator argIter, OptionHelper helper) { String fullArg = argIter.current(); // "-tr" or "-log=level" if (hasOption() ? fullArg.startsWith(arg) : fullArg.equals(arg)) { processMatching(argIter, helper); return true; } // Did not match return false; }
Called by process if the current argument matches this option.
/** Called by process if the current argument matches this option. */
protected abstract void processMatching(ArgumentIterator argIter, OptionHelper helper); }