57 * The primary entry point, processArguments():
58 * Processes and validates command line arguments, constructing DeployParams.
59 * Validates the DeployParams, and generate the BundleParams.
60 * Generates List of Bundlers from BundleParams valid for this platform.
61 * Executes each Bundler in the list.
62 */
63 public class Arguments {
64 private static final ResourceBundle I18N = ResourceBundle.getBundle(
65 "jdk.jpackage.internal.resources.MainResources");
66
67 private static final String IMAGE_MODE = "image";
68 private static final String INSTALLER_MODE = "installer";
69
70 private static final String FA_EXTENSIONS = "extension";
71 private static final String FA_CONTENT_TYPE = "mime-type";
72 private static final String FA_DESCRIPTION = "description";
73 private static final String FA_ICON = "icon";
74
75 public static final BundlerParamInfo<Boolean> CREATE_IMAGE =
76 new StandardBundlerParam<>(
77 I18N.getString("param.create-image.name"),
78 I18N.getString("param.create-image.description"),
79 IMAGE_MODE,
80 Boolean.class,
81 p -> Boolean.FALSE,
82 (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
83 true : Boolean.valueOf(s));
84
85 public static final BundlerParamInfo<Boolean> CREATE_INSTALLER =
86 new StandardBundlerParam<>(
87 I18N.getString("param.create-installer.name"),
88 I18N.getString("param.create-installer.description"),
89 INSTALLER_MODE,
90 Boolean.class,
91 p -> Boolean.FALSE,
92 (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
93 true : Boolean.valueOf(s));
94
95 // regexp for parsing args (for example, for secondary launchers)
96 private static Pattern pattern = Pattern.compile(
97 "(?:(?:([\"'])(?:\\\\\\1|.)*?(?:\\1|$))|(?:\\\\[\"'\\s]|[^\\s]))++");
98
99 private DeployParams deployParams = null;
100 private BundlerType bundleType = null;
101
102 private int pos = 0;
103 private List<String> argList = null;
104
105 private List<CLIOptions> allOptions = null;
106
107 private ArrayList<String> files = null;
108
109 private String input = null;
110 private String output = null;
111
112 private boolean hasMainJar = false;
113 private boolean hasMainClass = false;
114 private boolean hasMainModule = false;
115 private boolean hasTargetFormat = false;
116 private boolean hasAppImage = false;
117 public boolean userProvidedBuildRoot = false;
118
119 private String buildRoot = null;
120 private String mainJarPath = null;
121
122 private static boolean runtimeInstaller = false;
123
124 private List<jdk.jpackage.internal.Bundler> platformBundlers = null;
125
126 private List<SecondaryLauncherArguments> secondaryLaunchers = null;
127
128 private static Map<String, CLIOptions> argIds = new HashMap<>();
129 private static Map<String, CLIOptions> argShortIds = new HashMap<>();
130
131 {
132 // init maps for parsing arguments
133 EnumSet<CLIOptions> options = EnumSet.allOf(CLIOptions.class);
134
135 options.forEach(option -> {
136 argIds.put(option.getIdWithPrefix(), option);
137 if (option.getShortIdWithPrefix() != null) {
138 argShortIds.put(option.getShortIdWithPrefix(), option);
139 }
140 });
141 }
142
143 public Arguments(String[] args) throws PackagerException {
144 initArgumentList(args);
145 }
146
147 // CLIOptions is public for DeployParamsTest
148 public enum CLIOptions {
149 CREATE_IMAGE(IMAGE_MODE, OptionCategories.MODE, () -> {
150 context().bundleType = BundlerType.IMAGE;
151 context().deployParams.setTargetFormat("image");
152 setOptionValue(IMAGE_MODE, true);
153 }),
154
155 CREATE_INSTALLER(INSTALLER_MODE, OptionCategories.MODE, () -> {
156 setOptionValue(INSTALLER_MODE, true);
157 context().bundleType = BundlerType.INSTALLER;
158 String format = "installer";
159 context().deployParams.setTargetFormat(format);
160 }),
161
162 RUNTIME_INSTALLER("runtime-installer",
163 OptionCategories.PROPERTY, () -> {
164 runtimeInstaller = true;
165 setOptionValue("runtime-installer", true);
166 }),
167
168 INSTALLER_TYPE("installer-type", OptionCategories.PROPERTY, () -> {
169 String type = popArg();
170 if (BundlerType.INSTALLER.equals(context().bundleType)) {
171 context().deployParams.setTargetFormat(type);
172 context().hasTargetFormat = true;
173 }
174 setOptionValue("installer-type", type);
175 }),
176
177 INPUT ("input", "i", OptionCategories.PROPERTY, () -> {
178 context().input = popArg();
179 setOptionValue("input", context().input);
180 }),
181
182 OUTPUT ("output", "o", OptionCategories.PROPERTY, () -> {
183 context().output = popArg();
184 context().deployParams.setOutput(new File(context().output));
185 }),
186
187 DESCRIPTION ("description", "d", OptionCategories.PROPERTY),
188
189 VENDOR ("vendor", OptionCategories.PROPERTY),
190
191 APPCLASS ("main-class", "c", OptionCategories.PROPERTY, () -> {
192 context().hasMainClass = true;
193 setOptionValue("main-class", popArg());
194 }),
195
196 NAME ("name", "n", OptionCategories.PROPERTY),
197
198 IDENTIFIER ("identifier", OptionCategories.PROPERTY),
199
200 VERBOSE ("verbose", OptionCategories.PROPERTY, () -> {
201 setOptionValue("verbose", true);
202 Log.setVerbose(true);
203 }),
204
205 OVERWRITE ("overwrite", OptionCategories.PROPERTY, () -> {
206 setOptionValue("overwrite", true);
207 }),
208
209 RESOURCE_DIR("resource-dir",
210 OptionCategories.PROPERTY, () -> {
211 String resourceDir = popArg();
212 setOptionValue("resource-dir", resourceDir);
213 }),
214
215 FILES ("files", "f", OptionCategories.PROPERTY, () -> {
216 context().files = new ArrayList<>();
217 String files = popArg();
218 context().files.addAll(
219 Arrays.asList(files.split(File.pathSeparator)));
220 }),
221
222 ARGUMENTS ("arguments", "a", OptionCategories.PROPERTY, () -> {
223 List<String> arguments = getArgumentList(popArg());
224 setOptionValue("arguments", arguments);
225 }),
226
227 STRIP_NATIVE_COMMANDS ("strip-native-commands",
228 OptionCategories.PROPERTY, () -> {
229 setOptionValue("strip-native-commands", true);
230 }),
231
232 ICON ("icon", OptionCategories.PROPERTY),
233 CATEGORY ("category", OptionCategories.PROPERTY),
234 COPYRIGHT ("copyright", OptionCategories.PROPERTY),
235
236 LICENSE_FILE ("license-file", OptionCategories.PROPERTY),
237
238 VERSION ("app-version", OptionCategories.PROPERTY),
239
240 JVM_ARGS ("jvm-args", OptionCategories.PROPERTY, () -> {
241 List<String> args = getArgumentList(popArg());
242 args.forEach(a -> setOptionValue("jvm-args", a));
243 }),
244
245 FILE_ASSOCIATIONS ("file-associations",
246 OptionCategories.PROPERTY, () -> {
247 Map<String, ? super Object> args = new HashMap<>();
248
249 // load .properties file
250 Map<String, String> initialMap = getPropertiesFromFile(popArg());
251
262 String desc = initialMap.get(FA_DESCRIPTION);
263 if (desc != null) {
264 args.put(StandardBundlerParam.FA_DESCRIPTION.getID(), desc);
265 }
266
267 String icon = initialMap.get(FA_ICON);
268 if (icon != null) {
269 args.put(StandardBundlerParam.FA_ICON.getID(), icon);
270 }
271
272 ArrayList<Map<String, ? super Object>> associationList =
273 new ArrayList<Map<String, ? super Object>>();
274
275 associationList.add(args);
276
277 // check that we really add _another_ value to the list
278 setOptionValue("file-associations", associationList);
279
280 }),
281
282 SECONDARY_LAUNCHER ("secondary-launcher",
283 OptionCategories.PROPERTY, () -> {
284 context().secondaryLaunchers.add(
285 new SecondaryLauncherArguments(popArg()));
286 }),
287
288 BUILD_ROOT ("build-root", OptionCategories.PROPERTY, () -> {
289 context().buildRoot = popArg();
290 context().userProvidedBuildRoot = true;
291 setOptionValue("build-root", context().buildRoot);
292 }),
293
294 INSTALL_DIR ("install-dir", OptionCategories.PROPERTY),
295
296 PREDEFINED_APP_IMAGE ("app-image", OptionCategories.PROPERTY, ()-> {
297 setOptionValue("app-image", popArg());
298 context().hasAppImage = true;
299 }),
300
301 PREDEFINED_RUNTIME_IMAGE ("runtime-image", OptionCategories.PROPERTY),
302
303 MAIN_JAR ("main-jar", "j", OptionCategories.PROPERTY, () -> {
304 context().mainJarPath = popArg();
305 context().hasMainJar = true;
306 setOptionValue("main-jar", context().mainJarPath);
307 }),
308
309 MODULE ("module", "m", OptionCategories.MODULAR, () -> {
310 context().hasMainModule = true;
311 setOptionValue("module", popArg());
312 }),
313
314 ADD_MODULES ("add-modules", OptionCategories.MODULAR),
315
316 MODULE_PATH ("module-path", "p", OptionCategories.MODULAR),
317
318 MAC_SIGN ("mac-sign", "s", OptionCategories.PLATFORM_MAC, () -> {
319 setOptionValue("mac-sign", true);
320 }),
321
322 MAC_BUNDLE_NAME ("mac-bundle-name", OptionCategories.PLATFORM_MAC),
323
487 MODULAR,
488 PROPERTY,
489 PLATFORM_MAC,
490 PLATFORM_WIN,
491 PLATFORM_LINUX;
492 }
493
494 private void initArgumentList(String[] args) throws PackagerException {
495 argList = new ArrayList<String>(args.length);
496 for (String arg : args) {
497 argList.add(arg);
498 }
499 Log.debug ("\njpackage argument list: \n" + argList + "\n");
500 pos = 0;
501
502 deployParams = new DeployParams();
503 bundleType = BundlerType.NONE;
504
505 allOptions = new ArrayList<>();
506
507 secondaryLaunchers = new ArrayList<>();
508 }
509
510 public boolean processArguments() throws Exception {
511 try {
512
513 // init context of arguments
514 CLIOptions.setContext(this);
515
516 // parse cmd line
517 String arg;
518 CLIOptions option;
519 for (; CLIOptions.hasNextArg(); CLIOptions.nextArg()) {
520 arg = CLIOptions.getArg();
521 if ((option = toCLIOption(arg)) != null) {
522 // found a CLI option
523 allOptions.add(option);
524 option.execute();
525 } else {
526 throw new PackagerException("ERR_InvalidOption", arg);
527 }
536 // try to get main-class from manifest
537 String mainClass = getMainClassFromManifest();
538 if (mainClass != null) {
539 CLIOptions.setOptionValue(
540 CLIOptions.APPCLASS.getId(), mainClass);
541 }
542 }
543
544 // display warning for arguments that are not supported
545 // for current configuration.
546
547 validateArguments();
548
549 addResources(deployParams, input, files);
550
551 deployParams.setBundleType(bundleType);
552
553 List<Map<String, ? super Object>> launchersAsMap =
554 new ArrayList<>();
555
556 for (SecondaryLauncherArguments sl : secondaryLaunchers) {
557 launchersAsMap.add(sl.getLauncherMap());
558 }
559
560 deployParams.addBundleArgument(
561 StandardBundlerParam.SECONDARY_LAUNCHERS.getID(),
562 launchersAsMap);
563
564 // at this point deployParams should be already configured
565
566 deployParams.validate();
567
568 BundleParams bp = deployParams.getBundleParams();
569
570 // validate name(s)
571 ArrayList<String> usedNames = new ArrayList<String>();
572 usedNames.add(bp.getName()); // add main app name
573
574 for (SecondaryLauncherArguments sl : secondaryLaunchers) {
575 Map<String, ? super Object> slMap = sl.getLauncherMap();
576 String slName =
577 (String) slMap.get(Arguments.CLIOptions.NAME.getId());
578 if (slName == null) {
579 throw new PackagerException("ERR_NoSecondaryLauncherName");
580 }
581 // same rules apply to secondary launcher names as app name
582 DeployParams.validateName(slName, false);
583 for (String usedName : usedNames) {
584 if (slName.equals(usedName)) {
585 throw new PackagerException("ERR_NoUniqueName");
586 }
587 }
588 usedNames.add(slName);
589 }
590 if (runtimeInstaller && bp.getName() == null) {
591 throw new PackagerException("ERR_NoJreInstallerName");
592 }
593
594 return generateBundle(bp.getBundleParamsAsMap());
595 } catch (Exception e) {
596 if (Log.isVerbose()) {
597 throw e;
598 } else {
599 Log.error(e.getMessage());
600 if (e.getCause() != null && e.getCause() != e) {
601 Log.error(e.getCause().getMessage());
602 }
603 return false;
604 }
605 }
606 }
607
608 private void validateArguments() {
609 CLIOptions mode = allOptions.get(0);
610 for (CLIOptions option : allOptions) {
611 if(!ValidOptions.checkIfSupported(mode, option)) {
612 String key = "warning.unsupported.option";
613 if (ValidOptions.checkIfOtherSupported(mode, option)) {
614 key = "warning.unsupported.mode.option";
615 }
616 Log.info(MessageFormat.format(I18N.getString(key),
617 option.getId(), mode));
618 }
619 }
620 }
621
622 private List<jdk.jpackage.internal.Bundler> getPlatformBundlers() {
623
624 if (platformBundlers != null) {
625 return platformBundlers;
626 }
627
628 platformBundlers = new ArrayList<>();
629 for (jdk.jpackage.internal.Bundler bundler :
630 Bundlers.createBundlersInstance().getBundlers(
631 bundleType.toString())) {
632 if (hasTargetFormat && deployParams.getTargetFormat() != null &&
633 !deployParams.getTargetFormat().equalsIgnoreCase(
634 bundler.getID())) {
635 continue;
636 }
637 if (bundler.supported(runtimeInstaller)) {
638 platformBundlers.add(bundler);
639 }
640 }
641
642 return platformBundlers;
643 }
644
645 private boolean generateBundle(Map<String,? super Object> params)
646 throws PackagerException {
647
648 boolean bundleCreated = false;
649
650 // the build-root needs to be fetched from the params early,
651 // to prevent each copy of the params (such as may be used for
652 // secondary launchers) from generating a separate build-root when
653 // the default is used (the default is a new temp directory)
654 // The bundler.cleanup() below would not otherwise be able to
655 // clean these extra (and unneeded) temp directories.
656 StandardBundlerParam.BUILD_ROOT.fetchFrom(params);
657
658 for (jdk.jpackage.internal.Bundler bundler : getPlatformBundlers()) {
659 Map<String, ? super Object> localParams = new HashMap<>(params);
660 try {
661 if (bundler.validate(localParams)) {
662 File result =
663 bundler.execute(localParams, deployParams.outdir);
664 if (!userProvidedBuildRoot) {
665 bundler.cleanup(localParams);
666 }
667 if (result == null) {
668 throw new PackagerException("MSG_BundlerFailed",
669 bundler.getID(), bundler.getName());
670 }
671 bundleCreated = true; // at least one bundle was created
672 }
673 } catch (UnsupportedPlatformException e) {
674 throw new PackagerException(e,
675 "MSG_BundlerPlatformException",
676 bundler.getName());
677 } catch (ConfigException e) {
678 Log.debug(e);
|
57 * The primary entry point, processArguments():
58 * Processes and validates command line arguments, constructing DeployParams.
59 * Validates the DeployParams, and generate the BundleParams.
60 * Generates List of Bundlers from BundleParams valid for this platform.
61 * Executes each Bundler in the list.
62 */
63 public class Arguments {
64 private static final ResourceBundle I18N = ResourceBundle.getBundle(
65 "jdk.jpackage.internal.resources.MainResources");
66
67 private static final String IMAGE_MODE = "image";
68 private static final String INSTALLER_MODE = "installer";
69
70 private static final String FA_EXTENSIONS = "extension";
71 private static final String FA_CONTENT_TYPE = "mime-type";
72 private static final String FA_DESCRIPTION = "description";
73 private static final String FA_ICON = "icon";
74
75 public static final BundlerParamInfo<Boolean> CREATE_IMAGE =
76 new StandardBundlerParam<>(
77 IMAGE_MODE,
78 Boolean.class,
79 p -> Boolean.FALSE,
80 (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
81 true : Boolean.valueOf(s));
82
83 public static final BundlerParamInfo<Boolean> CREATE_INSTALLER =
84 new StandardBundlerParam<>(
85 INSTALLER_MODE,
86 Boolean.class,
87 p -> Boolean.FALSE,
88 (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
89 true : Boolean.valueOf(s));
90
91 // regexp for parsing args (for example, for additional launchers)
92 private static Pattern pattern = Pattern.compile(
93 "(?:(?:([\"'])(?:\\\\\\1|.)*?(?:\\1|$))|(?:\\\\[\"'\\s]|[^\\s]))++");
94
95 private DeployParams deployParams = null;
96 private BundlerType bundleType = null;
97
98 private int pos = 0;
99 private List<String> argList = null;
100
101 private List<CLIOptions> allOptions = null;
102
103 private ArrayList<String> files = null;
104
105 private String input = null;
106 private String output = null;
107
108 private boolean hasMainJar = false;
109 private boolean hasMainClass = false;
110 private boolean hasMainModule = false;
111 private boolean hasTargetFormat = false;
112 private boolean hasAppImage = false;
113 public boolean userProvidedBuildRoot = false;
114
115 private String buildRoot = null;
116 private String mainJarPath = null;
117
118 private static boolean runtimeInstaller = false;
119
120 private List<jdk.jpackage.internal.Bundler> platformBundlers = null;
121
122 private List<AddLauncherArguments> addLaunchers = null;
123
124 private static Map<String, CLIOptions> argIds = new HashMap<>();
125 private static Map<String, CLIOptions> argShortIds = new HashMap<>();
126
127 {
128 // init maps for parsing arguments
129 EnumSet<CLIOptions> options = EnumSet.allOf(CLIOptions.class);
130
131 options.forEach(option -> {
132 argIds.put(option.getIdWithPrefix(), option);
133 if (option.getShortIdWithPrefix() != null) {
134 argShortIds.put(option.getShortIdWithPrefix(), option);
135 }
136 });
137 }
138
139 public Arguments(String[] args) throws PackagerException {
140 initArgumentList(args);
141 }
142
143 // CLIOptions is public for DeployParamsTest
144 public enum CLIOptions {
145 CREATE_IMAGE(IMAGE_MODE, OptionCategories.MODE, () -> {
146 context().bundleType = BundlerType.IMAGE;
147 context().deployParams.setTargetFormat("image");
148 setOptionValue(IMAGE_MODE, true);
149 }),
150
151 CREATE_INSTALLER(INSTALLER_MODE, OptionCategories.MODE, () -> {
152 setOptionValue(INSTALLER_MODE, true);
153 context().bundleType = BundlerType.INSTALLER;
154 String format = "installer";
155 context().deployParams.setTargetFormat(format);
156 }),
157
158 INSTALLER_TYPE("installer-type", OptionCategories.PROPERTY, () -> {
159 String type = popArg();
160 if (BundlerType.INSTALLER.equals(context().bundleType)) {
161 context().deployParams.setTargetFormat(type);
162 context().hasTargetFormat = true;
163 }
164 setOptionValue("installer-type", type);
165 }),
166
167 INPUT ("input", "i", OptionCategories.PROPERTY, () -> {
168 context().input = popArg();
169 setOptionValue("input", context().input);
170 }),
171
172 OUTPUT ("output", "o", OptionCategories.PROPERTY, () -> {
173 context().output = popArg();
174 context().deployParams.setOutput(new File(context().output));
175 }),
176
177 DESCRIPTION ("description", "d", OptionCategories.PROPERTY),
178
179 VENDOR ("vendor", OptionCategories.PROPERTY),
180
181 APPCLASS ("main-class", OptionCategories.PROPERTY, () -> {
182 context().hasMainClass = true;
183 setOptionValue("main-class", popArg());
184 }),
185
186 NAME ("name", "n", OptionCategories.PROPERTY),
187
188 IDENTIFIER ("identifier", OptionCategories.PROPERTY),
189
190 VERBOSE ("verbose", OptionCategories.PROPERTY, () -> {
191 setOptionValue("verbose", true);
192 Log.setVerbose(true);
193 }),
194
195 RESOURCE_DIR("resource-dir",
196 OptionCategories.PROPERTY, () -> {
197 String resourceDir = popArg();
198 setOptionValue("resource-dir", resourceDir);
199 }),
200
201 FILES ("files", "f", OptionCategories.PROPERTY, () -> {
202 context().files = new ArrayList<>();
203 String files = popArg();
204 context().files.addAll(
205 Arrays.asList(files.split(File.pathSeparator)));
206 }),
207
208 ARGUMENTS ("arguments", OptionCategories.PROPERTY, () -> {
209 List<String> arguments = getArgumentList(popArg());
210 setOptionValue("arguments", arguments);
211 }),
212
213 ICON ("icon", OptionCategories.PROPERTY),
214 CATEGORY ("category", OptionCategories.PROPERTY),
215 COPYRIGHT ("copyright", OptionCategories.PROPERTY),
216
217 LICENSE_FILE ("license-file", OptionCategories.PROPERTY),
218
219 VERSION ("app-version", OptionCategories.PROPERTY),
220
221 JVM_ARGS ("jvm-args", OptionCategories.PROPERTY, () -> {
222 List<String> args = getArgumentList(popArg());
223 args.forEach(a -> setOptionValue("jvm-args", a));
224 }),
225
226 FILE_ASSOCIATIONS ("file-associations",
227 OptionCategories.PROPERTY, () -> {
228 Map<String, ? super Object> args = new HashMap<>();
229
230 // load .properties file
231 Map<String, String> initialMap = getPropertiesFromFile(popArg());
232
243 String desc = initialMap.get(FA_DESCRIPTION);
244 if (desc != null) {
245 args.put(StandardBundlerParam.FA_DESCRIPTION.getID(), desc);
246 }
247
248 String icon = initialMap.get(FA_ICON);
249 if (icon != null) {
250 args.put(StandardBundlerParam.FA_ICON.getID(), icon);
251 }
252
253 ArrayList<Map<String, ? super Object>> associationList =
254 new ArrayList<Map<String, ? super Object>>();
255
256 associationList.add(args);
257
258 // check that we really add _another_ value to the list
259 setOptionValue("file-associations", associationList);
260
261 }),
262
263 ADD_LAUNCHER ("add-launcher",
264 OptionCategories.PROPERTY, () -> {
265 context().addLaunchers.add(
266 new AddLauncherArguments(popArg()));
267 }),
268
269 TEMP_ROOT ("temp-root", OptionCategories.PROPERTY, () -> {
270 context().buildRoot = popArg();
271 context().userProvidedBuildRoot = true;
272 setOptionValue("temp-root", context().buildRoot);
273 }),
274
275 INSTALL_DIR ("install-dir", OptionCategories.PROPERTY),
276
277 PREDEFINED_APP_IMAGE ("app-image", OptionCategories.PROPERTY, ()-> {
278 setOptionValue("app-image", popArg());
279 context().hasAppImage = true;
280 }),
281
282 PREDEFINED_RUNTIME_IMAGE ("runtime-image", OptionCategories.PROPERTY),
283
284 MAIN_JAR ("main-jar", OptionCategories.PROPERTY, () -> {
285 context().mainJarPath = popArg();
286 context().hasMainJar = true;
287 setOptionValue("main-jar", context().mainJarPath);
288 }),
289
290 MODULE ("module", "m", OptionCategories.MODULAR, () -> {
291 context().hasMainModule = true;
292 setOptionValue("module", popArg());
293 }),
294
295 ADD_MODULES ("add-modules", OptionCategories.MODULAR),
296
297 MODULE_PATH ("module-path", "p", OptionCategories.MODULAR),
298
299 MAC_SIGN ("mac-sign", "s", OptionCategories.PLATFORM_MAC, () -> {
300 setOptionValue("mac-sign", true);
301 }),
302
303 MAC_BUNDLE_NAME ("mac-bundle-name", OptionCategories.PLATFORM_MAC),
304
468 MODULAR,
469 PROPERTY,
470 PLATFORM_MAC,
471 PLATFORM_WIN,
472 PLATFORM_LINUX;
473 }
474
475 private void initArgumentList(String[] args) throws PackagerException {
476 argList = new ArrayList<String>(args.length);
477 for (String arg : args) {
478 argList.add(arg);
479 }
480 Log.debug ("\njpackage argument list: \n" + argList + "\n");
481 pos = 0;
482
483 deployParams = new DeployParams();
484 bundleType = BundlerType.NONE;
485
486 allOptions = new ArrayList<>();
487
488 addLaunchers = new ArrayList<>();
489 }
490
491 public boolean processArguments() throws Exception {
492 try {
493
494 // init context of arguments
495 CLIOptions.setContext(this);
496
497 // parse cmd line
498 String arg;
499 CLIOptions option;
500 for (; CLIOptions.hasNextArg(); CLIOptions.nextArg()) {
501 arg = CLIOptions.getArg();
502 if ((option = toCLIOption(arg)) != null) {
503 // found a CLI option
504 allOptions.add(option);
505 option.execute();
506 } else {
507 throw new PackagerException("ERR_InvalidOption", arg);
508 }
517 // try to get main-class from manifest
518 String mainClass = getMainClassFromManifest();
519 if (mainClass != null) {
520 CLIOptions.setOptionValue(
521 CLIOptions.APPCLASS.getId(), mainClass);
522 }
523 }
524
525 // display warning for arguments that are not supported
526 // for current configuration.
527
528 validateArguments();
529
530 addResources(deployParams, input, files);
531
532 deployParams.setBundleType(bundleType);
533
534 List<Map<String, ? super Object>> launchersAsMap =
535 new ArrayList<>();
536
537 for (AddLauncherArguments sl : addLaunchers) {
538 launchersAsMap.add(sl.getLauncherMap());
539 }
540
541 deployParams.addBundleArgument(
542 StandardBundlerParam.ADD_LAUNCHERS.getID(),
543 launchersAsMap);
544
545 // at this point deployParams should be already configured
546
547 deployParams.validate();
548
549 BundleParams bp = deployParams.getBundleParams();
550
551 // validate name(s)
552 ArrayList<String> usedNames = new ArrayList<String>();
553 usedNames.add(bp.getName()); // add main app name
554
555 for (AddLauncherArguments sl : addLaunchers) {
556 Map<String, ? super Object> slMap = sl.getLauncherMap();
557 String slName =
558 (String) slMap.get(Arguments.CLIOptions.NAME.getId());
559 if (slName == null) {
560 throw new PackagerException("ERR_NoAddLauncherName");
561 }
562 // same rules apply to additional launcher names as app name
563 DeployParams.validateName(slName, false);
564 for (String usedName : usedNames) {
565 if (slName.equals(usedName)) {
566 throw new PackagerException("ERR_NoUniqueName");
567 }
568 }
569 usedNames.add(slName);
570 }
571 if (runtimeInstaller && bp.getName() == null) {
572 throw new PackagerException("ERR_NoJreInstallerName");
573 }
574
575 return generateBundle(bp.getBundleParamsAsMap());
576 } catch (Exception e) {
577 if (Log.isVerbose()) {
578 throw e;
579 } else {
580 Log.error(e.getMessage());
581 if (e.getCause() != null && e.getCause() != e) {
582 Log.error(e.getCause().getMessage());
583 }
584 return false;
585 }
586 }
587 }
588
589 private void validateArguments() throws PackagerException {
590 CLIOptions mode = allOptions.get(0);
591 boolean imageOnly = (mode == CLIOptions.CREATE_IMAGE);
592 boolean hasAppImage = allOptions.contains(
593 CLIOptions.PREDEFINED_APP_IMAGE);
594 boolean hasRuntime = allOptions.contains(
595 CLIOptions.PREDEFINED_RUNTIME_IMAGE);
596 boolean installerOnly = !imageOnly && hasAppImage;
597 boolean runtimeInstall = !imageOnly && hasRuntime && !hasAppImage &&
598 !hasMainModule && !hasMainJar;
599
600 for (CLIOptions option : allOptions) {
601 if (!ValidOptions.checkIfSupported(option)) {
602 // includes option valid only on different platform
603 throw new PackagerException("ERR_UnsupportedOption",
604 option.getIdWithPrefix());
605 }
606 if (imageOnly) {
607 if (!ValidOptions.checkIfImageSupported(option)) {
608 throw new PackagerException("ERR_NotImageOption",
609 option.getIdWithPrefix());
610 }
611 } else if (installerOnly || runtimeInstall) {
612 if (!ValidOptions.checkIfInstallerSupported(option)) {
613 String key = runtimeInstaller ?
614 "ERR_NoInstallerEntryPoint" : "ERR_NotInstallerOption";
615 throw new PackagerException(key, option.getIdWithPrefix());
616 }
617 }
618 }
619 if (installerOnly && hasRuntime) {
620 // note --runtime-image is only for image or runtime installer.
621 throw new PackagerException("ERR_NotInstallerOption",
622 CLIOptions.PREDEFINED_RUNTIME_IMAGE.getIdWithPrefix());
623 }
624 if (hasMainJar && hasMainModule) {
625 throw new PackagerException("ERR_BothMainJarAndModule");
626 }
627 if (imageOnly && !hasMainJar && !hasMainModule) {
628 throw new PackagerException("ERR_NoEntryPoint");
629 }
630 }
631
632 private List<jdk.jpackage.internal.Bundler> getPlatformBundlers() {
633
634 if (platformBundlers != null) {
635 return platformBundlers;
636 }
637
638 platformBundlers = new ArrayList<>();
639 for (jdk.jpackage.internal.Bundler bundler :
640 Bundlers.createBundlersInstance().getBundlers(
641 bundleType.toString())) {
642 if (hasTargetFormat && deployParams.getTargetFormat() != null &&
643 !deployParams.getTargetFormat().equalsIgnoreCase(
644 bundler.getID())) {
645 continue;
646 }
647 if (bundler.supported(runtimeInstaller)) {
648 platformBundlers.add(bundler);
649 }
650 }
651
652 return platformBundlers;
653 }
654
655 private boolean generateBundle(Map<String,? super Object> params)
656 throws PackagerException {
657
658 boolean bundleCreated = false;
659
660 // the temp-root needs to be fetched from the params early,
661 // to prevent each copy of the params (such as may be used for
662 // additional launchers) from generating a separate temp-root when
663 // the default is used (the default is a new temp directory)
664 // The bundler.cleanup() below would not otherwise be able to
665 // clean these extra (and unneeded) temp directories.
666 StandardBundlerParam.TEMP_ROOT.fetchFrom(params);
667 List<jdk.jpackage.internal.Bundler> bundlers = getPlatformBundlers();
668 if (bundlers.isEmpty()) {
669 throw new PackagerException("ERR_InvalidInstallerType",
670 deployParams.getTargetFormat());
671 }
672 for (jdk.jpackage.internal.Bundler bundler : bundlers) {
673 Map<String, ? super Object> localParams = new HashMap<>(params);
674 try {
675 if (bundler.validate(localParams)) {
676 File result =
677 bundler.execute(localParams, deployParams.outdir);
678 if (!userProvidedBuildRoot) {
679 bundler.cleanup(localParams);
680 }
681 if (result == null) {
682 throw new PackagerException("MSG_BundlerFailed",
683 bundler.getID(), bundler.getName());
684 }
685 bundleCreated = true; // at least one bundle was created
686 }
687 } catch (UnsupportedPlatformException e) {
688 throw new PackagerException(e,
689 "MSG_BundlerPlatformException",
690 bundler.getName());
691 } catch (ConfigException e) {
692 Log.debug(e);
|