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
332 }
333 } catch (IOException io) {
334 log.println(taskHelper.getMessage("error.prefix") + " " + io.getMessage());
335 if (DEBUG) {
336 io.printStackTrace(log);
337 }
338 }
339 }
340
341 /*
342 * Jlink API entry point.
343 */
344 public static void createImage(JlinkConfiguration config,
345 PluginsConfiguration plugins)
346 throws Exception {
347 Objects.requireNonNull(config);
348 Objects.requireNonNull(config.getOutput());
349 plugins = plugins == null ? new PluginsConfiguration() : plugins;
350
351 // First create the image provider
352 ImageProvider imageProvider =
353 createImageProvider(config,
354 null,
355 IGNORE_SIGNING_DEFAULT,
356 false,
357 null,
358 false,
359 new OptionsValues(),
360 null);
361
362 // Then create the Plugin Stack
363 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins);
364
365 //Ask the stack to proceed;
366 stack.operate(imageProvider);
367 }
368
369 // the token for "all modules on the module path"
370 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
371 private JlinkConfiguration initJlinkConfig() throws BadArgs {
372 // Empty module path not allowed with ALL-MODULE-PATH in --add-modules
373 if (options.addMods.contains(ALL_MODULE_PATH) && options.modulePath.isEmpty()) {
374 throw taskHelper.newBadArgs("err.no.module.path");
375 }
376 ModuleFinder appModuleFinder = newModuleFinder(options.modulePath);
377 ModuleFinder finder = appModuleFinder;
378
379 boolean isLinkFromRuntime = false;
380 if (!appModuleFinder.find("java.base").isPresent()) {
381 // If the application module finder doesn't contain the
382 // java.base module we have one of two cases:
383 // 1. A custom module is being linked into a runtime, but the JDK
384 // modules have not been provided on the module path.
385 // 2. We have a run-time image based link.
386 //
469
470 /*
471 * Creates a ModuleFinder for the given module paths.
472 */
473 public static ModuleFinder newModuleFinder(List<Path> paths) {
474 Runtime.Version version = Runtime.version();
475 Path[] entries = paths.toArray(new Path[0]);
476 return ModulePath.of(version, true, entries);
477 }
478
479 private void createImage(JlinkConfiguration config) throws Exception {
480 if (options.output == null) {
481 throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
482 }
483 if (options.addMods.isEmpty()) {
484 throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
485 .showUsage(true);
486 }
487
488 // First create the image provider
489 ImageHelper imageProvider = createImageProvider(config,
490 options.packagedModulesPath,
491 options.ignoreSigning,
492 options.bindServices,
493 options.endian,
494 options.verbose,
495 options,
496 log);
497
498 // Then create the Plugin Stack
499 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(
500 taskHelper.getPluginsConfig(options.output, options.launchers,
501 imageProvider.targetPlatform));
502
503 //Ask the stack to proceed
504 stack.operate(imageProvider);
505 }
506
507 /**
508 * @return the system module path or null
509 */
510 public static Path getDefaultModulePath() {
511 Path jmods = Paths.get(System.getProperty("java.home"), "jmods");
512 return Files.isDirectory(jmods)? jmods : null;
513 }
514
515 /*
516 * Returns a module finder of the given module finder that limits the
517 * observable modules to those in the transitive closure of the modules
518 * specified in {@code limitMods} plus other modules specified in the
519 * {@code roots} set.
520 */
521 public static ModuleFinder limitFinder(ModuleFinder finder,
522 Set<String> limitMods,
523 Set<String> roots) {
524 // if limitMods is specified then limit the universe
1010 if (!names.isEmpty()) {
1011 log.println(taskHelper.getMessage("warn.provider.notfound",
1012 names.stream().sorted().collect(Collectors.joining(","))));
1013 }
1014
1015 String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header"));
1016 printProviders(log, msg, mrefs, uses);
1017 }
1018 }
1019
1020 private String getSaveOpts() {
1021 StringBuilder sb = new StringBuilder();
1022 sb.append('#').append(new Date()).append("\n");
1023 for (String c : optionsHelper.getInputCommand()) {
1024 sb.append(c).append(" ");
1025 }
1026
1027 return sb.toString();
1028 }
1029
1030 private static record ImageHelper(Set<Archive> archives,
1031 Platform targetPlatform,
1032 Path packagedModulesPath,
1033 boolean generateRuntimeImage) implements ImageProvider {
1034 @Override
1035 public ExecutableImage retrieve(ImagePluginStack stack) throws IOException {
1036 ExecutableImage image = ImageFileCreator.create(archives,
1037 targetPlatform.arch().byteOrder(), stack, generateRuntimeImage);
1038 if (packagedModulesPath != null) {
1039 // copy the packaged modules to the given path
1040 Files.createDirectories(packagedModulesPath);
1041 for (Archive a : archives) {
1042 Path file = a.getPath();
1043 Path dest = packagedModulesPath.resolve(file.getFileName());
1044 Files.copy(file, dest);
1045 }
1046 }
1047 return image;
1048 }
1049 }
1050 }
|
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
332 }
333 } catch (IOException io) {
334 log.println(taskHelper.getMessage("error.prefix") + " " + io.getMessage());
335 if (DEBUG) {
336 io.printStackTrace(log);
337 }
338 }
339 }
340
341 /*
342 * Jlink API entry point.
343 */
344 public static void createImage(JlinkConfiguration config,
345 PluginsConfiguration plugins)
346 throws Exception {
347 Objects.requireNonNull(config);
348 Objects.requireNonNull(config.getOutput());
349 plugins = plugins == null ? new PluginsConfiguration() : plugins;
350
351 // First create the image provider
352 try (ImageHelper imageProvider =
353 createImageProvider(config,
354 null,
355 IGNORE_SIGNING_DEFAULT,
356 false,
357 null,
358 false,
359 new OptionsValues(),
360 null)) {
361
362 // Then create the Plugin Stack
363 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins);
364
365 // Ask the stack to proceed;
366 stack.operate(imageProvider);
367 }
368 }
369
370 // the token for "all modules on the module path"
371 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
372 private JlinkConfiguration initJlinkConfig() throws BadArgs {
373 // Empty module path not allowed with ALL-MODULE-PATH in --add-modules
374 if (options.addMods.contains(ALL_MODULE_PATH) && options.modulePath.isEmpty()) {
375 throw taskHelper.newBadArgs("err.no.module.path");
376 }
377 ModuleFinder appModuleFinder = newModuleFinder(options.modulePath);
378 ModuleFinder finder = appModuleFinder;
379
380 boolean isLinkFromRuntime = false;
381 if (!appModuleFinder.find("java.base").isPresent()) {
382 // If the application module finder doesn't contain the
383 // java.base module we have one of two cases:
384 // 1. A custom module is being linked into a runtime, but the JDK
385 // modules have not been provided on the module path.
386 // 2. We have a run-time image based link.
387 //
470
471 /*
472 * Creates a ModuleFinder for the given module paths.
473 */
474 public static ModuleFinder newModuleFinder(List<Path> paths) {
475 Runtime.Version version = Runtime.version();
476 Path[] entries = paths.toArray(new Path[0]);
477 return ModulePath.of(version, true, entries);
478 }
479
480 private void createImage(JlinkConfiguration config) throws Exception {
481 if (options.output == null) {
482 throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
483 }
484 if (options.addMods.isEmpty()) {
485 throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
486 .showUsage(true);
487 }
488
489 // First create the image provider
490 try (ImageHelper imageProvider = createImageProvider(config,
491 options.packagedModulesPath,
492 options.ignoreSigning,
493 options.bindServices,
494 options.endian,
495 options.verbose,
496 options,
497 log)) {
498 // Then create the Plugin Stack
499 ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(
500 taskHelper.getPluginsConfig(
501 options.output,
502 options.launchers,
503 imageProvider.targetPlatform));
504
505 //Ask the stack to proceed
506 stack.operate(imageProvider);
507 }
508 }
509
510 /**
511 * @return the system module path or null
512 */
513 public static Path getDefaultModulePath() {
514 Path jmods = Paths.get(System.getProperty("java.home"), "jmods");
515 return Files.isDirectory(jmods)? jmods : null;
516 }
517
518 /*
519 * Returns a module finder of the given module finder that limits the
520 * observable modules to those in the transitive closure of the modules
521 * specified in {@code limitMods} plus other modules specified in the
522 * {@code roots} set.
523 */
524 public static ModuleFinder limitFinder(ModuleFinder finder,
525 Set<String> limitMods,
526 Set<String> roots) {
527 // if limitMods is specified then limit the universe
1013 if (!names.isEmpty()) {
1014 log.println(taskHelper.getMessage("warn.provider.notfound",
1015 names.stream().sorted().collect(Collectors.joining(","))));
1016 }
1017
1018 String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header"));
1019 printProviders(log, msg, mrefs, uses);
1020 }
1021 }
1022
1023 private String getSaveOpts() {
1024 StringBuilder sb = new StringBuilder();
1025 sb.append('#').append(new Date()).append("\n");
1026 for (String c : optionsHelper.getInputCommand()) {
1027 sb.append(c).append(" ");
1028 }
1029
1030 return sb.toString();
1031 }
1032
1033 private record ImageHelper(Set<Archive> archives,
1034 Platform targetPlatform,
1035 Path packagedModulesPath,
1036 boolean generateRuntimeImage)
1037 implements ImageProvider, AutoCloseable {
1038 @Override
1039 public ExecutableImage retrieve(ImagePluginStack stack) throws IOException {
1040 ExecutableImage image = ImageFileCreator.create(archives,
1041 targetPlatform.arch().byteOrder(), stack, generateRuntimeImage);
1042 if (packagedModulesPath != null) {
1043 // copy the packaged modules to the given path
1044 Files.createDirectories(packagedModulesPath);
1045 for (Archive a : archives) {
1046 Path file = a.getPath();
1047 Path dest = packagedModulesPath.resolve(file.getFileName());
1048 Files.copy(file, dest);
1049 }
1050 }
1051 return image;
1052 }
1053
1054 @Override
1055 public void close() throws IOException {
1056 List<IOException> thrown = null;
1057 for (Archive archive : archives) {
1058 try {
1059 archive.close();
1060 } catch (IOException ex) {
1061 if (thrown == null) {
1062 thrown = new ArrayList<>();
1063 }
1064 thrown.add(ex);
1065 }
1066 }
1067 if (thrown != null) {
1068 IOException ex = new IOException("Archives could not be closed", thrown.getFirst());
1069 thrown.subList(1, thrown.size()).forEach(ex::addSuppressed);
1070 throw ex;
1071 }
1072 }
1073 }
1074 }
|