jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
changeset 42174 fa763b059501
parent 41953 3e89e6103470
child 42330 bd999576b78d
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java	Sun Nov 20 23:19:54 2016 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java	Mon Nov 21 10:08:20 2016 -0400
@@ -46,8 +46,8 @@
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.Set;
+import java.util.stream.Stream;
 
-import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
 import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.Plugin.Category;
@@ -90,8 +90,7 @@
         public boolean showUsage;
     }
 
-    public static class Option<T> {
-
+    public static class Option<T> implements Comparable<T> {
         public interface Processing<T> {
 
             void process(T task, String opt, String arg) throws BadArgs;
@@ -100,17 +99,34 @@
         final boolean hasArg;
         final Processing<T> processing;
         final boolean hidden;
-        final String[] aliases;
+        final String name;
+        final String shortname;
 
-        public Option(boolean hasArg, Processing<T> processing, boolean hidden, String... aliases) {
+        public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name, String shortname) {
+            if (!name.startsWith("--")) {
+                throw new RuntimeException("option name missing --, " + name);
+            }
+            if (!shortname.isEmpty() && !shortname.startsWith("-")) {
+                throw new RuntimeException("short name missing -, " + shortname);
+            }
+
             this.hasArg = hasArg;
             this.processing = processing;
-            this.aliases = aliases;
             this.hidden = hidden;
+            this.name = name;
+            this.shortname = shortname;
         }
 
-        public Option(boolean hasArg, Processing<T> processing, String... aliases) {
-            this(hasArg, processing, false, aliases);
+        public Option(boolean hasArg, Processing<T> processing, String name, String shortname) {
+            this(hasArg, processing, false, name, shortname);
+        }
+
+        public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name) {
+            this(hasArg, processing, hidden, name, "");
+        }
+
+        public Option(boolean hasArg, Processing<T> processing, String name) {
+            this(hasArg, processing, false, name, "");
         }
 
         public boolean isHidden() {
@@ -118,16 +134,10 @@
         }
 
         public boolean matches(String opt) {
-            for (String a : aliases) {
-                if (a.equals(opt)) {
-                    return true;
-                } else if (opt.startsWith("--")
-                        && (hasArg && opt.startsWith(a + "="))) {
-                    return true;
-                }
-            }
-            return false;
-        }
+            return opt.equals(name) ||
+                   opt.equals(shortname) ||
+                   hasArg && opt.startsWith("--") && opt.startsWith(name + "=");
+         }
 
         public boolean ignoreRest() {
             return false;
@@ -137,28 +147,54 @@
             processing.process(task, opt, arg);
         }
 
-        public String[] aliases() {
-            return aliases;
+        public String getName() {
+            return name;
+        }
+
+        public String resourceName() {
+            return resourcePrefix() + name.substring(2);
+        }
+
+        public String getShortname() {
+            return shortname;
+        }
+
+        public String resourcePrefix() {
+            return "main.opt.";
+        }
+
+        @Override
+        public int compareTo(Object object) {
+            if (!(object instanceof Option<?>)) {
+                throw new RuntimeException("comparing non-Option");
+            }
+
+            Option<?> option = (Option<?>)object;
+
+            return name.compareTo(option.name);
+        }
+
+    }
+
+    private static class PluginOption extends Option<PluginsHelper> {
+        public PluginOption(boolean hasArg,
+                Processing<PluginsHelper> processing, boolean hidden, String name, String shortname) {
+            super(hasArg, processing, hidden, name, shortname);
+        }
+
+        public PluginOption(boolean hasArg,
+                Processing<PluginsHelper> processing, boolean hidden, String name) {
+            super(hasArg, processing, hidden, name, "");
+        }
+
+        public String resourcePrefix() {
+            return "plugin.opt.";
         }
     }
 
-    private static class PlugOption extends Option<PluginsOptions> {
-
-        public PlugOption(boolean hasArg,
-                Processing<PluginsOptions> processing, boolean hidden, String... aliases) {
-            super(hasArg, processing, hidden, aliases);
-        }
-
-        public PlugOption(boolean hasArg,
-                Processing<PluginsOptions> processing, String... aliases) {
-            super(hasArg, processing, aliases);
-        }
-    }
-
-    private final class PluginsOptions {
+    private final class PluginsHelper {
 
         private static final String PLUGINS_PATH = "--plugin-module-path";
-        private static final String POST_PROCESS = "--post-process-path";
 
         private Layer pluginsLayer = Layer.boot();
         private final List<Plugin> plugins;
@@ -170,10 +206,10 @@
         // Each such occurrence results in a Map of arguments. So, there could be multiple
         // args maps per plugin instance.
         private final Map<Plugin, List<Map<String, String>>> pluginToMaps = new HashMap<>();
-        private final List<PlugOption> pluginsOptions = new ArrayList<>();
-        private final List<PlugOption> mainOptions = new ArrayList<>();
+        private final List<PluginOption> pluginsOptions = new ArrayList<>();
+        private final List<PluginOption> mainOptions = new ArrayList<>();
 
-        private PluginsOptions(String pp) throws BadArgs {
+        private PluginsHelper(String pp) throws BadArgs {
 
             if (pp != null) {
                 String[] dirs = pp.split(File.pathSeparator);
@@ -193,13 +229,13 @@
                     addOrderedPluginOptions(plugin, optionsSeen);
                 }
             }
-            mainOptions.add(new PlugOption(false,
+            mainOptions.add(new PluginOption(false,
                     (task, opt, arg) -> {
                         // This option is handled prior
                         // to have the options parsed.
                     },
-                    "--plugin-module-path"));
-            mainOptions.add(new PlugOption(true, (task, opt, arg) -> {
+                    false, "--plugin-module-path"));
+            mainOptions.add(new PluginOption(true, (task, opt, arg) -> {
                     for (Plugin plugin : plugins) {
                         if (plugin.getName().equals(arg)) {
                             pluginToMaps.remove(plugin);
@@ -208,24 +244,24 @@
                     }
                     throw newBadArgs("err.no.such.plugin", arg);
                 },
-                "--disable-plugin"));
-            mainOptions.add(new PlugOption(true, (task, opt, arg) -> {
+                false, "--disable-plugin"));
+            mainOptions.add(new PluginOption(true, (task, opt, arg) -> {
                 Path path = Paths.get(arg);
                 if (!Files.exists(path) || !Files.isDirectory(path)) {
                     throw newBadArgs("err.image.must.exist", path);
                 }
                 existingImage = path.toAbsolutePath();
-            }, true, POST_PROCESS));
-            mainOptions.add(new PlugOption(true,
+            }, true, "--post-process-path"));
+            mainOptions.add(new PluginOption(true,
                     (task, opt, arg) -> {
                         lastSorter = arg;
                     },
                     true, "--resources-last-sorter"));
-            mainOptions.add(new PlugOption(false,
+            mainOptions.add(new PluginOption(false,
                     (task, opt, arg) -> {
                         listPlugins = true;
                     },
-                    "--list-plugins"));
+                    false, "--list-plugins"));
         }
 
         private List<Map<String, String>> argListFor(Plugin plugin) {
@@ -261,8 +297,8 @@
             }
             optionsSeen.add(option);
 
-            PlugOption plugOption
-                    = new PlugOption(plugin.hasArguments(),
+            PluginOption plugOption
+                    = new PluginOption(plugin.hasArguments(),
                             (task, opt, arg) -> {
                                 if (!Utils.isFunctional(plugin)) {
                                     throw newBadArgs("err.provider.not.functional",
@@ -312,7 +348,7 @@
                                     }
                                 }
                             },
-                            "--" + option);
+                            false, "--" + option);
             pluginsOptions.add(plugOption);
 
             if (Utils.isFunctional(plugin)) {
@@ -322,44 +358,44 @@
 
                 if (plugin instanceof DefaultCompressPlugin) {
                     plugOption
-                        = new PlugOption(false,
+                        = new PluginOption(false,
                             (task, opt, arg) -> {
                                 Map<String, String> m = addArgumentMap(plugin);
                                 m.put(DefaultCompressPlugin.NAME, DefaultCompressPlugin.LEVEL_2);
-                            }, "-c");
+                            }, false, "--compress", "-c");
                     mainOptions.add(plugOption);
                 } else if (plugin instanceof StripDebugPlugin) {
                     plugOption
-                        = new PlugOption(false,
+                        = new PluginOption(false,
                             (task, opt, arg) -> {
                                 addArgumentMap(plugin);
-                            }, "-G");
+                            }, false, "--strip-debug", "-G");
                     mainOptions.add(plugOption);
                 } else if (plugin instanceof ExcludeJmodSectionPlugin) {
-                    plugOption = new PlugOption(false, (task, opt, arg) -> {
+                    plugOption = new PluginOption(false, (task, opt, arg) -> {
                             Map<String, String> m = addArgumentMap(plugin);
                             m.put(ExcludeJmodSectionPlugin.NAME,
                                   ExcludeJmodSectionPlugin.MAN_PAGES);
-                        }, "--no-man-pages");
+                        }, false, "--no-man-pages");
                     mainOptions.add(plugOption);
 
-                    plugOption = new PlugOption(false, (task, opt, arg) -> {
+                    plugOption = new PluginOption(false, (task, opt, arg) -> {
                         Map<String, String> m = addArgumentMap(plugin);
                         m.put(ExcludeJmodSectionPlugin.NAME,
                               ExcludeJmodSectionPlugin.INCLUDE_HEADER_FILES);
-                    }, "--no-header-files");
+                    }, false, "--no-header-files");
                     mainOptions.add(plugOption);
                 }
             }
         }
 
-        private PlugOption getOption(String name) throws BadArgs {
-            for (PlugOption o : pluginsOptions) {
+        private PluginOption getOption(String name) throws BadArgs {
+            for (PluginOption o : pluginsOptions) {
                 if (o.matches(name)) {
                     return o;
                 }
             }
-            for (PlugOption o : mainOptions) {
+            for (PluginOption o : mainOptions) {
                 if (o.matches(name)) {
                     return o;
                 }
@@ -461,7 +497,7 @@
         private String getPluginsPath(String[] args) throws BadArgs {
             String pp = null;
             for (int i = 0; i < args.length; i++) {
-                if (args[i].equals(PluginsOptions.PLUGINS_PATH)) {
+                if (args[i].equals(PluginsHelper.PLUGINS_PATH)) {
                     if (i == args.length - 1) {
                         throw new BadArgs("err.no.plugins.path").showUsage(true);
                     } else {
@@ -498,13 +534,13 @@
             // Must extract it prior to do any option analysis.
             // Required to interpret custom plugin options.
             // Unit tests can call Task multiple time in same JVM.
-            pluginOptions = new PluginsOptions(getPluginsPath(args));
+            pluginOptions = new PluginsHelper(getPluginsPath(args));
 
             // First extract plugins path if any
             String pp = null;
             List<String> filteredArgs = new ArrayList<>();
             for (int i = 0; i < args.length; i++) {
-                if (args[i].equals(PluginsOptions.PLUGINS_PATH)) {
+                if (args[i].equals(PluginsHelper.PLUGINS_PATH)) {
                     if (i == args.length - 1) {
                         throw new BadArgs("err.no.plugins.path").showUsage(true);
                     } else {
@@ -529,7 +565,7 @@
             for (int i = 0; i < args.length; i++) {
                 if (args[i].charAt(0) == '-') {
                     String name = args[i];
-                    PlugOption pluginOption = null;
+                    PluginOption pluginOption = null;
                     Option<T> option = getOption(name);
                     if (option == null) {
                         pluginOption = pluginOptions.getOption(name);
@@ -585,32 +621,13 @@
         }
 
         public void showHelp(String progName) {
-            showHelp(progName, true);
-        }
-
-        private void showHelp(String progName, boolean showsImageBuilder) {
             log.println(bundleHelper.getMessage("main.usage", progName));
-            for (Option<?> o : options) {
-                String name = o.aliases[0].substring(1); // there must always be at least one name
-                name = name.charAt(0) == '-' ? name.substring(1) : name;
-                if (o.isHidden() || name.equals("h")) {
-                    continue;
-                }
-                log.println(bundleHelper.getMessage("main.opt." + name));
-            }
-
-            for (Option<?> o : pluginOptions.mainOptions) {
-                if (o.aliases[0].equals(PluginsOptions.POST_PROCESS)
-                        && !showsImageBuilder) {
-                    continue;
-                }
-                String name = o.aliases[0].substring(1); // there must always be at least one name
-                name = name.charAt(0) == '-' ? name.substring(1) : name;
-                if (o.isHidden()) {
-                    continue;
-                }
-                log.println(bundleHelper.getMessage("plugin.opt." + name));
-            }
+            Stream.concat(options.stream(), pluginOptions.mainOptions.stream())
+                .filter(option -> !option.isHidden())
+                .sorted()
+                .forEach(option -> {
+                     log.println(bundleHelper.getMessage(option.resourceName()));
+                });
 
             log.println(bundleHelper.getMessage("main.command.files"));
         }
@@ -619,6 +636,7 @@
             log.println("\n" + bundleHelper.getMessage("main.extended.help"));
             List<Plugin> pluginList = PluginRepository.
                     getPlugins(pluginOptions.pluginsLayer);
+
             for (Plugin plugin : Utils.getSortedPlugins(pluginList)) {
                 showPlugin(plugin, log);
             }
@@ -671,7 +689,7 @@
         }
     }
 
-    private PluginsOptions pluginOptions;
+    private PluginsHelper pluginOptions;
     private PrintWriter log;
     private final ResourceBundleHelper bundleHelper;