src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java
branchJDK-8200758-branch
changeset 57256 d7c27451f759
parent 57255 f686bda3b831
child 57291 f2d429260ad4
equal deleted inserted replaced
57255:f686bda3b831 57256:d7c27451f759
    56 import java.util.jar.Manifest;
    56 import java.util.jar.Manifest;
    57 import java.util.regex.Pattern;
    57 import java.util.regex.Pattern;
    58 import java.util.stream.Collectors;
    58 import java.util.stream.Collectors;
    59 
    59 
    60 /**
    60 /**
    61  * StandardBundlerParams
    61  * StandardBundlerParam
    62  *
    62  *
    63  * A parameter to a bundler.
    63  * A parameter to a bundler.
    64  *
    64  *
    65  * Also contains static definitions of all of the common bundler parameters.
    65  * Also contains static definitions of all of the common bundler parameters.
    66  * (additional platform specific and mode specific bundler parameters
    66  * (additional platform specific and mode specific bundler parameters
    72 
    72 
    73     private static final ResourceBundle I18N = ResourceBundle.getBundle(
    73     private static final ResourceBundle I18N = ResourceBundle.getBundle(
    74             "jdk.jpackage.internal.resources.MainResources");
    74             "jdk.jpackage.internal.resources.MainResources");
    75     private static final String JAVABASEJMOD = "java.base.jmod";
    75     private static final String JAVABASEJMOD = "java.base.jmod";
    76 
    76 
    77     StandardBundlerParam(String name, String description, String id,
    77     StandardBundlerParam(String id, Class<T> valueType,
    78             Class<T> valueType,
       
    79             Function<Map<String, ? super Object>, T> defaultValueFunction,
    78             Function<Map<String, ? super Object>, T> defaultValueFunction,
    80             BiFunction<String, Map<String, ? super Object>, T> stringConverter)
    79             BiFunction<String, Map<String, ? super Object>, T> stringConverter)
    81     {
    80     {
    82         this.name = name;
       
    83         this.description = description;
       
    84         this.id = id;
    81         this.id = id;
    85         this.valueType = valueType;
    82         this.valueType = valueType;
    86         this.defaultValueFunction = defaultValueFunction;
    83         this.defaultValueFunction = defaultValueFunction;
    87         this.stringConverter = stringConverter;
    84         this.stringConverter = stringConverter;
    88     }
    85     }
    89 
    86 
    90     static final StandardBundlerParam<RelativeFileSet> APP_RESOURCES =
    87     static final StandardBundlerParam<RelativeFileSet> APP_RESOURCES =
    91             new StandardBundlerParam<>(
    88             new StandardBundlerParam<>(
    92                     I18N.getString("param.app-resources.name"),
       
    93                     I18N.getString("param.app-resource.description"),
       
    94                     BundleParams.PARAM_APP_RESOURCES,
    89                     BundleParams.PARAM_APP_RESOURCES,
    95                     RelativeFileSet.class,
    90                     RelativeFileSet.class,
    96                     null, // no default.  Required parameter
    91                     null, // no default.  Required parameter
    97                     null  // no string translation,
    92                     null  // no string translation,
    98                           // tool must provide complex type
    93                           // tool must provide complex type
   100 
    95 
   101     @SuppressWarnings("unchecked")
    96     @SuppressWarnings("unchecked")
   102     static final
    97     static final
   103             StandardBundlerParam<List<RelativeFileSet>> APP_RESOURCES_LIST =
    98             StandardBundlerParam<List<RelativeFileSet>> APP_RESOURCES_LIST =
   104             new StandardBundlerParam<>(
    99             new StandardBundlerParam<>(
   105                     I18N.getString("param.app-resources-list.name"),
       
   106                     I18N.getString("param.app-resource-list.description"),
       
   107                     BundleParams.PARAM_APP_RESOURCES + "List",
   100                     BundleParams.PARAM_APP_RESOURCES + "List",
   108                     (Class<List<RelativeFileSet>>) (Object) List.class,
   101                     (Class<List<RelativeFileSet>>) (Object) List.class,
   109                     // Default is appResources, as a single item list
   102                     // Default is appResources, as a single item list
   110                     p -> new ArrayList<>(Collections.singletonList(
   103                     p -> new ArrayList<>(Collections.singletonList(
   111                             APP_RESOURCES.fetchFrom(p))),
   104                             APP_RESOURCES.fetchFrom(p))),
   112                     StandardBundlerParam::createAppResourcesListFromString
   105                     StandardBundlerParam::createAppResourcesListFromString
   113             );
   106             );
   114 
   107 
   115     static final StandardBundlerParam<String> SOURCE_DIR =
   108     static final StandardBundlerParam<String> SOURCE_DIR =
   116             new StandardBundlerParam<>(
   109             new StandardBundlerParam<>(
   117                     I18N.getString("param.source-dir.name"),
       
   118                     I18N.getString("param.source-dir.description"),
       
   119                     Arguments.CLIOptions.INPUT.getId(),
   110                     Arguments.CLIOptions.INPUT.getId(),
   120                     String.class,
   111                     String.class,
   121                     p -> null,
   112                     p -> null,
   122                     (s, p) -> {
   113                     (s, p) -> {
   123                         String value = String.valueOf(s);
   114                         String value = String.valueOf(s);
   133 
   124 
   134     // note that each bundler is likely to replace this one with
   125     // note that each bundler is likely to replace this one with
   135     // their own converter
   126     // their own converter
   136     static final StandardBundlerParam<RelativeFileSet> MAIN_JAR =
   127     static final StandardBundlerParam<RelativeFileSet> MAIN_JAR =
   137             new StandardBundlerParam<>(
   128             new StandardBundlerParam<>(
   138                     I18N.getString("param.main-jar.name"),
       
   139                     I18N.getString("param.main-jar.description"),
       
   140                     Arguments.CLIOptions.MAIN_JAR.getId(),
   129                     Arguments.CLIOptions.MAIN_JAR.getId(),
   141                     RelativeFileSet.class,
   130                     RelativeFileSet.class,
   142                     params -> {
   131                     params -> {
   143                         extractMainClassInfoFromAppResources(params);
   132                         extractMainClassInfoFromAppResources(params);
   144                         return (RelativeFileSet) params.get("mainJar");
   133                         return (RelativeFileSet) params.get("mainJar");
   147             );
   136             );
   148 
   137 
   149     // TODO: test CLASSPATH jar manifest Attributet
   138     // TODO: test CLASSPATH jar manifest Attributet
   150     static final StandardBundlerParam<String> CLASSPATH =
   139     static final StandardBundlerParam<String> CLASSPATH =
   151             new StandardBundlerParam<>(
   140             new StandardBundlerParam<>(
   152                     I18N.getString("param.classpath.name"),
       
   153                     I18N.getString("param.classpath.description"),
       
   154                     "classpath",
   141                     "classpath",
   155                     String.class,
   142                     String.class,
   156                     params -> {
   143                     params -> {
   157                         extractMainClassInfoFromAppResources(params);
   144                         extractMainClassInfoFromAppResources(params);
   158                         String cp = (String) params.get("classpath");
   145                         String cp = (String) params.get("classpath");
   159                         return cp == null ? "" : cp;
   146                         return cp == null ? "" : cp;
   160                     },
   147                     },
   161                     (s, p) -> s.replace(File.pathSeparator, " ")
   148                     (s, p) -> s.replace(File.pathSeparator, " ")
   162             );
   149             );
   163 
   150 
   164     static final StandardBundlerParam<Boolean> RUNTIME_INSTALLER  =
       
   165             new StandardBundlerParam<>(
       
   166                     "",
       
   167                     "",
       
   168                     Arguments.CLIOptions.RUNTIME_INSTALLER.getId(),
       
   169                     Boolean.class,
       
   170                     params -> false,
       
   171                     // valueOf(null) is false, and we actually do want null
       
   172                     (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
       
   173                             true : Boolean.valueOf(s)
       
   174             );
       
   175 
       
   176 
       
   177     static final StandardBundlerParam<String> MAIN_CLASS =
   151     static final StandardBundlerParam<String> MAIN_CLASS =
   178             new StandardBundlerParam<>(
   152             new StandardBundlerParam<>(
   179                     I18N.getString("param.main-class.name"),
       
   180                     I18N.getString("param.main-class.description"),
       
   181                     Arguments.CLIOptions.APPCLASS.getId(),
   153                     Arguments.CLIOptions.APPCLASS.getId(),
   182                     String.class,
   154                     String.class,
   183                     params -> {
   155                     params -> {
   184                         if (RUNTIME_INSTALLER.fetchFrom(params)) {
   156                         if (isRuntimeInstaller(params)) {
   185                             return null;
   157                             return null;
   186                         }
   158                         }
   187                         extractMainClassInfoFromAppResources(params);
   159                         extractMainClassInfoFromAppResources(params);
   188                         String s = (String) params.get(
   160                         String s = (String) params.get(
   189                                 BundleParams.PARAM_APPLICATION_CLASS);
   161                                 BundleParams.PARAM_APPLICATION_CLASS);
   195                     (s, p) -> s
   167                     (s, p) -> s
   196             );
   168             );
   197 
   169 
   198     static final StandardBundlerParam<String> APP_NAME =
   170     static final StandardBundlerParam<String> APP_NAME =
   199             new StandardBundlerParam<>(
   171             new StandardBundlerParam<>(
   200                     I18N.getString("param.app-name.name"),
       
   201                     I18N.getString("param.app-name.description"),
       
   202                     Arguments.CLIOptions.NAME.getId(),
   172                     Arguments.CLIOptions.NAME.getId(),
   203                     String.class,
   173                     String.class,
   204                     params -> {
   174                     params -> {
   205                         String s = MAIN_CLASS.fetchFrom(params);
   175                         String s = MAIN_CLASS.fetchFrom(params);
   206                         if (s == null) return null;
   176                         if (s == null) return null;
   214                     (s, p) -> s
   184                     (s, p) -> s
   215             );
   185             );
   216 
   186 
   217     static final StandardBundlerParam<File> ICON =
   187     static final StandardBundlerParam<File> ICON =
   218             new StandardBundlerParam<>(
   188             new StandardBundlerParam<>(
   219                     I18N.getString("param.icon-file.name"),
       
   220                     I18N.getString("param.icon-file.description"),
       
   221                     Arguments.CLIOptions.ICON.getId(),
   189                     Arguments.CLIOptions.ICON.getId(),
   222                     File.class,
   190                     File.class,
   223                     params -> null,
   191                     params -> null,
   224                     (s, p) -> new File(s)
   192                     (s, p) -> new File(s)
   225             );
   193             );
   226 
   194 
   227     static final StandardBundlerParam<String> VENDOR =
   195     static final StandardBundlerParam<String> VENDOR =
   228             new StandardBundlerParam<>(
   196             new StandardBundlerParam<>(
   229                     I18N.getString("param.vendor.name"),
       
   230                     I18N.getString("param.vendor.description"),
       
   231                     Arguments.CLIOptions.VENDOR.getId(),
   197                     Arguments.CLIOptions.VENDOR.getId(),
   232                     String.class,
   198                     String.class,
   233                     params -> I18N.getString("param.vendor.default"),
   199                     params -> I18N.getString("param.vendor.default"),
   234                     (s, p) -> s
   200                     (s, p) -> s
   235             );
   201             );
   236 
   202 
   237     static final StandardBundlerParam<String> CATEGORY =
       
   238             new StandardBundlerParam<>(
       
   239                     I18N.getString("param.category.name"),
       
   240                     I18N.getString("param.category.description"),
       
   241                    Arguments.CLIOptions.CATEGORY.getId(),
       
   242                     String.class,
       
   243                     params -> I18N.getString("param.category.default"),
       
   244                     (s, p) -> s
       
   245             );
       
   246 
       
   247     static final StandardBundlerParam<String> DESCRIPTION =
   203     static final StandardBundlerParam<String> DESCRIPTION =
   248             new StandardBundlerParam<>(
   204             new StandardBundlerParam<>(
   249                     I18N.getString("param.description.name"),
       
   250                     I18N.getString("param.description.description"),
       
   251                     Arguments.CLIOptions.DESCRIPTION.getId(),
   205                     Arguments.CLIOptions.DESCRIPTION.getId(),
   252                     String.class,
   206                     String.class,
   253                     params -> params.containsKey(APP_NAME.getID())
   207                     params -> params.containsKey(APP_NAME.getID())
   254                             ? APP_NAME.fetchFrom(params)
   208                             ? APP_NAME.fetchFrom(params)
   255                             : I18N.getString("param.description.default"),
   209                             : I18N.getString("param.description.default"),
   256                     (s, p) -> s
   210                     (s, p) -> s
   257             );
   211             );
   258 
   212 
   259     static final StandardBundlerParam<String> COPYRIGHT =
   213     static final StandardBundlerParam<String> COPYRIGHT =
   260             new StandardBundlerParam<>(
   214             new StandardBundlerParam<>(
   261                     I18N.getString("param.copyright.name"),
       
   262                     I18N.getString("param.copyright.description"),
       
   263                     Arguments.CLIOptions.COPYRIGHT.getId(),
   215                     Arguments.CLIOptions.COPYRIGHT.getId(),
   264                     String.class,
   216                     String.class,
   265                     params -> MessageFormat.format(I18N.getString(
   217                     params -> MessageFormat.format(I18N.getString(
   266                             "param.copyright.default"), new Date()),
   218                             "param.copyright.default"), new Date()),
   267                     (s, p) -> s
   219                     (s, p) -> s
   268             );
   220             );
   269 
   221 
   270     @SuppressWarnings("unchecked")
   222     @SuppressWarnings("unchecked")
   271     static final StandardBundlerParam<List<String>> ARGUMENTS =
   223     static final StandardBundlerParam<List<String>> ARGUMENTS =
   272             new StandardBundlerParam<>(
   224             new StandardBundlerParam<>(
   273                     I18N.getString("param.arguments.name"),
       
   274                     I18N.getString("param.arguments.description"),
       
   275                     Arguments.CLIOptions.ARGUMENTS.getId(),
   225                     Arguments.CLIOptions.ARGUMENTS.getId(),
   276                     (Class<List<String>>) (Object) List.class,
   226                     (Class<List<String>>) (Object) List.class,
   277                     params -> Collections.emptyList(),
   227                     params -> Collections.emptyList(),
   278                     (s, p) -> splitStringWithEscapes(s)
   228                     (s, p) -> splitStringWithEscapes(s)
   279             );
   229             );
   280 
   230 
   281     @SuppressWarnings("unchecked")
   231     @SuppressWarnings("unchecked")
   282     static final StandardBundlerParam<List<String>> JVM_OPTIONS =
   232     static final StandardBundlerParam<List<String>> JVM_OPTIONS =
   283             new StandardBundlerParam<>(
   233             new StandardBundlerParam<>(
   284                     I18N.getString("param.jvm-options.name"),
       
   285                     I18N.getString("param.jvm-options.description"),
       
   286                     Arguments.CLIOptions.JVM_ARGS.getId(),
   234                     Arguments.CLIOptions.JVM_ARGS.getId(),
   287                     (Class<List<String>>) (Object) List.class,
   235                     (Class<List<String>>) (Object) List.class,
   288                     params -> Collections.emptyList(),
   236                     params -> Collections.emptyList(),
   289                     (s, p) -> Arrays.asList(s.split("\n\n"))
   237                     (s, p) -> Arrays.asList(s.split("\n\n"))
   290             );
   238             );
   291 
   239 
   292     // note that each bundler is likely to replace this one with
   240     // note that each bundler is likely to replace this one with
   293     // their own converter
   241     // their own converter
   294     static final StandardBundlerParam<String> VERSION =
   242     static final StandardBundlerParam<String> VERSION =
   295             new StandardBundlerParam<>(
   243             new StandardBundlerParam<>(
   296                     I18N.getString("param.version.name"),
       
   297                     I18N.getString("param.version.description"),
       
   298                     Arguments.CLIOptions.VERSION.getId(),
   244                     Arguments.CLIOptions.VERSION.getId(),
   299                     String.class,
   245                     String.class,
   300                     params -> I18N.getString("param.version.default"),
   246                     params -> I18N.getString("param.version.default"),
   301                     (s, p) -> s
   247                     (s, p) -> s
   302             );
   248             );
   303 
   249 
   304     @SuppressWarnings("unchecked")
   250     @SuppressWarnings("unchecked")
   305     public static final StandardBundlerParam<String> LICENSE_FILE =
   251     public static final StandardBundlerParam<String> LICENSE_FILE =
   306             new StandardBundlerParam<>(
   252             new StandardBundlerParam<>(
   307                     I18N.getString("param.license-file.name"),
       
   308                     I18N.getString("param.license-file.description"),
       
   309                     Arguments.CLIOptions.LICENSE_FILE.getId(),
   253                     Arguments.CLIOptions.LICENSE_FILE.getId(),
   310                     String.class,
   254                     String.class,
   311                     params -> null,
   255                     params -> null,
   312                     (s, p) -> s
   256                     (s, p) -> s
   313             );
   257             );
   314 
   258 
   315     static final StandardBundlerParam<File> BUILD_ROOT =
   259     static final StandardBundlerParam<File> TEMP_ROOT =
   316             new StandardBundlerParam<>(
   260             new StandardBundlerParam<>(
   317                     I18N.getString("param.build-root.name"),
   261                     Arguments.CLIOptions.TEMP_ROOT.getId(),
   318                     I18N.getString("param.build-root.description"),
       
   319                     Arguments.CLIOptions.BUILD_ROOT.getId(),
       
   320                     File.class,
   262                     File.class,
   321                     params -> {
   263                     params -> {
   322                         try {
   264                         try {
   323                             return Files.createTempDirectory(
   265                             return Files.createTempDirectory(
   324                                     "jdk.jpackage").toFile();
   266                                     "jdk.jpackage").toFile();
   329                     (s, p) -> new File(s)
   271                     (s, p) -> new File(s)
   330             );
   272             );
   331 
   273 
   332     public static final StandardBundlerParam<File> CONFIG_ROOT =
   274     public static final StandardBundlerParam<File> CONFIG_ROOT =
   333             new StandardBundlerParam<>(
   275             new StandardBundlerParam<>(
   334                 I18N.getString("param.config-root.name"),
       
   335                 I18N.getString("param.config-root.description"),
       
   336                 "configRoot",
   276                 "configRoot",
   337                 File.class,
   277                 File.class,
   338                 params -> {
   278                 params -> {
   339                     File root =
   279                     File root =
   340                             new File(BUILD_ROOT.fetchFrom(params), "config");
   280                             new File(TEMP_ROOT.fetchFrom(params), "config");
   341                     root.mkdirs();
   281                     root.mkdirs();
   342                     return root;
   282                     return root;
   343                 },
   283                 },
   344                 (s, p) -> null
   284                 (s, p) -> null
   345             );
   285             );
   346 
   286 
   347     static final StandardBundlerParam<String> IDENTIFIER =
   287     static final StandardBundlerParam<String> IDENTIFIER =
   348             new StandardBundlerParam<>(
   288             new StandardBundlerParam<>(
   349                     I18N.getString("param.identifier.name"),
       
   350                     I18N.getString("param.identifier.description"),
       
   351                     Arguments.CLIOptions.IDENTIFIER.getId(),
   289                     Arguments.CLIOptions.IDENTIFIER.getId(),
   352                     String.class,
   290                     String.class,
   353                     params -> {
   291                     params -> {
   354                         String s = MAIN_CLASS.fetchFrom(params);
   292                         String s = MAIN_CLASS.fetchFrom(params);
   355                         if (s == null) return null;
   293                         if (s == null) return null;
   363                     (s, p) -> s
   301                     (s, p) -> s
   364             );
   302             );
   365 
   303 
   366     static final StandardBundlerParam<String> PREFERENCES_ID =
   304     static final StandardBundlerParam<String> PREFERENCES_ID =
   367             new StandardBundlerParam<>(
   305             new StandardBundlerParam<>(
   368                     I18N.getString("param.preferences-id.name"),
       
   369                     I18N.getString("param.preferences-id.description"),
       
   370                     "preferencesID",
   306                     "preferencesID",
   371                     String.class,
   307                     String.class,
   372                     p -> Optional.ofNullable(IDENTIFIER.fetchFrom(p)).
   308                     p -> Optional.ofNullable(IDENTIFIER.fetchFrom(p)).
   373                              orElse("").replace('.', '/'),
   309                              orElse("").replace('.', '/'),
   374                     (s, p) -> s
   310                     (s, p) -> s
   375             );
   311             );
   376 
   312 
   377     static final StandardBundlerParam<Boolean> VERBOSE  =
   313     static final StandardBundlerParam<Boolean> VERBOSE  =
   378             new StandardBundlerParam<>(
   314             new StandardBundlerParam<>(
   379                     I18N.getString("param.verbose.name"),
       
   380                     I18N.getString("param.verbose.description"),
       
   381                     Arguments.CLIOptions.VERBOSE.getId(),
   315                     Arguments.CLIOptions.VERBOSE.getId(),
   382                     Boolean.class,
   316                     Boolean.class,
   383                     params -> false,
   317                     params -> false,
   384                     // valueOf(null) is false, and we actually do want null
   318                     // valueOf(null) is false, and we actually do want null
   385                     (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
   319                     (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
   386                             true : Boolean.valueOf(s)
   320                             true : Boolean.valueOf(s)
   387             );
   321             );
   388 
   322 
   389     static final StandardBundlerParam<Boolean> OVERWRITE  =
       
   390             new StandardBundlerParam<>(
       
   391                     I18N.getString("param.overwrite.name"),
       
   392                     I18N.getString("param.overwrite.description"),
       
   393                     Arguments.CLIOptions.OVERWRITE.getId(),
       
   394                     Boolean.class,
       
   395                     params -> false,
       
   396                     // valueOf(null) is false, and we actually do want null
       
   397                     (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
       
   398                             true : Boolean.valueOf(s)
       
   399             );
       
   400 
       
   401     static final StandardBundlerParam<File> RESOURCE_DIR =
   323     static final StandardBundlerParam<File> RESOURCE_DIR =
   402             new StandardBundlerParam<>(
   324             new StandardBundlerParam<>(
   403                     I18N.getString("param.resource-dir.name"),
       
   404                     I18N.getString("param.resource-dir.description"),
       
   405                     Arguments.CLIOptions.RESOURCE_DIR.getId(),
   325                     Arguments.CLIOptions.RESOURCE_DIR.getId(),
   406                     File.class,
   326                     File.class,
   407                     params -> null,
   327                     params -> null,
   408                     (s, p) -> new File(s)
   328                     (s, p) -> new File(s)
   409             );
   329             );
   410 
   330 
   411     static final BundlerParamInfo<String> INSTALL_DIR =
   331     static final BundlerParamInfo<String> INSTALL_DIR =
   412             new StandardBundlerParam<>(
   332             new StandardBundlerParam<>(
   413                     I18N.getString("param.install-dir.name"),
       
   414                     I18N.getString("param.install-dir.description"),
       
   415                     Arguments.CLIOptions.INSTALL_DIR.getId(),
   333                     Arguments.CLIOptions.INSTALL_DIR.getId(),
   416                     String.class,
   334                     String.class,
   417                      params -> null,
   335                      params -> null,
   418                     (s, p) -> s
   336                     (s, p) -> s
   419     );
   337     );
   420 
   338 
   421     static final StandardBundlerParam<File> PREDEFINED_APP_IMAGE =
   339     static final StandardBundlerParam<File> PREDEFINED_APP_IMAGE =
   422             new StandardBundlerParam<>(
   340             new StandardBundlerParam<>(
   423             I18N.getString("param.predefined-app-image.name"),
       
   424             I18N.getString("param.predefined-app-image.description"),
       
   425             Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId(),
   341             Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId(),
   426             File.class,
   342             File.class,
   427             params -> null,
   343             params -> null,
   428             (s, p) -> new File(s));
   344             (s, p) -> new File(s));
   429 
   345 
   430     static final StandardBundlerParam<File> PREDEFINED_RUNTIME_IMAGE =
   346     static final StandardBundlerParam<File> PREDEFINED_RUNTIME_IMAGE =
   431             new StandardBundlerParam<>(
   347             new StandardBundlerParam<>(
   432             I18N.getString("param.predefined-runtime-image.name"),
       
   433             I18N.getString("param.predefined-runtime-image.description"),
       
   434             Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(),
   348             Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(),
   435             File.class,
   349             File.class,
   436             params -> null,
   350             params -> null,
   437             (s, p) -> new File(s));
   351             (s, p) -> new File(s));
   438 
   352 
   439     @SuppressWarnings("unchecked")
   353     @SuppressWarnings("unchecked")
   440     static final StandardBundlerParam<List<Map<String, ? super Object>>> SECONDARY_LAUNCHERS =
   354     static final StandardBundlerParam<List<Map<String, ? super Object>>> ADD_LAUNCHERS =
   441             new StandardBundlerParam<>(
   355             new StandardBundlerParam<>(
   442                     I18N.getString("param.secondary-launchers.name"),
   356                     Arguments.CLIOptions.ADD_LAUNCHER.getId(),
   443                     I18N.getString("param.secondary-launchers.description"),
       
   444                     Arguments.CLIOptions.SECONDARY_LAUNCHER.getId(),
       
   445                     (Class<List<Map<String, ? super Object>>>) (Object)
   357                     (Class<List<Map<String, ? super Object>>>) (Object)
   446                             List.class,
   358                             List.class,
   447                     params -> new ArrayList<>(1),
   359                     params -> new ArrayList<>(1),
   448                     // valueOf(null) is false, and we actually do want null
   360                     // valueOf(null) is false, and we actually do want null
   449                     (s, p) -> null
   361                     (s, p) -> null
   451 
   363 
   452     @SuppressWarnings("unchecked")
   364     @SuppressWarnings("unchecked")
   453     static final StandardBundlerParam
   365     static final StandardBundlerParam
   454             <List<Map<String, ? super Object>>> FILE_ASSOCIATIONS =
   366             <List<Map<String, ? super Object>>> FILE_ASSOCIATIONS =
   455             new StandardBundlerParam<>(
   367             new StandardBundlerParam<>(
   456                     I18N.getString("param.file-associations.name"),
       
   457                     I18N.getString("param.file-associations.description"),
       
   458                     Arguments.CLIOptions.FILE_ASSOCIATIONS.getId(),
   368                     Arguments.CLIOptions.FILE_ASSOCIATIONS.getId(),
   459                     (Class<List<Map<String, ? super Object>>>) (Object)
   369                     (Class<List<Map<String, ? super Object>>>) (Object)
   460                             List.class,
   370                             List.class,
   461                     params -> new ArrayList<>(1),
   371                     params -> new ArrayList<>(1),
   462                     // valueOf(null) is false, and we actually do want null
   372                     // valueOf(null) is false, and we actually do want null
   464             );
   374             );
   465 
   375 
   466     @SuppressWarnings("unchecked")
   376     @SuppressWarnings("unchecked")
   467     static final StandardBundlerParam<List<String>> FA_EXTENSIONS =
   377     static final StandardBundlerParam<List<String>> FA_EXTENSIONS =
   468             new StandardBundlerParam<>(
   378             new StandardBundlerParam<>(
   469                     I18N.getString("param.fa-extension.name"),
       
   470                     I18N.getString("param.fa-extension.description"),
       
   471                     "fileAssociation.extension",
   379                     "fileAssociation.extension",
   472                     (Class<List<String>>) (Object) List.class,
   380                     (Class<List<String>>) (Object) List.class,
   473                     params -> null, // null means not matched to an extension
   381                     params -> null, // null means not matched to an extension
   474                     (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
   382                     (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
   475             );
   383             );
   476 
   384 
   477     @SuppressWarnings("unchecked")
   385     @SuppressWarnings("unchecked")
   478     static final StandardBundlerParam<List<String>> FA_CONTENT_TYPE =
   386     static final StandardBundlerParam<List<String>> FA_CONTENT_TYPE =
   479             new StandardBundlerParam<>(
   387             new StandardBundlerParam<>(
   480                     I18N.getString("param.fa-content-type.name"),
       
   481                     I18N.getString("param.fa-content-type.description"),
       
   482                     "fileAssociation.contentType",
   388                     "fileAssociation.contentType",
   483                     (Class<List<String>>) (Object) List.class,
   389                     (Class<List<String>>) (Object) List.class,
   484                     params -> null,
   390                     params -> null,
   485                             // null means not matched to a content/mime type
   391                             // null means not matched to a content/mime type
   486                     (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
   392                     (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
   487             );
   393             );
   488 
   394 
   489     static final StandardBundlerParam<String> FA_DESCRIPTION =
   395     static final StandardBundlerParam<String> FA_DESCRIPTION =
   490             new StandardBundlerParam<>(
   396             new StandardBundlerParam<>(
   491                     I18N.getString("param.fa-description.name"),
       
   492                     I18N.getString("param.fa-description.description"),
       
   493                     "fileAssociation.description",
   397                     "fileAssociation.description",
   494                     String.class,
   398                     String.class,
   495                     params -> APP_NAME.fetchFrom(params) + " File",
   399                     params -> APP_NAME.fetchFrom(params) + " File",
   496                     null
   400                     null
   497             );
   401             );
   498 
   402 
   499     static final StandardBundlerParam<File> FA_ICON =
   403     static final StandardBundlerParam<File> FA_ICON =
   500             new StandardBundlerParam<>(
   404             new StandardBundlerParam<>(
   501                     I18N.getString("param.fa-icon.name"),
       
   502                     I18N.getString("param.fa-icon.description"),
       
   503                     "fileAssociation.icon",
   405                     "fileAssociation.icon",
   504                     File.class,
   406                     File.class,
   505                     ICON::fetchFrom,
   407                     ICON::fetchFrom,
   506                     (s, p) -> new File(s)
   408                     (s, p) -> new File(s)
   507             );
   409             );
   508 
   410 
   509     @SuppressWarnings("unchecked")
   411     @SuppressWarnings("unchecked")
   510     static final BundlerParamInfo<List<Path>> MODULE_PATH =
   412     static final BundlerParamInfo<List<Path>> MODULE_PATH =
   511             new StandardBundlerParam<>(
   413             new StandardBundlerParam<>(
   512                     I18N.getString("param.module-path.name"),
       
   513                     I18N.getString("param.module-path.description"),
       
   514                     Arguments.CLIOptions.MODULE_PATH.getId(),
   414                     Arguments.CLIOptions.MODULE_PATH.getId(),
   515                     (Class<List<Path>>) (Object)List.class,
   415                     (Class<List<Path>>) (Object)List.class,
   516                     p -> { return getDefaultModulePath(); },
   416                     p -> { return getDefaultModulePath(); },
   517                     (s, p) -> {
   417                     (s, p) -> {
   518                         List<Path> modulePath = Arrays.asList(s
   418                         List<Path> modulePath = Arrays.asList(s
   548                         return modulePath;
   448                         return modulePath;
   549                     });
   449                     });
   550 
   450 
   551     static final BundlerParamInfo<String> MODULE =
   451     static final BundlerParamInfo<String> MODULE =
   552             new StandardBundlerParam<>(
   452             new StandardBundlerParam<>(
   553                     I18N.getString("param.main.module.name"),
       
   554                     I18N.getString("param.main.module.description"),
       
   555                     Arguments.CLIOptions.MODULE.getId(),
   453                     Arguments.CLIOptions.MODULE.getId(),
   556                     String.class,
   454                     String.class,
   557                     p -> null,
   455                     p -> null,
   558                     (s, p) -> {
   456                     (s, p) -> {
   559                         return String.valueOf(s);
   457                         return String.valueOf(s);
   560                     });
   458                     });
   561 
   459 
   562     @SuppressWarnings("unchecked")
   460     @SuppressWarnings("unchecked")
   563     static final BundlerParamInfo<Set<String>> ADD_MODULES =
   461     static final BundlerParamInfo<Set<String>> ADD_MODULES =
   564             new StandardBundlerParam<>(
   462             new StandardBundlerParam<>(
   565                     I18N.getString("param.add-modules.name"),
       
   566                     I18N.getString("param.add-modules.description"),
       
   567                     Arguments.CLIOptions.ADD_MODULES.getId(),
   463                     Arguments.CLIOptions.ADD_MODULES.getId(),
   568                     (Class<Set<String>>) (Object) Set.class,
   464                     (Class<Set<String>>) (Object) Set.class,
   569                     p -> new LinkedHashSet<String>(),
   465                     p -> new LinkedHashSet<String>(),
   570                     (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
   466                     (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
   571             );
   467             );
   572 
   468 
   573     @SuppressWarnings("unchecked")
   469     @SuppressWarnings("unchecked")
   574     static final BundlerParamInfo<Set<String>> LIMIT_MODULES =
   470     static final BundlerParamInfo<Set<String>> LIMIT_MODULES =
   575             new StandardBundlerParam<>(
   471             new StandardBundlerParam<>(
   576                     I18N.getString("param.limit-modules.name"),
       
   577                     I18N.getString("param.limit-modules.description"),
       
   578                     "limit-modules",
   472                     "limit-modules",
   579                     (Class<Set<String>>) (Object) Set.class,
   473                     (Class<Set<String>>) (Object) Set.class,
   580                     p -> new LinkedHashSet<String>(),
   474                     p -> new LinkedHashSet<String>(),
   581                     (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
   475                     (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
   582             );
   476             );
   583 
   477 
   584     static final BundlerParamInfo<Boolean> STRIP_NATIVE_COMMANDS =
   478     static boolean isRuntimeInstaller(Map<String, ? super Object> p) {
   585             new StandardBundlerParam<>(
   479         if (p.containsKey(MODULE.getID()) ||
   586                     I18N.getString("param.strip-executables.name"),
   480                 p.containsKey(MAIN_JAR.getID()) ||
   587                     I18N.getString("param.strip-executables.description"),
   481                 p.containsKey(PREDEFINED_APP_IMAGE.getID())) {
   588                     Arguments.CLIOptions.STRIP_NATIVE_COMMANDS.getId(),
   482             return false; // we are building or are given an application
   589                     Boolean.class,
   483         }
   590                     p -> Boolean.FALSE,
   484         // runtime installer requires --runtime-image, if this is false
   591                     (s, p) -> Boolean.valueOf(s)
   485         // here then we should have thrown error validating args.
   592             );
   486         return p.containsKey(PREDEFINED_RUNTIME_IMAGE.getID());
       
   487     }
   593 
   488 
   594     static File getPredefinedAppImage(Map<String, ? super Object> p) {
   489     static File getPredefinedAppImage(Map<String, ? super Object> p) {
   595         File applicationImage = null;
   490         File applicationImage = null;
   596         if (PREDEFINED_APP_IMAGE.fetchFrom(p) != null) {
   491         if (PREDEFINED_APP_IMAGE.fetchFrom(p) != null) {
   597             applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(p);
   492             applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(p);
   648             Map<String, ? super Object> params) {
   543             Map<String, ? super Object> params) {
   649         boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
   544         boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
   650         boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
   545         boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
   651         boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
   546         boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
   652         boolean hasModule = params.containsKey(MODULE.getID());
   547         boolean hasModule = params.containsKey(MODULE.getID());
   653         boolean runtimeInstaller =
       
   654                 params.containsKey(RUNTIME_INSTALLER.getID());
       
   655 
   548 
   656         if (hasMainClass && hasMainJar && hasMainJarClassPath || hasModule ||
   549         if (hasMainClass && hasMainJar && hasMainJarClassPath || hasModule ||
   657                 runtimeInstaller) {
   550                 isRuntimeInstaller(params)) {
   658             return;
   551             return;
   659         }
   552         }
   660 
   553 
   661         // it's a pair.
   554         // it's a pair.
   662         // The [0] is the srcdir [1] is the file relative to sourcedir
   555         // The [0] is the srcdir [1] is the file relative to sourcedir
   736         boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
   629         boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
   737         boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
   630         boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
   738         boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
   631         boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
   739         boolean hasModule = params.containsKey(MODULE.getID());
   632         boolean hasModule = params.containsKey(MODULE.getID());
   740         boolean hasAppImage = params.containsKey(PREDEFINED_APP_IMAGE.getID());
   633         boolean hasAppImage = params.containsKey(PREDEFINED_APP_IMAGE.getID());
   741         boolean runtimeInstaller =
       
   742                 params.containsKey(RUNTIME_INSTALLER.getID());
       
   743 
   634 
   744         if (hasMainClass && hasMainJar && hasMainJarClassPath ||
   635         if (hasMainClass && hasMainJar && hasMainJarClassPath ||
   745                hasModule || runtimeInstaller || hasAppImage) {
   636                hasModule || hasAppImage || isRuntimeInstaller(params)) {
   746             return;
   637             return;
   747         }
   638         }
   748 
   639 
   749         extractMainClassInfoFromAppResources(params);
   640         extractMainClassInfoFromAppResources(params);
   750 
   641 
   762                         I18N.getString("error.no-main-class"),
   653                         I18N.getString("error.no-main-class"),
   763                         I18N.getString("error.no-main-class.advice"));
   654                         I18N.getString("error.no-main-class.advice"));
   764             }
   655             }
   765         }
   656         }
   766     }
   657     }
   767 
       
   768 
   658 
   769     private static List<String> splitStringWithEscapes(String s) {
   659     private static List<String> splitStringWithEscapes(String s) {
   770         List<String> l = new ArrayList<>();
   660         List<String> l = new ArrayList<>();
   771         StringBuilder current = new StringBuilder();
   661         StringBuilder current = new StringBuilder();
   772         boolean quoted = false;
   662         boolean quoted = false;