< prev index next >

src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java

Print this page




  29 import java.io.PrintWriter;
  30 import java.lang.module.Configuration;
  31 import java.lang.module.ModuleFinder;
  32 import java.lang.reflect.Layer;
  33 import java.nio.file.Files;
  34 import java.nio.file.Path;
  35 import java.nio.file.Paths;
  36 import java.text.MessageFormat;
  37 import java.util.ArrayList;
  38 import java.util.Arrays;
  39 import java.util.Collections;
  40 import java.util.HashMap;
  41 import java.util.HashSet;
  42 import java.util.List;
  43 import java.util.Locale;
  44 import java.util.Map;
  45 import java.util.Map.Entry;
  46 import java.util.MissingResourceException;
  47 import java.util.ResourceBundle;
  48 import java.util.Set;

  49 import java.util.stream.Stream;
  50 
  51 import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin;
  52 import jdk.tools.jlink.plugin.Plugin;
  53 import jdk.tools.jlink.plugin.Plugin.Category;
  54 import jdk.tools.jlink.builder.DefaultImageBuilder;
  55 import jdk.tools.jlink.builder.ImageBuilder;
  56 import jdk.tools.jlink.plugin.PluginException;
  57 import jdk.tools.jlink.internal.Jlink.PluginsConfiguration;
  58 import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
  59 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
  60 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
  61 import jdk.internal.module.ModulePath;
  62 
  63 /**
  64  *
  65  * JLink and JImage tools shared helper.
  66  */
  67 public final class TaskHelper {
  68 


  84         public BadArgs showUsage(boolean b) {
  85             showUsage = b;
  86             return this;
  87         }
  88         public final String key;
  89         public final Object[] args;
  90         public boolean showUsage;
  91     }
  92 
  93     public static class Option<T> implements Comparable<T> {
  94         public interface Processing<T> {
  95 
  96             void process(T task, String opt, String arg) throws BadArgs;
  97         }
  98 
  99         final boolean hasArg;
 100         final Processing<T> processing;
 101         final boolean hidden;
 102         final String name;
 103         final String shortname;

 104 
 105         public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name, String shortname) {






 106             if (!name.startsWith("--")) {
 107                 throw new RuntimeException("option name missing --, " + name);
 108             }
 109             if (!shortname.isEmpty() && !shortname.startsWith("-")) {
 110                 throw new RuntimeException("short name missing -, " + shortname);
 111             }
 112 
 113             this.hasArg = hasArg;
 114             this.processing = processing;
 115             this.hidden = hidden;
 116             this.name = name;
 117             this.shortname = shortname;





 118         }
 119 
 120         public Option(boolean hasArg, Processing<T> processing, String name, String shortname) {
 121             this(hasArg, processing, false, name, shortname);
 122         }
 123 
 124         public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name) {
 125             this(hasArg, processing, hidden, name, "");
 126         }
 127 
 128         public Option(boolean hasArg, Processing<T> processing, String name) {
 129             this(hasArg, processing, false, name, "");
 130         }
 131 
 132         public boolean isHidden() {
 133             return hidden;
 134         }
 135 




 136         public boolean matches(String opt) {
 137             return opt.equals(name) ||
 138                    opt.equals(shortname) ||
 139                    hasArg && opt.startsWith("--") && opt.startsWith(name + "=");
 140          }
 141 
 142         public boolean ignoreRest() {
 143             return false;
 144         }
 145 
 146         void process(T task, String opt, String arg) throws BadArgs {
 147             processing.process(task, opt, arg);
 148         }
 149 
 150         public String getName() {
 151             return name;
 152         }
 153 
 154         public String resourceName() {
 155             return resourcePrefix() + name.substring(2);


 162         public String resourcePrefix() {
 163             return "main.opt.";
 164         }
 165 
 166         @Override
 167         public int compareTo(Object object) {
 168             if (!(object instanceof Option<?>)) {
 169                 throw new RuntimeException("comparing non-Option");
 170             }
 171 
 172             Option<?> option = (Option<?>)object;
 173 
 174             return name.compareTo(option.name);
 175         }
 176 
 177     }
 178 
 179     private static class PluginOption extends Option<PluginsHelper> {
 180         public PluginOption(boolean hasArg,
 181                 Processing<PluginsHelper> processing, boolean hidden, String name, String shortname) {
 182             super(hasArg, processing, hidden, name, shortname);
 183         }
 184 
 185         public PluginOption(boolean hasArg,
 186                 Processing<PluginsHelper> processing, boolean hidden, String name) {
 187             super(hasArg, processing, hidden, name, "");
 188         }
 189 
 190         public String resourcePrefix() {
 191             return "plugin.opt.";
 192         }
 193     }
 194 
 195     private final class PluginsHelper {
 196 
 197         private Layer pluginsLayer = Layer.boot();
 198         private final List<Plugin> plugins;
 199         private String lastSorter;
 200         private boolean listPlugins;
 201         private Path existingImage;
 202 
 203         // plugin to args maps. Each plugin may be used more than once in command line.
 204         // Each such occurrence results in a Map of arguments. So, there could be multiple
 205         // args maps per plugin instance.
 206         private final Map<Plugin, List<Map<String, String>>> pluginToMaps = new HashMap<>();
 207         private final List<PluginOption> pluginsOptions = new ArrayList<>();


 481         private boolean hasArgument(String optionName) throws BadArgs {
 482             Option<?> opt = getOption(optionName);
 483             if (opt == null) {
 484                 opt = pluginOptions.getOption(optionName);
 485                 if (opt == null) {
 486                     throw new BadArgs("err.unknown.option", optionName).
 487                             showUsage(true);
 488                 }
 489             }
 490             return opt.hasArg;
 491         }
 492 
 493         public boolean shouldListPlugins() {
 494             return pluginOptions.listPlugins;
 495         }
 496 
 497         private String getPluginsPath(String[] args) throws BadArgs {
 498             return null;
 499         }
 500 
 501         // used by jimage. Return unhandled arguments like "create", "describe".





 502         public List<String> handleOptions(T task, String[] args) throws BadArgs {
 503             return handleOptions(task, args, true);
 504         }
 505 
 506         // used by jlink. No unhandled arguments like "create", "describe".
 507         void handleOptionsNoUnhandled(T task, String[] args) throws BadArgs {
 508             handleOptions(task, args, false);
 509         }
 510 
 511         // shared code that handles options for both jlink and jimage. jimage uses arguments like
 512         // "create", "describe" etc. as "task names". Those arguments are unhandled here and returned
 513         // as "unhandled arguments list". jlink does not want such arguments. "collectUnhandled" flag
 514         // tells whether to allow for unhandled arguments or not.
 515         private List<String> handleOptions(T task, String[] args, boolean collectUnhandled) throws BadArgs {
 516             // findbugs warning, copy instead of keeping a reference.
 517             command = Arrays.copyOf(args, args.length);
 518 
 519             // Must extract it prior to do any option analysis.
 520             // Required to interpret custom plugin options.
 521             // Unit tests can call Task multiple time in same JVM.
 522             pluginOptions = new PluginsHelper(null);
 523 
 524             List<String> rest = collectUnhandled? new ArrayList<>() : null;
 525             // process options
 526             for (int i = 0; i < args.length; i++) {
 527                 if (args[i].startsWith("-")) {
 528                     String name = args[i];
 529                     PluginOption pluginOption = null;
 530                     Option<T> option = getOption(name);
 531                     if (option == null) {
 532                         pluginOption = pluginOptions.getOption(name);
 533                         if (pluginOption == null) {
 534 
 535                             throw new BadArgs("err.unknown.option", name).
 536                                     showUsage(true);
 537                         }
 538                     }
 539                     Option<?> opt = pluginOption == null ? option : pluginOption;
 540                     String param = null;
 541                     if (opt.hasArg) {
 542                         if (name.startsWith("--") && name.indexOf('=') > 0) {
 543                             param = name.substring(name.indexOf('=') + 1,
 544                                     name.length());
 545                         } else if (i + 1 < args.length) {
 546                             param = args[++i];
 547                         }
 548                         if (param == null || param.isEmpty()
 549                                 || (param.length() >= 2 && param.charAt(0) == '-'
 550                                 && param.charAt(1) == '-')) {
 551                             throw new BadArgs("err.missing.arg", name).
 552                                     showUsage(true);
 553                         }
 554                     }
 555                     if (pluginOption != null) {
 556                         pluginOption.process(pluginOptions, name, param);
 557                     } else {
 558                         option.process(task, name, param);







 559                     }
 560                     if (opt.ignoreRest()) {
 561                         i = args.length;
 562                     }
 563                 } else {
 564                     if (collectUnhandled) {
 565                         rest.add(args[i]);
 566                     } else {
 567                         throw new BadArgs("err.orphan.argument", args[i]).
 568                             showUsage(true);
 569                     }
 570                 }
 571             }
 572             return rest;
 573         }
 574 
 575         private Option<T> getOption(String name) {
 576             for (Option<T> o : options) {
 577                 if (o.matches(name)) {
 578                     return o;
 579                 }
 580             }
 581             return null;
 582         }
 583 
 584         public void showHelp(String progName) {
 585             log.println(bundleHelper.getMessage("main.usage", progName));
 586             Stream.concat(options.stream(), pluginOptions.mainOptions.stream())
 587                 .filter(option -> !option.isHidden())
 588                 .sorted()
 589                 .forEach(option -> {
 590                      log.println(bundleHelper.getMessage(option.resourceName()));
 591                 });
 592 




  29 import java.io.PrintWriter;
  30 import java.lang.module.Configuration;
  31 import java.lang.module.ModuleFinder;
  32 import java.lang.reflect.Layer;
  33 import java.nio.file.Files;
  34 import java.nio.file.Path;
  35 import java.nio.file.Paths;
  36 import java.text.MessageFormat;
  37 import java.util.ArrayList;
  38 import java.util.Arrays;
  39 import java.util.Collections;
  40 import java.util.HashMap;
  41 import java.util.HashSet;
  42 import java.util.List;
  43 import java.util.Locale;
  44 import java.util.Map;
  45 import java.util.Map.Entry;
  46 import java.util.MissingResourceException;
  47 import java.util.ResourceBundle;
  48 import java.util.Set;
  49 import java.util.stream.Collectors;
  50 import java.util.stream.Stream;
  51 
  52 import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin;
  53 import jdk.tools.jlink.plugin.Plugin;
  54 import jdk.tools.jlink.plugin.Plugin.Category;
  55 import jdk.tools.jlink.builder.DefaultImageBuilder;
  56 import jdk.tools.jlink.builder.ImageBuilder;
  57 import jdk.tools.jlink.plugin.PluginException;
  58 import jdk.tools.jlink.internal.Jlink.PluginsConfiguration;
  59 import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
  60 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
  61 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
  62 import jdk.internal.module.ModulePath;
  63 
  64 /**
  65  *
  66  * JLink and JImage tools shared helper.
  67  */
  68 public final class TaskHelper {
  69 


  85         public BadArgs showUsage(boolean b) {
  86             showUsage = b;
  87             return this;
  88         }
  89         public final String key;
  90         public final Object[] args;
  91         public boolean showUsage;
  92     }
  93 
  94     public static class Option<T> implements Comparable<T> {
  95         public interface Processing<T> {
  96 
  97             void process(T task, String opt, String arg) throws BadArgs;
  98         }
  99 
 100         final boolean hasArg;
 101         final Processing<T> processing;
 102         final boolean hidden;
 103         final String name;
 104         final String shortname;
 105         final boolean terminalOption;
 106 
 107         public Option(boolean hasArg,
 108                       Processing<T> processing,
 109                       boolean hidden,
 110                       String name,
 111                       String shortname,
 112                       boolean isTerminal)
 113         {
 114             if (!name.startsWith("--")) {
 115                 throw new RuntimeException("option name missing --, " + name);
 116             }
 117             if (!shortname.isEmpty() && !shortname.startsWith("-")) {
 118                 throw new RuntimeException("short name missing -, " + shortname);
 119             }
 120 
 121             this.hasArg = hasArg;
 122             this.processing = processing;
 123             this.hidden = hidden;
 124             this.name = name;
 125             this.shortname = shortname;
 126             this.terminalOption = isTerminal;
 127         }
 128 
 129         public Option(boolean hasArg, Processing<T> processing, String name, String shortname, boolean isTerminal) {
 130             this(hasArg, processing, false, name, shortname, isTerminal);
 131         }
 132 
 133         public Option(boolean hasArg, Processing<T> processing, String name, String shortname) {
 134             this(hasArg, processing, false, name, shortname, false);
 135         }
 136 
 137         public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name) {
 138             this(hasArg, processing, hidden, name, "", false);
 139         }
 140 
 141         public Option(boolean hasArg, Processing<T> processing, String name) {
 142             this(hasArg, processing, false, name, "", false);
 143         }
 144 
 145         public boolean isHidden() {
 146             return hidden;
 147         }
 148 
 149         public boolean isTerminal() {
 150             return terminalOption;
 151         }
 152 
 153         public boolean matches(String opt) {
 154             return opt.equals(name) ||
 155                    opt.equals(shortname) ||
 156                    hasArg && opt.startsWith("--") && opt.startsWith(name + "=");
 157          }
 158 
 159         public boolean ignoreRest() {
 160             return false;
 161         }
 162 
 163         void process(T task, String opt, String arg) throws BadArgs {
 164             processing.process(task, opt, arg);
 165         }
 166 
 167         public String getName() {
 168             return name;
 169         }
 170 
 171         public String resourceName() {
 172             return resourcePrefix() + name.substring(2);


 179         public String resourcePrefix() {
 180             return "main.opt.";
 181         }
 182 
 183         @Override
 184         public int compareTo(Object object) {
 185             if (!(object instanceof Option<?>)) {
 186                 throw new RuntimeException("comparing non-Option");
 187             }
 188 
 189             Option<?> option = (Option<?>)object;
 190 
 191             return name.compareTo(option.name);
 192         }
 193 
 194     }
 195 
 196     private static class PluginOption extends Option<PluginsHelper> {
 197         public PluginOption(boolean hasArg,
 198                 Processing<PluginsHelper> processing, boolean hidden, String name, String shortname) {
 199             super(hasArg, processing, hidden, name, shortname, false);
 200         }
 201 
 202         public PluginOption(boolean hasArg,
 203                 Processing<PluginsHelper> processing, boolean hidden, String name) {
 204             super(hasArg, processing, hidden, name, "", false);
 205         }
 206 
 207         public String resourcePrefix() {
 208             return "plugin.opt.";
 209         }
 210     }
 211 
 212     private final class PluginsHelper {
 213 
 214         private Layer pluginsLayer = Layer.boot();
 215         private final List<Plugin> plugins;
 216         private String lastSorter;
 217         private boolean listPlugins;
 218         private Path existingImage;
 219 
 220         // plugin to args maps. Each plugin may be used more than once in command line.
 221         // Each such occurrence results in a Map of arguments. So, there could be multiple
 222         // args maps per plugin instance.
 223         private final Map<Plugin, List<Map<String, String>>> pluginToMaps = new HashMap<>();
 224         private final List<PluginOption> pluginsOptions = new ArrayList<>();


 498         private boolean hasArgument(String optionName) throws BadArgs {
 499             Option<?> opt = getOption(optionName);
 500             if (opt == null) {
 501                 opt = pluginOptions.getOption(optionName);
 502                 if (opt == null) {
 503                     throw new BadArgs("err.unknown.option", optionName).
 504                             showUsage(true);
 505                 }
 506             }
 507             return opt.hasArg;
 508         }
 509 
 510         public boolean shouldListPlugins() {
 511             return pluginOptions.listPlugins;
 512         }
 513 
 514         private String getPluginsPath(String[] args) throws BadArgs {
 515             return null;
 516         }
 517 
 518         /**
 519          * Handles all options.  This method stops processing the argument
 520          * at the first non-option argument i.e. not starts with `-`, or
 521          * at the first terminal option and returns the remaining arguments,
 522          * if any.
 523          */
 524         public List<String> handleOptions(T task, String[] args) throws BadArgs {













 525             // findbugs warning, copy instead of keeping a reference.
 526             command = Arrays.copyOf(args, args.length);
 527 
 528             // Must extract it prior to do any option analysis.
 529             // Required to interpret custom plugin options.
 530             // Unit tests can call Task multiple time in same JVM.
 531             pluginOptions = new PluginsHelper(null);
 532 

 533             // process options
 534             for (int i = 0; i < args.length; i++) {
 535                 if (args[i].startsWith("-")) {
 536                     String name = args[i];
 537                     PluginOption pluginOption = null;
 538                     Option<T> option = getOption(name);
 539                     if (option == null) {
 540                         pluginOption = pluginOptions.getOption(name);
 541                         if (pluginOption == null) {

 542                             throw new BadArgs("err.unknown.option", name).
 543                                     showUsage(true);
 544                         }
 545                     }
 546                     Option<?> opt = pluginOption == null ? option : pluginOption;
 547                     String param = null;
 548                     if (opt.hasArg) {
 549                         if (name.startsWith("--") && name.indexOf('=') > 0) {
 550                             param = name.substring(name.indexOf('=') + 1,
 551                                     name.length());
 552                         } else if (i + 1 < args.length) {
 553                             param = args[++i];
 554                         }
 555                         if (param == null || param.isEmpty()
 556                                 || (param.length() >= 2 && param.charAt(0) == '-'
 557                                 && param.charAt(1) == '-')) {
 558                             throw new BadArgs("err.missing.arg", name).
 559                                     showUsage(true);
 560                         }
 561                     }
 562                     if (pluginOption != null) {
 563                         pluginOption.process(pluginOptions, name, param);
 564                     } else {
 565                         option.process(task, name, param);
 566                         if (option.isTerminal()) {
 567                             return ++i < args.length
 568                                         ? Stream.of(Arrays.copyOfRange(args, i, args.length))
 569                                                 .collect(Collectors.toList())
 570                                         : Collections.emptyList();
 571 
 572                         }
 573                     }
 574                     if (opt.ignoreRest()) {
 575                         i = args.length;
 576                     }
 577                 } else {
 578                     return Stream.of(Arrays.copyOfRange(args, i, args.length))
 579                                  .collect(Collectors.toList());




 580                 }
 581             }
 582             return Collections.emptyList();
 583         }
 584 
 585         private Option<T> getOption(String name) {
 586             for (Option<T> o : options) {
 587                 if (o.matches(name)) {
 588                     return o;
 589                 }
 590             }
 591             return null;
 592         }
 593 
 594         public void showHelp(String progName) {
 595             log.println(bundleHelper.getMessage("main.usage", progName));
 596             Stream.concat(options.stream(), pluginOptions.mainOptions.stream())
 597                 .filter(option -> !option.isHidden())
 598                 .sorted()
 599                 .forEach(option -> {
 600                      log.println(bundleHelper.getMessage(option.resourceName()));
 601                 });
 602 


< prev index next >