8236128: Allow jpackage create installers for services
Reviewed-by: almatvee
This commit is contained in:
parent
ef27081fe7
commit
b675c597e3
@ -25,6 +25,6 @@
|
||||
|
||||
COPY += .gif .png .txt .spec .script .prerm .preinst \
|
||||
.postrm .postinst .list .sh .desktop .copyright .control .plist .template \
|
||||
.icns .scpt .wxs .wxl .wxi .ico .bmp .tiff
|
||||
.icns .scpt .wxs .wxl .wxi .ico .bmp .tiff .service
|
||||
|
||||
CLEAN += .properties
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,11 +25,8 @@
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -39,8 +36,8 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.imageio.ImageIO;
|
||||
@ -56,16 +53,19 @@ import static jdk.jpackage.internal.StandardBundlerParam.DESCRIPTION;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.FILE_ASSOCIATIONS;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.ICON;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT;;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT;
|
||||
|
||||
/**
|
||||
* Helper to create files for desktop integration.
|
||||
*/
|
||||
final class DesktopIntegration {
|
||||
final class DesktopIntegration extends ShellCustomAction {
|
||||
|
||||
static final String DESKTOP_COMMANDS_INSTALL = "DESKTOP_COMMANDS_INSTALL";
|
||||
static final String DESKTOP_COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
|
||||
static final String UTILITY_SCRIPTS = "UTILITY_SCRIPTS";
|
||||
private static final String COMMANDS_INSTALL = "DESKTOP_COMMANDS_INSTALL";
|
||||
private static final String COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
|
||||
private static final String SCRIPTS = "DESKTOP_SCRIPTS";
|
||||
|
||||
private static final List<String> REPLACEMENT_STRING_IDS = List.of(
|
||||
COMMANDS_INSTALL, COMMANDS_UNINSTALL, SCRIPTS);
|
||||
|
||||
private DesktopIntegration(PlatformPackage thePackage,
|
||||
Map<String, ? super Object> params,
|
||||
@ -171,21 +171,28 @@ final class DesktopIntegration {
|
||||
}
|
||||
}
|
||||
|
||||
static DesktopIntegration create(PlatformPackage thePackage,
|
||||
static ShellCustomAction create(PlatformPackage thePackage,
|
||||
Map<String, ? super Object> params) throws IOException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
return null;
|
||||
return ShellCustomAction.nop(REPLACEMENT_STRING_IDS);
|
||||
}
|
||||
return new DesktopIntegration(thePackage, params, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
List<String> requiredPackages() {
|
||||
return Stream.of(List.of(this), nestedIntegrations).flatMap(
|
||||
List::stream).map(DesktopIntegration::requiredPackagesSelf).flatMap(
|
||||
List::stream).distinct().toList();
|
||||
}
|
||||
|
||||
Map<String, String> create() throws IOException {
|
||||
@Override
|
||||
protected List<String> replacementStringIds() {
|
||||
return REPLACEMENT_STRING_IDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> createImpl() throws IOException {
|
||||
associations.forEach(assoc -> assoc.data.verify());
|
||||
|
||||
if (iconFile != null) {
|
||||
@ -230,9 +237,9 @@ final class DesktopIntegration {
|
||||
// of the additional launchers and append them to the corresponding
|
||||
// commands of the main launcher.
|
||||
List<String> installShellCmds = new ArrayList<>(Arrays.asList(
|
||||
data.get(DESKTOP_COMMANDS_INSTALL)));
|
||||
data.get(COMMANDS_INSTALL)));
|
||||
List<String> uninstallShellCmds = new ArrayList<>(Arrays.asList(
|
||||
data.get(DESKTOP_COMMANDS_UNINSTALL)));
|
||||
data.get(COMMANDS_UNINSTALL)));
|
||||
for (var integration: nestedIntegrations) {
|
||||
if (!integration.associations.isEmpty()) {
|
||||
needCleanupScripts = true;
|
||||
@ -240,26 +247,16 @@ final class DesktopIntegration {
|
||||
|
||||
Map<String, String> launcherData = integration.create();
|
||||
|
||||
installShellCmds.add(launcherData.get(DESKTOP_COMMANDS_INSTALL));
|
||||
uninstallShellCmds.add(launcherData.get(
|
||||
DESKTOP_COMMANDS_UNINSTALL));
|
||||
installShellCmds.add(launcherData.get(COMMANDS_INSTALL));
|
||||
uninstallShellCmds.add(launcherData.get(COMMANDS_UNINSTALL));
|
||||
}
|
||||
|
||||
data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(
|
||||
installShellCmds));
|
||||
data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(
|
||||
uninstallShellCmds));
|
||||
data.put(COMMANDS_INSTALL, stringifyShellCommands(installShellCmds));
|
||||
data.put(COMMANDS_UNINSTALL, stringifyShellCommands(uninstallShellCmds));
|
||||
|
||||
if (needCleanupScripts) {
|
||||
// Pull in utils.sh scrips library.
|
||||
try (InputStream is = OverridableResource.readDefault("utils.sh");
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader reader = new BufferedReader(isr)) {
|
||||
data.put(UTILITY_SCRIPTS, reader.lines().collect(
|
||||
Collectors.joining(System.lineSeparator())));
|
||||
}
|
||||
} else {
|
||||
data.put(UTILITY_SCRIPTS, "");
|
||||
// Pull in desktop_utils.sh scrips library.
|
||||
data.put(SCRIPTS, stringifyTextFile("desktop_utils.sh"));
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -277,17 +274,12 @@ final class DesktopIntegration {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
|
||||
data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
|
||||
data.put("APPLICATION_ICON",
|
||||
iconFile != null ? iconFile.installPath().toString() : null);
|
||||
data.put("APPLICATION_ICON", Optional.ofNullable(iconFile).map(
|
||||
f -> f.installPath().toString()).orElse(null));
|
||||
data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
|
||||
|
||||
String appLauncher = thePackage.installedApplicationLayout().launchersDirectory().resolve(
|
||||
LinuxAppImageBuilder.getLauncherName(params)).toString();
|
||||
if (Pattern.compile("\\s").matcher(appLauncher).find()) {
|
||||
// Path contains whitespace(s). Enclose in double quotes.
|
||||
appLauncher = "\"" + appLauncher + "\"";
|
||||
}
|
||||
data.put("APPLICATION_LAUNCHER", appLauncher);
|
||||
data.put("APPLICATION_LAUNCHER", Enquoter.forPropertyValues().applyTo(
|
||||
thePackage.installedApplicationLayout().launchersDirectory().resolve(
|
||||
LinuxAppImageBuilder.getLauncherName(params)).toString()));
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -356,13 +348,13 @@ final class DesktopIntegration {
|
||||
cmds.add(registerDesktopFileCmd);
|
||||
cmds.add(registerFileAssociationsCmd);
|
||||
cmds.addAll(registerIconCmds);
|
||||
data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(cmds));
|
||||
data.put(COMMANDS_INSTALL, stringifyShellCommands(cmds));
|
||||
|
||||
cmds.clear();
|
||||
cmds.add(unregisterDesktopFileCmd);
|
||||
cmds.add(unregisterFileAssociationsCmd);
|
||||
cmds.addAll(unregisterIconCmds);
|
||||
data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(cmds));
|
||||
data.put(COMMANDS_UNINSTALL, stringifyShellCommands(cmds));
|
||||
}
|
||||
|
||||
private String registerDesktopFileCmd;
|
||||
@ -385,24 +377,25 @@ final class DesktopIntegration {
|
||||
private class DesktopFile {
|
||||
|
||||
DesktopFile(String fileName) {
|
||||
installPath = thePackage
|
||||
var installPath = thePackage
|
||||
.installedApplicationLayout()
|
||||
.destktopIntegrationDirectory().resolve(fileName);
|
||||
srcPath = thePackage
|
||||
var srcPath = thePackage
|
||||
.sourceApplicationLayout()
|
||||
.destktopIntegrationDirectory().resolve(fileName);
|
||||
|
||||
impl = new InstallableFile(srcPath, installPath);
|
||||
}
|
||||
|
||||
private final Path installPath;
|
||||
private final Path srcPath;
|
||||
|
||||
Path installPath() {
|
||||
return installPath;
|
||||
return impl.installPath();
|
||||
}
|
||||
|
||||
Path srcPath() {
|
||||
return srcPath;
|
||||
return impl.srcPath();
|
||||
}
|
||||
|
||||
private final InstallableFile impl;
|
||||
}
|
||||
|
||||
private void appendFileAssociation(XMLStreamWriter xml,
|
||||
@ -526,15 +519,6 @@ final class DesktopIntegration {
|
||||
return commonIconSize;
|
||||
}
|
||||
|
||||
private static String stringifyShellCommands(String... commands) {
|
||||
return stringifyShellCommands(Arrays.asList(commands));
|
||||
}
|
||||
|
||||
private static String stringifyShellCommands(List<String> commands) {
|
||||
return String.join(System.lineSeparator(), commands.stream().filter(
|
||||
s -> s != null && !s.isEmpty()).toList());
|
||||
}
|
||||
|
||||
private static class LinuxFileAssociation {
|
||||
LinuxFileAssociation(FileAssociation fa) {
|
||||
this.data = fa;
|
||||
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||
|
||||
/**
|
||||
* Helper to install launchers as services using "systemd".
|
||||
*/
|
||||
public final class LinuxLaunchersAsServices extends UnixLaunchersAsServices {
|
||||
|
||||
private LinuxLaunchersAsServices(PlatformPackage thePackage,
|
||||
Map<String, Object> params) throws IOException {
|
||||
super(thePackage, REQUIRED_PACKAGES, params, li -> {
|
||||
return new Launcher(thePackage, li.getName(), params);
|
||||
});
|
||||
}
|
||||
|
||||
static ShellCustomAction create(PlatformPackage thePackage,
|
||||
Map<String, Object> params) throws IOException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
return ShellCustomAction.nop(REPLACEMENT_STRING_IDS);
|
||||
}
|
||||
return new LinuxLaunchersAsServices(thePackage, params);
|
||||
}
|
||||
|
||||
public static Path getServiceUnitFileName(String packageName,
|
||||
String launcherName) {
|
||||
String baseName = launcherName.replaceAll("[\\s]", "_");
|
||||
return Path.of(packageName + "-" + baseName + ".service");
|
||||
}
|
||||
|
||||
private static class Launcher extends UnixLauncherAsService {
|
||||
|
||||
Launcher(PlatformPackage thePackage, String name,
|
||||
Map<String, Object> mainParams) {
|
||||
super(name, mainParams, createResource("unit-template.service",
|
||||
mainParams).setCategory(I18N.getString(
|
||||
"resource.systemd-unit-file")));
|
||||
|
||||
unitFilename = getServiceUnitFileName(thePackage.name(), getName());
|
||||
|
||||
getResource()
|
||||
.setPublicName(unitFilename)
|
||||
.addSubstitutionDataEntry("APPLICATION_LAUNCHER",
|
||||
Enquoter.forPropertyValues().applyTo(
|
||||
thePackage.installedApplicationLayout().launchersDirectory().resolve(
|
||||
getName()).toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
Path descriptorFilePath(Path root) {
|
||||
return root.resolve("lib/systemd/system").resolve(unitFilename);
|
||||
}
|
||||
|
||||
private final Path unitFilename;
|
||||
}
|
||||
|
||||
private final static List<String> REQUIRED_PACKAGES = List.of("systemd",
|
||||
"coreutils" /* /usr/bin/wc */, "grep");
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,12 +38,9 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import static jdk.jpackage.internal.DesktopIntegration.*;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_RUNTIME_IMAGE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.RELEASE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VENDOR;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.DESCRIPTION;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
|
||||
@ -53,6 +50,9 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
LinuxPackageBundler(BundlerParamInfo<String> packageName) {
|
||||
this.packageName = packageName;
|
||||
appImageBundler = new LinuxAppBundler().setDependentTask(true);
|
||||
customActions = List.of(new CustomActionInstance(
|
||||
DesktopIntegration::create), new CustomActionInstance(
|
||||
LinuxLaunchersAsServices::create));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -148,14 +148,14 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
}
|
||||
}
|
||||
|
||||
desktopIntegration = DesktopIntegration.create(thePackage, params);
|
||||
for (var ca : customActions) {
|
||||
ca.init(thePackage, params);
|
||||
}
|
||||
|
||||
Map<String, String> data = createDefaultReplacementData(params);
|
||||
if (desktopIntegration != null) {
|
||||
data.putAll(desktopIntegration.create());
|
||||
} else {
|
||||
Stream.of(DESKTOP_COMMANDS_INSTALL, DESKTOP_COMMANDS_UNINSTALL,
|
||||
UTILITY_SCRIPTS).forEach(v -> data.put(v, ""));
|
||||
|
||||
for (var ca : customActions) {
|
||||
data.putAll(ca.instance.create());
|
||||
}
|
||||
|
||||
data.putAll(createReplacementData(params));
|
||||
@ -182,12 +182,10 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
|
||||
PlatformPackage thePackage = createMetaPackage(params);
|
||||
|
||||
final List<String> xdgUtilsPackage;
|
||||
if (desktopIntegration != null) {
|
||||
xdgUtilsPackage = desktopIntegration.requiredPackages();
|
||||
} else {
|
||||
xdgUtilsPackage = Collections.emptyList();
|
||||
}
|
||||
final List<String> caPackages = customActions.stream()
|
||||
.map(ca -> ca.instance)
|
||||
.map(ShellCustomAction::requiredPackages)
|
||||
.flatMap(List::stream).toList();
|
||||
|
||||
final List<String> neededLibPackages;
|
||||
if (withFindNeededPackages && Files.exists(thePackage.sourceRoot())) {
|
||||
@ -204,7 +202,7 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
|
||||
// Merge all package lists together.
|
||||
// Filter out empty names, sort and remove duplicates.
|
||||
List<String> result = Stream.of(xdgUtilsPackage, neededLibPackages).flatMap(
|
||||
List<String> result = Stream.of(caPackages, neededLibPackages).flatMap(
|
||||
List::stream).filter(Predicate.not(String::isEmpty)).sorted().distinct().toList();
|
||||
|
||||
Log.verbose(String.format("Required packages: %s", result));
|
||||
@ -345,7 +343,23 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
private final BundlerParamInfo<String> packageName;
|
||||
private final Bundler appImageBundler;
|
||||
private boolean withFindNeededPackages;
|
||||
private DesktopIntegration desktopIntegration;
|
||||
private final List<CustomActionInstance> customActions;
|
||||
|
||||
private static final class CustomActionInstance {
|
||||
|
||||
CustomActionInstance(ShellCustomActionFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
void init(PlatformPackage thePackage, Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
instance = factory.create(thePackage, params);
|
||||
Objects.requireNonNull(instance);
|
||||
}
|
||||
|
||||
private final ShellCustomActionFactory factory;
|
||||
ShellCustomAction instance;
|
||||
}
|
||||
|
||||
private static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
|
||||
new StandardBundlerParam<>(
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,7 @@ resource.copyright-file=Copyright file
|
||||
resource.menu-shortcut-descriptor=Menu shortcut descriptor
|
||||
resource.menu-icon=menu icon
|
||||
resource.rpm-spec-file=RPM spec file
|
||||
resource.systemd-unit-file=systemd unit file
|
||||
|
||||
error.tool-not-found.advice=Please install required packages
|
||||
error.tool-old-version.advice=Please install required packages
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,7 @@ resource.copyright-file=\u30B3\u30D4\u30FC\u30E9\u30A4\u30C8\u30FB\u30D5\u30A1\u
|
||||
resource.menu-shortcut-descriptor=\u30E1\u30CB\u30E5\u30FC\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF
|
||||
resource.menu-icon=\u30E1\u30CB\u30E5\u30FC\u30FB\u30A2\u30A4\u30B3\u30F3
|
||||
resource.rpm-spec-file=RPM\u4ED5\u69D8\u30D5\u30A1\u30A4\u30EB
|
||||
resource.systemd-unit-file=systemd unit file
|
||||
|
||||
error.tool-not-found.advice=\u5FC5\u8981\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044
|
||||
error.tool-old-version.advice=\u5FC5\u8981\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,7 @@ resource.copyright-file=\u7248\u6743\u6587\u4EF6
|
||||
resource.menu-shortcut-descriptor=\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\u63CF\u8FF0\u7B26
|
||||
resource.menu-icon=\u83DC\u5355\u56FE\u6807
|
||||
resource.rpm-spec-file=RPM \u89C4\u8303\u6587\u4EF6
|
||||
resource.systemd-unit-file=systemd unit file
|
||||
|
||||
error.tool-not-found.advice=\u8BF7\u5B89\u88C5\u6240\u9700\u7684\u7A0B\u5E8F\u5305
|
||||
error.tool-old-version.advice=\u8BF7\u5B89\u88C5\u6240\u9700\u7684\u7A0B\u5E8F\u5305
|
||||
|
@ -0,0 +1,38 @@
|
||||
#
|
||||
# Register $@ unit files with systemd service.
|
||||
#
|
||||
register_services ()
|
||||
{
|
||||
for unit in "$@"; do
|
||||
systemctl enable --now "$unit"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Unregister $@ unit files with systemd service.
|
||||
#
|
||||
unregister_services ()
|
||||
{
|
||||
for unit in "$@"; do
|
||||
if file_belongs_to_single_package "$unit"; then
|
||||
local unit_name=`basename "$unit"`
|
||||
if systemctl list-units --full -all | grep -q "$unit_name"; then
|
||||
systemctl disable --now "$unit_name"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
file_belongs_to_single_package ()
|
||||
{
|
||||
if [ ! -e "$1" ]; then
|
||||
false
|
||||
elif [ "$package_type" = rpm ]; then
|
||||
test `rpm -q --whatprovides "$1" | wc -l` = 1
|
||||
elif [ "$package_type" = deb ]; then
|
||||
test `dpkg -S "$1" | wc -l` = 1
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
@ -17,9 +17,13 @@ set -e
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
package_type=deb
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
DESKTOP_COMMANDS_INSTALL
|
||||
LAUNCHER_AS_SERVICE_COMMANDS_INSTALL
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
|
@ -13,9 +13,14 @@ set -e
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
package_type=deb
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
if [ -n "$2" ]; then
|
||||
true; LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
|
@ -17,11 +17,14 @@ set -e
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
UTILITY_SCRIPTS
|
||||
package_type=deb
|
||||
DESKTOP_SCRIPTS
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
DESKTOP_COMMANDS_UNINSTALL
|
||||
LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
@ -34,4 +37,3 @@ DESKTOP_COMMANDS_UNINSTALL
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
|
@ -49,12 +49,16 @@ APPLICATION_DESCRIPTION
|
||||
rm -rf %{buildroot}
|
||||
install -d -m 755 %{buildroot}APPLICATION_DIRECTORY
|
||||
cp -r %{_sourcedir}APPLICATION_DIRECTORY/* %{buildroot}APPLICATION_DIRECTORY
|
||||
if [ "$(echo %{_sourcedir}/lib/systemd/system/*.service)" != '%{_sourcedir}/lib/systemd/system/*.service' ]; then
|
||||
install -d -m 755 %{buildroot}/lib/systemd/system
|
||||
cp %{_sourcedir}/lib/systemd/system/*.service %{buildroot}/lib/systemd/system
|
||||
fi
|
||||
%if "xAPPLICATION_LICENSE_FILE" != "x"
|
||||
%define license_install_file %{_defaultlicensedir}/%{name}-%{version}/%{basename:APPLICATION_LICENSE_FILE}
|
||||
install -d -m 755 "%{buildroot}%{dirname:%{license_install_file}}"
|
||||
install -m 644 "APPLICATION_LICENSE_FILE" "%{buildroot}%{license_install_file}"
|
||||
%endif
|
||||
(cd %{buildroot} && find . -type d) | sed -e 's/^\.//' -e '/^$/d' | sort > %{app_filelist}
|
||||
(cd %{buildroot} && find . -path ./lib/systemd -prune -o -type d -print) | sed -e 's/^\.//' -e '/^$/d' | sort > %{app_filelist}
|
||||
{ rpm -ql filesystem || echo %{default_filesystem}; } | sort > %{filesystem_filelist}
|
||||
comm -23 %{app_filelist} %{filesystem_filelist} > %{package_filelist}
|
||||
sed -i -e 's/.*/%dir "&"/' %{package_filelist}
|
||||
@ -69,10 +73,23 @@ sed -i -e 's/.*/%dir "&"/' %{package_filelist}
|
||||
%endif
|
||||
|
||||
%post
|
||||
package_type=rpm
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
DESKTOP_COMMANDS_INSTALL
|
||||
LAUNCHER_AS_SERVICE_COMMANDS_INSTALL
|
||||
|
||||
%pre
|
||||
package_type=rpm
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
if [ "$1" = 2 ]; then
|
||||
true; LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
fi
|
||||
|
||||
%preun
|
||||
UTILITY_SCRIPTS
|
||||
package_type=rpm
|
||||
DESKTOP_SCRIPTS
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
DESKTOP_COMMANDS_UNINSTALL
|
||||
LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
|
||||
%clean
|
||||
|
@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=SERVICE_DESCRIPTION
|
||||
|
||||
[Service]
|
||||
ExecStart=APPLICATION_LAUNCHER
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,7 +33,6 @@ import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
|
||||
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
|
||||
import static jdk.jpackage.internal.MacAppImageBuilder.APP_STORE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.MAIN_CLASS;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VERBOSE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE;
|
||||
|
||||
@ -45,13 +44,6 @@ public class MacAppBundler extends AppImageBundler {
|
||||
|
||||
private static final String TEMPLATE_BUNDLE_ICON = "JavaApp.icns";
|
||||
|
||||
public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
|
||||
String.class,
|
||||
params -> null,
|
||||
(s, p) -> s);
|
||||
|
||||
public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
|
||||
new StandardBundlerParam<>(
|
||||
".mac.default.icns",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -95,7 +95,7 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler {
|
||||
},
|
||||
(s, p) -> s);
|
||||
|
||||
protected static String getInstallDir(
|
||||
static String getInstallDir(
|
||||
Map<String, ? super Object> params, boolean defaultOnly) {
|
||||
String returnValue = INSTALL_DIR.fetchFrom(params);
|
||||
if (defaultOnly && returnValue != null) {
|
||||
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
|
||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
|
||||
/**
|
||||
* Helper to install launchers as services using "launchd".
|
||||
*/
|
||||
public final class MacLaunchersAsServices extends UnixLaunchersAsServices {
|
||||
|
||||
private MacLaunchersAsServices(PlatformPackage thePackage,
|
||||
Map<String, Object> params) throws IOException {
|
||||
super(thePackage, List.of(), params, li -> {
|
||||
return new Launcher(thePackage, li.getName(), params);
|
||||
});
|
||||
}
|
||||
|
||||
static ShellCustomAction create(Map<String, Object> params,
|
||||
Path outputDir) throws IOException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
return null;
|
||||
}
|
||||
return Optional.of(new MacLaunchersAsServices(new PlatformPackage() {
|
||||
@Override
|
||||
public String name() {
|
||||
return MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path sourceRoot() {
|
||||
return outputDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationLayout sourceApplicationLayout() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationLayout installedApplicationLayout() {
|
||||
return ApplicationLayout.macAppImage().resolveAt(Path.of(
|
||||
MacBaseInstallerBundler.getInstallDir(params, false),
|
||||
APP_NAME.fetchFrom(params) + ".app"));
|
||||
}
|
||||
}, params)).filter(Predicate.not(MacLaunchersAsServices::isEmpty)).orElse(
|
||||
null);
|
||||
}
|
||||
|
||||
public static Path getServicePListFileName(String packageName,
|
||||
String launcherName) {
|
||||
String baseName = launcherName.replaceAll("[\\s]", "_");
|
||||
return Path.of(packageName + "-" + baseName + ".plist");
|
||||
}
|
||||
|
||||
private static class Launcher extends UnixLauncherAsService {
|
||||
|
||||
Launcher(PlatformPackage thePackage, String name,
|
||||
Map<String, Object> mainParams) {
|
||||
super(name, mainParams, createResource("launchd.plist.template",
|
||||
mainParams).setCategory(I18N.getString(
|
||||
"resource.launchd-plist-file")));
|
||||
|
||||
plistFilename = getServicePListFileName(thePackage.name(), getName());
|
||||
|
||||
// It is recommended to set value of "label" property in launchd
|
||||
// .plist file equal to the name of this .plist file without the suffix.
|
||||
String label = IOUtils.replaceSuffix(plistFilename.getFileName(), "").toString();
|
||||
|
||||
getResource()
|
||||
.setPublicName(plistFilename)
|
||||
.addSubstitutionDataEntry("LABEL", label)
|
||||
.addSubstitutionDataEntry("APPLICATION_LAUNCHER",
|
||||
thePackage.installedApplicationLayout().launchersDirectory().resolve(
|
||||
getName()).toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
Path descriptorFilePath(Path root) {
|
||||
return root.resolve("Library/LaunchDaemons").resolve(plistFilename);
|
||||
}
|
||||
|
||||
private final Path plistFilename;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,15 +34,17 @@ import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.TEMP_ROOT;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VERBOSE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
@ -52,6 +54,7 @@ import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
|
||||
import static jdk.jpackage.internal.MacAppImageBuilder.APP_STORE;
|
||||
import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
|
||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
|
||||
|
||||
public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
|
||||
@ -61,11 +64,6 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
private static final String DEFAULT_BACKGROUND_IMAGE = "background_pkg.png";
|
||||
private static final String DEFAULT_PDF = "product-def.plist";
|
||||
|
||||
private static final String TEMPLATE_PREINSTALL_SCRIPT =
|
||||
"preinstall.template";
|
||||
private static final String TEMPLATE_POSTINSTALL_SCRIPT =
|
||||
"postinstall.template";
|
||||
|
||||
private static final BundlerParamInfo<Path> PACKAGES_ROOT =
|
||||
new StandardBundlerParam<>(
|
||||
"mac.pkg.packagesRoot",
|
||||
@ -171,6 +169,16 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
APP_NAME.fetchFrom(params) + "-app.pkg");
|
||||
}
|
||||
|
||||
private Path getPackages_ServicesPackage(Map<String, ? super Object> params) {
|
||||
return PACKAGES_ROOT.fetchFrom(params).resolve(
|
||||
APP_NAME.fetchFrom(params) + "-services.pkg");
|
||||
}
|
||||
|
||||
private Path getPackages_SupportPackage(Map<String, ? super Object> params) {
|
||||
return PACKAGES_ROOT.fetchFrom(params).resolve(
|
||||
APP_NAME.fetchFrom(params) + "-support.pkg");
|
||||
}
|
||||
|
||||
private Path getConfig_DistributionXMLFile(
|
||||
Map<String, ? super Object> params) {
|
||||
return CONFIG_ROOT.fetchFrom(params).resolve("distribution.dist");
|
||||
@ -190,19 +198,18 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
APP_NAME.fetchFrom(params) + "-background-darkAqua.png");
|
||||
}
|
||||
|
||||
private Path getScripts_PreinstallFile(Map<String, ? super Object> params) {
|
||||
return SCRIPTS_DIR.fetchFrom(params).resolve("preinstall");
|
||||
}
|
||||
|
||||
private Path getScripts_PostinstallFile(
|
||||
Map<String, ? super Object> params) {
|
||||
return SCRIPTS_DIR.fetchFrom(params).resolve("postinstall");
|
||||
}
|
||||
|
||||
private String getAppIdentifier(Map<String, ? super Object> params) {
|
||||
return MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params);
|
||||
}
|
||||
|
||||
private String getServicesIdentifier(Map<String, ? super Object> params) {
|
||||
return MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) + ".services";
|
||||
}
|
||||
|
||||
private String getSupportIdentifier(Map<String, ? super Object> params) {
|
||||
return MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) + ".support";
|
||||
}
|
||||
|
||||
private void preparePackageScripts(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
Log.verbose(I18N.getString("message.preparing-scripts"));
|
||||
@ -215,22 +222,35 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
data.put("INSTALL_LOCATION", getInstallDir(params, false));
|
||||
data.put("APP_LOCATION", appLocation.toString());
|
||||
|
||||
createResource(TEMPLATE_PREINSTALL_SCRIPT, params)
|
||||
.setCategory(I18N.getString("resource.pkg-preinstall-script"))
|
||||
MacPkgInstallerScripts.createAppScripts()
|
||||
.setResourceDir(RESOURCE_DIR.fetchFrom(params))
|
||||
.setSubstitutionData(data)
|
||||
.saveToFile(getScripts_PreinstallFile(params));
|
||||
getScripts_PreinstallFile(params).toFile().setExecutable(true, false);
|
||||
|
||||
createResource(TEMPLATE_POSTINSTALL_SCRIPT, params)
|
||||
.setCategory(I18N.getString("resource.pkg-postinstall-script"))
|
||||
.setSubstitutionData(data)
|
||||
.saveToFile(getScripts_PostinstallFile(params));
|
||||
getScripts_PostinstallFile(params).toFile().setExecutable(true, false);
|
||||
.saveInFolder(SCRIPTS_DIR.fetchFrom(params));
|
||||
}
|
||||
|
||||
private static String URLEncoding(String pkgName) throws URISyntaxException {
|
||||
URI uri = new URI(null, null, pkgName, null);
|
||||
return uri.toASCIIString();
|
||||
private void addPackageToInstallerGuiScript(XMLStreamWriter xml,
|
||||
String pkgId, String pkgName, String pkgVersion) throws IOException,
|
||||
XMLStreamException {
|
||||
xml.writeStartElement("pkg-ref");
|
||||
xml.writeAttribute("id", pkgId);
|
||||
xml.writeEndElement(); // </pkg-ref>
|
||||
xml.writeStartElement("choice");
|
||||
xml.writeAttribute("id", pkgId);
|
||||
xml.writeAttribute("visible", "false");
|
||||
xml.writeStartElement("pkg-ref");
|
||||
xml.writeAttribute("id", pkgId);
|
||||
xml.writeEndElement(); // </pkg-ref>
|
||||
xml.writeEndElement(); // </choice>
|
||||
xml.writeStartElement("pkg-ref");
|
||||
xml.writeAttribute("id", pkgId);
|
||||
xml.writeAttribute("version", pkgVersion);
|
||||
xml.writeAttribute("onConclusion", "none");
|
||||
try {
|
||||
xml.writeCharacters(new URI(null, null, pkgName, null).toASCIIString());
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
xml.writeEndElement(); // </pkg-ref>
|
||||
}
|
||||
|
||||
private void prepareDistributionXMLFile(Map<String, ? super Object> params)
|
||||
@ -277,11 +297,23 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
* Note that the content of the distribution file
|
||||
* below is generated by productbuild --synthesize
|
||||
*/
|
||||
String appId = getAppIdentifier(params);
|
||||
|
||||
xml.writeStartElement("pkg-ref");
|
||||
xml.writeAttribute("id", appId);
|
||||
xml.writeEndElement(); // </pkg-ref>
|
||||
Map<String, Path> pkgs = new LinkedHashMap<>();
|
||||
|
||||
pkgs.put(getAppIdentifier(params), getPackages_AppPackage(params));
|
||||
if (withServicesPkg(params)) {
|
||||
pkgs.put(getServicesIdentifier(params),
|
||||
getPackages_ServicesPackage(params));
|
||||
pkgs.put(getSupportIdentifier(params),
|
||||
getPackages_SupportPackage(params));
|
||||
}
|
||||
|
||||
for (var pkg : pkgs.entrySet()) {
|
||||
addPackageToInstallerGuiScript(xml, pkg.getKey(),
|
||||
pkg.getValue().getFileName().toString(),
|
||||
VERSION.fetchFrom(params));
|
||||
}
|
||||
|
||||
xml.writeStartElement("options");
|
||||
xml.writeAttribute("customize", "never");
|
||||
xml.writeAttribute("require-scripts", "false");
|
||||
@ -291,32 +323,16 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
xml.writeStartElement("choices-outline");
|
||||
xml.writeStartElement("line");
|
||||
xml.writeAttribute("choice", "default");
|
||||
xml.writeStartElement("line");
|
||||
xml.writeAttribute("choice", appId);
|
||||
xml.writeEndElement(); // </line>
|
||||
for (var pkgId : pkgs.keySet()) {
|
||||
xml.writeStartElement("line");
|
||||
xml.writeAttribute("choice", pkgId);
|
||||
xml.writeEndElement(); // </line>
|
||||
}
|
||||
xml.writeEndElement(); // </line>
|
||||
xml.writeEndElement(); // </choices-outline>
|
||||
xml.writeStartElement("choice");
|
||||
xml.writeAttribute("id", "default");
|
||||
xml.writeEndElement(); // </choice>
|
||||
xml.writeStartElement("choice");
|
||||
xml.writeAttribute("id", appId);
|
||||
xml.writeAttribute("visible", "false");
|
||||
xml.writeStartElement("pkg-ref");
|
||||
xml.writeAttribute("id", appId);
|
||||
xml.writeEndElement(); // </pkg-ref>
|
||||
xml.writeEndElement(); // </choice>
|
||||
xml.writeStartElement("pkg-ref");
|
||||
xml.writeAttribute("id", appId);
|
||||
xml.writeAttribute("version", VERSION.fetchFrom(params));
|
||||
xml.writeAttribute("onConclusion", "none");
|
||||
try {
|
||||
xml.writeCharacters(URLEncoding(
|
||||
getPackages_AppPackage(params).getFileName().toString()));
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
xml.writeEndElement(); // </pkg-ref>
|
||||
|
||||
xml.writeEndElement(); // </installer-gui-script>
|
||||
});
|
||||
@ -434,6 +450,81 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
return newRoot.toString();
|
||||
}
|
||||
|
||||
private boolean withServicesPkg(Map<String, Object> params) {
|
||||
try {
|
||||
return !APP_STORE.fetchFrom(params)
|
||||
&& MacLaunchersAsServices.create(params, null) != null;
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void createServicesPkg(Map<String, Object> params) throws
|
||||
IOException {
|
||||
Path root = TEMP_ROOT.fetchFrom(params).resolve("services");
|
||||
|
||||
Path srcRoot = root.resolve("src");
|
||||
|
||||
var services = MacLaunchersAsServices.create(params, srcRoot);
|
||||
|
||||
Path scriptsDir = root.resolve("scripts");
|
||||
|
||||
var data = services.create();
|
||||
data.put("SERVICES_PACKAGE_ID", getServicesIdentifier(params));
|
||||
|
||||
MacPkgInstallerScripts.createServicesScripts()
|
||||
.setResourceDir(RESOURCE_DIR.fetchFrom(params))
|
||||
.setSubstitutionData(data)
|
||||
.saveInFolder(scriptsDir);
|
||||
|
||||
var pb = new ProcessBuilder("/usr/bin/pkgbuild",
|
||||
"--root",
|
||||
srcRoot.toString(),
|
||||
"--install-location",
|
||||
"/",
|
||||
"--scripts",
|
||||
scriptsDir.toString(),
|
||||
"--identifier",
|
||||
getServicesIdentifier(params),
|
||||
getPackages_ServicesPackage(params).toAbsolutePath().toString());
|
||||
IOUtils.exec(pb, false, null, true, Executor.INFINITE_TIMEOUT);
|
||||
|
||||
createSupportPkg(params, data);
|
||||
}
|
||||
|
||||
private void createSupportPkg(Map<String, Object> params,
|
||||
Map<String, String> servicesSubstitutionData) throws IOException {
|
||||
Path root = TEMP_ROOT.fetchFrom(params).resolve("support");
|
||||
|
||||
Path srcRoot = root.resolve("src");
|
||||
|
||||
var enqouter = Enquoter.forShellLiterals().setEnquotePredicate(str -> true);
|
||||
|
||||
Map<String, String> data = new HashMap<>(servicesSubstitutionData);
|
||||
data.put("APP_INSTALLATION_FOLDER", enqouter.applyTo(Path.of(
|
||||
getInstallDir(params, false), APP_NAME.fetchFrom(params)
|
||||
+ ".app").toString()));
|
||||
data.put("SUPPORT_INSTALLATION_FOLDER", enqouter.applyTo(Path.of(
|
||||
"/Library/Application Support", APP_NAME.fetchFrom(params)).toString()));
|
||||
|
||||
new ShellScriptResource("uninstall.command")
|
||||
.setResource(createResource("uninstall.command.template", params)
|
||||
.setCategory(I18N.getString("resource.pkg-uninstall-script"))
|
||||
.setPublicName("uninstaller")
|
||||
.setSubstitutionData(data))
|
||||
.saveInFolder(srcRoot.resolve(APP_NAME.fetchFrom(params)));
|
||||
|
||||
var pb = new ProcessBuilder("/usr/bin/pkgbuild",
|
||||
"--root",
|
||||
srcRoot.toString(),
|
||||
"--install-location",
|
||||
"/Library/Application Support",
|
||||
"--identifier",
|
||||
getSupportIdentifier(params),
|
||||
getPackages_SupportPackage(params).toAbsolutePath().toString());
|
||||
IOUtils.exec(pb, false, null, true, Executor.INFINITE_TIMEOUT);
|
||||
}
|
||||
|
||||
private Path createPKG(Map<String, ? super Object> params,
|
||||
Path outdir, Path appLocation) {
|
||||
// generic find attempt
|
||||
@ -442,6 +533,10 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
|
||||
String root = getRoot(params, appLocation);
|
||||
|
||||
if (withServicesPkg(params)) {
|
||||
createServicesPkg(params);
|
||||
}
|
||||
|
||||
// Generate default CPL file
|
||||
Path cpl = CONFIG_ROOT.fetchFrom(params).resolve("cpl.plist");
|
||||
ProcessBuilder pb = new ProcessBuilder("/usr/bin/pkgbuild",
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import jdk.jpackage.internal.PackageScripts.ResourceConfig;
|
||||
|
||||
/**
|
||||
* MacOS PKG installer scripts.
|
||||
*/
|
||||
final class MacPkgInstallerScripts {
|
||||
|
||||
enum AppScripts implements Supplier<OverridableResource> {
|
||||
preinstall(new ResourceConfig("preinstall.template",
|
||||
"resource.pkg-preinstall-script")),
|
||||
postinstall(new ResourceConfig("postinstall.template",
|
||||
"resource.pkg-postinstall-script"));
|
||||
|
||||
AppScripts(ResourceConfig cfg) {
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OverridableResource get() {
|
||||
return cfg.createResource();
|
||||
}
|
||||
|
||||
private final ResourceConfig cfg;
|
||||
}
|
||||
|
||||
enum ServicesScripts implements Supplier<OverridableResource> {
|
||||
preinstall(new ResourceConfig("services-preinstall.template",
|
||||
"resource.pkg-services-preinstall-script")),
|
||||
postinstall(new ResourceConfig("services-postinstall.template",
|
||||
"resource.pkg-services-postinstall-script"));
|
||||
|
||||
ServicesScripts(ResourceConfig cfg) {
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OverridableResource get() {
|
||||
return cfg.createResource();
|
||||
}
|
||||
|
||||
private final ResourceConfig cfg;
|
||||
}
|
||||
|
||||
static PackageScripts<AppScripts> createAppScripts() {
|
||||
return PackageScripts.create(AppScripts.class);
|
||||
}
|
||||
|
||||
static PackageScripts<ServicesScripts> createServicesScripts() {
|
||||
return PackageScripts.create(ServicesScripts.class);
|
||||
}
|
||||
}
|
@ -54,8 +54,12 @@ resource.volume-icon=volume icon
|
||||
resource.post-install-script=script to run after application image is populated
|
||||
resource.pkg-preinstall-script=PKG preinstall script
|
||||
resource.pkg-postinstall-script=PKG postinstall script
|
||||
resource.pkg-services-preinstall-script=PKG preinstall script for services package
|
||||
resource.pkg-services-postinstall-script=PKG postinstall script for services package
|
||||
resource.pkg-uninstall-script=PKG uninstaller script
|
||||
resource.pkg-background-image=pkg background image
|
||||
resource.pkg-pdf=project definition file
|
||||
resource.launchd-plist-file=launchd plist file
|
||||
|
||||
|
||||
message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
|
||||
|
@ -54,8 +54,12 @@ resource.volume-icon=\u30DC\u30EA\u30E5\u30FC\u30E0\u30FB\u30A2\u30A4\u30B3\u30F
|
||||
resource.post-install-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u79FB\u5165\u3057\u305F\u5F8C\u306B\u5B9F\u884C\u3059\u308B\u30B9\u30AF\u30EA\u30D7\u30C8
|
||||
resource.pkg-preinstall-script=PKG\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u524D\u30B9\u30AF\u30EA\u30D7\u30C8
|
||||
resource.pkg-postinstall-script=PKG\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u5F8C\u30B9\u30AF\u30EA\u30D7\u30C8
|
||||
resource.pkg-services-preinstall-script=PKG preinstall script for services package
|
||||
resource.pkg-services-postinstall-script=PKG postinstall script for services package
|
||||
resource.pkg-uninstall-script=PKG uninstaller script
|
||||
resource.pkg-background-image=pkg\u80CC\u666F\u30A4\u30E1\u30FC\u30B8
|
||||
resource.pkg-pdf=\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u5B9A\u7FA9\u30D5\u30A1\u30A4\u30EB
|
||||
resource.pkg-pdf=project definition file
|
||||
resource.launchd-plist-file=launchd plist file
|
||||
|
||||
|
||||
message.bundle-name-too-long-warning={0}\u304C16\u6587\u5B57\u3092\u8D85\u3048\u308B''{1}''\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\u3002Mac\u3067\u306E\u64CD\u4F5C\u6027\u3092\u3088\u308A\u826F\u304F\u3059\u308B\u305F\u3081\u306B\u77ED\u304F\u3059\u308B\u3053\u3068\u3092\u691C\u8A0E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
||||
|
@ -54,8 +54,12 @@ resource.volume-icon=\u5377\u56FE\u6807
|
||||
resource.post-install-script=\u8981\u5728\u586B\u5145\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u4E4B\u540E\u8FD0\u884C\u7684\u811A\u672C
|
||||
resource.pkg-preinstall-script=PKG \u5B89\u88C5\u524D\u811A\u672C
|
||||
resource.pkg-postinstall-script=PKG \u5B89\u88C5\u540E\u811A\u672C
|
||||
resource.pkg-services-preinstall-script=PKG preinstall script for services package
|
||||
resource.pkg-services-postinstall-script=PKG postinstall script for services package
|
||||
resource.pkg-uninstall-script=PKG uninstaller script
|
||||
resource.pkg-background-image=pkg \u80CC\u666F\u56FE\u50CF
|
||||
resource.pkg-pdf=\u9879\u76EE\u5B9A\u4E49\u6587\u4EF6
|
||||
resource.pkg-pdf=project definition file
|
||||
resource.launchd-plist-file=launchd plist file
|
||||
|
||||
|
||||
message.bundle-name-too-long-warning={0}\u5DF2\u8BBE\u7F6E\u4E3A ''{1}'', \u5176\u957F\u5EA6\u8D85\u8FC7\u4E86 16 \u4E2A\u5B57\u7B26\u3002\u4E3A\u4E86\u83B7\u5F97\u66F4\u597D\u7684 Mac \u4F53\u9A8C, \u8BF7\u8003\u8651\u5C06\u5176\u7F29\u77ED\u3002
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>LABEL</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>APPLICATION_LAUNCHER</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key><true/>
|
||||
<key>KeepAlive</key><true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
LAUNCHER_AS_SERVICE_COMMANDS_INSTALL
|
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
|
||||
unregister_services `/usr/sbin/pkgutil --files SERVICES_PACKAGE_ID | /usr/bin/grep '\.plist$' | /usr/bin/awk '{print "/"$0}'`
|
@ -0,0 +1,30 @@
|
||||
#
|
||||
# Register $@ .plist files with launchd service.
|
||||
#
|
||||
register_services ()
|
||||
{
|
||||
for daemonPlistFilePath in "$@"; do
|
||||
daemonPlistFileName="${daemonPlistFilePath#/Library/LaunchDaemons/}";
|
||||
|
||||
/bin/launchctl load "$daemonPlistFilePath"
|
||||
|
||||
/bin/launchctl start "${daemonPlistFileName%.plist}"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Unregister $@ .plist files with launchd service.
|
||||
#
|
||||
unregister_services ()
|
||||
{
|
||||
for daemonPlistFilePath in "$@"; do
|
||||
daemonPlistFileName="${daemonPlistFilePath#/Library/LaunchDaemons/}";
|
||||
|
||||
sudo /bin/launchctl stop "${daemonPlistFileName%.plist}"
|
||||
|
||||
sudo /bin/launchctl unload "$daemonPlistFilePath"
|
||||
|
||||
test -z "$delete_plist_files" || sudo rm -f "$daemonPlistFilePath"
|
||||
done
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
|
||||
delete_plist_files=yes
|
||||
LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
|
||||
sudo rm -rf APP_INSTALLATION_FOLDER
|
||||
sudo rm -rf SUPPORT_INSTALLATION_FOLDER
|
@ -29,6 +29,7 @@ import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import jdk.jpackage.internal.Arguments.CLIOptions;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.LAUNCHER_DATA;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
@ -61,6 +62,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT;
|
||||
* icon
|
||||
* arguments
|
||||
* java-options
|
||||
* launcher-as-service
|
||||
* win-console
|
||||
* win-shortcut
|
||||
* win-menu
|
||||
@ -118,9 +120,13 @@ class AddLauncherArguments {
|
||||
Arguments.putUnlessNull(bundleParams, CLIOptions.RELEASE.getId(),
|
||||
getOptionValue(CLIOptions.RELEASE));
|
||||
|
||||
String value = getOptionValue(CLIOptions.ICON);
|
||||
Arguments.putUnlessNull(bundleParams, CLIOptions.ICON.getId(),
|
||||
(value == null) ? null : Path.of(value));
|
||||
Optional.ofNullable(getOptionValue(CLIOptions.ICON)).map(
|
||||
Path::of).orElse(null));
|
||||
|
||||
Arguments.putUnlessNull(bundleParams,
|
||||
CLIOptions.LAUNCHER_AS_SERVICE.getId(), getOptionValue(
|
||||
CLIOptions.LAUNCHER_AS_SERVICE));
|
||||
|
||||
if (Platform.isWindows()) {
|
||||
Arguments.putUnlessNull(bundleParams,
|
||||
|
@ -32,6 +32,7 @@ import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
@ -48,11 +49,12 @@ import org.xml.sax.SAXException;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.ADD_LAUNCHERS;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.LAUNCHER_AS_SERVICE;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.MENU_HINT;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE;
|
||||
|
||||
public class AppImageFile {
|
||||
public final class AppImageFile {
|
||||
|
||||
// These values will be loaded from AppImage xml file.
|
||||
private final String creatorVersion;
|
||||
@ -143,13 +145,13 @@ public class AppImageFile {
|
||||
List<Map<String, ? super Object>> addLaunchers =
|
||||
ADD_LAUNCHERS.fetchFrom(params);
|
||||
|
||||
for (int i = 0; i < addLaunchers.size(); i++) {
|
||||
Map<String, ? super Object> sl = addLaunchers.get(i);
|
||||
for (var launcherParams : addLaunchers) {
|
||||
var li = new LauncherInfo(launcherParams);
|
||||
xml.writeStartElement("add-launcher");
|
||||
xml.writeAttribute("name", APP_NAME.fetchFrom(sl));
|
||||
xml.writeAttribute("shortcut",
|
||||
SHORTCUT_HINT.fetchFrom(sl).toString());
|
||||
xml.writeAttribute("menu", MENU_HINT.fetchFrom(sl).toString());
|
||||
xml.writeAttribute("name", li.getName());
|
||||
xml.writeAttribute("shortcut", Boolean.toString(li.isShortcut()));
|
||||
xml.writeAttribute("menu", Boolean.toString(li.isMenu()));
|
||||
xml.writeAttribute("service", Boolean.toString(li.isService()));
|
||||
xml.writeEndElement();
|
||||
}
|
||||
});
|
||||
@ -190,14 +192,7 @@ public class AppImageFile {
|
||||
XPathConstants.NODESET);
|
||||
|
||||
for (int i = 0; i != launcherNodes.getLength(); i++) {
|
||||
Node item = launcherNodes.item(i);
|
||||
String name = getAttribute(item, "name");
|
||||
String shortcut = getAttribute(item, "shortcut");
|
||||
String menu = getAttribute(item, "menu");
|
||||
|
||||
launcherInfos.add(new LauncherInfo(name,
|
||||
!("false".equals(shortcut)),
|
||||
!("false".equals(menu))));
|
||||
launcherInfos.add(new LauncherInfo(launcherNodes.item(i)));
|
||||
}
|
||||
|
||||
AppImageFile file = new AppImageFile(
|
||||
@ -241,31 +236,32 @@ public class AppImageFile {
|
||||
* Following items in the list are names of additional launchers.
|
||||
*/
|
||||
static List<LauncherInfo> getLaunchers(Path appImageDir,
|
||||
Map<String, ? super Object> params) {
|
||||
Map<String, Object> params) {
|
||||
List<LauncherInfo> launchers = new ArrayList<>();
|
||||
try {
|
||||
AppImageFile appImageInfo = AppImageFile.load(appImageDir);
|
||||
if (appImageInfo != null) {
|
||||
launchers.add(new LauncherInfo(
|
||||
appImageInfo.getLauncherName(), true, true));
|
||||
launchers.addAll(appImageInfo.getAddLaunchers());
|
||||
return launchers;
|
||||
if (appImageDir != null) {
|
||||
try {
|
||||
AppImageFile appImageInfo = AppImageFile.load(appImageDir);
|
||||
if (appImageInfo != null) {
|
||||
launchers.add(new LauncherInfo(
|
||||
appImageInfo.getLauncherName(), params));
|
||||
launchers.addAll(appImageInfo.getAddLaunchers());
|
||||
return launchers;
|
||||
}
|
||||
} catch (NoSuchFileException nsfe) {
|
||||
// non jpackage generated app-image (no app/.jpackage.xml)
|
||||
Log.info(MessageFormat.format(I18N.getString(
|
||||
"warning.foreign-app-image"), appImageDir));
|
||||
} catch (IOException ioe) {
|
||||
Log.verbose(ioe);
|
||||
Log.info(MessageFormat.format(I18N.getString(
|
||||
"warning.invalid-app-image"), appImageDir));
|
||||
}
|
||||
} catch (NoSuchFileException nsfe) {
|
||||
// non jpackage generated app-image (no app/.jpackage.xml)
|
||||
Log.info(MessageFormat.format(I18N.getString(
|
||||
"warning.foreign-app-image"), appImageDir));
|
||||
} catch (IOException ioe) {
|
||||
Log.verbose(ioe);
|
||||
Log.info(MessageFormat.format(I18N.getString(
|
||||
"warning.invalid-app-image"), appImageDir));
|
||||
|
||||
}
|
||||
// this should never be the case, but maintaining behavior of
|
||||
// creating default launchers without AppImageFile present
|
||||
|
||||
ADD_LAUNCHERS.fetchFrom(params).stream().map(APP_NAME::fetchFrom).map(
|
||||
name -> new LauncherInfo(name, true, true)).forEach(launchers::add);
|
||||
launchers.add(new LauncherInfo(params));
|
||||
ADD_LAUNCHERS.fetchFrom(params).stream()
|
||||
.map(launcherParams -> new LauncherInfo(launcherParams))
|
||||
.forEach(launchers::add);
|
||||
return launchers;
|
||||
}
|
||||
|
||||
@ -289,11 +285,11 @@ public class AppImageFile {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getVersion() {
|
||||
return System.getProperty("java.version");
|
||||
static String getVersion() {
|
||||
return "1.0";
|
||||
}
|
||||
|
||||
private static String getPlatform() {
|
||||
static String getPlatform() {
|
||||
return PLATFORM_LABELS.get(Platform.getPlatform());
|
||||
}
|
||||
|
||||
@ -301,34 +297,63 @@ public class AppImageFile {
|
||||
if (launcherName == null || launcherName.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var launcher : addLauncherInfos) {
|
||||
if ("".equals(launcher.getName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Objects.equals(getVersion(), creatorVersion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(getPlatform(), creatorPlatform)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static class LauncherInfo {
|
||||
private String name;
|
||||
private boolean shortcut;
|
||||
private boolean menu;
|
||||
private final String name;
|
||||
private final boolean shortcut;
|
||||
private final boolean menu;
|
||||
private final boolean service;
|
||||
|
||||
public LauncherInfo(String name, boolean shortcut, boolean menu) {
|
||||
this.name = name;
|
||||
this.shortcut = shortcut;
|
||||
this.menu = menu;
|
||||
private LauncherInfo(Map<String, Object> params) {
|
||||
this(APP_NAME.fetchFrom(params), params);
|
||||
}
|
||||
|
||||
private LauncherInfo(String name, Map<String, Object> params) {
|
||||
this.name = name;
|
||||
this.shortcut = SHORTCUT_HINT.fetchFrom(params);
|
||||
this.menu = MENU_HINT.fetchFrom(params);
|
||||
this.service = LAUNCHER_AS_SERVICE.fetchFrom(params);
|
||||
}
|
||||
|
||||
private LauncherInfo(Node node) {
|
||||
this.name = getAttribute(node, "name");
|
||||
this.shortcut = !"false".equals(getAttribute(node, "shortcut"));
|
||||
this.menu = !"false".equals(getAttribute(node, "menu"));
|
||||
this.service = !"false".equals(getAttribute(node, "service"));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isShortcut() {
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
public boolean isMenu() {
|
||||
return menu;
|
||||
}
|
||||
|
||||
public boolean isService() {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -314,6 +314,10 @@ public class Arguments {
|
||||
|
||||
MODULE_PATH ("module-path", "p", OptionCategories.MODULAR),
|
||||
|
||||
LAUNCHER_AS_SERVICE ("launcher-as-service", OptionCategories.PROPERTY, () -> {
|
||||
setOptionValue("launcher-as-service", true);
|
||||
}),
|
||||
|
||||
MAC_SIGN ("mac-sign", "s", OptionCategories.PLATFORM_MAC, () -> {
|
||||
setOptionValue("mac-sign", true);
|
||||
}),
|
||||
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Add quotes to the given string in a configurable way.
|
||||
*/
|
||||
final class Enquoter {
|
||||
|
||||
private Enquoter() {
|
||||
setQuoteChar('"');
|
||||
}
|
||||
|
||||
static Enquoter forPropertyValues() {
|
||||
return new Enquoter()
|
||||
.setEnquotePredicate(QUOTE_IF_WHITESPACES)
|
||||
.setEscaper(PREPEND_BACKSLASH);
|
||||
}
|
||||
|
||||
static Enquoter forShellLiterals() {
|
||||
return forShellLiterals('\'');
|
||||
}
|
||||
|
||||
static Enquoter forShellLiterals(char quoteChar) {
|
||||
return new Enquoter()
|
||||
.setQuoteChar(quoteChar)
|
||||
.setEnquotePredicate(x -> true)
|
||||
.setEscaper(PREPEND_BACKSLASH);
|
||||
}
|
||||
|
||||
String applyTo(String v) {
|
||||
if (!needQuotes.test(v)) {
|
||||
return v;
|
||||
} else {
|
||||
var buf = new StringBuilder();
|
||||
buf.appendCodePoint(beginQuoteChr);
|
||||
Optional.of(escaper).ifPresentOrElse(op -> {
|
||||
v.codePoints().forEachOrdered(chr -> {
|
||||
if (chr == beginQuoteChr || chr == endQuoteChr) {
|
||||
escaper.accept(chr, buf);
|
||||
} else {
|
||||
buf.appendCodePoint(chr);
|
||||
}
|
||||
});
|
||||
}, () -> {
|
||||
buf.append(v);
|
||||
});
|
||||
buf.appendCodePoint(endQuoteChr);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Enquoter setQuoteChar(char chr) {
|
||||
beginQuoteChr = chr;
|
||||
endQuoteChr = chr;
|
||||
return this;
|
||||
}
|
||||
|
||||
Enquoter setEscaper(BiConsumer<Integer, StringBuilder> v) {
|
||||
escaper = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
Enquoter setEnquotePredicate(Predicate<String> v) {
|
||||
needQuotes = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
private int beginQuoteChr;
|
||||
private int endQuoteChr;
|
||||
private BiConsumer<Integer, StringBuilder> escaper;
|
||||
private Predicate<String> needQuotes = str -> false;
|
||||
|
||||
private final static Predicate<String> QUOTE_IF_WHITESPACES = new Predicate<String>() {
|
||||
@Override
|
||||
public boolean test(String t) {
|
||||
return pattern.matcher(t).find();
|
||||
}
|
||||
private final Pattern pattern = Pattern.compile("\\s");
|
||||
};
|
||||
|
||||
private final static BiConsumer<Integer, StringBuilder> PREPEND_BACKSLASH = (chr, buf) -> {
|
||||
buf.append('\\');
|
||||
buf.appendCodePoint(chr);
|
||||
};
|
||||
}
|
@ -40,14 +40,23 @@ import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.stax.StAXResult;
|
||||
|
||||
/**
|
||||
* IOUtils
|
||||
@ -323,6 +332,44 @@ public class IOUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void mergeXmls(XMLStreamWriter xml, Collection<Source> sources)
|
||||
throws XMLStreamException, IOException {
|
||||
xml = (XMLStreamWriter) Proxy.newProxyInstance(
|
||||
XMLStreamWriter.class.getClassLoader(), new Class<?>[]{
|
||||
XMLStreamWriter.class}, new SkipDocumentHandler(xml));
|
||||
|
||||
try {
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Result result = new StAXResult(xml);
|
||||
for (var src : sources) {
|
||||
tf.newTransformer().transform(src, result);
|
||||
}
|
||||
} catch (TransformerException ex) {
|
||||
// Should never happen
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static DocumentBuilderFactory initDocumentBuilderFactory() {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance();
|
||||
try {
|
||||
dbf.setFeature(
|
||||
"http://apache.org/xml/features/nonvalidating/load-external-dtd",
|
||||
false);
|
||||
} catch (ParserConfigurationException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
return dbf;
|
||||
}
|
||||
|
||||
public static DocumentBuilder initDocumentBuilder() {
|
||||
try {
|
||||
return initDocumentBuilderFactory().newDocumentBuilder();
|
||||
} catch (ParserConfigurationException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Path getParent(Path p) {
|
||||
Path parent = p.getParent();
|
||||
if (parent == null) {
|
||||
@ -416,4 +463,24 @@ public class IOUtils {
|
||||
private static final String INDENT = " ";
|
||||
private static final String EOL = "\n";
|
||||
}
|
||||
|
||||
private static class SkipDocumentHandler implements InvocationHandler {
|
||||
|
||||
SkipDocumentHandler(XMLStreamWriter target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws
|
||||
Throwable {
|
||||
switch (method.getName()) {
|
||||
case "writeStartDocument", "writeEndDocument" -> {
|
||||
}
|
||||
default -> method.invoke(target, args);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final XMLStreamWriter target;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
final class InstallableFile {
|
||||
|
||||
InstallableFile(Path srcPath, Path installPath) {
|
||||
Objects.requireNonNull(srcPath);
|
||||
|
||||
this.srcPath = srcPath;
|
||||
this.installPath = installPath;
|
||||
}
|
||||
|
||||
Path installPath() {
|
||||
return installPath;
|
||||
}
|
||||
|
||||
Path srcPath() {
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
void applyToApplicationLayouts(ApplicationLayout src,
|
||||
ApplicationLayout install) {
|
||||
var key = new Object();
|
||||
src.pathGroup().setPath(key, srcPath);
|
||||
if (installPath != null && install != null) {
|
||||
install.pathGroup().setPath(key, installPath);
|
||||
}
|
||||
}
|
||||
|
||||
void excludeFromApplicationLayout(ApplicationLayout layout) {
|
||||
applyToApplicationLayouts(layout, null);
|
||||
}
|
||||
|
||||
private final Path installPath;
|
||||
private final Path srcPath;
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.util.Map;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.DESCRIPTION;
|
||||
|
||||
class LauncherAsService {
|
||||
|
||||
LauncherAsService(String name, Map<String, Object> mainParams,
|
||||
OverridableResource resource) {
|
||||
if (name == null || APP_NAME.fetchFrom(mainParams).equals(name)) {
|
||||
// Main launcher
|
||||
name = APP_NAME.fetchFrom(mainParams);
|
||||
this.description = DESCRIPTION.fetchFrom(mainParams);
|
||||
} else {
|
||||
// Additional launcher
|
||||
this.description = String.format("%s (%s)", DESCRIPTION.fetchFrom(
|
||||
mainParams), name);
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
this.resource = resource;
|
||||
resource.addSubstitutionDataEntry("SERVICE_DESCRIPTION", description);
|
||||
}
|
||||
|
||||
protected OverridableResource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final OverridableResource resource;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -76,6 +76,22 @@ final class OverridableResource {
|
||||
setSourceOrder(Source.values());
|
||||
}
|
||||
|
||||
Path getResourceDir() {
|
||||
return resourceDir;
|
||||
}
|
||||
|
||||
String getDefaultName() {
|
||||
return defaultName;
|
||||
}
|
||||
|
||||
Path getPublicName() {
|
||||
return publicName;
|
||||
}
|
||||
|
||||
Path getExternalPath() {
|
||||
return externalPath;
|
||||
}
|
||||
|
||||
OverridableResource setSubstitutionData(Map<String, String> v) {
|
||||
if (v != null) {
|
||||
// Disconnect `v`
|
||||
@ -86,6 +102,13 @@ final class OverridableResource {
|
||||
return this;
|
||||
}
|
||||
|
||||
OverridableResource addSubstitutionDataEntry(String key, String value) {
|
||||
var entry = Map.of(key, value);
|
||||
Optional.ofNullable(substitutionData).ifPresentOrElse(v -> v.putAll(
|
||||
entry), () -> setSubstitutionData(entry));
|
||||
return this;
|
||||
}
|
||||
|
||||
OverridableResource setCategory(String v) {
|
||||
category = v;
|
||||
return this;
|
||||
@ -163,6 +186,10 @@ final class OverridableResource {
|
||||
});
|
||||
}
|
||||
|
||||
Source saveInFolder(Path folderPath) throws IOException {
|
||||
return saveToFile(folderPath.resolve(getPublicName()));
|
||||
}
|
||||
|
||||
Source saveToFile(Path dest) throws IOException {
|
||||
if (dest == null) {
|
||||
return sendToConsumer(null);
|
||||
@ -240,12 +267,8 @@ final class OverridableResource {
|
||||
final Path customResource = resourceDir.resolve(resourceName);
|
||||
used = Files.exists(customResource);
|
||||
if (used && dest != null) {
|
||||
final Path logResourceName;
|
||||
if (logPublicName != null) {
|
||||
logResourceName = logPublicName.normalize();
|
||||
} else {
|
||||
logResourceName = resourceName.normalize();
|
||||
}
|
||||
final Path logResourceName = Optional.ofNullable(logPublicName).orElse(
|
||||
resourceName).normalize();
|
||||
|
||||
Log.verbose(MessageFormat.format(I18N.getString(
|
||||
"message.using-custom-resource"), getPrintableCategory(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,13 +31,15 @@ import java.nio.file.Path;
|
||||
* Platform package of an application.
|
||||
*/
|
||||
interface PlatformPackage {
|
||||
|
||||
/**
|
||||
* Platform-specific package name.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Root directory where sources for packaging tool should be stored
|
||||
* Root directory where sources for packaging tool should be stored. On Unix
|
||||
* systems contents of this directory will be installed in "/" directory.
|
||||
*/
|
||||
Path sourceRoot();
|
||||
|
||||
|
@ -345,6 +345,16 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
(s, p) -> s
|
||||
);
|
||||
|
||||
static final StandardBundlerParam<Boolean> LAUNCHER_AS_SERVICE =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.LAUNCHER_AS_SERVICE.getId(),
|
||||
Boolean.class,
|
||||
params -> false,
|
||||
// valueOf(null) is false, and we actually do want null
|
||||
(s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
|
||||
true : Boolean.valueOf(s)
|
||||
);
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final StandardBundlerParam<List<Map<String, ? super Object>>> ADD_LAUNCHERS =
|
||||
|
@ -87,6 +87,7 @@ class ValidOptions {
|
||||
options.put(CLIOptions.LICENSE_FILE.getId(), USE.INSTALL);
|
||||
options.put(CLIOptions.INSTALL_DIR.getId(), USE.INSTALL);
|
||||
options.put(CLIOptions.PREDEFINED_APP_IMAGE.getId(), USE.INSTALL);
|
||||
options.put(CLIOptions.LAUNCHER_AS_SERVICE.getId(), USE.INSTALL);
|
||||
|
||||
options.put(CLIOptions.ABOUT_URL.getId(), USE.INSTALL);
|
||||
|
||||
|
@ -140,6 +140,7 @@ Generic Options:\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ The keys "module", "main-jar", "main-class", "description",\n\
|
||||
\ "arguments", "java-options", "app-version", "icon",\n\
|
||||
\ "launcher-as-service",\n\
|
||||
\ "win-console", "win-shortcut", "win-menu",\n\
|
||||
\ "linux-app-category", and "linux-shortcut" can be used.\n\
|
||||
\ These options are added to, or used to overwrite, the original\n\
|
||||
@ -197,6 +198,9 @@ Generic Options:\n\
|
||||
\ Path of the predefined runtime image to install\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ Option is required when creating a runtime package.\n\
|
||||
\ --launcher-as-service\n\
|
||||
\ Request to create an installer that will register the main\n\
|
||||
\ application launcher as a background service-type application.\n\
|
||||
\n\
|
||||
\Platform dependent options for creating the application package:\n\
|
||||
{3}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,11 +24,186 @@
|
||||
#
|
||||
#
|
||||
|
||||
MSG_Help=\u4F7F\u7528\u65B9\u6CD5: jpackage <options>\n\n\u4F7F\u7528\u4F8B:\n--------------\n \u30DB\u30B9\u30C8\u30FB\u30B7\u30B9\u30C6\u30E0\u306B\u9069\u3057\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u751F\u6210\u3057\u307E\u3059\u3002\n \u30E2\u30B8\u30E5\u30E9\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u5834\u5408:\n jpackage -n name -p modulePath -m moduleName/className\n \u975E\u30E2\u30B8\u30E5\u30E9\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u5834\u5408:\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n \u4E8B\u524D\u4F5C\u6210\u3055\u308C\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u304B\u3089:\n jpackage -n name --app-image appImageDir\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u306E\u751F\u6210:\n \u30E2\u30B8\u30E5\u30E9\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u5834\u5408:\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n \u975E\u30E2\u30B8\u30E5\u30E9\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u5834\u5408:\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n jlink\u306B\u72EC\u81EA\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3059\u308B\u306B\u306F\u3001jlink\u3092\u5225\u500B\u306B\u5B9F\u884C\u3057\u307E\u3059\u3002\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [<additional jlink options>...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage\n Java\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u751F\u6210\u3057\u307E\u3059\u3002\n jpackage -n name --runtime-image <runtime-image>\n\n\u4E00\u822C\u7684\u306A\u30AA\u30D7\u30B7\u30E7\u30F3:\n @<filename> \n \u30D5\u30A1\u30A4\u30EB\u304B\u3089\u306E\u8AAD\u53D6\u308A\u30AA\u30D7\u30B7\u30E7\u30F3\u304A\u3088\u3073\u30E2\u30FC\u30C9 \n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --type -t <type> \n \u4F5C\u6210\u3059\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30BF\u30A4\u30D7\n \u6709\u52B9\u306A\u5024: {1} \n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u3001\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u4F9D\u5B58\u306E\n \u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30BF\u30A4\u30D7\u304C\u4F5C\u6210\u3055\u308C\u307E\u3059\n --app-version <version>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u304A\u3088\u3073\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\n --copyright <copyright string>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30B3\u30D4\u30FC\u30E9\u30A4\u30C8\n --description <description string>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8AAC\u660E\n --help -h \n \u4F7F\u7528\u65B9\u6CD5\u30C6\u30AD\u30B9\u30C8\u3068\u73FE\u5728\u306E\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u306E\u6709\u52B9\u306A\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30EA\u30B9\u30C8\u3068\u8AAC\u660E\u3092\n \u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u3001\u7D42\u4E86\u3057\u307E\u3059\n --icon <file path>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30A2\u30A4\u30B3\u30F3\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n --name \
|
||||
-n <name>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u304A\u3088\u3073\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u540D\u524D\n --dest -d <destination path>\n \u751F\u6210\u3055\u308C\u305F\u51FA\u529B\u30D5\u30A1\u30A4\u30EB\u304C\u914D\u7F6E\u3055\u308C\u308B\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n \u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u73FE\u5728\u306E\u4F5C\u696D\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u3059\u3002\n --temp <directory path>\n \u4E00\u6642\u30D5\u30A1\u30A4\u30EB\u306E\u4F5C\u6210\u306B\u4F7F\u7528\u3055\u308C\u308B\u65B0\u898F\u307E\u305F\u306F\u7A7A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n \u6307\u5B9A\u3057\u305F\u5834\u5408\u3001\u30BF\u30B9\u30AF\u5B8C\u4E86\u6642\u306B\u4E00\u6642\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u524A\u9664\u3055\u308C\u306A\u3044\u305F\u3081\n \u624B\u52D5\u3067\u524A\u9664\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\n \u6307\u5B9A\u3057\u306A\u304B\u3063\u305F\u5834\u5408\u3001\u4E00\u6642\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u4F5C\u6210\u3055\u308C\n \u30BF\u30B9\u30AF\u5B8C\u4E86\u6642\u306B\u524A\u9664\u3055\u308C\u307E\u3059\u3002\n --vendor <vendor string>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30D9\u30F3\u30C0\u30FC\n --verbose\n \u8A73\u7D30\u306A\u51FA\u529B\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n --version\n \u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u51FA\u529B\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\n\n\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:\n --add-modules <module name>[,<module name>...]\n \u8FFD\u52A0\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30AB\u30F3\u30DE(",")\u533A\u5207\u308A\u30EA\u30B9\u30C8\n \u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30EA\u30B9\u30C8\u3068\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB(\u6307\u5B9A\u3057\u305F\u5834\u5408)\n \u304C--add-module\u5F15\u6570\u3068\u3057\u3066jlink\u306B\u6E21\u3055\u308C\u307E\u3059\u3002\n \u6307\u5B9A\u3057\u306A\u304B\u3063\u305F\u5834\u5408\u3001\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u307F(--module\u304C\n \u6307\u5B9A\u3055\u308C\u305F\u5834\u5408)\u3001\u307E\u305F\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30BB\u30C3\u30C8(--main-jar\u304C \n \u6307\u5B9A\u3055\u308C\u305F\u5834\u5408)\u304C\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --module-path -p <module path>...\n \u30D1\u30B9\u306E{0}\u533A\u5207\u308A\u30EA\u30B9\u30C8\n \u5404\u30D1\u30B9\u306F\u3001\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u307E\u305F\u306F\n \u30E2\u30B8\u30E5\u30E9jar\u3078\u306E\u30D1\u30B9\u3067\u3059\u3002\n (\u5404\u30D1\u30B9\u306F\u3001\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9\u3067\u3059\u3002)\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --jlink-options <jlink options> \n jlink\u306B\u6E21\u3059\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30B9\u30DA\u30FC\u30B9\u533A\u5207\u308A\u306E\u30EA\u30B9\u30C8 \n \u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u3001"--strip-native-commands \n --strip-debug --no-man-pages \
|
||||
--no-header-files"\u3002 \n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --runtime-image <directory path>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u306B\u30B3\u30D4\u30FC\u3055\u308C\u308B\u3001\u4E8B\u524D\u5B9A\u7FA9\u6E08\u307F\u306E\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\n \u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n --runtime-image\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u3001jpackage\u306Fjlink\u3092\u5B9F\u884C\u3057\u3001\n \u6B21\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u4F5C\u6210\u3057\u307E\u3059:\n --strip-debug\u3001--no-header-files\u3001--no-man-pages\u304A\u3088\u3073\n --strip-native-commands\u3002\n\n\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:\n --input -i <directory path>\n \u30D1\u30C3\u30B1\u30FC\u30B8\u5316\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3080\u5165\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3078\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n \u5165\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u306B\n \u30D1\u30C3\u30B1\u30FC\u30B8\u5316\u3055\u308C\u307E\u3059\u3002\n --app-content <additional content>[,<additional content>...]\n \u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA(\u3042\u308B\u3044\u306F\u4E21\u65B9)\u306E\u30D1\u30B9\u306E\u30AB\u30F3\u30DE\u533A\u5207\u308A\u306E\u30EA\u30B9\u30C8\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30DA\u30A4\u30ED\u30FC\u30C9\u306B\u8FFD\u52A0\u3057\u307E\u3059\u3002\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n\n\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:\n --add-launcher <launcher name>=<file path>\n \u30E9\u30F3\u30C1\u30E3\u306E\u540D\u524D\u3001\u304A\u3088\u3073\u30AD\u30FC\u3001\u5024\u306E\u30DA\u30A2\u306E\u30EA\u30B9\u30C8\n \u3092\u542B\u3080\u30D7\u30ED\u30D1\u30C6\u30A3\u30FB\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n \u30AD\u30FC"module"\u3001"main-jar"\u3001"main-class"\u3001\n "arguments"\u3001"java-options"\u3001"app-version"\u3001"icon"\u3001\n "win-console"\u3001"win-shortcut"\u3001"win-menu"\u3001\n "linux-app-category"\u304A\u3088\u3073"linux-shortcut"\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n \u3053\u308C\u3089\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u5143\u306E\u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u8FFD\u52A0\u3059\u308B\u304B\u3001\u3053\u308C\u3089\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\n \u4F7F\u7528\u3057\u3066\u5143\u306E\u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4E0A\u66F8\u304D\u3057\u3066\u3001\u8FFD\u52A0\u306E\u4EE3\u66FF\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3057\u307E\u3059\u3002\n \
|
||||
\u30E1\u30A4\u30F3\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30E9\u30F3\u30C1\u30E3\u306F\u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u304B\u3089\u4F5C\u6210\u3055\u308C\u307E\u3059\u3002\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u8FFD\u52A0\u306E\u4EE3\u66FF\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3067\u304D\u3001\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u8907\u6570\u56DE\u4F7F\u7528\u3057\u3066\n \u8907\u6570\u306E\u8FFD\u52A0\u306E\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3067\u304D\u307E\u3059\u3002 \n --arguments <main class arguments>\n \u30E9\u30F3\u30C1\u30E3\u306B\u30B3\u30DE\u30F3\u30C9\u30FB\u30E9\u30A4\u30F3\u5F15\u6570\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u306B\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u306B\u6E21\u3059\n \u30B3\u30DE\u30F3\u30C9\u30FB\u30E9\u30A4\u30F3\u5F15\u6570\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --java-options <java options>\n Java\u30E9\u30F3\u30BF\u30A4\u30E0\u306B\u6E21\u3059\u30AA\u30D7\u30B7\u30E7\u30F3\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --main-class <class name>\n \u5B9F\u884C\u3059\u308B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u306E\u4FEE\u98FE\u540D\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3067\u304D\u308B\u306E\u306F\u3001--main-jar\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3060\u3051\u3067\u3059\u3002\n --main-jar <main jar file>\n \u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u3092\u542B\u3080\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30E1\u30A4\u30F3JAR\n (\u5165\u529B\u30D1\u30B9\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9\u3068\u3057\u3066\u6307\u5B9A)\n --module\u307E\u305F\u306F--main-jar\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3067\u304D\u307E\u3059\u304C\u3001\u4E21\u65B9\u306F\n \u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002\n --module -m <module name>[/<main class>]\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB(\u304A\u3088\u3073\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9)\n \u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u3001\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30D1\u30B9\u306B\u7F6E\u304B\u308C\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\n Java\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u5185\u3067\u30EA\u30F3\u30AF\u3055\u308C\u307E\u3059\u3002--module\u307E\u305F\u306F--main-jar\n \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3067\u304D\u307E\u3059\u304C\u3001\u4E21\u65B9\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002\n{2}\n\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:\n --about-url <url>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30DB\u30FC\u30E0\u30DA\u30FC\u30B8\u306EURL\n --app-image <directory path>\n \u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u53EF\u80FD\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u4F5C\u6210\u306B\u4F7F\u7528\u3059\u308B\u3001\u4E8B\u524D\u5B9A\u7FA9\u6E08\u307F\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u306E\u5834\u6240\n \
|
||||
(\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n --file-associations <file path>\n \u30AD\u30FC\u3001\u5024\u306E\u30DA\u30A2\u306E\u30EA\u30B9\u30C8\u3092\u542B\u3080\u30D7\u30ED\u30D1\u30C6\u30A3\u30FB\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n \u30AD\u30FC"extension"\u3001"mime-type"\u3001"icon"\u3001"description"\n \u3092\u4F7F\u7528\u3057\u3066\u95A2\u9023\u4ED8\u3051\u3092\u8A18\u8FF0\u3067\u304D\u307E\u3059\u3002\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --install-dir <directory path>\n {4} --license-file <file path>\n \u30E9\u30A4\u30BB\u30F3\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n --resource-dir <directory path>\n \u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9jpackage\u30EA\u30BD\u30FC\u30B9\u3078\u306E\u30D1\u30B9\n \u30A2\u30A4\u30B3\u30F3\u3001\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304A\u3088\u3073jpackage\u306E\u305D\u306E\u4ED6\u306E\u30EA\u30BD\u30FC\u30B9\u306F\u3001\n \u3053\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u7F6E\u63DB\u30EA\u30BD\u30FC\u30B9\u3092\u8FFD\u52A0\u3059\u308B\u3053\u3068\u3067\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3067\u304D\u307E\u3059\u3002\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n --runtime-image <directory path>\n \u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3059\u308B\u4E8B\u524D\u5B9A\u7FA9\u6E08\u307F\u306E\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n \u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u4F5C\u6210\u6642\u306B\u306F\u3001\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u5FC5\u8981\u3067\u3059\u3002\n\n\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u4F9D\u5B58\u30AA\u30D7\u30B7\u30E7\u30F3:\n{3}
|
||||
MSG_Help=Usage: jpackage <options>\n\
|
||||
\n\
|
||||
Sample usages:\n\
|
||||
--------------\n\
|
||||
\ Generate an application package suitable for the host system:\n\
|
||||
\ For a modular application:\n\
|
||||
\ jpackage -n name -p modulePath -m moduleName/className\n\
|
||||
\ For a non-modular application:\n\
|
||||
\ jpackage -i inputDir -n name \\\n\
|
||||
\ --main-class className --main-jar myJar.jar\n\
|
||||
\ From a pre-built application image:\n\
|
||||
\ jpackage -n name --app-image appImageDir\n\
|
||||
\ Generate an application image:\n\
|
||||
\ For a modular application:\n\
|
||||
\ jpackage --type app-image -n name -p modulePath \\\n\
|
||||
\ -m moduleName/className\n\
|
||||
\ For a non-modular application:\n\
|
||||
\ jpackage --type app-image -i inputDir -n name \\\n\
|
||||
\ --main-class className --main-jar myJar.jar\n\
|
||||
\ To provide your own options to jlink, run jlink separately:\n\
|
||||
\ jlink --output appRuntimeImage -p modulePath \\\n\
|
||||
\ --add-modules moduleName \\\n\
|
||||
\ --no-header-files [<additional jlink options>...]\n\
|
||||
\ jpackage --type app-image -n name \\\n\
|
||||
\ -m moduleName/className --runtime-image appRuntimeImage\n\
|
||||
\ Generate a Java runtime package:\n\
|
||||
\ jpackage -n name --runtime-image <runtime-image>\n\
|
||||
\n\
|
||||
Generic Options:\n\
|
||||
\ @<filename> \n\
|
||||
\ Read options and/or mode from a file \n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --type -t <type> \n\
|
||||
\ The type of package to create\n\
|
||||
\ Valid values are: {1} \n\
|
||||
\ If this option is not specified a platform dependent\n\
|
||||
\ default type will be created.\n\
|
||||
\ --app-version <version>\n\
|
||||
\ Version of the application and/or package\n\
|
||||
\ --copyright <copyright string>\n\
|
||||
\ Copyright for the application\n\
|
||||
\ --description <description string>\n\
|
||||
\ Description of the application\n\
|
||||
\ --help -h \n\
|
||||
\ Print the usage text with a list and description of each valid\n\
|
||||
\ option for the current platform to the output stream, and exit\n\
|
||||
\ --icon <file path>\n\
|
||||
\ Path of the icon of the application package\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --name -n <name>\n\
|
||||
\ Name of the application and/or package\n\
|
||||
\ --dest -d <destination path>\n\
|
||||
\ Path where generated output file is placed\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ Defaults to the current working directory.\n\
|
||||
\ --temp <directory path>\n\
|
||||
\ Path of a new or empty directory used to create temporary files\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ If specified, the temp dir will not be removed upon the task\n\
|
||||
\ completion and must be removed manually.\n\
|
||||
\ If not specified, a temporary directory will be created and\n\
|
||||
\ removed upon the task completion.\n\
|
||||
\ --vendor <vendor string>\n\
|
||||
\ Vendor of the application\n\
|
||||
\ --verbose\n\
|
||||
\ Enables verbose output\n\
|
||||
\ --version\n\
|
||||
\ Print the product version to the output stream and exit.\n\
|
||||
\n\
|
||||
\Options for creating the runtime image:\n\
|
||||
\ --add-modules <module name>[,<module name>...]\n\
|
||||
\ A comma (",") separated list of modules to add\n\
|
||||
\ This module list, along with the main module (if specified)\n\
|
||||
\ will be passed to jlink as the --add-module argument.\n\
|
||||
\ If not specified, either just the main module (if --module is\n\
|
||||
\ specified), or the default set of modules (if --main-jar is \n\
|
||||
\ specified) are used.\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --module-path -p <module path>...\n\
|
||||
\ A {0} separated list of paths\n\
|
||||
\ Each path is either a directory of modules or the path to a\n\
|
||||
\ modular jar.\n\
|
||||
\ (Each path is absolute or relative to the current directory.)\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --jlink-options <jlink options> \n\
|
||||
\ A space separated list of options to pass to jlink \n\
|
||||
\ If not specified, defaults to "--strip-native-commands \n\
|
||||
\ --strip-debug --no-man-pages --no-header-files". \n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --runtime-image <directory path>\n\
|
||||
\ Path of the predefined runtime image that will be copied into\n\
|
||||
\ the application image\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ If --runtime-image is not specified, jpackage will run jlink to\n\
|
||||
\ create the runtime image using options:\n\
|
||||
\ --strip-debug, --no-header-files, --no-man-pages, and\n\
|
||||
\ --strip-native-commands.\n\
|
||||
\n\
|
||||
\Options for creating the application image:\n\
|
||||
\ --input -i <directory path>\n\
|
||||
\ Path of the input directory that contains the files to be packaged\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ All files in the input directory will be packaged into the\n\
|
||||
\ application image.\n\
|
||||
\ --app-content <additional content>[,<additional content>...]\n\
|
||||
\ A comma separated list of paths to files and/or directories\n\
|
||||
\ to add to the application payload.\n\
|
||||
\ This option can be used more than once.\n\
|
||||
\n\
|
||||
\Options for creating the application launcher(s):\n\
|
||||
\ --add-launcher <launcher name>=<file path>\n\
|
||||
\ Name of launcher, and a path to a Properties file that contains\n\
|
||||
\ a list of key, value pairs\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ The keys "module", "main-jar", "main-class",\n\
|
||||
\ "arguments", "java-options", "app-version", "icon",\n\
|
||||
\ "launcher-as-service",\n\
|
||||
\ "win-console", "win-shortcut", "win-menu",\n\
|
||||
\ "linux-app-category", and "linux-shortcut" can be used.\n\
|
||||
\ These options are added to, or used to overwrite, the original\n\
|
||||
\ command line options to build an additional alternative launcher.\n\
|
||||
\ The main application launcher will be built from the command line\n\
|
||||
\ options. Additional alternative launchers can be built using\n\
|
||||
\ this option, and this option can be used multiple times to\n\
|
||||
\ build multiple additional launchers. \n\
|
||||
\ --arguments <main class arguments>\n\
|
||||
\ Command line arguments to pass to the main class if no command\n\
|
||||
\ line arguments are given to the launcher\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --java-options <java options>\n\
|
||||
\ Options to pass to the Java runtime\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --main-class <class name>\n\
|
||||
\ Qualified name of the application main class to execute\n\
|
||||
\ This option can only be used if --main-jar is specified.\n\
|
||||
\ --main-jar <main jar file>\n\
|
||||
\ The main JAR of the application; containing the main class\n\
|
||||
\ (specified as a path relative to the input path)\n\
|
||||
\ Either --module or --main-jar option can be specified but not\n\
|
||||
\ both.\n\
|
||||
\ --module -m <module name>[/<main class>]\n\
|
||||
\ The main module (and optionally main class) of the application\n\
|
||||
\ This module must be located on the module path.\n\
|
||||
\ When this option is specified, the main module will be linked\n\
|
||||
\ in the Java runtime image. Either --module or --main-jar\n\
|
||||
\ option can be specified but not both.\n\
|
||||
{2}\n\
|
||||
\Options for creating the application package:\n\
|
||||
\ --about-url <url>\n\
|
||||
\ URL of the application''s home page\n\
|
||||
\ --app-image <directory path>\n\
|
||||
\ Location of the predefined application image that is used\n\
|
||||
\ to build an installable package\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --file-associations <file path>\n\
|
||||
\ Path to a Properties file that contains list of key, value pairs\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ The keys "extension", "mime-type", "icon", and "description"\n\
|
||||
\ can be used to describe the association.\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --install-dir <directory path>\n\
|
||||
\ {4}\
|
||||
\ --license-file <file path>\n\
|
||||
\ Path to the license file\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --resource-dir <directory path>\n\
|
||||
\ Path to override jpackage resources\n\
|
||||
\ Icons, template files, and other resources of jpackage can be\n\
|
||||
\ over-ridden by adding replacement resources to this directory.\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --runtime-image <directory path>\n\
|
||||
\ Path of the predefined runtime image to install\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ Option is required when creating a runtime package.\n\
|
||||
\ --launcher-as-service\n\
|
||||
\ Request to create an installer that will register the main\n\
|
||||
\ application launcher as a background service-type application.\n\
|
||||
\n\
|
||||
\Platform dependent options for creating the application package:\n\
|
||||
{3}
|
||||
|
||||
MSG_Help_win_launcher=\n\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u4F9D\u5B58\u30AA\u30D7\u30B7\u30E7\u30F3:\n --win-console\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30B3\u30F3\u30BD\u30FC\u30EB\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3057\u307E\u3059\u3002\u30B3\u30F3\u30BD\u30FC\u30EB\u30FB\n \u30A4\u30F3\u30BF\u30E9\u30AF\u30B7\u30E7\u30F3\u304C\u5FC5\u8981\u306A\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306B\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\n
|
||||
MSG_Help_win_install=\ --win-dir-chooser\n \u30E6\u30FC\u30B6\u30FC\u304C\u88FD\u54C1\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3059\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u9078\u629E\u3059\u308B\u305F\u3081\u306E\n \u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002\n --win-help-url <url>\n \u30E6\u30FC\u30B6\u30FC\u304C\u8A73\u7D30\u60C5\u5831\u307E\u305F\u306F\u6280\u8853\u7684\u306A\u30B5\u30DD\u30FC\u30C8\u3092\u53D6\u5F97\u3067\u304D\u308BURL\n --win-menu\n \u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30B9\u30BF\u30FC\u30C8\u30FB\u30E1\u30CB\u30E5\u30FC\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u8FFD\u52A0\u3059\u308B\u3088\u3046\u306B\u30EA\u30AF\u30A8\u30B9\u30C8\u3057\u307E\u3059\n --win-menu-group <menu group name>\n \u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u914D\u7F6E\u3059\u308B\u30B9\u30BF\u30FC\u30C8\u30FB\u30E1\u30CB\u30E5\u30FC\u30FB\u30B0\u30EB\u30FC\u30D7\n --win-per-user-install\n \u30E6\u30FC\u30B6\u30FC\u3054\u3068\u306B\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3092\u5B9F\u884C\u3059\u308B\u3088\u3046\u306B\u30EA\u30AF\u30A8\u30B9\u30C8\u3057\u307E\u3059\n --win-shortcut\n \u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u8FFD\u52A0\u3059\u308B\u3088\u3046\u306B\u30EA\u30AF\u30A8\u30B9\u30C8\u3057\u307E\u3059\n --win-shortcut-prompt\n \u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u3067\u4F5C\u6210\u3059\u308B\u304B\u3069\u3046\u304B\u3092\u30E6\u30FC\u30B6\u30FC\u304C\u9078\u629E\u3067\u304D\u308B\u3088\u3046\u306B\u3059\u308B\n \u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002\n --win-update-url <url>\n \u4F7F\u7528\u53EF\u80FD\u306A\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u66F4\u65B0\u60C5\u5831\u306EURL\n --win-upgrade-uuid <id string>\n \u3053\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u306B\u95A2\u9023\u4ED8\u3051\u3089\u308C\u305FUUID\n
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,10 +24,186 @@
|
||||
#
|
||||
#
|
||||
|
||||
MSG_Help=\u7528\u6CD5\uFF1Ajpackage <options>\n\n\u793A\u4F8B\u7528\u6CD5:\n--------------\n \u751F\u6210\u9002\u5408\u4E3B\u673A\u7CFB\u7EDF\u7684\u5E94\u7528\u7A0B\u5E8F\u5305\uFF1A\n \u5BF9\u4E8E\u6A21\u5757\u5316\u5E94\u7528\u7A0B\u5E8F\uFF1A\n jpackage -n name -p modulePath -m moduleName/className\n \u5BF9\u4E8E\u975E\u6A21\u5757\u5316\u5E94\u7528\u7A0B\u5E8F\uFF1A\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n \u4ECE\u9884\u6784\u5EFA\u7684\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\uFF1A\n jpackage -n name --app-image appImageDir\n \u751F\u6210\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\uFF1A\n \u5BF9\u4E8E\u6A21\u5757\u5316\u5E94\u7528\u7A0B\u5E8F\uFF1A\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n \u5BF9\u4E8E\u975E\u6A21\u5757\u5316\u5E94\u7528\u7A0B\u5E8F\uFF1A\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n \u8981\u4E3A jlink \u63D0\u4F9B\u60A8\u81EA\u5DF1\u7684\u9009\u9879\uFF0C\u8BF7\u5355\u72EC\u8FD0\u884C jlink\uFF1A\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [<additional jlink options>...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage\n \u751F\u6210 Java \u8FD0\u884C\u65F6\u7A0B\u5E8F\u5305\uFF1A\n jpackage -n name --runtime-image <runtime-image>\n\n\u4E00\u822C\u9009\u9879\uFF1A\n @<filename> \n \u4ECE\u6587\u4EF6\u8BFB\u53D6\u9009\u9879\u548C/\u6216\u6A21\u5F0F \n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --type -t <type> \n \u8981\u521B\u5EFA\u7684\u7A0B\u5E8F\u5305\u7684\u7C7B\u578B\n \u6709\u6548\u503C\u4E3A\uFF1A{1} \n \u5982\u679C\u672A\u6307\u5B9A\u6B64\u9009\u9879\uFF0C\u5219\u5C06\u521B\u5EFA\u4E0E\u5E73\u53F0\u76F8\u5173\u7684\n \u9ED8\u8BA4\u7C7B\u578B\u3002\n --app-version <version>\n \u5E94\u7528\u7A0B\u5E8F\u548C/\u6216\u7A0B\u5E8F\u5305\u7684\u7248\u672C\n --copyright <copyright string>\n \u5E94\u7528\u7A0B\u5E8F\u7684\u7248\u6743\n --description <description string>\n \u5E94\u7528\u7A0B\u5E8F\u7684\u8BF4\u660E\n --help -h \n \u5C06\u7528\u6CD5\u6587\u672C\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\u5E76\u9000\u51FA\uFF0C\u7528\u6CD5\u6587\u672C\u4E2D\u5305\u542B\n \u9002\u7528\u4E8E\u5F53\u524D\u5E73\u53F0\u7684\u6BCF\u4E2A\u6709\u6548\u9009\u9879\u7684\u5217\u8868\u548C\u8BF4\u660E\n --icon <file path>\n \u5E94\u7528\u7A0B\u5E8F\u5305\u56FE\u6807\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n --name -n <name>\n \u5E94\u7528\u7A0B\u5E8F\u548C/\u6216\u7A0B\u5E8F\u5305\u7684\u540D\u79F0\n --dest -d <destination path>\n \u7528\u6765\u653E\u7F6E\u6240\u751F\u6210\u7684\u8F93\u51FA\u6587\u4EF6\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \u9ED8\u8BA4\u4E3A\u5F53\u524D\u7684\u5DE5\u4F5C\u76EE\u5F55\u3002\n --temp <directory path>\n \u7528\u6765\u521B\u5EFA\u4E34\u65F6\u6587\u4EF6\u7684\u65B0\u76EE\u5F55\u6216\u7A7A\u767D\u76EE\u5F55\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \u5982\u679C\u6307\u5B9A\uFF0C\u5219\u5728\u4EFB\u52A1\u5B8C\u6210\u65F6\u5C06\u4E0D\u5220\u9664\u4E34\u65F6\u76EE\u5F55\uFF0C\n \u5FC5\u987B\u624B\u52A8\u5220\u9664\u4E34\u65F6\u76EE\u5F55\u3002\n \u5982\u679C\u672A\u6307\u5B9A\uFF0C\u5219\u5C06\u521B\u5EFA\u4E00\u4E2A\u4E34\u65F6\u76EE\u5F55\uFF0C\n \
|
||||
\u5E76\u5728\u4EFB\u52A1\u5B8C\u6210\u65F6\u5220\u9664\u8BE5\u4E34\u65F6\u76EE\u5F55\u3002\n --vendor <vendor string>\n \u5E94\u7528\u7A0B\u5E8F\u7684\u4F9B\u5E94\u5546\n --verbose\n \u542F\u7528\u8BE6\u7EC6\u7684\u8F93\u51FA\n --version\n \u5C06\u4EA7\u54C1\u7248\u672C\u8F93\u51FA\u5230\u8F93\u51FA\u6D41\u5E76\u9000\u51FA\u3002\n\n\u7528\u6765\u521B\u5EFA\u8FD0\u884C\u65F6\u6620\u50CF\u7684\u9009\u9879\uFF1A\n --add-modules <\u6A21\u5757\u540D\u79F0>[,<\u6A21\u5757\u540D\u79F0>...]\n \u8981\u6DFB\u52A0\u7684\u6A21\u5757\u7684\u9017\u53F7 (",") \u5206\u9694\u5217\u8868\n \u6B64\u6A21\u5757\u5217\u8868\u8FDE\u540C\u4E3B\u6A21\u5757\uFF08\u5982\u679C\u6307\u5B9A\uFF09\n \u5C06\u4F5C\u4E3A --add-module \u53C2\u6570\u4F20\u9012\u5230 jlink\u3002\n \u5982\u679C\u672A\u6307\u5B9A\uFF0C\u5219\u4EC5\u4F7F\u7528\u4E3B\u6A21\u5757\uFF08\u5982\u679C\u6307\u5B9A\u4E86 --module\uFF09\uFF0C\n \u6216\u8005\u4F7F\u7528\u9ED8\u8BA4\u7684\u6A21\u5757\u96C6\uFF08\u5982\u679C\u6307\u5B9A\u4E86 \n --main-jar\uFF09\u3002\n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --module-path -p <module path>...\n \u8DEF\u5F84\u7684 {0} \u5206\u9694\u5217\u8868\n \u6BCF\u4E2A\u8DEF\u5F84\u8981\u4E48\u662F\u6A21\u5757\u7684\u76EE\u5F55\uFF0C\u8981\u4E48\u662F\n \u6A21\u5757 jar \u7684\u8DEF\u5F84\u3002\n \uFF08\u6BCF\u4E2A\u8DEF\u5F84\u53EF\u4EE5\u662F\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u4E5F\u53EF\u4EE5\u662F\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\u3002\uFF09\n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --jlink-options <jlink \u9009\u9879> \n \u8981\u4F20\u9012\u7ED9 jlink \u7684\u9009\u9879\u5217\u8868\uFF08\u7528\u7A7A\u683C\u5206\u9694\uFF09 \n \u5982\u679C\u672A\u6307\u5B9A\uFF0C\u5219\u9ED8\u8BA4\u4E3A "--strip-native-commands \n --strip-debug --no-man-pages --no-header-files"\u3002 \n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --runtime-image <directory path>\n \u5C06\u590D\u5236\u5230\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u7684\u9884\u5B9A\u4E49\n \u8FD0\u884C\u65F6\u6620\u50CF\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \u5982\u679C\u672A\u6307\u5B9A --runtime-image\uFF0Cjpackage \u5C06\u8FD0\u884C jlink \u4EE5\n \u4F7F\u7528\u5982\u4E0B\u9009\u9879\u521B\u5EFA\u8FD0\u884C\u65F6\u6620\u50CF\uFF1A\n --strip-debug\u3001--no-header-files\u3001--no-man-pages \u548C \n --strip-native-commands\u3002\n\n\u7528\u6765\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u7684\u9009\u9879\uFF1A\n --input -i <directory path>\n \u5305\u542B\u8981\u6253\u5305\u7684\u6587\u4EF6\u7684\u8F93\u5165\u76EE\u5F55\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \u8F93\u5165\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u5C06\u6253\u5305\u5230\n \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u4E2D\u3002\n --app-content <additional content>[,<additional content>...]\n \u8981\u6DFB\u52A0\u5230\u5E94\u7528\u7A0B\u5E8F\u6709\u6548\u8D1F\u8F7D\u4E2D\u7684\u6587\u4EF6\u548C/\u6216\n \u76EE\u5F55\u7684\u9017\u53F7\u5206\u9694\u8DEF\u5F84\u5217\u8868\u3002\n \u6B64\u9009\u9879\u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u3002\n\n\u7528\u6765\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u542F\u52A8\u7A0B\u5E8F\u7684\u9009\u9879\uFF1A\n --add-launcher <launcher name>=<file path>\n \u542F\u52A8\u7A0B\u5E8F\u7684\u540D\u79F0\u548C\u5305\u542B\u5173\u952E\u5B57-\u503C\u5BF9\u5217\u8868\u7684\n \u5C5E\u6027\u6587\u4EF6\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \
|
||||
\u53EF\u4EE5\u4F7F\u7528\u5173\u952E\u5B57 "module"\u3001"main-jar"\u3001"main-class"\u3001\n "arguments"\u3001"java-options"\u3001"app-version"\u3001"icon"\u3001\n "win-console"\u3001"win-shortcut"\u3001"win-menu"\u3001\n "linux-app-category" \u548C "linux-shortcut"\u3002\n \u8FD9\u4E9B\u9009\u9879\u5C06\u6DFB\u52A0\u5230\u539F\u59CB\u547D\u4EE4\u884C\u9009\u9879\u4E2D\u6216\u8005\u7528\u6765\u8986\u76D6\n \u539F\u59CB\u547D\u4EE4\u884C\u9009\u9879\uFF0C\u4EE5\u6784\u5EFA\u989D\u5916\u7684\u66FF\u4EE3\u542F\u52A8\u7A0B\u5E8F\u3002\n \u5C06\u4ECE\u547D\u4EE4\u884C\u9009\u9879\u6784\u5EFA\u4E3B\u5E94\u7528\u7A0B\u5E8F\u542F\u52A8\u7A0B\u5E8F\u3002\n \u53EF\u4EE5\u4F7F\u7528\u6B64\u9009\u9879\u6784\u5EFA\u989D\u5916\u7684\u66FF\u4EE3\u542F\u52A8\u7A0B\u5E8F\uFF0C\n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u6765\u6784\u5EFA\n \u591A\u4E2A\u989D\u5916\u7684\u542F\u52A8\u7A0B\u5E8F\u3002 \n --arguments <main class arguments>\n \u5728\u6CA1\u6709\u4E3A\u542F\u52A8\u7A0B\u5E8F\u63D0\u4F9B\u547D\u4EE4\u884C\u53C2\u6570\u65F6\uFF0C\n \u8981\u4F20\u9012\u5230\u4E3B\u7C7B\u7684\u547D\u4EE4\u884C\u53C2\u6570\n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --java-options <java options>\n \u8981\u4F20\u9012\u5230 Java \u8FD0\u884C\u65F6\u7684\u9009\u9879\n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --main-class <class name>\n \u8981\u6267\u884C\u7684\u5E94\u7528\u7A0B\u5E8F\u4E3B\u7C7B\u7684\u9650\u5B9A\u540D\u79F0\n \u53EA\u6709\u5728\u6307\u5B9A\u4E86 --main-jar \u65F6\u624D\u80FD\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --main-jar <main jar file>\n \u5E94\u7528\u7A0B\u5E8F\u7684\u4E3B JAR\uFF1B\u5305\u542B\u4E3B\u7C7B\n \uFF08\u6307\u5B9A\u4E3A\u76F8\u5BF9\u4E8E\u8F93\u5165\u8DEF\u5F84\u7684\u8DEF\u5F84\uFF09\n \u53EF\u4EE5\u6307\u5B9A --module \u6216 --main-jar \u9009\u9879\uFF0C\u4F46\u662F\u4E0D\u80FD\u540C\u65F6\u6307\u5B9A\n \u4E24\u8005\u3002\n --module -m <module name>[/<main class>]\n \u5E94\u7528\u7A0B\u5E8F\u7684\u4E3B\u6A21\u5757\uFF08\u4EE5\u53CA\u53EF\u9009\u7684\u4E3B\u7C7B\uFF09\n \u6B64\u6A21\u5757\u5FC5\u987B\u4F4D\u4E8E\u6A21\u5757\u8DEF\u5F84\u4E2D\u3002\n \u5982\u679C\u6307\u5B9A\u4E86\u6B64\u9009\u9879\uFF0C\u5219\u5C06\u5728 Java \u8FD0\u884C\u65F6\u6620\u50CF\u4E2D\n \u94FE\u63A5\u4E3B\u6A21\u5757\u3002\u53EF\u4EE5\u6307\u5B9A --module \u6216 --main-jar \u9009\u9879\uFF0C\n \u4F46\u662F\u4E0D\u80FD\u540C\u65F6\u6307\u5B9A\u8FD9\u4E24\u4E2A\u9009\u9879\u3002\n{2}\n\u7528\u6765\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u5305\u7684\u9009\u9879\uFF1A\n --about-url <url>\n \u5E94\u7528\u7A0B\u5E8F\u4E3B\u9875\u7684 URL\n --app-image <directory path>\n \u7528\u6765\u6784\u5EFA\u53EF\u5B89\u88C5\u7A0B\u5E8F\u5305\u7684\n \u9884\u5B9A\u4E49\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u7684\u4F4D\u7F6E\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n --file-associations <file path>\n \u5305\u542B\u5173\u952E\u5B57-\u503C\u5BF9\u5217\u8868\u7684\u5C5E\u6027\u6587\u4EF6\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \u53EF\u4EE5\u4F7F\u7528\u5173\u952E\u5B57 "extension"\u3001"mime-type"\u3001"icon" \u548C "description" \n \u6765\u63CF\u8FF0\u6B64\u5173\u8054\u3002\n \u53EF\u4EE5\u591A\u6B21\u4F7F\u7528\u6B64\u9009\u9879\u3002\n --install-dir <directory path>\n {4} --license-file <file path>\n \u8BB8\u53EF\u8BC1\u6587\u4EF6\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n --resource-dir <directory path>\n \u8986\u76D6 jpackage \
|
||||
\u8D44\u6E90\u7684\u8DEF\u5F84\n \u53EF\u4EE5\u901A\u8FC7\u5411\u8BE5\u76EE\u5F55\u4E2D\u6DFB\u52A0\u66FF\u4EE3\u8D44\u6E90\u6765\u8986\u76D6 jpackage \u7684\n \u56FE\u6807\u3001\u6A21\u677F\u6587\u4EF6\u548C\u5176\u4ED6\u8D44\u6E90\u3002\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n --runtime-image <directory path>\n \u8981\u5B89\u88C5\u7684\u9884\u5B9A\u4E49\u8FD0\u884C\u65F6\u6620\u50CF\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \u5728\u521B\u5EFA\u8FD0\u884C\u65F6\u7A0B\u5E8F\u5305\u65F6\u9700\u8981\u4F7F\u7528\u9009\u9879\u3002\n\n\u7528\u6765\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u5305\u7684\u4E0E\u5E73\u53F0\u76F8\u5173\u7684\u9009\u9879\uFF1A\n{3}
|
||||
MSG_Help=Usage: jpackage <options>\n\
|
||||
\n\
|
||||
Sample usages:\n\
|
||||
--------------\n\
|
||||
\ Generate an application package suitable for the host system:\n\
|
||||
\ For a modular application:\n\
|
||||
\ jpackage -n name -p modulePath -m moduleName/className\n\
|
||||
\ For a non-modular application:\n\
|
||||
\ jpackage -i inputDir -n name \\\n\
|
||||
\ --main-class className --main-jar myJar.jar\n\
|
||||
\ From a pre-built application image:\n\
|
||||
\ jpackage -n name --app-image appImageDir\n\
|
||||
\ Generate an application image:\n\
|
||||
\ For a modular application:\n\
|
||||
\ jpackage --type app-image -n name -p modulePath \\\n\
|
||||
\ -m moduleName/className\n\
|
||||
\ For a non-modular application:\n\
|
||||
\ jpackage --type app-image -i inputDir -n name \\\n\
|
||||
\ --main-class className --main-jar myJar.jar\n\
|
||||
\ To provide your own options to jlink, run jlink separately:\n\
|
||||
\ jlink --output appRuntimeImage -p modulePath \\\n\
|
||||
\ --add-modules moduleName \\\n\
|
||||
\ --no-header-files [<additional jlink options>...]\n\
|
||||
\ jpackage --type app-image -n name \\\n\
|
||||
\ -m moduleName/className --runtime-image appRuntimeImage\n\
|
||||
\ Generate a Java runtime package:\n\
|
||||
\ jpackage -n name --runtime-image <runtime-image>\n\
|
||||
\n\
|
||||
Generic Options:\n\
|
||||
\ @<filename> \n\
|
||||
\ Read options and/or mode from a file \n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --type -t <type> \n\
|
||||
\ The type of package to create\n\
|
||||
\ Valid values are: {1} \n\
|
||||
\ If this option is not specified a platform dependent\n\
|
||||
\ default type will be created.\n\
|
||||
\ --app-version <version>\n\
|
||||
\ Version of the application and/or package\n\
|
||||
\ --copyright <copyright string>\n\
|
||||
\ Copyright for the application\n\
|
||||
\ --description <description string>\n\
|
||||
\ Description of the application\n\
|
||||
\ --help -h \n\
|
||||
\ Print the usage text with a list and description of each valid\n\
|
||||
\ option for the current platform to the output stream, and exit\n\
|
||||
\ --icon <file path>\n\
|
||||
\ Path of the icon of the application package\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --name -n <name>\n\
|
||||
\ Name of the application and/or package\n\
|
||||
\ --dest -d <destination path>\n\
|
||||
\ Path where generated output file is placed\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ Defaults to the current working directory.\n\
|
||||
\ --temp <directory path>\n\
|
||||
\ Path of a new or empty directory used to create temporary files\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ If specified, the temp dir will not be removed upon the task\n\
|
||||
\ completion and must be removed manually.\n\
|
||||
\ If not specified, a temporary directory will be created and\n\
|
||||
\ removed upon the task completion.\n\
|
||||
\ --vendor <vendor string>\n\
|
||||
\ Vendor of the application\n\
|
||||
\ --verbose\n\
|
||||
\ Enables verbose output\n\
|
||||
\ --version\n\
|
||||
\ Print the product version to the output stream and exit.\n\
|
||||
\n\
|
||||
\Options for creating the runtime image:\n\
|
||||
\ --add-modules <module name>[,<module name>...]\n\
|
||||
\ A comma (",") separated list of modules to add\n\
|
||||
\ This module list, along with the main module (if specified)\n\
|
||||
\ will be passed to jlink as the --add-module argument.\n\
|
||||
\ If not specified, either just the main module (if --module is\n\
|
||||
\ specified), or the default set of modules (if --main-jar is \n\
|
||||
\ specified) are used.\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --module-path -p <module path>...\n\
|
||||
\ A {0} separated list of paths\n\
|
||||
\ Each path is either a directory of modules or the path to a\n\
|
||||
\ modular jar.\n\
|
||||
\ (Each path is absolute or relative to the current directory.)\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --jlink-options <jlink options> \n\
|
||||
\ A space separated list of options to pass to jlink \n\
|
||||
\ If not specified, defaults to "--strip-native-commands \n\
|
||||
\ --strip-debug --no-man-pages --no-header-files". \n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --runtime-image <directory path>\n\
|
||||
\ Path of the predefined runtime image that will be copied into\n\
|
||||
\ the application image\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ If --runtime-image is not specified, jpackage will run jlink to\n\
|
||||
\ create the runtime image using options:\n\
|
||||
\ --strip-debug, --no-header-files, --no-man-pages, and\n\
|
||||
\ --strip-native-commands.\n\
|
||||
\n\
|
||||
\Options for creating the application image:\n\
|
||||
\ --input -i <directory path>\n\
|
||||
\ Path of the input directory that contains the files to be packaged\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ All files in the input directory will be packaged into the\n\
|
||||
\ application image.\n\
|
||||
\ --app-content <additional content>[,<additional content>...]\n\
|
||||
\ A comma separated list of paths to files and/or directories\n\
|
||||
\ to add to the application payload.\n\
|
||||
\ This option can be used more than once.\n\
|
||||
\n\
|
||||
\Options for creating the application launcher(s):\n\
|
||||
\ --add-launcher <launcher name>=<file path>\n\
|
||||
\ Name of launcher, and a path to a Properties file that contains\n\
|
||||
\ a list of key, value pairs\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ The keys "module", "main-jar", "main-class",\n\
|
||||
\ "arguments", "java-options", "app-version", "icon",\n\
|
||||
\ "launcher-as-service",\n\
|
||||
\ "win-console", "win-shortcut", "win-menu",\n\
|
||||
\ "linux-app-category", and "linux-shortcut" can be used.\n\
|
||||
\ These options are added to, or used to overwrite, the original\n\
|
||||
\ command line options to build an additional alternative launcher.\n\
|
||||
\ The main application launcher will be built from the command line\n\
|
||||
\ options. Additional alternative launchers can be built using\n\
|
||||
\ this option, and this option can be used multiple times to\n\
|
||||
\ build multiple additional launchers. \n\
|
||||
\ --arguments <main class arguments>\n\
|
||||
\ Command line arguments to pass to the main class if no command\n\
|
||||
\ line arguments are given to the launcher\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --java-options <java options>\n\
|
||||
\ Options to pass to the Java runtime\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --main-class <class name>\n\
|
||||
\ Qualified name of the application main class to execute\n\
|
||||
\ This option can only be used if --main-jar is specified.\n\
|
||||
\ --main-jar <main jar file>\n\
|
||||
\ The main JAR of the application; containing the main class\n\
|
||||
\ (specified as a path relative to the input path)\n\
|
||||
\ Either --module or --main-jar option can be specified but not\n\
|
||||
\ both.\n\
|
||||
\ --module -m <module name>[/<main class>]\n\
|
||||
\ The main module (and optionally main class) of the application\n\
|
||||
\ This module must be located on the module path.\n\
|
||||
\ When this option is specified, the main module will be linked\n\
|
||||
\ in the Java runtime image. Either --module or --main-jar\n\
|
||||
\ option can be specified but not both.\n\
|
||||
{2}\n\
|
||||
\Options for creating the application package:\n\
|
||||
\ --about-url <url>\n\
|
||||
\ URL of the application''s home page\n\
|
||||
\ --app-image <directory path>\n\
|
||||
\ Location of the predefined application image that is used\n\
|
||||
\ to build an installable package\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --file-associations <file path>\n\
|
||||
\ Path to a Properties file that contains list of key, value pairs\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ The keys "extension", "mime-type", "icon", and "description"\n\
|
||||
\ can be used to describe the association.\n\
|
||||
\ This option can be used multiple times.\n\
|
||||
\ --install-dir <directory path>\n\
|
||||
\ {4}\
|
||||
\ --license-file <file path>\n\
|
||||
\ Path to the license file\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --resource-dir <directory path>\n\
|
||||
\ Path to override jpackage resources\n\
|
||||
\ Icons, template files, and other resources of jpackage can be\n\
|
||||
\ over-ridden by adding replacement resources to this directory.\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ --runtime-image <directory path>\n\
|
||||
\ Path of the predefined runtime image to install\n\
|
||||
\ (absolute path or relative to the current directory)\n\
|
||||
\ Option is required when creating a runtime package.\n\
|
||||
\ --launcher-as-service\n\
|
||||
\ Request to create an installer that will register the main\n\
|
||||
\ application launcher as a background service-type application.\n\
|
||||
\n\
|
||||
\Platform dependent options for creating the application package:\n\
|
||||
{3}
|
||||
|
||||
MSG_Help_win_launcher=\n\u7528\u6765\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u542F\u52A8\u7A0B\u5E8F\u7684\u4E0E\u5E73\u53F0\u76F8\u5173\u7684\u9009\u9879\uFF1A\n --win-console\n \u4E3A\u5E94\u7528\u7A0B\u5E8F\u521B\u5EFA\u63A7\u5236\u53F0\u542F\u52A8\u7A0B\u5E8F\uFF0C\u5E94\u5F53\u4E3A\n \u9700\u8981\u63A7\u5236\u53F0\u4EA4\u4E92\u7684\u5E94\u7528\u7A0B\u5E8F\u6307\u5B9A\n
|
||||
MSG_Help_win_install=\ --win-dir-chooser\n \u6DFB\u52A0\u4E00\u4E2A\u5BF9\u8BDD\u6846\u4EE5\u5141\u8BB8\u7528\u6237\u9009\u62E9\n \u4EA7\u54C1\u7684\u5B89\u88C5\u76EE\u5F55\u3002\n --win-help-url <url>\n \u7528\u6237\u53EF\u4EE5\u4ECE\u4E2D\u83B7\u53D6\u66F4\u591A\u4FE1\u606F\u6216\u6280\u672F\u652F\u6301\u7684 URL\n --win-menu\n \u8BF7\u6C42\u4E3A\u6B64\u5E94\u7528\u7A0B\u5E8F\u6DFB\u52A0\u5F00\u59CB\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\n --win-menu-group <menu group name>\n \u6B64\u5E94\u7528\u7A0B\u5E8F\u6240\u5728\u7684\u5F00\u59CB\u83DC\u5355\u7EC4\n --win-per-user-install\n \u8BF7\u6C42\u57FA\u4E8E\u6BCF\u4E2A\u7528\u6237\u6267\u884C\u5B89\u88C5\n --win-shortcut\n \u8BF7\u6C42\u4E3A\u6B64\u5E94\u7528\u7A0B\u5E8F\u6DFB\u52A0\u684C\u9762\u5FEB\u6377\u65B9\u5F0F\n --win-shortcut-prompt\n \u6DFB\u52A0\u4E00\u4E2A\u5BF9\u8BDD\u6846\u4EE5\u5141\u8BB8\u7528\u6237\u9009\u62E9\u662F\u5426\u5C06\u7531\u5B89\u88C5\u7A0B\u5E8F\n \u521B\u5EFA\u5FEB\u6377\u65B9\u5F0F\u3002\n --win-update-url <url>\n \u53EF\u7528\u5E94\u7528\u7A0B\u5E8F\u66F4\u65B0\u4FE1\u606F\u7684 URL\n --win-upgrade-uuid <id string>\n \u4E0E\u6B64\u7A0B\u5E8F\u5305\u7684\u5347\u7EA7\u76F8\u5173\u8054\u7684 UUID\n
|
||||
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Shell scripts of a package.
|
||||
*/
|
||||
final class PackageScripts<T extends Enum<T> & Supplier<OverridableResource>> {
|
||||
|
||||
static <T extends Enum<T> & Supplier<OverridableResource>> PackageScripts<T> create(
|
||||
Class<T> scriptIdsType) {
|
||||
return new PackageScripts<>(scriptIdsType);
|
||||
}
|
||||
|
||||
PackageScripts(Class<T> scriptIdsType) {
|
||||
scripts = EnumSet.allOf(scriptIdsType).stream().collect(
|
||||
Collectors.toMap(UnaryOperator.identity(), scriptId -> {
|
||||
return new ShellScriptResource(scriptId.name()).setResource(
|
||||
scriptId.get());
|
||||
}));
|
||||
}
|
||||
|
||||
PackageScripts<T> setSubstitutionData(T id, Map<String, String> data) {
|
||||
scripts.get(id).getResource().setSubstitutionData(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
PackageScripts<T> setSubstitutionData(Map<String, String> data) {
|
||||
scripts.values().forEach(
|
||||
script -> script.getResource().setSubstitutionData(data));
|
||||
return this;
|
||||
}
|
||||
|
||||
PackageScripts<T> setResourceDir(Path v) throws IOException {
|
||||
for (var script : scripts.values()) {
|
||||
script.getResource().setResourceDir(v);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void saveInFolder(Path folder) throws IOException {
|
||||
for (var script : scripts.values()) {
|
||||
script.saveInFolder(folder);
|
||||
}
|
||||
}
|
||||
|
||||
static class ResourceConfig {
|
||||
|
||||
ResourceConfig(String defaultName, String categoryId) {
|
||||
this.defaultName = defaultName;
|
||||
this.category = I18N.getString(categoryId);
|
||||
}
|
||||
|
||||
OverridableResource createResource() {
|
||||
var resource = new OverridableResource(defaultName).setCategory(category);
|
||||
return getDefaultPublicName().map(resource::setPublicName).orElse(
|
||||
resource);
|
||||
}
|
||||
|
||||
private Optional<String> getDefaultPublicName() {
|
||||
final String wellKnownSuffix = ".template";
|
||||
if (defaultName.endsWith(wellKnownSuffix)) {
|
||||
return Optional.of(defaultName.substring(0, defaultName.length()
|
||||
- wellKnownSuffix.length()));
|
||||
}
|
||||
return Optional.ofNullable(null);
|
||||
}
|
||||
|
||||
private final String defaultName;
|
||||
private final String category;
|
||||
}
|
||||
|
||||
private final Map<T, ShellScriptResource> scripts;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Interface to add custom actions composed of shell commands to installers.
|
||||
*/
|
||||
abstract class ShellCustomAction {
|
||||
|
||||
List<String> requiredPackages() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final Map<String, String> create() throws IOException {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
replacementStringIds().forEach(key -> {
|
||||
result.put(key, "");
|
||||
});
|
||||
result.putAll(createImpl());
|
||||
return result;
|
||||
}
|
||||
|
||||
protected List<String> replacementStringIds() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected abstract Map<String, String> createImpl() throws IOException;
|
||||
|
||||
static ShellCustomAction nop(List<String> replacementStringIds) {
|
||||
return new ShellCustomAction() {
|
||||
@Override
|
||||
protected List<String> replacementStringIds() {
|
||||
return replacementStringIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> createImpl() throws IOException {
|
||||
return Map.of();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected static String stringifyShellCommands(String... commands) {
|
||||
return stringifyShellCommands(Arrays.asList(commands));
|
||||
}
|
||||
|
||||
protected static String stringifyShellCommands(List<String> commands) {
|
||||
return String.join("\n", commands.stream().filter(
|
||||
s -> s != null && !s.isEmpty()).toList());
|
||||
}
|
||||
|
||||
protected static String stringifyTextFile(String resourceName) throws IOException {
|
||||
try ( InputStream is = OverridableResource.readDefault(resourceName);
|
||||
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
|
||||
BufferedReader reader = new BufferedReader(isr)) {
|
||||
return reader.lines().collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
interface ShellCustomActionFactory {
|
||||
|
||||
ShellCustomAction create(PlatformPackage thePackage,
|
||||
Map<String, ? super Object> params) throws IOException;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Shell script resource.
|
||||
*/
|
||||
final class ShellScriptResource {
|
||||
|
||||
ShellScriptResource(String publicFileName) {
|
||||
this.publicFileName = Path.of(publicFileName);
|
||||
}
|
||||
|
||||
void saveInFolder(Path folder) throws IOException {
|
||||
Path dstFile = folder.resolve(publicFileName);
|
||||
resource.saveToFile(dstFile);
|
||||
|
||||
Files.setPosixFilePermissions(dstFile, Stream.of(execPerms, Set.of(
|
||||
PosixFilePermission.OWNER_READ,
|
||||
PosixFilePermission.OWNER_WRITE,
|
||||
PosixFilePermission.GROUP_READ,
|
||||
PosixFilePermission.OTHERS_READ
|
||||
)).flatMap(x -> x.stream()).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
ShellScriptResource setResource(OverridableResource v) {
|
||||
resource = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
ShellScriptResource onlyOwnerCanExecute(boolean v) {
|
||||
execPerms = v ? OWNER_CAN_EXECUTE : ALL_CAN_EXECUTE;
|
||||
return this;
|
||||
}
|
||||
|
||||
OverridableResource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
final Path publicFileName;
|
||||
private Set<PosixFilePermission> execPerms = ALL_CAN_EXECUTE;
|
||||
private OverridableResource resource;
|
||||
|
||||
private final static Set<PosixFilePermission> ALL_CAN_EXECUTE = Set.of(
|
||||
PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.GROUP_EXECUTE,
|
||||
PosixFilePermission.OTHERS_EXECUTE);
|
||||
private final static Set<PosixFilePermission> OWNER_CAN_EXECUTE = Set.of(
|
||||
PosixFilePermission.OWNER_EXECUTE);
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.internal.AppImageFile.LauncherInfo;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE;
|
||||
|
||||
/**
|
||||
* Helper to install launchers as services for Unix installers.
|
||||
*/
|
||||
class UnixLaunchersAsServices extends ShellCustomAction {
|
||||
|
||||
UnixLaunchersAsServices(PlatformPackage thePackage,
|
||||
List<String> requiredPackages, Map<String, Object> params,
|
||||
Function<LauncherInfo, UnixLauncherAsService> factory) throws
|
||||
IOException {
|
||||
|
||||
this.thePackage = thePackage;
|
||||
this.requiredPackages = requiredPackages;
|
||||
|
||||
// Read launchers information
|
||||
launchers = AppImageFile.getLaunchers(PREDEFINED_APP_IMAGE.fetchFrom(
|
||||
params), params).stream().filter(LauncherInfo::isService).map(
|
||||
factory::apply).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
final List<String> requiredPackages() {
|
||||
if (launchers.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return requiredPackages;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected List<String> replacementStringIds() {
|
||||
return List.of(COMMANDS_INSTALL, COMMANDS_UNINSTALL, SCRIPTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected Map<String, String> createImpl() throws IOException {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
|
||||
if (launchers.isEmpty()) {
|
||||
return data;
|
||||
}
|
||||
|
||||
var installedDescriptorFiles = launchers.stream().map(
|
||||
launcher -> enqouter.applyTo(launcher.descriptorFilePath(
|
||||
Path.of("/")).toString())).toList();
|
||||
|
||||
Function<String, String> strigifier = cmd -> {
|
||||
return stringifyShellCommands(Stream.of(List.of(
|
||||
cmd), installedDescriptorFiles).flatMap(x -> x.stream()).collect(
|
||||
Collectors.joining(" ")));
|
||||
};
|
||||
|
||||
try {
|
||||
data.put(SCRIPTS, stringifyTextFile("services_utils.sh"));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
data.put(COMMANDS_INSTALL, strigifier.apply("register_services"));
|
||||
data.put(COMMANDS_UNINSTALL, strigifier.apply("unregister_services"));
|
||||
|
||||
for (var launcher : launchers) {
|
||||
launcher.getResource().saveToFile(launcher.descriptorFilePath(
|
||||
thePackage.sourceRoot()));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return launchers.isEmpty();
|
||||
}
|
||||
|
||||
static abstract class UnixLauncherAsService extends LauncherAsService {
|
||||
|
||||
UnixLauncherAsService(String name, Map<String, Object> mainParams,
|
||||
OverridableResource resource) {
|
||||
super(name, mainParams, resource);
|
||||
}
|
||||
|
||||
abstract Path descriptorFilePath(Path root);
|
||||
}
|
||||
|
||||
private final PlatformPackage thePackage;
|
||||
private final List<String> requiredPackages;
|
||||
private final List<UnixLauncherAsService> launchers;
|
||||
private final Enquoter enqouter = Enquoter.forShellLiterals();
|
||||
|
||||
private static final String COMMANDS_INSTALL = "LAUNCHER_AS_SERVICE_COMMANDS_INSTALL";
|
||||
private static final String COMMANDS_UNINSTALL = "LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL";
|
||||
private static final String SCRIPTS = "LAUNCHER_AS_SERVICE_SCRIPTS";
|
||||
|
||||
protected static final List<String> REPLACEMENT_STRING_IDS = List.of(
|
||||
COMMANDS_INSTALL, COMMANDS_UNINSTALL, SCRIPTS);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,6 +54,7 @@ import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import jdk.jpackage.internal.AppImageFile.LauncherInfo;
|
||||
|
||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.ABOUT_URL;
|
||||
@ -157,6 +158,14 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
null,
|
||||
(s, p) -> null);
|
||||
|
||||
static final StandardBundlerParam<InstallableFile> SERVICE_INSTALLER
|
||||
= new StandardBundlerParam<>(
|
||||
"win.msi.serviceInstaller",
|
||||
InstallableFile.class,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
public static final StandardBundlerParam<Boolean> MSI_SYSTEM_WIDE =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.WIN_PER_USER_INSTALLATION.getId(),
|
||||
@ -323,6 +332,15 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
|
||||
FileAssociation.verify(FileAssociation.fetchFrom(params));
|
||||
|
||||
var serviceInstallerResource = initServiceInstallerResource(params);
|
||||
if (serviceInstallerResource != null) {
|
||||
if (!Files.exists(serviceInstallerResource.getExternalPath())) {
|
||||
throw new ConfigException(I18N.getString(
|
||||
"error.missing-service-installer"), I18N.getString(
|
||||
"error.missing-service-installer.advice"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() instanceof ConfigException) {
|
||||
@ -385,6 +403,13 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
destFile.toFile().setWritable(true);
|
||||
ensureByMutationFileIsRTF(destFile);
|
||||
}
|
||||
|
||||
var serviceInstallerResource = initServiceInstallerResource(params);
|
||||
if (serviceInstallerResource != null) {
|
||||
var serviceInstallerPath = serviceInstallerResource.getExternalPath();
|
||||
params.put(SERVICE_INSTALLER.getID(), new InstallableFile(
|
||||
serviceInstallerPath, serviceInstallerPath.getFileName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -676,9 +701,35 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
|
||||
}
|
||||
|
||||
private static OverridableResource initServiceInstallerResource(
|
||||
Map<String, ? super Object> params) {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
// Runtime installer doesn't install launchers,
|
||||
// service installer not needed
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!AppImageFile.getLaunchers(
|
||||
StandardBundlerParam.getPredefinedAppImage(params), params).stream().anyMatch(
|
||||
LauncherInfo::isService)) {
|
||||
// Not a single launcher is requested to be installed as a service,
|
||||
// service installer not needed
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = createResource(null, params)
|
||||
.setPublicName("service-installer.exe")
|
||||
.setSourceOrder(OverridableResource.Source.External);
|
||||
if (result.getResourceDir() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return result.setExternal(result.getResourceDir().resolve(
|
||||
result.getPublicName()));
|
||||
}
|
||||
|
||||
private Path installerIcon;
|
||||
private Map<WixTool, WixTool.ToolInfo> wixToolset;
|
||||
private AppImageBundler appImageBundler;
|
||||
private List<WixFragmentBuilder> wixFragments;
|
||||
|
||||
private final List<WixFragmentBuilder> wixFragments;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,15 +47,24 @@ import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import jdk.jpackage.internal.AppImageFile.LauncherInfo;
|
||||
import jdk.jpackage.internal.IOUtils.XmlConsumer;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VENDOR;
|
||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
import static jdk.jpackage.internal.WinMsiBundler.MSI_SYSTEM_WIDE;
|
||||
import static jdk.jpackage.internal.WinMsiBundler.SERVICE_INSTALLER;
|
||||
import static jdk.jpackage.internal.WinMsiBundler.WIN_APP_IMAGE;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Creates WiX fragment with components for contents of app image.
|
||||
@ -89,10 +98,8 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
do {
|
||||
ApplicationLayout layout = appImageSupplier.get();
|
||||
// Don't want AppImageFile.FILENAME in installed application.
|
||||
// Register it with app image at a role without a match in installed
|
||||
// app layout to exclude it from layout transformation.
|
||||
layout.pathGroup().setPath(new Object(),
|
||||
AppImageFile.getPathInAppImage(Path.of("")));
|
||||
new InstallableFile(AppImageFile.getPathInAppImage(Path.of("")),
|
||||
null).excludeFromApplicationLayout(layout);
|
||||
|
||||
// Want absolute paths to source files in generated WiX sources.
|
||||
// This is to handle scenario if sources would be processed from
|
||||
@ -112,6 +119,27 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
launchers = AppImageFile.getLaunchers(appImageRoot, params);
|
||||
}
|
||||
|
||||
launchersAsServices = launchers.stream()
|
||||
.filter(LauncherInfo::isService)
|
||||
.map(launcher -> {
|
||||
var launcherPath = addExeSuffixToPath(
|
||||
installedAppImage.launchersDirectory().resolve(
|
||||
launcher.getName()));
|
||||
var id = Id.File.of(launcherPath);
|
||||
return new WixLauncherAsService(launcher.getName(), params)
|
||||
.setLauncherInstallPath(toWixPath(launcherPath))
|
||||
.setLauncherInstallPathId(id);
|
||||
}).toList();
|
||||
|
||||
if (!launchersAsServices.isEmpty()) {
|
||||
serviceInstaller = SERVICE_INSTALLER.fetchFrom(params);
|
||||
// Service installer tool will be installed in launchers directory
|
||||
serviceInstaller = new InstallableFile(
|
||||
serviceInstaller.srcPath().toAbsolutePath().normalize(),
|
||||
installedAppImage.launchersDirectory().resolve(
|
||||
serviceInstaller.installPath()));
|
||||
}
|
||||
|
||||
programMenuFolderName = MENU_GROUP.fetchFrom(params);
|
||||
|
||||
initFileAssociations(params);
|
||||
@ -388,6 +416,13 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
xmlConsumer.accept(xml);
|
||||
xml.writeEndElement();
|
||||
|
||||
if (role == Component.File && serviceInstaller != null && path.equals(
|
||||
serviceInstaller.installPath())) {
|
||||
for (var launcherAsService : launchersAsServices) {
|
||||
launcherAsService.writeServiceInstall(xml);
|
||||
}
|
||||
}
|
||||
|
||||
xml.writeEndElement(); // <Component>
|
||||
xml.writeEndElement(); // <DirectoryRef>
|
||||
|
||||
@ -643,6 +678,11 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
}
|
||||
});
|
||||
|
||||
if (serviceInstaller != null) {
|
||||
files.add(Map.entry(serviceInstaller.srcPath(),
|
||||
serviceInstaller.installPath()));
|
||||
}
|
||||
|
||||
List<String> componentIds = new ArrayList<>();
|
||||
for (var file : files) {
|
||||
Path src = file.getKey();
|
||||
@ -661,9 +701,52 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
|
||||
componentIds.add(addDirectoryCleaner(xml, INSTALLDIR));
|
||||
|
||||
componentIds.addAll(addServiceConfigs(xml));
|
||||
|
||||
addComponentGroup(xml, "Files", componentIds);
|
||||
}
|
||||
|
||||
private List<String> addServiceConfigs(XMLStreamWriter xml) throws
|
||||
XMLStreamException, IOException {
|
||||
if (launchersAsServices.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
try {
|
||||
var buffer = new DOMResult(IOUtils.initDocumentBuilder().newDocument());
|
||||
var bufferWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(
|
||||
buffer);
|
||||
|
||||
bufferWriter.writeStartDocument();
|
||||
bufferWriter.writeStartElement("Include");
|
||||
for (var launcherAsService : launchersAsServices) {
|
||||
launcherAsService.writeServiceConfig(xml);
|
||||
launcherAsService.writeServiceConfig(bufferWriter);
|
||||
}
|
||||
bufferWriter.writeEndElement();
|
||||
bufferWriter.writeEndDocument();
|
||||
bufferWriter.flush();
|
||||
bufferWriter.close();
|
||||
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
NodeList nodes = (NodeList) xPath.evaluate("/Include/descendant::Component/@Id",
|
||||
buffer.getNode(), XPathConstants.NODESET);
|
||||
|
||||
List<String> componentIds = new ArrayList<>();
|
||||
for (int i = 0; i != nodes.getLength(); i++) {
|
||||
var node = nodes.item(i);
|
||||
componentIds.add(node.getNodeValue());
|
||||
}
|
||||
return componentIds;
|
||||
} catch (XMLStreamException ex) {
|
||||
throw new IOException(ex);
|
||||
} catch (XPathExpressionException ex) {
|
||||
// Should never happen
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void addIcons(XMLStreamWriter xml) throws
|
||||
XMLStreamException, IOException {
|
||||
|
||||
@ -747,18 +830,7 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
Component.startElement(xml, componentId, "*");
|
||||
|
||||
addRegistryKeyPath(xml, INSTALLDIR, () -> propertyId, () -> {
|
||||
// The following code converts a path to value to be saved in registry.
|
||||
// E.g.:
|
||||
// INSTALLDIR -> [INSTALLDIR]
|
||||
// TERGETDIR/ProgramFiles64Folder/foo/bar -> [ProgramFiles64Folder]foo/bar
|
||||
final Path rootDir = KNOWN_DIRS.stream()
|
||||
.sorted(Comparator.comparing(Path::getNameCount).reversed())
|
||||
.filter(path::startsWith)
|
||||
.findFirst().get();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("[%s]", rootDir.getFileName().toString()));
|
||||
sb.append(rootDir.relativize(path).toString());
|
||||
return sb.toString();
|
||||
return toWixPath(path);
|
||||
});
|
||||
|
||||
xml.writeStartElement(
|
||||
@ -773,6 +845,20 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
return componentId;
|
||||
}
|
||||
|
||||
// Does the following conversions:
|
||||
// INSTALLDIR -> [INSTALLDIR]
|
||||
// TARGETDIR/ProgramFiles64Folder/foo/bar -> [ProgramFiles64Folder]foo/bar
|
||||
private static String toWixPath(Path path) {
|
||||
final Path rootDir = KNOWN_DIRS.stream()
|
||||
.sorted(Comparator.comparing(Path::getNameCount).reversed())
|
||||
.filter(path::startsWith)
|
||||
.findFirst().get();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("[%s]", rootDir.getFileName().toString()));
|
||||
sb.append(rootDir.relativize(path).toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static IllegalArgumentException throwInvalidPathException(Path v) {
|
||||
throw new IllegalArgumentException(String.format("Invalid path [%s]", v));
|
||||
}
|
||||
@ -831,7 +917,11 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
||||
|
||||
private Set<ShortcutsFolder> shortcutFolders;
|
||||
|
||||
private List<AppImageFile.LauncherInfo> launchers;
|
||||
private List<LauncherInfo> launchers;
|
||||
|
||||
private List<WixLauncherAsService> launchersAsServices;
|
||||
|
||||
private InstallableFile serviceInstaller;
|
||||
|
||||
private ApplicationLayout appImage;
|
||||
private ApplicationLayout installedAppImage;
|
||||
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
class WixLauncherAsService extends LauncherAsService {
|
||||
|
||||
WixLauncherAsService(String name, Map<String, ? super Object> mainParams) {
|
||||
super(name, mainParams,
|
||||
createResource("service-install.wxi", mainParams).setCategory(
|
||||
I18N.getString("resource.launcher-as-service-wix-file")));
|
||||
|
||||
serviceConfigResource = createResource("service-config.wxi", mainParams).setCategory(
|
||||
I18N.getString("resource.launcher-as-service-wix-file"));
|
||||
|
||||
addSubstitutionDataEntry("SERVICE_NAME", getName());
|
||||
|
||||
setPublicName(getResource());
|
||||
setPublicName(serviceConfigResource);
|
||||
}
|
||||
|
||||
WixLauncherAsService setLauncherInstallPath(String v) {
|
||||
return addSubstitutionDataEntry("APPLICATION_LAUNCHER", v);
|
||||
}
|
||||
|
||||
WixLauncherAsService setLauncherInstallPathId(String v) {
|
||||
return addSubstitutionDataEntry("APPLICATION_LAUNCHER_ID", v);
|
||||
}
|
||||
|
||||
void writeServiceConfig(XMLStreamWriter xml) throws XMLStreamException,
|
||||
IOException {
|
||||
writeResource(serviceConfigResource, xml);
|
||||
}
|
||||
|
||||
void writeServiceInstall(XMLStreamWriter xml) throws XMLStreamException,
|
||||
IOException {
|
||||
writeResource(getResource(), xml);
|
||||
}
|
||||
|
||||
private WixLauncherAsService addSubstitutionDataEntry(String name,
|
||||
String value) {
|
||||
getResource().addSubstitutionDataEntry(name, value);
|
||||
serviceConfigResource.addSubstitutionDataEntry(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
private OverridableResource setPublicName(OverridableResource r) {
|
||||
return r.setPublicName(getName() + "-" + r.getDefaultName());
|
||||
}
|
||||
|
||||
private void writeResource(OverridableResource resource, XMLStreamWriter xml)
|
||||
throws XMLStreamException, IOException {
|
||||
var buffer = new ByteArrayOutputStream();
|
||||
resource.saveToStream(buffer);
|
||||
|
||||
try {
|
||||
Document doc = IOUtils.initDocumentBuilder().parse(
|
||||
new ByteArrayInputStream(buffer.toByteArray()));
|
||||
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
NodeList nodes = (NodeList) xPath.evaluate("/Include/*", doc,
|
||||
XPathConstants.NODESET);
|
||||
|
||||
List<Source> sources = new ArrayList<>();
|
||||
for (int i = 0; i != nodes.getLength(); i++) {
|
||||
Node n = nodes.item(i);
|
||||
sources.add(new DOMSource(n));
|
||||
}
|
||||
|
||||
IOUtils.mergeXmls(xml, sources);
|
||||
|
||||
} catch (SAXException ex) {
|
||||
throw new IOException(ex);
|
||||
} catch (XPathExpressionException ex) {
|
||||
// Should never happen
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private final OverridableResource serviceConfigResource;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,7 @@ resource.main-wix-file=Main WiX project file
|
||||
resource.overrides-wix-file=Overrides WiX project file
|
||||
resource.shortcutpromptdlg-wix-file=Shortcut prompt dialog WiX project file
|
||||
resource.installdirnotemptydlg-wix-file=Not empty install directory dialog WiX project file
|
||||
resource.launcher-as-service-wix-file=Service installer WiX project file
|
||||
|
||||
error.no-wix-tools=Can not find WiX tools (light.exe, candle.exe)
|
||||
error.no-wix-tools.advice=Download WiX 3.0 or later from https://wixtoolset.org and add it to the PATH.
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,7 @@ resource.main-wix-file=\u30E1\u30A4\u30F3WiX\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8
|
||||
resource.overrides-wix-file=WiX\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9
|
||||
resource.shortcutpromptdlg-wix-file=\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30FB\u30D7\u30ED\u30F3\u30D7\u30C8\u30FB\u30C0\u30A4\u30A2\u30ED\u30B0WiX\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB
|
||||
resource.installdirnotemptydlg-wix-file=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FB\u30C0\u30A4\u30A2\u30ED\u30B0\u306EWiX\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u7A7A\u3067\u306F\u3042\u308A\u307E\u305B\u3093
|
||||
resource.launcher-as-service-wix-file=Service installer WiX project file
|
||||
|
||||
error.no-wix-tools=WiX\u30C4\u30FC\u30EB(light.exe\u3001candle.exe)\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
|
||||
error.no-wix-tools.advice=WiX 3.0\u4EE5\u964D\u3092https://wixtoolset.org\u304B\u3089\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u3001PATH\u306B\u8FFD\u52A0\u3057\u307E\u3059\u3002
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,7 @@ resource.main-wix-file=\u4E3B WiX \u9879\u76EE\u6587\u4EF6
|
||||
resource.overrides-wix-file=\u8986\u76D6 WiX \u9879\u76EE\u6587\u4EF6
|
||||
resource.shortcutpromptdlg-wix-file=\u5FEB\u6377\u65B9\u5F0F\u63D0\u793A\u5BF9\u8BDD\u6846 WiX \u9879\u76EE\u6587\u4EF6
|
||||
resource.installdirnotemptydlg-wix-file=\u5B89\u88C5\u76EE\u5F55\u5BF9\u8BDD\u6846 WiX \u9879\u76EE\u6587\u4EF6\u975E\u7A7A
|
||||
resource.launcher-as-service-wix-file=Service installer WiX project file
|
||||
|
||||
error.no-wix-tools=\u627E\u4E0D\u5230 WiX \u5DE5\u5177 (light.exe, candle.exe)
|
||||
error.no-wix-tools.advice=\u4ECE https://wixtoolset.org \u4E0B\u8F7D WiX 3.0 \u6216\u66F4\u9AD8\u7248\u672C\uFF0C\u7136\u540E\u5C06\u5176\u6DFB\u52A0\u5230 PATH\u3002
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
|
||||
<!--
|
||||
Configuration correponds to NSSM
|
||||
-->
|
||||
<DirectoryRef Id="INSTALLDIR">
|
||||
<Component Id="nssm_Application_APPLICATION_LAUNCHER_ID" Guid="*">
|
||||
<RegistryValue Root="HKLM"
|
||||
Key="System\CurrentControlSet\Services\SERVICE_NAME\Parameters"
|
||||
Type="string"
|
||||
KeyPath="yes"
|
||||
Name="Application"
|
||||
Value="APPLICATION_LAUNCHER"
|
||||
/>
|
||||
</Component>
|
||||
<Component Id="nssm_AppDirectory_APPLICATION_LAUNCHER_ID" Guid="*">
|
||||
<RegistryValue Root="HKLM"
|
||||
Key="System\CurrentControlSet\Services\SERVICE_NAME\Parameters"
|
||||
Type="string"
|
||||
KeyPath="yes"
|
||||
Name="AppDirectory"
|
||||
Value="[INSTALLDIR]"
|
||||
/>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
</Include>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
|
||||
|
||||
<ServiceInstall Type="ownProcess"
|
||||
Start="auto"
|
||||
Id="si_APPLICATION_LAUNCHER_ID"
|
||||
Name="SERVICE_NAME"
|
||||
Description="SERVICE_DESCRIPTION"
|
||||
ErrorControl="normal"
|
||||
Account="LocalSystem"
|
||||
Vital="yes"
|
||||
/>
|
||||
<ServiceControl Start="install"
|
||||
Stop="both"
|
||||
Remove="uninstall"
|
||||
Wait="yes"
|
||||
Id="sc_APPLICATION_LAUNCHER_ID"
|
||||
Name="SERVICE_NAME"
|
||||
/>
|
||||
</Include>
|
@ -76,6 +76,10 @@ public class AdditionalLauncher {
|
||||
return this;
|
||||
}
|
||||
|
||||
final public AdditionalLauncher setLauncherAsService() {
|
||||
return addRawProperties(LAUNCHER_AS_SERVICE);
|
||||
}
|
||||
|
||||
final public AdditionalLauncher addRawProperties(
|
||||
Map.Entry<String, String>... v) {
|
||||
return addRawProperties(List.of(v));
|
||||
@ -338,7 +342,13 @@ public class AdditionalLauncher {
|
||||
"--java-options"))).stream().map(
|
||||
str -> resolveVariables(cmd, str)).toList());
|
||||
|
||||
appVerifier.executeAndVerifyOutput();
|
||||
if (!rawProperties.contains(LAUNCHER_AS_SERVICE)) {
|
||||
appVerifier.executeAndVerifyOutput();
|
||||
} else if (!cmd.isPackageUnpacked(String.format(
|
||||
"Not verifying contents of test output file for [%s] launcher",
|
||||
launcherPath))) {
|
||||
appVerifier.verifyOutput();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PropertyFile {
|
||||
@ -394,4 +404,6 @@ public class AdditionalLauncher {
|
||||
private Boolean withShortcut;
|
||||
|
||||
private final static Path NO_ICON = Path.of("");
|
||||
private final static Map.Entry<String, String> LAUNCHER_AS_SERVICE = Map.entry(
|
||||
"launcher-as-service", "true");
|
||||
}
|
||||
|
@ -51,6 +51,14 @@ public final class CfgFile {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getValueUnchecked(String section, String key) {
|
||||
Objects.requireNonNull(section);
|
||||
Objects.requireNonNull(key);
|
||||
|
||||
return Optional.ofNullable(data.get(section)).map(v -> v.get(key)).orElse(
|
||||
null);
|
||||
}
|
||||
|
||||
private CfgFile(Map<String, Map<String, String>> data, String id) {
|
||||
this.data = data;
|
||||
this.id = id;
|
||||
|
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jpackage.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.internal.IOUtils;
|
||||
import static jdk.jpackage.test.Functional.ThrowingConsumer.toConsumer;
|
||||
import static jdk.jpackage.test.PackageType.LINUX;
|
||||
import static jdk.jpackage.test.PackageType.MAC_PKG;
|
||||
import static jdk.jpackage.test.PackageType.WINDOWS;
|
||||
|
||||
public final class LauncherAsServiceVerifier {
|
||||
|
||||
public final static class Builder {
|
||||
|
||||
public Builder setExpectedValue(String v) {
|
||||
expectedValue = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLauncherName(String v) {
|
||||
launcherName = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAppOutputFileName(String v) {
|
||||
appOutputFileName = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LauncherAsServiceVerifier create() {
|
||||
Objects.requireNonNull(expectedValue);
|
||||
return new LauncherAsServiceVerifier(launcherName, appOutputFileName,
|
||||
expectedValue);
|
||||
}
|
||||
|
||||
public Builder applyTo(PackageTest pkg) {
|
||||
create().applyTo(pkg);
|
||||
return this;
|
||||
}
|
||||
|
||||
private String launcherName;
|
||||
private String expectedValue;
|
||||
private String appOutputFileName = "launcher-as-service.txt";
|
||||
}
|
||||
|
||||
public static Builder build() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private LauncherAsServiceVerifier(String launcherName,
|
||||
String appOutputFileName,
|
||||
String expectedArgValue) {
|
||||
this.expectedValue = expectedArgValue;
|
||||
this.launcherName = launcherName;
|
||||
this.appOutputFileName = Path.of(appOutputFileName);
|
||||
}
|
||||
|
||||
public void applyTo(PackageTest pkg) {
|
||||
if (launcherName == null) {
|
||||
pkg.forTypes(WINDOWS, () -> {
|
||||
pkg.addInitializer(cmd -> {
|
||||
// Remove parameter added to jpackage command line in HelloApp.addTo()
|
||||
cmd.removeArgument("--win-console");
|
||||
});
|
||||
});
|
||||
applyToMainLauncher(pkg);
|
||||
} else {
|
||||
applyToAdditionalLauncher(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
static void verify(JPackageCommand cmd) {
|
||||
cmd.verifyIsOfType(SUPPORTED_PACKAGES);
|
||||
|
||||
var launcherNames = getLaunchersAsServices(cmd);
|
||||
|
||||
launcherNames.forEach(toConsumer(launcherName -> {
|
||||
verify(cmd, launcherName);
|
||||
}));
|
||||
|
||||
if (WINDOWS.contains(cmd.packageType()) && !cmd.isRuntime()) {
|
||||
Path serviceInstallerPath = cmd.appLayout().launchersDirectory().resolve(
|
||||
"service-installer.exe");
|
||||
if (launcherNames.isEmpty()) {
|
||||
TKit.assertPathExists(serviceInstallerPath, false);
|
||||
|
||||
} else {
|
||||
TKit.assertFileExists(serviceInstallerPath);
|
||||
}
|
||||
}
|
||||
|
||||
List<Path> servicesSpecificFiles = new ArrayList<>();
|
||||
List<Path> servicesSpecificFolders = new ArrayList<>();
|
||||
|
||||
if (MAC_PKG.equals(cmd.packageType())) {
|
||||
servicesSpecificFiles.add(MacHelper.getUninstallCommand(cmd));
|
||||
|
||||
if (cmd.isPackageUnpacked()) {
|
||||
servicesSpecificFolders.add(MacHelper.getServicePlistFilePath(
|
||||
cmd, null).getParent());
|
||||
}
|
||||
} else if (LINUX.contains(cmd.packageType())) {
|
||||
if (cmd.isPackageUnpacked()) {
|
||||
servicesSpecificFolders.add(LinuxHelper.getServiceUnitFilePath(
|
||||
cmd, null).getParent());
|
||||
}
|
||||
}
|
||||
|
||||
if (launcherNames.isEmpty() || cmd.isRuntime()) {
|
||||
servicesSpecificFiles.forEach(path -> TKit.assertPathExists(path,
|
||||
false));
|
||||
servicesSpecificFolders.forEach(path -> TKit.assertPathExists(path,
|
||||
false));
|
||||
} else {
|
||||
servicesSpecificFiles.forEach(TKit::assertFileExists);
|
||||
servicesSpecificFolders.forEach(TKit::assertDirectoryExists);
|
||||
}
|
||||
}
|
||||
|
||||
static void verifyUninstalled(JPackageCommand cmd) {
|
||||
cmd.verifyIsOfType(SUPPORTED_PACKAGES);
|
||||
|
||||
var launcherNames = getLaunchersAsServices(cmd);
|
||||
for (var launcherName : launcherNames) {
|
||||
if (TKit.isLinux()) {
|
||||
TKit.assertPathExists(LinuxHelper.getServiceUnitFilePath(cmd,
|
||||
launcherName), false);
|
||||
} else if (TKit.isOSX()) {
|
||||
TKit.assertPathExists(MacHelper.getServicePlistFilePath(cmd,
|
||||
launcherName), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (TKit.isOSX()) {
|
||||
TKit.assertPathExists(MacHelper.getUninstallCommand(cmd).getParent(),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
static List<String> getLaunchersAsServices(JPackageCommand cmd) {
|
||||
List<String> launcherNames = new ArrayList<>();
|
||||
|
||||
if (cmd.hasArgument("--launcher-as-service")) {
|
||||
launcherNames.add(null);
|
||||
}
|
||||
|
||||
AdditionalLauncher.forEachAdditionalLauncher(cmd,
|
||||
Functional.ThrowingBiConsumer.toBiConsumer(
|
||||
(launcherName, propFilePath) -> {
|
||||
if (Files.readAllLines(propFilePath).stream().anyMatch(
|
||||
line -> {
|
||||
if (line.startsWith(
|
||||
"launcher-as-service=")) {
|
||||
return Boolean.parseBoolean(
|
||||
line.substring(
|
||||
"launcher-as-service=".length()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})) {
|
||||
launcherNames.add(launcherName);
|
||||
}
|
||||
}));
|
||||
|
||||
return launcherNames;
|
||||
}
|
||||
|
||||
private boolean canVerifyInstall(JPackageCommand cmd) throws IOException {
|
||||
String msg = String.format(
|
||||
"Not verifying contents of test output file [%s] for %s launcher",
|
||||
appOutputFilePathInitialize(),
|
||||
Optional.ofNullable(launcherName).orElse("the main"));
|
||||
if (cmd.isPackageUnpacked(msg) || cmd.isFakeRuntime(msg)) {
|
||||
return false;
|
||||
}
|
||||
var cfgFile = CfgFile.readFromFile(cmd.appLauncherCfgPath(launcherName));
|
||||
if (!expectedValue.equals(cfgFile.getValueUnchecked("ArgOptions",
|
||||
"arguments"))) {
|
||||
TKit.trace(String.format(
|
||||
"%s because different version of the package is installed",
|
||||
msg));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void applyToMainLauncher(PackageTest pkg) {
|
||||
pkg.addInitializer(cmd -> {
|
||||
cmd.addArgument("--launcher-as-service");
|
||||
cmd.addArguments("--arguments",
|
||||
JPackageCommand.escapeAndJoin(expectedValue));
|
||||
cmd.addArguments("--java-options", "-Djpackage.test.appOutput="
|
||||
+ appOutputFilePathInitialize().toString());
|
||||
cmd.addArguments("--java-options", "-Djpackage.test.noexit=true");
|
||||
});
|
||||
pkg.addInstallVerifier(cmd -> {
|
||||
if (canVerifyInstall(cmd)) {
|
||||
delayInstallVerify();
|
||||
HelloApp.assertApp(cmd.appLauncherPath())
|
||||
.addParam("jpackage.test.appOutput",
|
||||
appOutputFilePathVerify(cmd).toString())
|
||||
.addDefaultArguments(expectedValue)
|
||||
.verifyOutput();
|
||||
TKit.deleteIfExists(appOutputFileName);
|
||||
}
|
||||
});
|
||||
pkg.addInstallVerifier(cmd -> {
|
||||
verify(cmd, launcherName);
|
||||
});
|
||||
}
|
||||
|
||||
private void applyToAdditionalLauncher(PackageTest pkg) {
|
||||
new AdditionalLauncher(launcherName) {
|
||||
@Override
|
||||
protected void verify(JPackageCommand cmd) throws IOException {
|
||||
if (canVerifyInstall(cmd)) {
|
||||
delayInstallVerify();
|
||||
super.verify(cmd);
|
||||
TKit.deleteIfExists(appOutputFileName);
|
||||
}
|
||||
LauncherAsServiceVerifier.verify(cmd, launcherName);
|
||||
}
|
||||
}.setLauncherAsService()
|
||||
.addJavaOptions("-Djpackage.test.appOutput="
|
||||
+ appOutputFilePathInitialize().toString())
|
||||
.addJavaOptions("-Djpackage.test.noexit=true")
|
||||
.addDefaultArguments(expectedValue)
|
||||
.applyTo(pkg);
|
||||
}
|
||||
|
||||
private static void verify(JPackageCommand cmd, String launcherName) throws
|
||||
IOException {
|
||||
if (LINUX.contains(cmd.packageType())) {
|
||||
verifyLinuxUnitFile(cmd, launcherName);
|
||||
} else if (MAC_PKG.equals(cmd.packageType())) {
|
||||
verifyMacDaemonPlistFile(cmd, launcherName);
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyLinuxUnitFile(JPackageCommand cmd,
|
||||
String launcherName) throws IOException {
|
||||
|
||||
var serviceUnitFile = LinuxHelper.getServiceUnitFilePath(cmd, launcherName);
|
||||
|
||||
TKit.traceFileContents(serviceUnitFile, "unit file");
|
||||
|
||||
var installedLauncherPath = cmd.pathToPackageFile(cmd.appLauncherPath(
|
||||
launcherName));
|
||||
|
||||
var execStartValue = (Pattern.compile("\\s").matcher(
|
||||
installedLauncherPath.toString()).find() ? String.format(
|
||||
"\"%s\"", installedLauncherPath) : installedLauncherPath);
|
||||
TKit.assertTextStream("ExecStart=" + execStartValue)
|
||||
.label("unit file")
|
||||
.predicate(String::equals)
|
||||
.apply(Files.readAllLines(serviceUnitFile).stream());
|
||||
}
|
||||
|
||||
private static void verifyMacDaemonPlistFile(JPackageCommand cmd,
|
||||
String launcherName) throws IOException {
|
||||
|
||||
var servicePlistFile = MacHelper.getServicePlistFilePath(cmd, launcherName);
|
||||
|
||||
TKit.traceFileContents(servicePlistFile, "property file");
|
||||
|
||||
var installedLauncherPath = cmd.pathToPackageFile(cmd.appLauncherPath(
|
||||
launcherName));
|
||||
|
||||
var servicePlist = MacHelper.readPList(servicePlistFile);
|
||||
|
||||
var args = servicePlist.queryArrayValue("ProgramArguments");
|
||||
TKit.assertEquals(1, args.size(),
|
||||
"Check number of array elements in 'ProgramArguments' property in the property file");
|
||||
TKit.assertEquals(installedLauncherPath.toString(), args.get(0),
|
||||
"Check path to launcher in 'ProgramArguments' property in the property file");
|
||||
|
||||
var expectedLabel = IOUtils.replaceSuffix(servicePlistFile.getFileName(), "").toString();
|
||||
TKit.assertEquals(expectedLabel, servicePlist.queryValue("Label"),
|
||||
"Check value of 'Label' property in the property file");
|
||||
}
|
||||
|
||||
private static void delayInstallVerify() {
|
||||
// Sleep a bit to let system launch the service
|
||||
Functional.ThrowingRunnable.toRunnable(() -> Thread.sleep(5 * 1000)).run();
|
||||
}
|
||||
|
||||
private Path appOutputFilePathInitialize() {
|
||||
final Path dir;
|
||||
if (TKit.isWindows()) {
|
||||
dir = Path.of("$ROOTDIR");
|
||||
} else {
|
||||
dir = Path.of(System.getProperty("java.io.tmpdir"));
|
||||
}
|
||||
return dir.resolve(appOutputFileName);
|
||||
}
|
||||
|
||||
private Path appOutputFilePathVerify(JPackageCommand cmd) {
|
||||
if (TKit.isWindows()) {
|
||||
return cmd.appInstallationDirectory().resolve(appOutputFileName);
|
||||
} else {
|
||||
return appOutputFilePathInitialize();
|
||||
}
|
||||
}
|
||||
|
||||
private final String expectedValue;
|
||||
private final String launcherName;
|
||||
private final Path appOutputFileName;
|
||||
|
||||
final static Set<PackageType> SUPPORTED_PACKAGES = Stream.of(LINUX, WINDOWS,
|
||||
Set.of(MAC_PKG)).flatMap(x -> x.stream()).collect(Collectors.toSet());
|
||||
}
|
@ -23,6 +23,8 @@
|
||||
package jdk.jpackage.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -80,6 +82,14 @@ public final class LinuxHelper {
|
||||
desktopFileName);
|
||||
}
|
||||
|
||||
static Path getServiceUnitFilePath(JPackageCommand cmd, String launcherName) {
|
||||
cmd.verifyIsOfType(PackageType.LINUX);
|
||||
return cmd.pathToUnpackedPackageFile(
|
||||
Path.of("/lib/systemd/system").resolve(getServiceUnitFileName(
|
||||
getPackageName(cmd),
|
||||
Optional.ofNullable(launcherName).orElseGet(cmd::name))));
|
||||
}
|
||||
|
||||
static String getBundleName(JPackageCommand cmd) {
|
||||
cmd.verifyIsOfType(PackageType.LINUX);
|
||||
|
||||
@ -668,6 +678,31 @@ public final class LinuxHelper {
|
||||
return arch;
|
||||
}
|
||||
|
||||
private static String getServiceUnitFileName(String packageName,
|
||||
String launcherName) {
|
||||
try {
|
||||
return getServiceUnitFileName.invoke(null, packageName, launcherName).toString();
|
||||
} catch (InvocationTargetException | IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method initGetServiceUnitFileName() {
|
||||
try {
|
||||
return Class.forName(
|
||||
"jdk.jpackage.internal.LinuxLaunchersAsServices").getMethod(
|
||||
"getServiceUnitFileName", String.class, String.class);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
if (TKit.isLinux()) {
|
||||
throw new RuntimeException(ex);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static final Set<Path> CRITICAL_RUNTIME_FILES = Set.of(Path.of(
|
||||
"lib/server/libjvm.so"));
|
||||
|
||||
@ -677,4 +712,6 @@ public final class LinuxHelper {
|
||||
|
||||
// Values grabbed from https://linux.die.net/man/1/xdg-icon-resource
|
||||
private final static Set<Integer> XDG_CMD_VALID_ICON_SIZES = Set.of(16, 22, 32, 48, 64, 128);
|
||||
|
||||
private final static Method getServiceUnitFileName = initGetServiceUnitFileName();
|
||||
}
|
||||
|
@ -24,11 +24,14 @@ package jdk.jpackage.test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@ -225,10 +228,14 @@ public final class MacHelper {
|
||||
pkg.uninstallHandler = cmd -> {
|
||||
cmd.verifyIsOfType(PackageType.MAC_PKG);
|
||||
|
||||
Executor.of("sudo", "rm", "-rf")
|
||||
.addArgument(cmd.appInstallationDirectory())
|
||||
.execute();
|
||||
|
||||
if (Files.exists(getUninstallCommand(cmd))) {
|
||||
Executor.of("sudo", "/bin/sh",
|
||||
getUninstallCommand(cmd).toString()).execute();
|
||||
} else {
|
||||
Executor.of("sudo", "rm", "-rf")
|
||||
.addArgument(cmd.appInstallationDirectory())
|
||||
.execute();
|
||||
}
|
||||
};
|
||||
|
||||
return pkg;
|
||||
@ -247,10 +254,34 @@ public final class MacHelper {
|
||||
cmd.name() + (cmd.isRuntime() ? "" : ".app"));
|
||||
}
|
||||
|
||||
static Path getUninstallCommand(JPackageCommand cmd) {
|
||||
cmd.verifyIsOfType(PackageType.MAC_PKG);
|
||||
return cmd.pathToUnpackedPackageFile(Path.of(
|
||||
"/Library/Application Support", getPackageName(cmd),
|
||||
"uninstall.command"));
|
||||
}
|
||||
|
||||
static Path getServicePlistFilePath(JPackageCommand cmd, String launcherName) {
|
||||
cmd.verifyIsOfType(PackageType.MAC_PKG);
|
||||
return cmd.pathToUnpackedPackageFile(
|
||||
Path.of("/Library/LaunchDaemons").resolve(
|
||||
getServicePListFileName(getPackageId(cmd),
|
||||
Optional.ofNullable(launcherName).orElseGet(
|
||||
cmd::name))));
|
||||
}
|
||||
|
||||
private static String getPackageName(JPackageCommand cmd) {
|
||||
return cmd.getArgumentValue("--mac-package-name", cmd::installerName);
|
||||
}
|
||||
|
||||
private static String getPackageId(JPackageCommand cmd) {
|
||||
return cmd.getArgumentValue("--mac-package-identifier", () -> {
|
||||
return cmd.getArgumentValue("--main-class", cmd::name, className -> {
|
||||
return JavaAppDesc.parse(className).packageName();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static final class PListWrapper {
|
||||
public String queryValue(String keyName) {
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
@ -314,6 +345,34 @@ public final class MacHelper {
|
||||
return dbf.newDocumentBuilder();
|
||||
}
|
||||
|
||||
private static String getServicePListFileName(String packageName,
|
||||
String launcherName) {
|
||||
try {
|
||||
return getServicePListFileName.invoke(null, packageName,
|
||||
launcherName).toString();
|
||||
} catch (InvocationTargetException | IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method initGetServicePListFileName() {
|
||||
try {
|
||||
return Class.forName(
|
||||
"jdk.jpackage.internal.MacLaunchersAsServices").getMethod(
|
||||
"getServicePListFileName", String.class, String.class);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
if (TKit.isOSX()) {
|
||||
throw new RuntimeException(ex);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static final Set<Path> CRITICAL_RUNTIME_FILES = Set.of(Path.of(
|
||||
"Contents/Home/lib/server/libjvm.dylib"));
|
||||
|
||||
private final static Method getServicePListFileName = initGetServicePListFileName();
|
||||
}
|
||||
|
@ -324,6 +324,13 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
public PackageTest addHelloAppInitializer(String javaAppDesc) {
|
||||
addInitializer(
|
||||
cmd -> new HelloApp(JavaAppDesc.parse(javaAppDesc)).addTo(cmd),
|
||||
"HelloApp");
|
||||
return this;
|
||||
}
|
||||
|
||||
public final static class Group extends RunnablePackageTest {
|
||||
public Group(PackageTest... tests) {
|
||||
handlers = Stream.of(tests)
|
||||
@ -367,12 +374,6 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private void addHelloAppInitializer(String javaAppDesc) {
|
||||
addInitializer(
|
||||
cmd -> new HelloApp(JavaAppDesc.parse(javaAppDesc)).addTo(cmd),
|
||||
"HelloApp");
|
||||
}
|
||||
|
||||
private List<Consumer<Action>> createPackageTypeHandlers() {
|
||||
return NATIVE.stream()
|
||||
.map(type -> {
|
||||
@ -600,6 +601,11 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
}
|
||||
}
|
||||
|
||||
if (LauncherAsServiceVerifier.SUPPORTED_PACKAGES.contains(
|
||||
cmd.packageType())) {
|
||||
LauncherAsServiceVerifier.verify(cmd);
|
||||
}
|
||||
|
||||
cmd.assertAppLayout();
|
||||
|
||||
installVerifiers.forEach(v -> v.accept(cmd));
|
||||
@ -608,15 +614,24 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
private void verifyRootCountInUnpackedPackage(JPackageCommand cmd,
|
||||
Path unpackedDir) {
|
||||
|
||||
final boolean withServices = !cmd.isRuntime()
|
||||
&& !LauncherAsServiceVerifier.getLaunchersAsServices(cmd).isEmpty();
|
||||
|
||||
final long expectedRootCount;
|
||||
if (WINDOWS.contains(cmd.packageType())) {
|
||||
// On Windows it is always two entries:
|
||||
// installation home directory and MSI file
|
||||
expectedRootCount = 2;
|
||||
} else if (withServices && MAC_PKG.equals(cmd.packageType())) {
|
||||
expectedRootCount = 2;
|
||||
} else if (LINUX.contains(cmd.packageType())) {
|
||||
Set<Path> roots = new HashSet<>();
|
||||
roots.add(Path.of("/").resolve(Path.of(cmd.getArgumentValue(
|
||||
"--install-dir", () -> "/opt")).getName(0)));
|
||||
if (withServices) {
|
||||
// /lib/systemd
|
||||
roots.add(Path.of("/lib"));
|
||||
}
|
||||
if (cmd.hasArgument("--license-file")) {
|
||||
switch (cmd.packageType()) {
|
||||
case LINUX_RPM -> {
|
||||
@ -673,6 +688,11 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
TKit.assertPathExists(appInstallDir, false);
|
||||
}
|
||||
|
||||
if (LauncherAsServiceVerifier.SUPPORTED_PACKAGES.contains(
|
||||
cmd.packageType())) {
|
||||
LauncherAsServiceVerifier.verifyUninstalled(cmd);
|
||||
}
|
||||
|
||||
uninstallVerifiers.forEach(v -> v.accept(cmd));
|
||||
}
|
||||
|
||||
|
@ -237,6 +237,13 @@ final public class TKit {
|
||||
trace("Done");
|
||||
}
|
||||
|
||||
public static void traceFileContents(Path path, String label) throws IOException {
|
||||
assertFileExists(path);
|
||||
trace(String.format("Dump [%s] %s...", path, label));
|
||||
Files.readAllLines(path).forEach(TKit::trace);
|
||||
trace("Done");
|
||||
}
|
||||
|
||||
public static void createPropertiesFile(Path propsFilename,
|
||||
Map.Entry<String, String>... props) {
|
||||
createPropertiesFile(propsFilename, List.of(props));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,7 +43,7 @@ public class AppImageFileTest {
|
||||
|
||||
@Test
|
||||
public void testIdentity() throws IOException {
|
||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put(Arguments.CLIOptions.NAME.getId(), "Foo");
|
||||
params.put(Arguments.CLIOptions.VERSION.getId(), "2.3");
|
||||
params.put(Arguments.CLIOptions.DESCRIPTION.getId(), "Duck is the King");
|
||||
@ -58,7 +58,7 @@ public class AppImageFileTest {
|
||||
// never create app image at both load/save phases.
|
||||
// People would edit this file just because they can.
|
||||
// We should be ready to handle curious minds.
|
||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put("invalidParamName", "randomStringValue");
|
||||
params.put(Arguments.CLIOptions.APPCLASS.getId(), "TestClass");
|
||||
params.put(Arguments.CLIOptions.MAIN_JAR.getId(), "test.jar");
|
||||
@ -74,12 +74,13 @@ public class AppImageFileTest {
|
||||
public void testInavlidXml() throws IOException {
|
||||
assertInvalid(createFromXml("<foo/>"));
|
||||
assertInvalid(createFromXml("<jpackage-state/>"));
|
||||
assertInvalid(createFromXml(JPACKAGE_STATE_OPEN, "</jpackage-state>"));
|
||||
assertInvalid(createFromXml(
|
||||
"<jpackage-state>",
|
||||
JPACKAGE_STATE_OPEN,
|
||||
"<main-launcher></main-launcher>",
|
||||
"</jpackage-state>"));
|
||||
assertInvalid(createFromXml(
|
||||
"<jpackage-state>",
|
||||
JPACKAGE_STATE_OPEN,
|
||||
"<launcher>A</launcher>",
|
||||
"<launcher>B</launcher>",
|
||||
"</jpackage-state>"));
|
||||
@ -88,18 +89,18 @@ public class AppImageFileTest {
|
||||
@Test
|
||||
public void testValidXml() throws IOException {
|
||||
Assert.assertEquals("Foo", (createFromXml(
|
||||
"<jpackage-state>",
|
||||
JPACKAGE_STATE_OPEN,
|
||||
"<main-launcher>Foo</main-launcher>",
|
||||
"</jpackage-state>")).getLauncherName());
|
||||
|
||||
Assert.assertEquals("Boo", (createFromXml(
|
||||
"<jpackage-state>",
|
||||
JPACKAGE_STATE_OPEN,
|
||||
"<main-launcher>Boo</main-launcher>",
|
||||
"<main-launcher>Bar</main-launcher>",
|
||||
"</jpackage-state>")).getLauncherName());
|
||||
|
||||
var file = createFromXml(
|
||||
"<jpackage-state>",
|
||||
JPACKAGE_STATE_OPEN,
|
||||
"<main-launcher>Foo</main-launcher>",
|
||||
"<launcher></launcher>",
|
||||
"</jpackage-state>");
|
||||
@ -110,7 +111,7 @@ public class AppImageFileTest {
|
||||
|
||||
@Test
|
||||
public void testMainLauncherName() throws IOException {
|
||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put("name", "Foo");
|
||||
params.put("description", "Duck App Description");
|
||||
AppImageFile aif = create(params);
|
||||
@ -120,14 +121,14 @@ public class AppImageFileTest {
|
||||
|
||||
@Test
|
||||
public void testAddLaunchers() throws IOException {
|
||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
||||
List<Map<String, ? super Object>> launchersAsMap = new ArrayList<>();
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
List<Map<String, Object>> launchersAsMap = new ArrayList<>();
|
||||
|
||||
Map<String, ? super Object> addLauncher2Params = new LinkedHashMap();
|
||||
Map<String, Object> addLauncher2Params = new LinkedHashMap<>();
|
||||
addLauncher2Params.put("name", "Launcher2Name");
|
||||
launchersAsMap.add(addLauncher2Params);
|
||||
|
||||
Map<String, ? super Object> addLauncher3Params = new LinkedHashMap();
|
||||
Map<String, Object> addLauncher3Params = new LinkedHashMap<>();
|
||||
addLauncher3Params.put("name", "Launcher3Name");
|
||||
launchersAsMap.add(addLauncher3Params);
|
||||
|
||||
@ -138,7 +139,7 @@ public class AppImageFileTest {
|
||||
|
||||
List<AppImageFile.LauncherInfo> addLaunchers = aif.getAddLaunchers();
|
||||
Assert.assertEquals(2, addLaunchers.size());
|
||||
List<String> names = new ArrayList<String>();
|
||||
List<String> names = new ArrayList<>();
|
||||
names.add(addLaunchers.get(0).getName());
|
||||
names.add(addLaunchers.get(1).getName());
|
||||
|
||||
@ -163,7 +164,7 @@ public class AppImageFileTest {
|
||||
path.toFile().mkdirs();
|
||||
Files.delete(path);
|
||||
|
||||
ArrayList<String> data = new ArrayList();
|
||||
List<String> data = new ArrayList<>();
|
||||
data.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>");
|
||||
data.addAll(List.of(xmlData));
|
||||
|
||||
@ -174,4 +175,8 @@ public class AppImageFileTest {
|
||||
return image;
|
||||
}
|
||||
|
||||
private final static String JPACKAGE_STATE_OPEN = String.format(
|
||||
"<jpackage-state platform=\"%s\" version=\"%s\">",
|
||||
AppImageFile.getPlatform(), AppImageFile.getVersion());
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class EnquoterTest {
|
||||
|
||||
@Test
|
||||
public void testForShellLiterals() {
|
||||
var enquoter = Enquoter.forShellLiterals();
|
||||
|
||||
assertEquals(null, "''", enquoter.applyTo(""));
|
||||
assertEquals(null, "'foo'", enquoter.applyTo("foo"));
|
||||
assertEquals(null, "' foo '", enquoter.applyTo(" foo "));
|
||||
assertEquals(null, "'foo bar'", enquoter.applyTo("foo bar"));
|
||||
assertEquals(null, "'foo\\' bar'", enquoter.applyTo("foo' bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForPropertyValues() {
|
||||
var enquoter = Enquoter.forPropertyValues();
|
||||
|
||||
assertEquals(null, "", enquoter.applyTo(""));
|
||||
assertEquals(null, "foo", enquoter.applyTo("foo"));
|
||||
assertEquals(null, "\" foo \"", enquoter.applyTo(" foo "));
|
||||
assertEquals(null, "\"foo bar\"", enquoter.applyTo("foo bar"));
|
||||
assertEquals(null, "\"foo' bar\"", enquoter.applyTo("foo' bar"));
|
||||
}
|
||||
}
|
174
test/jdk/tools/jpackage/share/ServiceTest.java
Normal file
174
test/jdk/tools/jpackage/share/ServiceTest.java
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.JavaTool;
|
||||
import jdk.jpackage.test.LauncherAsServiceVerifier;
|
||||
import static jdk.jpackage.test.PackageType.MAC_DMG;
|
||||
import static jdk.jpackage.test.PackageType.WINDOWS;
|
||||
import jdk.jpackage.test.RunnablePackageTest;
|
||||
import jdk.jpackage.test.TKit;
|
||||
|
||||
/**
|
||||
* Launcher as service packaging test. Output of the test should be
|
||||
* servicetest*.* and updateservicetest*.* package bundles.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Launcher as service packaging test
|
||||
* @library ../helpers
|
||||
* @key jpackagePlatformPackage
|
||||
* @build jdk.jpackage.test.*
|
||||
* @modules jdk.jpackage/jdk.jpackage.internal
|
||||
* @compile ServiceTest.java
|
||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=ServiceTest
|
||||
*/
|
||||
public class ServiceTest {
|
||||
|
||||
public ServiceTest() {
|
||||
if (TKit.isWindows()) {
|
||||
final String propName = "jpackage.test.ServiceTest.service-installer";
|
||||
String serviceInstallerExec = System.getProperty(propName);
|
||||
if (serviceInstallerExec == null) {
|
||||
if (Stream.of(RunnablePackageTest.Action.CREATE,
|
||||
RunnablePackageTest.Action.INSTALL).allMatch(
|
||||
RunnablePackageTest::hasAction)) {
|
||||
TKit.throwSkippedException(String.format(
|
||||
"%s system property not set", propName));
|
||||
} else {
|
||||
// Use cmd.exe as a stub as the output packages will not be
|
||||
// created and installed in the test run
|
||||
serviceInstallerExec = Optional.ofNullable(System.getenv(
|
||||
"COMSPEC")).orElseGet(() -> {
|
||||
return JavaTool.JAVA.getPath().toString();
|
||||
});
|
||||
TKit.trace(
|
||||
String.format("Using [%s] as a service installer",
|
||||
serviceInstallerExec));
|
||||
}
|
||||
}
|
||||
|
||||
winServiceInstaller = Path.of(serviceInstallerExec);
|
||||
|
||||
} else {
|
||||
winServiceInstaller = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Throwable {
|
||||
var testInitializer = createTestInitializer();
|
||||
var pkg = createPackageTest().addHelloAppInitializer("com.foo.ServiceTest");
|
||||
LauncherAsServiceVerifier.build().setExpectedValue("A1").applyTo(pkg);
|
||||
testInitializer.applyTo(pkg);
|
||||
pkg.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() throws Throwable {
|
||||
var testInitializer = createTestInitializer().setUpgradeCode(
|
||||
"4050AD4D-D6CC-452A-9CB0-58E5FA8C410F");
|
||||
|
||||
// Package name will be used as package ID on macOS. Keep it the same for
|
||||
// both packages to allow update installation.
|
||||
final String packageName = "com.bar";
|
||||
|
||||
var pkg = createPackageTest()
|
||||
.addHelloAppInitializer(String.join(".", packageName, "Hello"))
|
||||
.disablePackageUninstaller();
|
||||
testInitializer.applyTo(pkg);
|
||||
|
||||
LauncherAsServiceVerifier.build().setExpectedValue("Default").applyTo(pkg);
|
||||
|
||||
var pkg2 = createPackageTest()
|
||||
.addHelloAppInitializer(String.join(".", packageName, "Bye"))
|
||||
.addInitializer(cmd -> {
|
||||
cmd.addArguments("--app-version", "2.0");
|
||||
});
|
||||
testInitializer.applyTo(pkg2);
|
||||
|
||||
var builder = LauncherAsServiceVerifier.build()
|
||||
.setLauncherName("foo")
|
||||
.setAppOutputFileName("foo-launcher-as-service.txt");
|
||||
|
||||
builder.setExpectedValue("Foo").applyTo(pkg);
|
||||
|
||||
builder.setExpectedValue("Foo2").applyTo(pkg2);
|
||||
|
||||
builder.setExpectedValue("Bar")
|
||||
.setLauncherName("bar")
|
||||
.setAppOutputFileName("bar-launcher-as-service.txt")
|
||||
.applyTo(pkg2);
|
||||
|
||||
new PackageTest.Group(pkg, pkg2).run();
|
||||
}
|
||||
|
||||
private final class TestInitializer {
|
||||
|
||||
TestInitializer setUpgradeCode(String v) {
|
||||
upgradeCode = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
void applyTo(PackageTest test) throws IOException {
|
||||
if (winServiceInstaller != null) {
|
||||
var resourceDir = TKit.createTempDirectory("resource-dir");
|
||||
Files.copy(winServiceInstaller, resourceDir.resolve(
|
||||
"service-installer.exe"));
|
||||
|
||||
test.forTypes(WINDOWS, () -> test.addInitializer(cmd -> {
|
||||
cmd.addArguments("--resource-dir", resourceDir);
|
||||
}));
|
||||
}
|
||||
|
||||
if (upgradeCode != null) {
|
||||
test.forTypes(WINDOWS, () -> test.addInitializer(cmd -> {
|
||||
cmd.addArguments("--win-upgrade-uuid", upgradeCode);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private String upgradeCode;
|
||||
}
|
||||
|
||||
private TestInitializer createTestInitializer() {
|
||||
return new TestInitializer();
|
||||
}
|
||||
|
||||
private static PackageTest createPackageTest() {
|
||||
return new PackageTest()
|
||||
.excludeTypes(MAC_DMG) // DMG not supported
|
||||
.addInitializer(JPackageCommand::setInputToEmptyDirectory);
|
||||
}
|
||||
|
||||
private final Path winServiceInstaller;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user