Path: blob/master/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java
66646 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.jar;2627import java.io.File;28import java.io.PrintWriter;29import java.lang.module.ModuleDescriptor.Version;30import java.nio.file.Path;31import java.nio.file.Paths;32import java.util.regex.Pattern;33import java.util.regex.PatternSyntaxException;34import jdk.internal.module.ModulePath;35import jdk.internal.module.ModuleResolution;36import java.time.ZoneOffset;37import java.time.ZonedDateTime;38import java.time.LocalDateTime;39import java.time.format.DateTimeFormatter;40import java.time.format.DateTimeParseException;4142/**43* Parser for GNU Style Options.44*/45class GNUStyleOptions {4647// Valid --date range48static final ZonedDateTime DATE_MIN = ZonedDateTime.parse("1980-01-01T00:00:02Z");49static final ZonedDateTime DATE_MAX = ZonedDateTime.parse("2099-12-31T23:59:59Z");5051static class BadArgs extends Exception {52static final long serialVersionUID = 0L;5354boolean showUsage;5556BadArgs(String key, String arg) { super(Main.formatMsg(key, arg)); }57BadArgs(String key) { super(Main.getMsg(key)); }5859BadArgs showUsage(boolean b) {60showUsage = b;61return this;62}63}6465static Option[] recognizedOptions = {66// Main operations67new Option(false, OptionType.MAIN_OPERATION, "--create", "-c") {68void process(Main tool, String opt, String arg) throws BadArgs {69if (tool.iflag || tool.tflag || tool.uflag || tool.xflag || tool.dflag || tool.validate)70throw new BadArgs("error.multiple.main.operations").showUsage(true);71tool.cflag = true;72}73},74new Option(true, OptionType.MAIN_OPERATION, "--generate-index", "-i") {75void process(Main tool, String opt, String arg) throws BadArgs {76if (tool.cflag || tool.tflag || tool.uflag || tool.xflag || tool.dflag || tool.validate)77throw new BadArgs("error.multiple.main.operations").showUsage(true);78tool.iflag = true;79tool.rootjar = arg;80}81},82new Option(false, OptionType.MAIN_OPERATION, "--list", "-t") {83void process(Main tool, String opt, String arg) throws BadArgs {84if (tool.cflag || tool.iflag || tool.uflag || tool.xflag || tool.dflag || tool.validate)85throw new BadArgs("error.multiple.main.operations").showUsage(true);86tool.tflag = true;87}88},89new Option(false, OptionType.MAIN_OPERATION, "--update", "-u") {90void process(Main tool, String opt, String arg) throws BadArgs {91if (tool.cflag || tool.iflag || tool.tflag || tool.xflag || tool.dflag || tool.validate)92throw new BadArgs("error.multiple.main.operations").showUsage(true);93tool.uflag = true;94}95},96new Option(false, OptionType.MAIN_OPERATION, "--extract", "-x") {97void process(Main tool, String opt, String arg) throws BadArgs {98if (tool.cflag || tool.iflag || tool.tflag || tool.uflag || tool.dflag || tool.validate)99throw new BadArgs("error.multiple.main.operations").showUsage(true);100tool.xflag = true;101}102},103new Option(false, OptionType.MAIN_OPERATION, "--describe-module", "-d") {104void process(Main tool, String opt, String arg) throws BadArgs {105if (tool.cflag || tool.iflag || tool.tflag || tool.uflag || tool.xflag || tool.validate)106throw new BadArgs("error.multiple.main.operations").showUsage(true);107tool.dflag = true;108}109},110new Option(false, OptionType.MAIN_OPERATION, "--validate") {111void process(Main tool, String opt, String arg) throws BadArgs {112if (tool.cflag || tool.iflag || tool.tflag || tool.uflag || tool.xflag || tool.dflag)113throw new BadArgs("error.multiple.main.operations").showUsage(true);114tool.validate = true;115}116},117118// Additional options119new Option(true, OptionType.ANY, "--file", "-f") {120void process(Main jartool, String opt, String arg) {121jartool.fname = arg;122}123},124new Option(false, OptionType.ANY, "--verbose", "-v") {125void process(Main jartool, String opt, String arg) {126jartool.vflag = true;127}128},129new Option(true, OptionType.CREATE_UPDATE, "--main-class", "-e") {130void process(Main jartool, String opt, String arg) {131jartool.ename = arg;132}133},134new Option(true, OptionType.CREATE_UPDATE, "--manifest", "-m") {135void process(Main jartool, String opt, String arg) {136jartool.mname = arg;137}138},139new Option(false, OptionType.CREATE_UPDATE, "--no-manifest", "-M") {140void process(Main jartool, String opt, String arg) {141jartool.Mflag = true;142}143},144new Option(true, OptionType.CREATE_UPDATE, "--module-version") {145void process(Main jartool, String opt, String arg) {146jartool.moduleVersion = Version.parse(arg);147}148},149new Option(true, OptionType.CREATE_UPDATE, "--hash-modules") {150void process(Main jartool, String opt, String arg) throws BadArgs {151try {152jartool.modulesToHash = Pattern.compile(arg);153} catch (PatternSyntaxException e) {154throw new BadArgs("err.badpattern", arg).showUsage(true);155}156}157},158new Option(true, OptionType.CREATE_UPDATE, "--module-path", "-p") {159void process(Main jartool, String opt, String arg) {160String[] dirs = arg.split(File.pathSeparator);161Path[] paths = new Path[dirs.length];162int i = 0;163for (String dir : dirs) {164paths[i++] = Paths.get(dir);165}166jartool.moduleFinder = ModulePath.of(Runtime.version(), true, paths);167}168},169new Option(false, OptionType.CREATE_UPDATE, "--do-not-resolve-by-default") {170void process(Main jartool, String opt, String arg) {171ModuleResolution mres = jartool.moduleResolution;172jartool.moduleResolution = mres.withDoNotResolveByDefault();173}174boolean isExtra() { return true; }175},176new Option(true, OptionType.CREATE_UPDATE, "--warn-if-resolved") {177void process(Main jartool, String opt, String arg) throws BadArgs {178ModuleResolution mres = ModuleResolution.empty();179if (jartool.moduleResolution.doNotResolveByDefault()) {180mres.withDoNotResolveByDefault();181}182if (arg.equals("deprecated")) {183jartool.moduleResolution = mres.withDeprecated();184} else if (arg.equals("deprecated-for-removal")) {185jartool.moduleResolution = mres.withDeprecatedForRemoval();186} else if (arg.equals("incubating")) {187jartool.moduleResolution = mres.withIncubating();188} else {189throw new BadArgs("error.bad.reason", arg);190}191}192boolean isExtra() { return true; }193},194new Option(false, OptionType.CREATE_UPDATE_INDEX, "--no-compress", "-0") {195void process(Main jartool, String opt, String arg) {196jartool.flag0 = true;197}198},199new Option(true, OptionType.CREATE_UPDATE_INDEX, "--date") {200void process(Main jartool, String opt, String arg) throws BadArgs {201try {202ZonedDateTime date = ZonedDateTime.parse(arg, DateTimeFormatter.ISO_ZONED_DATE_TIME)203.withZoneSameInstant(ZoneOffset.UTC);204if (date.isBefore(DATE_MIN) || date.isAfter(DATE_MAX)) {205throw new BadArgs("error.date.out.of.range", arg);206}207jartool.date = date.toLocalDateTime();208} catch (DateTimeParseException x) {209throw new BadArgs("error.date.notvalid", arg);210}211}212},213214// Hidden options215new Option(false, OptionType.OTHER, "-P") {216void process(Main jartool, String opt, String arg) {217jartool.pflag = true;218}219boolean isHidden() { return true; }220},221222// Other options223new Option(true, true, OptionType.OTHER, "--help", "-h", "-?") {224void process(Main jartool, String opt, String arg) throws BadArgs {225if (jartool.info == null) {226if (arg == null) {227jartool.info = GNUStyleOptions::printHelp; // Main.Info.HELP;228return;229}230if (!arg.equals("compat"))231throw new BadArgs("error.illegal.option", arg).showUsage(true);232// jartool.info = Main.Info.COMPAT_HELP;233jartool.info = GNUStyleOptions::printCompatHelp;234}235}236},237new Option(false, OptionType.OTHER, "--help-extra") {238void process(Main jartool, String opt, String arg) throws BadArgs {239jartool.info = GNUStyleOptions::printHelpExtra;240}241},242new Option(false, OptionType.OTHER, "--version") {243void process(Main jartool, String opt, String arg) {244if (jartool.info == null)245jartool.info = GNUStyleOptions::printVersion;246}247}248};249250enum OptionType {251MAIN_OPERATION("main"),252ANY("any"),253CREATE("create"),254CREATE_UPDATE("create.update"),255CREATE_UPDATE_INDEX("create.update.index"),256OTHER("other");257258/** Resource lookup section prefix. */259final String name;260261OptionType(String name) { this.name = name; }262}263264static abstract class Option {265final boolean hasArg;266final boolean argIsOptional;267final String[] aliases;268final OptionType type;269270Option(boolean hasArg, OptionType type, String... aliases) {271this(hasArg, false, type, aliases);272}273274Option(boolean hasArg, boolean argIsOptional, OptionType type, String... aliases) {275this.hasArg = hasArg;276this.argIsOptional = argIsOptional;277this.type = type;278this.aliases = aliases;279}280281boolean isHidden() { return false; }282283boolean isExtra() { return false; }284285boolean matches(String opt) {286for (String a : aliases) {287if (a.equals(opt)) {288return true;289} else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {290return true;291} else if (opt.startsWith("--help") && opt.startsWith(a + ":")) {292return true;293}294}295return false;296}297298abstract void process(Main jartool, String opt, String arg) throws BadArgs;299}300301static int parseOptions(Main jartool, String[] args) throws BadArgs {302int count = 0;303if (args.length == 0) {304jartool.info = GNUStyleOptions::printUsageTryHelp; // never be here305return 0;306}307308// process options309for (; count < args.length; count++) {310if (args[count].charAt(0) != '-' || args[count].equals("-C") ||311args[count].equals("--release"))312break;313314String name = args[count];315if (name.equals("-XDsuppress-tool-removal-message")) {316jartool.suppressDeprecateMsg = true;317continue;318}319Option option = getOption(name);320String param = null;321if (option.hasArg) {322if (name.startsWith("--help")) { // "special" optional separator323if (name.indexOf(':') > 0) {324param = name.substring(name.indexOf(':') + 1, name.length());325}326} else if (name.startsWith("--") && name.indexOf('=') > 0) {327param = name.substring(name.indexOf('=') + 1, name.length());328} else if (count + 1 < args.length) {329param = args[++count];330}331if (!option.argIsOptional &&332(param == null || param.isEmpty() || param.charAt(0) == '-')) {333throw new BadArgs("error.missing.arg", name).showUsage(true);334}335}336option.process(jartool, name, param);337}338339return count;340}341342private static Option getOption(String name) throws BadArgs {343for (Option o : recognizedOptions) {344if (o.matches(name)) {345return o;346}347}348throw new BadArgs("error.unrecognized.option", name).showUsage(true);349}350351static void printHelpExtra(PrintWriter out) {352printHelp0(out, true);353}354355static void printHelp(PrintWriter out) {356printHelp0(out, false);357}358359private static void printHelp0(PrintWriter out, boolean printExtra) {360out.format("%s%n", Main.getMsg("main.help.preopt"));361for (OptionType type : OptionType.values()) {362boolean typeHeadingWritten = false;363364for (Option o : recognizedOptions) {365if (!o.type.equals(type))366continue;367String name = o.aliases[0].substring(1); // there must always be at least one name368name = name.charAt(0) == '-' ? name.substring(1) : name;369if (o.isHidden() || name.equals("h")) {370continue;371}372if (o.isExtra() && !printExtra) {373continue;374}375if (!typeHeadingWritten) {376out.format("%n%s%n", Main.getMsg("main.help.opt." + type.name));377typeHeadingWritten = true;378}379out.format("%s%n", Main.getMsg("main.help.opt." + type.name + "." + name));380}381}382out.format("%n%s%n%n", Main.getMsg("main.help.postopt"));383}384385static void printCompatHelp(PrintWriter out) {386out.format("%s%n", Main.getMsg("usage.compat"));387}388389static void printUsageTryHelp(PrintWriter out) {390out.format("%s%n", Main.getMsg("main.usage.summary.try"));391}392393static void printVersion(PrintWriter out) {394out.format("%s %s%n", "jar", System.getProperty("java.version"));395}396}397398399