1 /*
2 * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
356 }
357 } catch (IOException io) {
358 log.println(taskHelper.getMessage("error.prefix") + " " + io.getMessage());
359 if (DEBUG) {
360 io.printStackTrace(log);
361 }
362 }
363 }
364
365 /*
366 * Jlink API entry point.
367 */
368 public static void createImage(JlinkConfiguration config,
369 PluginsConfiguration plugins)
370 throws Exception {
371 Objects.requireNonNull(config);
372 Objects.requireNonNull(config.getOutput());
373 plugins = plugins == null ? new PluginsConfiguration() : plugins;
374
375 // First create the image provider
376 ImageProvider imageProvider =
377 createImageProvider(config,
378 null,
379 IGNORE_SIGNING_DEFAULT,
380 false,
381 null,
382 false,
383 new OptionsValues(),
384 null);
385
386 // Then create the Plugin Stack
387 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins);
388
389 //Ask the stack to proceed;
390 stack.operate(imageProvider);
391 }
392
393 // the token for "all modules on the module path"
394 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
395 private JlinkConfiguration initJlinkConfig() throws BadArgs {
396 // Empty module path not allowed with ALL-MODULE-PATH in --add-modules
397 if (options.addMods.contains(ALL_MODULE_PATH) && options.modulePath.isEmpty()) {
398 throw taskHelper.newBadArgs("err.no.module.path");
399 }
400 ModuleFinder appModuleFinder = newModuleFinder(options.modulePath);
401 ModuleFinder finder = appModuleFinder;
402
403 boolean isLinkFromRuntime = false;
404 if (!appModuleFinder.find("java.base").isPresent()) {
405 // If the application module finder doesn't contain the
406 // java.base module we have one of two cases:
407 // 1. A custom module is being linked into a runtime, but the JDK
408 // modules have not been provided on the module path.
409 // 2. We have a run-time image based link.
410 //
494
495 /*
496 * Creates a ModuleFinder for the given module paths.
497 */
498 public static ModuleFinder newModuleFinder(List<Path> paths) {
499 Runtime.Version version = Runtime.version();
500 Path[] entries = paths.toArray(new Path[0]);
501 return ModulePath.of(version, true, entries);
502 }
503
504 private void createImage(JlinkConfiguration config) throws Exception {
505 if (options.output == null) {
506 throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
507 }
508 if (options.addMods.isEmpty()) {
509 throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
510 .showUsage(true);
511 }
512
513 // First create the image provider
514 ImageHelper imageProvider = createImageProvider(config,
515 options.packagedModulesPath,
516 options.ignoreSigning,
517 options.bindServices,
518 options.endian,
519 options.verbose,
520 options,
521 log);
522
523 // Then create the Plugin Stack
524 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(
525 taskHelper.getPluginsConfig(options.output, options.launchers,
526 imageProvider.targetPlatform));
527
528 //Ask the stack to proceed
529 stack.operate(imageProvider);
530 }
531
532 /**
533 * @return the system module path or null
534 */
535 public static Path getDefaultModulePath() {
536 Path jmods = Paths.get(System.getProperty("java.home"), "jmods");
537 return Files.isDirectory(jmods)? jmods : null;
538 }
539
540 /*
541 * Returns a module finder of the given module finder that limits the
542 * observable modules to those in the transitive closure of the modules
543 * specified in {@code limitMods} plus other modules specified in the
544 * {@code roots} set.
545 */
546 public static ModuleFinder limitFinder(ModuleFinder finder,
547 Set<String> limitMods,
548 Set<String> roots) {
549 // if limitMods is specified then limit the universe
1037 if (!names.isEmpty()) {
1038 log.println(taskHelper.getMessage("warn.provider.notfound",
1039 names.stream().sorted().collect(Collectors.joining(","))));
1040 }
1041
1042 String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header"));
1043 printProviders(log, msg, mrefs, uses);
1044 }
1045 }
1046
1047 private String getSaveOpts() {
1048 StringBuilder sb = new StringBuilder();
1049 sb.append('#').append(new Date()).append("\n");
1050 for (String c : optionsHelper.getInputCommand()) {
1051 sb.append(c).append(" ");
1052 }
1053
1054 return sb.toString();
1055 }
1056
1057 private static record ImageHelper(Set<Archive> archives,
1058 Platform targetPlatform,
1059 Path packagedModulesPath,
1060 boolean generateRuntimeImage) implements ImageProvider {
1061 @Override
1062 public ExecutableImage retrieve(ImagePluginStack stack) throws IOException {
1063 ExecutableImage image = ImageFileCreator.create(archives,
1064 targetPlatform.arch().byteOrder(), stack, generateRuntimeImage);
1065 if (packagedModulesPath != null) {
1066 // copy the packaged modules to the given path
1067 Files.createDirectories(packagedModulesPath);
1068 for (Archive a : archives) {
1069 Path file = a.getPath();
1070 Path dest = packagedModulesPath.resolve(file.getFileName());
1071 Files.copy(file, dest);
1072 }
1073 }
1074 return image;
1075 }
1076 }
1077 }
|
1 /*
2 * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
356 }
357 } catch (IOException io) {
358 log.println(taskHelper.getMessage("error.prefix") + " " + io.getMessage());
359 if (DEBUG) {
360 io.printStackTrace(log);
361 }
362 }
363 }
364
365 /*
366 * Jlink API entry point.
367 */
368 public static void createImage(JlinkConfiguration config,
369 PluginsConfiguration plugins)
370 throws Exception {
371 Objects.requireNonNull(config);
372 Objects.requireNonNull(config.getOutput());
373 plugins = plugins == null ? new PluginsConfiguration() : plugins;
374
375 // First create the image provider
376 try (ImageHelper imageProvider =
377 createImageProvider(config,
378 null,
379 IGNORE_SIGNING_DEFAULT,
380 false,
381 null,
382 false,
383 new OptionsValues(),
384 null)) {
385
386 // Then create the Plugin Stack
387 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins);
388
389 // Ask the stack to proceed;
390 stack.operate(imageProvider);
391 }
392 }
393
394 // the token for "all modules on the module path"
395 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
396 private JlinkConfiguration initJlinkConfig() throws BadArgs {
397 // Empty module path not allowed with ALL-MODULE-PATH in --add-modules
398 if (options.addMods.contains(ALL_MODULE_PATH) && options.modulePath.isEmpty()) {
399 throw taskHelper.newBadArgs("err.no.module.path");
400 }
401 ModuleFinder appModuleFinder = newModuleFinder(options.modulePath);
402 ModuleFinder finder = appModuleFinder;
403
404 boolean isLinkFromRuntime = false;
405 if (!appModuleFinder.find("java.base").isPresent()) {
406 // If the application module finder doesn't contain the
407 // java.base module we have one of two cases:
408 // 1. A custom module is being linked into a runtime, but the JDK
409 // modules have not been provided on the module path.
410 // 2. We have a run-time image based link.
411 //
495
496 /*
497 * Creates a ModuleFinder for the given module paths.
498 */
499 public static ModuleFinder newModuleFinder(List<Path> paths) {
500 Runtime.Version version = Runtime.version();
501 Path[] entries = paths.toArray(new Path[0]);
502 return ModulePath.of(version, true, entries);
503 }
504
505 private void createImage(JlinkConfiguration config) throws Exception {
506 if (options.output == null) {
507 throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
508 }
509 if (options.addMods.isEmpty()) {
510 throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
511 .showUsage(true);
512 }
513
514 // First create the image provider
515 try (ImageHelper imageProvider = createImageProvider(config,
516 options.packagedModulesPath,
517 options.ignoreSigning,
518 options.bindServices,
519 options.endian,
520 options.verbose,
521 options,
522 log)) {
523 // Then create the Plugin Stack
524 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(
525 taskHelper.getPluginsConfig(
526 options.output,
527 options.launchers,
528 imageProvider.targetPlatform));
529
530 //Ask the stack to proceed
531 stack.operate(imageProvider);
532 }
533 }
534
535 /**
536 * @return the system module path or null
537 */
538 public static Path getDefaultModulePath() {
539 Path jmods = Paths.get(System.getProperty("java.home"), "jmods");
540 return Files.isDirectory(jmods)? jmods : null;
541 }
542
543 /*
544 * Returns a module finder of the given module finder that limits the
545 * observable modules to those in the transitive closure of the modules
546 * specified in {@code limitMods} plus other modules specified in the
547 * {@code roots} set.
548 */
549 public static ModuleFinder limitFinder(ModuleFinder finder,
550 Set<String> limitMods,
551 Set<String> roots) {
552 // if limitMods is specified then limit the universe
1040 if (!names.isEmpty()) {
1041 log.println(taskHelper.getMessage("warn.provider.notfound",
1042 names.stream().sorted().collect(Collectors.joining(","))));
1043 }
1044
1045 String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header"));
1046 printProviders(log, msg, mrefs, uses);
1047 }
1048 }
1049
1050 private String getSaveOpts() {
1051 StringBuilder sb = new StringBuilder();
1052 sb.append('#').append(new Date()).append("\n");
1053 for (String c : optionsHelper.getInputCommand()) {
1054 sb.append(c).append(" ");
1055 }
1056
1057 return sb.toString();
1058 }
1059
1060 private record ImageHelper(Set<Archive> archives,
1061 Platform targetPlatform,
1062 Path packagedModulesPath,
1063 boolean generateRuntimeImage)
1064 implements ImageProvider, AutoCloseable {
1065 @Override
1066 public ExecutableImage retrieve(ImagePluginStack stack) throws IOException {
1067 ExecutableImage image = ImageFileCreator.create(archives,
1068 targetPlatform.arch().byteOrder(), stack, generateRuntimeImage);
1069 if (packagedModulesPath != null) {
1070 // copy the packaged modules to the given path
1071 Files.createDirectories(packagedModulesPath);
1072 for (Archive a : archives) {
1073 Path file = a.getPath();
1074 Path dest = packagedModulesPath.resolve(file.getFileName());
1075 Files.copy(file, dest);
1076 }
1077 }
1078 return image;
1079 }
1080
1081 @Override
1082 public void close() throws IOException {
1083 List<IOException> thrown = null;
1084 for (Archive archive : archives) {
1085 try {
1086 archive.close();
1087 } catch (IOException ex) {
1088 if (thrown == null) {
1089 thrown = new ArrayList<>();
1090 }
1091 thrown.add(ex);
1092 }
1093 }
1094 if (thrown != null) {
1095 IOException ex = new IOException("Archives could not be closed", thrown.getFirst());
1096 thrown.subList(1, thrown.size()).forEach(ex::addSuppressed);
1097 throw ex;
1098 }
1099 }
1100 }
1101 }
|