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 \
|
COPY += .gif .png .txt .spec .script .prerm .preinst \
|
||||||
.postrm .postinst .list .sh .desktop .copyright .control .plist .template \
|
.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
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,11 +25,8 @@
|
|||||||
package jdk.jpackage.internal;
|
package jdk.jpackage.internal;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -39,8 +36,8 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.imageio.ImageIO;
|
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.FILE_ASSOCIATIONS;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.ICON;
|
import static jdk.jpackage.internal.StandardBundlerParam.ICON;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE;
|
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.
|
* Helper to create files for desktop integration.
|
||||||
*/
|
*/
|
||||||
final class DesktopIntegration {
|
final class DesktopIntegration extends ShellCustomAction {
|
||||||
|
|
||||||
static final String DESKTOP_COMMANDS_INSTALL = "DESKTOP_COMMANDS_INSTALL";
|
private static final String COMMANDS_INSTALL = "DESKTOP_COMMANDS_INSTALL";
|
||||||
static final String DESKTOP_COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
|
private static final String COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
|
||||||
static final String UTILITY_SCRIPTS = "UTILITY_SCRIPTS";
|
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,
|
private DesktopIntegration(PlatformPackage thePackage,
|
||||||
Map<String, ? super Object> params,
|
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 {
|
Map<String, ? super Object> params) throws IOException {
|
||||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||||
return null;
|
return ShellCustomAction.nop(REPLACEMENT_STRING_IDS);
|
||||||
}
|
}
|
||||||
return new DesktopIntegration(thePackage, params, null);
|
return new DesktopIntegration(thePackage, params, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
List<String> requiredPackages() {
|
List<String> requiredPackages() {
|
||||||
return Stream.of(List.of(this), nestedIntegrations).flatMap(
|
return Stream.of(List.of(this), nestedIntegrations).flatMap(
|
||||||
List::stream).map(DesktopIntegration::requiredPackagesSelf).flatMap(
|
List::stream).map(DesktopIntegration::requiredPackagesSelf).flatMap(
|
||||||
List::stream).distinct().toList();
|
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());
|
associations.forEach(assoc -> assoc.data.verify());
|
||||||
|
|
||||||
if (iconFile != null) {
|
if (iconFile != null) {
|
||||||
@ -230,9 +237,9 @@ final class DesktopIntegration {
|
|||||||
// of the additional launchers and append them to the corresponding
|
// of the additional launchers and append them to the corresponding
|
||||||
// commands of the main launcher.
|
// commands of the main launcher.
|
||||||
List<String> installShellCmds = new ArrayList<>(Arrays.asList(
|
List<String> installShellCmds = new ArrayList<>(Arrays.asList(
|
||||||
data.get(DESKTOP_COMMANDS_INSTALL)));
|
data.get(COMMANDS_INSTALL)));
|
||||||
List<String> uninstallShellCmds = new ArrayList<>(Arrays.asList(
|
List<String> uninstallShellCmds = new ArrayList<>(Arrays.asList(
|
||||||
data.get(DESKTOP_COMMANDS_UNINSTALL)));
|
data.get(COMMANDS_UNINSTALL)));
|
||||||
for (var integration: nestedIntegrations) {
|
for (var integration: nestedIntegrations) {
|
||||||
if (!integration.associations.isEmpty()) {
|
if (!integration.associations.isEmpty()) {
|
||||||
needCleanupScripts = true;
|
needCleanupScripts = true;
|
||||||
@ -240,26 +247,16 @@ final class DesktopIntegration {
|
|||||||
|
|
||||||
Map<String, String> launcherData = integration.create();
|
Map<String, String> launcherData = integration.create();
|
||||||
|
|
||||||
installShellCmds.add(launcherData.get(DESKTOP_COMMANDS_INSTALL));
|
installShellCmds.add(launcherData.get(COMMANDS_INSTALL));
|
||||||
uninstallShellCmds.add(launcherData.get(
|
uninstallShellCmds.add(launcherData.get(COMMANDS_UNINSTALL));
|
||||||
DESKTOP_COMMANDS_UNINSTALL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(
|
data.put(COMMANDS_INSTALL, stringifyShellCommands(installShellCmds));
|
||||||
installShellCmds));
|
data.put(COMMANDS_UNINSTALL, stringifyShellCommands(uninstallShellCmds));
|
||||||
data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(
|
|
||||||
uninstallShellCmds));
|
|
||||||
|
|
||||||
if (needCleanupScripts) {
|
if (needCleanupScripts) {
|
||||||
// Pull in utils.sh scrips library.
|
// Pull in desktop_utils.sh scrips library.
|
||||||
try (InputStream is = OverridableResource.readDefault("utils.sh");
|
data.put(SCRIPTS, stringifyTextFile("desktop_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, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@ -277,17 +274,12 @@ final class DesktopIntegration {
|
|||||||
Map<String, String> data = new HashMap<>();
|
Map<String, String> data = new HashMap<>();
|
||||||
data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
|
data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
|
||||||
data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
|
data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
|
||||||
data.put("APPLICATION_ICON",
|
data.put("APPLICATION_ICON", Optional.ofNullable(iconFile).map(
|
||||||
iconFile != null ? iconFile.installPath().toString() : null);
|
f -> f.installPath().toString()).orElse(null));
|
||||||
data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
|
data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
|
||||||
|
data.put("APPLICATION_LAUNCHER", Enquoter.forPropertyValues().applyTo(
|
||||||
String appLauncher = thePackage.installedApplicationLayout().launchersDirectory().resolve(
|
thePackage.installedApplicationLayout().launchersDirectory().resolve(
|
||||||
LinuxAppImageBuilder.getLauncherName(params)).toString();
|
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);
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -356,13 +348,13 @@ final class DesktopIntegration {
|
|||||||
cmds.add(registerDesktopFileCmd);
|
cmds.add(registerDesktopFileCmd);
|
||||||
cmds.add(registerFileAssociationsCmd);
|
cmds.add(registerFileAssociationsCmd);
|
||||||
cmds.addAll(registerIconCmds);
|
cmds.addAll(registerIconCmds);
|
||||||
data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(cmds));
|
data.put(COMMANDS_INSTALL, stringifyShellCommands(cmds));
|
||||||
|
|
||||||
cmds.clear();
|
cmds.clear();
|
||||||
cmds.add(unregisterDesktopFileCmd);
|
cmds.add(unregisterDesktopFileCmd);
|
||||||
cmds.add(unregisterFileAssociationsCmd);
|
cmds.add(unregisterFileAssociationsCmd);
|
||||||
cmds.addAll(unregisterIconCmds);
|
cmds.addAll(unregisterIconCmds);
|
||||||
data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(cmds));
|
data.put(COMMANDS_UNINSTALL, stringifyShellCommands(cmds));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String registerDesktopFileCmd;
|
private String registerDesktopFileCmd;
|
||||||
@ -385,24 +377,25 @@ final class DesktopIntegration {
|
|||||||
private class DesktopFile {
|
private class DesktopFile {
|
||||||
|
|
||||||
DesktopFile(String fileName) {
|
DesktopFile(String fileName) {
|
||||||
installPath = thePackage
|
var installPath = thePackage
|
||||||
.installedApplicationLayout()
|
.installedApplicationLayout()
|
||||||
.destktopIntegrationDirectory().resolve(fileName);
|
.destktopIntegrationDirectory().resolve(fileName);
|
||||||
srcPath = thePackage
|
var srcPath = thePackage
|
||||||
.sourceApplicationLayout()
|
.sourceApplicationLayout()
|
||||||
.destktopIntegrationDirectory().resolve(fileName);
|
.destktopIntegrationDirectory().resolve(fileName);
|
||||||
|
|
||||||
|
impl = new InstallableFile(srcPath, installPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Path installPath;
|
|
||||||
private final Path srcPath;
|
|
||||||
|
|
||||||
Path installPath() {
|
Path installPath() {
|
||||||
return installPath;
|
return impl.installPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
Path srcPath() {
|
Path srcPath() {
|
||||||
return srcPath;
|
return impl.srcPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final InstallableFile impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendFileAssociation(XMLStreamWriter xml,
|
private void appendFileAssociation(XMLStreamWriter xml,
|
||||||
@ -526,15 +519,6 @@ final class DesktopIntegration {
|
|||||||
return commonIconSize;
|
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 {
|
private static class LinuxFileAssociation {
|
||||||
LinuxFileAssociation(FileAssociation fa) {
|
LinuxFileAssociation(FileAssociation fa) {
|
||||||
this.data = 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
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.PREDEFINED_RUNTIME_IMAGE;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
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.VENDOR;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.DESCRIPTION;
|
import static jdk.jpackage.internal.StandardBundlerParam.DESCRIPTION;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
|
import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
|
||||||
@ -53,6 +50,9 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
|||||||
LinuxPackageBundler(BundlerParamInfo<String> packageName) {
|
LinuxPackageBundler(BundlerParamInfo<String> packageName) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
appImageBundler = new LinuxAppBundler().setDependentTask(true);
|
appImageBundler = new LinuxAppBundler().setDependentTask(true);
|
||||||
|
customActions = List.of(new CustomActionInstance(
|
||||||
|
DesktopIntegration::create), new CustomActionInstance(
|
||||||
|
LinuxLaunchersAsServices::create));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
Map<String, String> data = createDefaultReplacementData(params);
|
||||||
if (desktopIntegration != null) {
|
|
||||||
data.putAll(desktopIntegration.create());
|
for (var ca : customActions) {
|
||||||
} else {
|
data.putAll(ca.instance.create());
|
||||||
Stream.of(DESKTOP_COMMANDS_INSTALL, DESKTOP_COMMANDS_UNINSTALL,
|
|
||||||
UTILITY_SCRIPTS).forEach(v -> data.put(v, ""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.putAll(createReplacementData(params));
|
data.putAll(createReplacementData(params));
|
||||||
@ -182,12 +182,10 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
|||||||
|
|
||||||
PlatformPackage thePackage = createMetaPackage(params);
|
PlatformPackage thePackage = createMetaPackage(params);
|
||||||
|
|
||||||
final List<String> xdgUtilsPackage;
|
final List<String> caPackages = customActions.stream()
|
||||||
if (desktopIntegration != null) {
|
.map(ca -> ca.instance)
|
||||||
xdgUtilsPackage = desktopIntegration.requiredPackages();
|
.map(ShellCustomAction::requiredPackages)
|
||||||
} else {
|
.flatMap(List::stream).toList();
|
||||||
xdgUtilsPackage = Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<String> neededLibPackages;
|
final List<String> neededLibPackages;
|
||||||
if (withFindNeededPackages && Files.exists(thePackage.sourceRoot())) {
|
if (withFindNeededPackages && Files.exists(thePackage.sourceRoot())) {
|
||||||
@ -204,7 +202,7 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
|||||||
|
|
||||||
// Merge all package lists together.
|
// Merge all package lists together.
|
||||||
// Filter out empty names, sort and remove duplicates.
|
// 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();
|
List::stream).filter(Predicate.not(String::isEmpty)).sorted().distinct().toList();
|
||||||
|
|
||||||
Log.verbose(String.format("Required packages: %s", result));
|
Log.verbose(String.format("Required packages: %s", result));
|
||||||
@ -345,7 +343,23 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
|||||||
private final BundlerParamInfo<String> packageName;
|
private final BundlerParamInfo<String> packageName;
|
||||||
private final Bundler appImageBundler;
|
private final Bundler appImageBundler;
|
||||||
private boolean withFindNeededPackages;
|
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 =
|
private static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
|
||||||
new StandardBundlerParam<>(
|
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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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-shortcut-descriptor=Menu shortcut descriptor
|
||||||
resource.menu-icon=menu icon
|
resource.menu-icon=menu icon
|
||||||
resource.rpm-spec-file=RPM spec file
|
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-not-found.advice=Please install required packages
|
||||||
error.tool-old-version.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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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-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.menu-icon=\u30E1\u30CB\u30E5\u30FC\u30FB\u30A2\u30A4\u30B3\u30F3
|
||||||
resource.rpm-spec-file=RPM\u4ED5\u69D8\u30D5\u30A1\u30A4\u30EB
|
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-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
|
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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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-shortcut-descriptor=\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\u63CF\u8FF0\u7B26
|
||||||
resource.menu-icon=\u83DC\u5355\u56FE\u6807
|
resource.menu-icon=\u83DC\u5355\u56FE\u6807
|
||||||
resource.rpm-spec-file=RPM \u89C4\u8303\u6587\u4EF6
|
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-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
|
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
|
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||||
# the debian-policy package
|
# the debian-policy package
|
||||||
|
|
||||||
|
package_type=deb
|
||||||
|
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
configure)
|
configure)
|
||||||
DESKTOP_COMMANDS_INSTALL
|
DESKTOP_COMMANDS_INSTALL
|
||||||
|
LAUNCHER_AS_SERVICE_COMMANDS_INSTALL
|
||||||
;;
|
;;
|
||||||
|
|
||||||
abort-upgrade|abort-remove|abort-deconfigure)
|
abort-upgrade|abort-remove|abort-deconfigure)
|
||||||
|
@ -13,9 +13,14 @@ set -e
|
|||||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||||
# the debian-policy package
|
# the debian-policy package
|
||||||
|
|
||||||
|
package_type=deb
|
||||||
|
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
install|upgrade)
|
install|upgrade)
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
true; LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
abort-upgrade)
|
abort-upgrade)
|
||||||
|
@ -17,11 +17,14 @@ set -e
|
|||||||
# the debian-policy package
|
# the debian-policy package
|
||||||
|
|
||||||
|
|
||||||
UTILITY_SCRIPTS
|
package_type=deb
|
||||||
|
DESKTOP_SCRIPTS
|
||||||
|
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
remove|upgrade|deconfigure)
|
remove|upgrade|deconfigure)
|
||||||
DESKTOP_COMMANDS_UNINSTALL
|
DESKTOP_COMMANDS_UNINSTALL
|
||||||
|
LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||||
;;
|
;;
|
||||||
|
|
||||||
failed-upgrade)
|
failed-upgrade)
|
||||||
@ -34,4 +37,3 @@ DESKTOP_COMMANDS_UNINSTALL
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
@ -49,12 +49,16 @@ APPLICATION_DESCRIPTION
|
|||||||
rm -rf %{buildroot}
|
rm -rf %{buildroot}
|
||||||
install -d -m 755 %{buildroot}APPLICATION_DIRECTORY
|
install -d -m 755 %{buildroot}APPLICATION_DIRECTORY
|
||||||
cp -r %{_sourcedir}APPLICATION_DIRECTORY/* %{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"
|
%if "xAPPLICATION_LICENSE_FILE" != "x"
|
||||||
%define license_install_file %{_defaultlicensedir}/%{name}-%{version}/%{basename:APPLICATION_LICENSE_FILE}
|
%define license_install_file %{_defaultlicensedir}/%{name}-%{version}/%{basename:APPLICATION_LICENSE_FILE}
|
||||||
install -d -m 755 "%{buildroot}%{dirname:%{license_install_file}}"
|
install -d -m 755 "%{buildroot}%{dirname:%{license_install_file}}"
|
||||||
install -m 644 "APPLICATION_LICENSE_FILE" "%{buildroot}%{license_install_file}"
|
install -m 644 "APPLICATION_LICENSE_FILE" "%{buildroot}%{license_install_file}"
|
||||||
%endif
|
%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}
|
{ rpm -ql filesystem || echo %{default_filesystem}; } | sort > %{filesystem_filelist}
|
||||||
comm -23 %{app_filelist} %{filesystem_filelist} > %{package_filelist}
|
comm -23 %{app_filelist} %{filesystem_filelist} > %{package_filelist}
|
||||||
sed -i -e 's/.*/%dir "&"/' %{package_filelist}
|
sed -i -e 's/.*/%dir "&"/' %{package_filelist}
|
||||||
@ -69,10 +73,23 @@ sed -i -e 's/.*/%dir "&"/' %{package_filelist}
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%post
|
%post
|
||||||
|
package_type=rpm
|
||||||
|
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||||
DESKTOP_COMMANDS_INSTALL
|
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
|
%preun
|
||||||
UTILITY_SCRIPTS
|
package_type=rpm
|
||||||
|
DESKTOP_SCRIPTS
|
||||||
|
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||||
DESKTOP_COMMANDS_UNINSTALL
|
DESKTOP_COMMANDS_UNINSTALL
|
||||||
|
LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||||
|
|
||||||
%clean
|
%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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.MacBaseInstallerBundler.SIGNING_KEY_USER;
|
||||||
import static jdk.jpackage.internal.MacAppImageBuilder.APP_STORE;
|
import static jdk.jpackage.internal.MacAppImageBuilder.APP_STORE;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.MAIN_CLASS;
|
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.VERSION;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE;
|
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";
|
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 =
|
public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
|
||||||
new StandardBundlerParam<>(
|
new StandardBundlerParam<>(
|
||||||
".mac.default.icns",
|
".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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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);
|
(s, p) -> s);
|
||||||
|
|
||||||
protected static String getInstallDir(
|
static String getInstallDir(
|
||||||
Map<String, ? super Object> params, boolean defaultOnly) {
|
Map<String, ? super Object> params, boolean defaultOnly) {
|
||||||
String returnValue = INSTALL_DIR.fetchFrom(params);
|
String returnValue = INSTALL_DIR.fetchFrom(params);
|
||||||
if (defaultOnly && returnValue != null) {
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
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.CONFIG_ROOT;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.TEMP_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.APP_NAME;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
|
import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
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.APP_STORE;
|
||||||
import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
|
import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
|
||||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||||
|
import static jdk.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
|
||||||
|
|
||||||
public class MacPkgBundler extends MacBaseInstallerBundler {
|
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_BACKGROUND_IMAGE = "background_pkg.png";
|
||||||
private static final String DEFAULT_PDF = "product-def.plist";
|
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 =
|
private static final BundlerParamInfo<Path> PACKAGES_ROOT =
|
||||||
new StandardBundlerParam<>(
|
new StandardBundlerParam<>(
|
||||||
"mac.pkg.packagesRoot",
|
"mac.pkg.packagesRoot",
|
||||||
@ -171,6 +169,16 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
|||||||
APP_NAME.fetchFrom(params) + "-app.pkg");
|
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(
|
private Path getConfig_DistributionXMLFile(
|
||||||
Map<String, ? super Object> params) {
|
Map<String, ? super Object> params) {
|
||||||
return CONFIG_ROOT.fetchFrom(params).resolve("distribution.dist");
|
return CONFIG_ROOT.fetchFrom(params).resolve("distribution.dist");
|
||||||
@ -190,19 +198,18 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
|||||||
APP_NAME.fetchFrom(params) + "-background-darkAqua.png");
|
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) {
|
private String getAppIdentifier(Map<String, ? super Object> params) {
|
||||||
return MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(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)
|
private void preparePackageScripts(Map<String, ? super Object> params)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Log.verbose(I18N.getString("message.preparing-scripts"));
|
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("INSTALL_LOCATION", getInstallDir(params, false));
|
||||||
data.put("APP_LOCATION", appLocation.toString());
|
data.put("APP_LOCATION", appLocation.toString());
|
||||||
|
|
||||||
createResource(TEMPLATE_PREINSTALL_SCRIPT, params)
|
MacPkgInstallerScripts.createAppScripts()
|
||||||
.setCategory(I18N.getString("resource.pkg-preinstall-script"))
|
.setResourceDir(RESOURCE_DIR.fetchFrom(params))
|
||||||
.setSubstitutionData(data)
|
.setSubstitutionData(data)
|
||||||
.saveToFile(getScripts_PreinstallFile(params));
|
.saveInFolder(SCRIPTS_DIR.fetchFrom(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String URLEncoding(String pkgName) throws URISyntaxException {
|
private void addPackageToInstallerGuiScript(XMLStreamWriter xml,
|
||||||
URI uri = new URI(null, null, pkgName, null);
|
String pkgId, String pkgName, String pkgVersion) throws IOException,
|
||||||
return uri.toASCIIString();
|
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)
|
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
|
* Note that the content of the distribution file
|
||||||
* below is generated by productbuild --synthesize
|
* below is generated by productbuild --synthesize
|
||||||
*/
|
*/
|
||||||
String appId = getAppIdentifier(params);
|
|
||||||
|
|
||||||
xml.writeStartElement("pkg-ref");
|
Map<String, Path> pkgs = new LinkedHashMap<>();
|
||||||
xml.writeAttribute("id", appId);
|
|
||||||
xml.writeEndElement(); // </pkg-ref>
|
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.writeStartElement("options");
|
||||||
xml.writeAttribute("customize", "never");
|
xml.writeAttribute("customize", "never");
|
||||||
xml.writeAttribute("require-scripts", "false");
|
xml.writeAttribute("require-scripts", "false");
|
||||||
@ -291,32 +323,16 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
|||||||
xml.writeStartElement("choices-outline");
|
xml.writeStartElement("choices-outline");
|
||||||
xml.writeStartElement("line");
|
xml.writeStartElement("line");
|
||||||
xml.writeAttribute("choice", "default");
|
xml.writeAttribute("choice", "default");
|
||||||
xml.writeStartElement("line");
|
for (var pkgId : pkgs.keySet()) {
|
||||||
xml.writeAttribute("choice", appId);
|
xml.writeStartElement("line");
|
||||||
xml.writeEndElement(); // </line>
|
xml.writeAttribute("choice", pkgId);
|
||||||
|
xml.writeEndElement(); // </line>
|
||||||
|
}
|
||||||
xml.writeEndElement(); // </line>
|
xml.writeEndElement(); // </line>
|
||||||
xml.writeEndElement(); // </choices-outline>
|
xml.writeEndElement(); // </choices-outline>
|
||||||
xml.writeStartElement("choice");
|
xml.writeStartElement("choice");
|
||||||
xml.writeAttribute("id", "default");
|
xml.writeAttribute("id", "default");
|
||||||
xml.writeEndElement(); // </choice>
|
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>
|
xml.writeEndElement(); // </installer-gui-script>
|
||||||
});
|
});
|
||||||
@ -434,6 +450,81 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
|||||||
return newRoot.toString();
|
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,
|
private Path createPKG(Map<String, ? super Object> params,
|
||||||
Path outdir, Path appLocation) {
|
Path outdir, Path appLocation) {
|
||||||
// generic find attempt
|
// generic find attempt
|
||||||
@ -442,6 +533,10 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
|||||||
|
|
||||||
String root = getRoot(params, appLocation);
|
String root = getRoot(params, appLocation);
|
||||||
|
|
||||||
|
if (withServicesPkg(params)) {
|
||||||
|
createServicesPkg(params);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate default CPL file
|
// Generate default CPL file
|
||||||
Path cpl = CONFIG_ROOT.fetchFrom(params).resolve("cpl.plist");
|
Path cpl = CONFIG_ROOT.fetchFrom(params).resolve("cpl.plist");
|
||||||
ProcessBuilder pb = new ProcessBuilder("/usr/bin/pkgbuild",
|
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.post-install-script=script to run after application image is populated
|
||||||
resource.pkg-preinstall-script=PKG preinstall script
|
resource.pkg-preinstall-script=PKG preinstall script
|
||||||
resource.pkg-postinstall-script=PKG postinstall 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-background-image=pkg background image
|
||||||
resource.pkg-pdf=project definition file
|
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.
|
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.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-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-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-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
|
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.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-preinstall-script=PKG \u5B89\u88C5\u524D\u811A\u672C
|
||||||
resource.pkg-postinstall-script=PKG \u5B89\u88C5\u540E\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-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
|
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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import jdk.jpackage.internal.Arguments.CLIOptions;
|
import jdk.jpackage.internal.Arguments.CLIOptions;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.LAUNCHER_DATA;
|
import static jdk.jpackage.internal.StandardBundlerParam.LAUNCHER_DATA;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||||
@ -61,6 +62,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT;
|
|||||||
* icon
|
* icon
|
||||||
* arguments
|
* arguments
|
||||||
* java-options
|
* java-options
|
||||||
|
* launcher-as-service
|
||||||
* win-console
|
* win-console
|
||||||
* win-shortcut
|
* win-shortcut
|
||||||
* win-menu
|
* win-menu
|
||||||
@ -118,9 +120,13 @@ class AddLauncherArguments {
|
|||||||
Arguments.putUnlessNull(bundleParams, CLIOptions.RELEASE.getId(),
|
Arguments.putUnlessNull(bundleParams, CLIOptions.RELEASE.getId(),
|
||||||
getOptionValue(CLIOptions.RELEASE));
|
getOptionValue(CLIOptions.RELEASE));
|
||||||
|
|
||||||
String value = getOptionValue(CLIOptions.ICON);
|
|
||||||
Arguments.putUnlessNull(bundleParams, CLIOptions.ICON.getId(),
|
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()) {
|
if (Platform.isWindows()) {
|
||||||
Arguments.putUnlessNull(bundleParams,
|
Arguments.putUnlessNull(bundleParams,
|
||||||
|
@ -32,6 +32,7 @@ import java.text.MessageFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
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.VERSION;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.ADD_LAUNCHERS;
|
import static jdk.jpackage.internal.StandardBundlerParam.ADD_LAUNCHERS;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
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.SHORTCUT_HINT;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.MENU_HINT;
|
import static jdk.jpackage.internal.StandardBundlerParam.MENU_HINT;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE;
|
import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE;
|
||||||
|
|
||||||
public class AppImageFile {
|
public final class AppImageFile {
|
||||||
|
|
||||||
// These values will be loaded from AppImage xml file.
|
// These values will be loaded from AppImage xml file.
|
||||||
private final String creatorVersion;
|
private final String creatorVersion;
|
||||||
@ -143,13 +145,13 @@ public class AppImageFile {
|
|||||||
List<Map<String, ? super Object>> addLaunchers =
|
List<Map<String, ? super Object>> addLaunchers =
|
||||||
ADD_LAUNCHERS.fetchFrom(params);
|
ADD_LAUNCHERS.fetchFrom(params);
|
||||||
|
|
||||||
for (int i = 0; i < addLaunchers.size(); i++) {
|
for (var launcherParams : addLaunchers) {
|
||||||
Map<String, ? super Object> sl = addLaunchers.get(i);
|
var li = new LauncherInfo(launcherParams);
|
||||||
xml.writeStartElement("add-launcher");
|
xml.writeStartElement("add-launcher");
|
||||||
xml.writeAttribute("name", APP_NAME.fetchFrom(sl));
|
xml.writeAttribute("name", li.getName());
|
||||||
xml.writeAttribute("shortcut",
|
xml.writeAttribute("shortcut", Boolean.toString(li.isShortcut()));
|
||||||
SHORTCUT_HINT.fetchFrom(sl).toString());
|
xml.writeAttribute("menu", Boolean.toString(li.isMenu()));
|
||||||
xml.writeAttribute("menu", MENU_HINT.fetchFrom(sl).toString());
|
xml.writeAttribute("service", Boolean.toString(li.isService()));
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -190,14 +192,7 @@ public class AppImageFile {
|
|||||||
XPathConstants.NODESET);
|
XPathConstants.NODESET);
|
||||||
|
|
||||||
for (int i = 0; i != launcherNodes.getLength(); i++) {
|
for (int i = 0; i != launcherNodes.getLength(); i++) {
|
||||||
Node item = launcherNodes.item(i);
|
launcherInfos.add(new LauncherInfo(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))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AppImageFile file = new AppImageFile(
|
AppImageFile file = new AppImageFile(
|
||||||
@ -241,31 +236,32 @@ public class AppImageFile {
|
|||||||
* Following items in the list are names of additional launchers.
|
* Following items in the list are names of additional launchers.
|
||||||
*/
|
*/
|
||||||
static List<LauncherInfo> getLaunchers(Path appImageDir,
|
static List<LauncherInfo> getLaunchers(Path appImageDir,
|
||||||
Map<String, ? super Object> params) {
|
Map<String, Object> params) {
|
||||||
List<LauncherInfo> launchers = new ArrayList<>();
|
List<LauncherInfo> launchers = new ArrayList<>();
|
||||||
try {
|
if (appImageDir != null) {
|
||||||
AppImageFile appImageInfo = AppImageFile.load(appImageDir);
|
try {
|
||||||
if (appImageInfo != null) {
|
AppImageFile appImageInfo = AppImageFile.load(appImageDir);
|
||||||
launchers.add(new LauncherInfo(
|
if (appImageInfo != null) {
|
||||||
appImageInfo.getLauncherName(), true, true));
|
launchers.add(new LauncherInfo(
|
||||||
launchers.addAll(appImageInfo.getAddLaunchers());
|
appImageInfo.getLauncherName(), params));
|
||||||
return launchers;
|
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(
|
launchers.add(new LauncherInfo(params));
|
||||||
name -> new LauncherInfo(name, true, true)).forEach(launchers::add);
|
ADD_LAUNCHERS.fetchFrom(params).stream()
|
||||||
|
.map(launcherParams -> new LauncherInfo(launcherParams))
|
||||||
|
.forEach(launchers::add);
|
||||||
return launchers;
|
return launchers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,11 +285,11 @@ public class AppImageFile {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getVersion() {
|
static String getVersion() {
|
||||||
return System.getProperty("java.version");
|
return "1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getPlatform() {
|
static String getPlatform() {
|
||||||
return PLATFORM_LABELS.get(Platform.getPlatform());
|
return PLATFORM_LABELS.get(Platform.getPlatform());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,34 +297,63 @@ public class AppImageFile {
|
|||||||
if (launcherName == null || launcherName.length() == 0) {
|
if (launcherName == null || launcherName.length() == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var launcher : addLauncherInfos) {
|
for (var launcher : addLauncherInfos) {
|
||||||
if ("".equals(launcher.getName())) {
|
if ("".equals(launcher.getName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(getVersion(), creatorVersion)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(getPlatform(), creatorPlatform)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class LauncherInfo {
|
static class LauncherInfo {
|
||||||
private String name;
|
private final String name;
|
||||||
private boolean shortcut;
|
private final boolean shortcut;
|
||||||
private boolean menu;
|
private final boolean menu;
|
||||||
|
private final boolean service;
|
||||||
|
|
||||||
public LauncherInfo(String name, boolean shortcut, boolean menu) {
|
private LauncherInfo(Map<String, Object> params) {
|
||||||
this.name = name;
|
this(APP_NAME.fetchFrom(params), params);
|
||||||
this.shortcut = shortcut;
|
|
||||||
this.menu = menu;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShortcut() {
|
public boolean isShortcut() {
|
||||||
return shortcut;
|
return shortcut;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMenu() {
|
public boolean isMenu() {
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isService() {
|
||||||
|
return service;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -314,6 +314,10 @@ public class Arguments {
|
|||||||
|
|
||||||
MODULE_PATH ("module-path", "p", OptionCategories.MODULAR),
|
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, () -> {
|
MAC_SIGN ("mac-sign", "s", OptionCategories.PLATFORM_MAC, () -> {
|
||||||
setOptionValue("mac-sign", true);
|
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.StandardCopyOption;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
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.XMLOutputFactory;
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
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
|
* 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) {
|
public static Path getParent(Path p) {
|
||||||
Path parent = p.getParent();
|
Path parent = p.getParent();
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
@ -416,4 +463,24 @@ public class IOUtils {
|
|||||||
private static final String INDENT = " ";
|
private static final String INDENT = " ";
|
||||||
private static final String EOL = "\n";
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -76,6 +76,22 @@ final class OverridableResource {
|
|||||||
setSourceOrder(Source.values());
|
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) {
|
OverridableResource setSubstitutionData(Map<String, String> v) {
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
// Disconnect `v`
|
// Disconnect `v`
|
||||||
@ -86,6 +102,13 @@ final class OverridableResource {
|
|||||||
return this;
|
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) {
|
OverridableResource setCategory(String v) {
|
||||||
category = v;
|
category = v;
|
||||||
return this;
|
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 {
|
Source saveToFile(Path dest) throws IOException {
|
||||||
if (dest == null) {
|
if (dest == null) {
|
||||||
return sendToConsumer(null);
|
return sendToConsumer(null);
|
||||||
@ -240,12 +267,8 @@ final class OverridableResource {
|
|||||||
final Path customResource = resourceDir.resolve(resourceName);
|
final Path customResource = resourceDir.resolve(resourceName);
|
||||||
used = Files.exists(customResource);
|
used = Files.exists(customResource);
|
||||||
if (used && dest != null) {
|
if (used && dest != null) {
|
||||||
final Path logResourceName;
|
final Path logResourceName = Optional.ofNullable(logPublicName).orElse(
|
||||||
if (logPublicName != null) {
|
resourceName).normalize();
|
||||||
logResourceName = logPublicName.normalize();
|
|
||||||
} else {
|
|
||||||
logResourceName = resourceName.normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.verbose(MessageFormat.format(I18N.getString(
|
Log.verbose(MessageFormat.format(I18N.getString(
|
||||||
"message.using-custom-resource"), getPrintableCategory(),
|
"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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.
|
* Platform package of an application.
|
||||||
*/
|
*/
|
||||||
interface PlatformPackage {
|
interface PlatformPackage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform-specific package name.
|
* Platform-specific package name.
|
||||||
*/
|
*/
|
||||||
String 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();
|
Path sourceRoot();
|
||||||
|
|
||||||
|
@ -345,6 +345,16 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
|||||||
(s, p) -> s
|
(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")
|
@SuppressWarnings("unchecked")
|
||||||
static final StandardBundlerParam<List<Map<String, ? super Object>>> ADD_LAUNCHERS =
|
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.LICENSE_FILE.getId(), USE.INSTALL);
|
||||||
options.put(CLIOptions.INSTALL_DIR.getId(), USE.INSTALL);
|
options.put(CLIOptions.INSTALL_DIR.getId(), USE.INSTALL);
|
||||||
options.put(CLIOptions.PREDEFINED_APP_IMAGE.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);
|
options.put(CLIOptions.ABOUT_URL.getId(), USE.INSTALL);
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ Generic Options:\n\
|
|||||||
\ (absolute path or relative to the current directory)\n\
|
\ (absolute path or relative to the current directory)\n\
|
||||||
\ The keys "module", "main-jar", "main-class", "description",\n\
|
\ The keys "module", "main-jar", "main-class", "description",\n\
|
||||||
\ "arguments", "java-options", "app-version", "icon",\n\
|
\ "arguments", "java-options", "app-version", "icon",\n\
|
||||||
|
\ "launcher-as-service",\n\
|
||||||
\ "win-console", "win-shortcut", "win-menu",\n\
|
\ "win-console", "win-shortcut", "win-menu",\n\
|
||||||
\ "linux-app-category", and "linux-shortcut" can be used.\n\
|
\ "linux-app-category", and "linux-shortcut" can be used.\n\
|
||||||
\ These options are added to, or used to overwrite, the original\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\
|
\ Path of the predefined runtime image to install\n\
|
||||||
\ (absolute path or relative to the current directory)\n\
|
\ (absolute path or relative to the current directory)\n\
|
||||||
\ Option is required when creating a runtime package.\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\
|
\n\
|
||||||
\Platform dependent options for creating the application package:\n\
|
\Platform dependent options for creating the application package:\n\
|
||||||
{3}
|
{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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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 \
|
MSG_Help=Usage: jpackage <options>\n\
|
||||||
-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 \
|
\n\
|
||||||
--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 \
|
Sample usages:\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 \
|
--------------\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}
|
\ 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_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
|
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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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 \
|
MSG_Help=Usage: jpackage <options>\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 \
|
\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 \
|
Sample usages:\n\
|
||||||
\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}
|
--------------\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_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
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.XPathConstants;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
import jdk.jpackage.internal.AppImageFile.LauncherInfo;
|
||||||
|
|
||||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.ABOUT_URL;
|
import static jdk.jpackage.internal.StandardBundlerParam.ABOUT_URL;
|
||||||
@ -157,6 +158,14 @@ public class WinMsiBundler extends AbstractBundler {
|
|||||||
null,
|
null,
|
||||||
(s, p) -> 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 =
|
public static final StandardBundlerParam<Boolean> MSI_SYSTEM_WIDE =
|
||||||
new StandardBundlerParam<>(
|
new StandardBundlerParam<>(
|
||||||
Arguments.CLIOptions.WIN_PER_USER_INSTALLATION.getId(),
|
Arguments.CLIOptions.WIN_PER_USER_INSTALLATION.getId(),
|
||||||
@ -323,6 +332,15 @@ public class WinMsiBundler extends AbstractBundler {
|
|||||||
|
|
||||||
FileAssociation.verify(FileAssociation.fetchFrom(params));
|
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;
|
return true;
|
||||||
} catch (RuntimeException re) {
|
} catch (RuntimeException re) {
|
||||||
if (re.getCause() instanceof ConfigException) {
|
if (re.getCause() instanceof ConfigException) {
|
||||||
@ -385,6 +403,13 @@ public class WinMsiBundler extends AbstractBundler {
|
|||||||
destFile.toFile().setWritable(true);
|
destFile.toFile().setWritable(true);
|
||||||
ensureByMutationFileIsRTF(destFile);
|
ensureByMutationFileIsRTF(destFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var serviceInstallerResource = initServiceInstallerResource(params);
|
||||||
|
if (serviceInstallerResource != null) {
|
||||||
|
var serviceInstallerPath = serviceInstallerResource.getExternalPath();
|
||||||
|
params.put(SERVICE_INSTALLER.getID(), new InstallableFile(
|
||||||
|
serviceInstallerPath, serviceInstallerPath.getFileName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 Path installerIcon;
|
||||||
private Map<WixTool, WixTool.ToolInfo> wixToolset;
|
private Map<WixTool, WixTool.ToolInfo> wixToolset;
|
||||||
private AppImageBundler appImageBundler;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import javax.xml.stream.XMLOutputFactory;
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
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 jdk.jpackage.internal.IOUtils.XmlConsumer;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
|
import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.VENDOR;
|
import static jdk.jpackage.internal.StandardBundlerParam.VENDOR;
|
||||||
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
|
||||||
import static jdk.jpackage.internal.WinMsiBundler.MSI_SYSTEM_WIDE;
|
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 static jdk.jpackage.internal.WinMsiBundler.WIN_APP_IMAGE;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates WiX fragment with components for contents of app image.
|
* Creates WiX fragment with components for contents of app image.
|
||||||
@ -89,10 +98,8 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
|||||||
do {
|
do {
|
||||||
ApplicationLayout layout = appImageSupplier.get();
|
ApplicationLayout layout = appImageSupplier.get();
|
||||||
// Don't want AppImageFile.FILENAME in installed application.
|
// Don't want AppImageFile.FILENAME in installed application.
|
||||||
// Register it with app image at a role without a match in installed
|
new InstallableFile(AppImageFile.getPathInAppImage(Path.of("")),
|
||||||
// app layout to exclude it from layout transformation.
|
null).excludeFromApplicationLayout(layout);
|
||||||
layout.pathGroup().setPath(new Object(),
|
|
||||||
AppImageFile.getPathInAppImage(Path.of("")));
|
|
||||||
|
|
||||||
// Want absolute paths to source files in generated WiX sources.
|
// Want absolute paths to source files in generated WiX sources.
|
||||||
// This is to handle scenario if sources would be processed from
|
// This is to handle scenario if sources would be processed from
|
||||||
@ -112,6 +119,27 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
|||||||
launchers = AppImageFile.getLaunchers(appImageRoot, params);
|
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);
|
programMenuFolderName = MENU_GROUP.fetchFrom(params);
|
||||||
|
|
||||||
initFileAssociations(params);
|
initFileAssociations(params);
|
||||||
@ -388,6 +416,13 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
|||||||
xmlConsumer.accept(xml);
|
xmlConsumer.accept(xml);
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
|
|
||||||
|
if (role == Component.File && serviceInstaller != null && path.equals(
|
||||||
|
serviceInstaller.installPath())) {
|
||||||
|
for (var launcherAsService : launchersAsServices) {
|
||||||
|
launcherAsService.writeServiceInstall(xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xml.writeEndElement(); // <Component>
|
xml.writeEndElement(); // <Component>
|
||||||
xml.writeEndElement(); // <DirectoryRef>
|
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<>();
|
List<String> componentIds = new ArrayList<>();
|
||||||
for (var file : files) {
|
for (var file : files) {
|
||||||
Path src = file.getKey();
|
Path src = file.getKey();
|
||||||
@ -661,9 +701,52 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
|||||||
|
|
||||||
componentIds.add(addDirectoryCleaner(xml, INSTALLDIR));
|
componentIds.add(addDirectoryCleaner(xml, INSTALLDIR));
|
||||||
|
|
||||||
|
componentIds.addAll(addServiceConfigs(xml));
|
||||||
|
|
||||||
addComponentGroup(xml, "Files", componentIds);
|
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
|
private void addIcons(XMLStreamWriter xml) throws
|
||||||
XMLStreamException, IOException {
|
XMLStreamException, IOException {
|
||||||
|
|
||||||
@ -747,18 +830,7 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
|||||||
Component.startElement(xml, componentId, "*");
|
Component.startElement(xml, componentId, "*");
|
||||||
|
|
||||||
addRegistryKeyPath(xml, INSTALLDIR, () -> propertyId, () -> {
|
addRegistryKeyPath(xml, INSTALLDIR, () -> propertyId, () -> {
|
||||||
// The following code converts a path to value to be saved in registry.
|
return toWixPath(path);
|
||||||
// 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();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
xml.writeStartElement(
|
xml.writeStartElement(
|
||||||
@ -773,6 +845,20 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
|||||||
return componentId;
|
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) {
|
private static IllegalArgumentException throwInvalidPathException(Path v) {
|
||||||
throw new IllegalArgumentException(String.format("Invalid path [%s]", v));
|
throw new IllegalArgumentException(String.format("Invalid path [%s]", v));
|
||||||
}
|
}
|
||||||
@ -831,7 +917,11 @@ class WixAppImageFragmentBuilder extends WixFragmentBuilder {
|
|||||||
|
|
||||||
private Set<ShortcutsFolder> shortcutFolders;
|
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 appImage;
|
||||||
private ApplicationLayout installedAppImage;
|
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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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.overrides-wix-file=Overrides WiX project file
|
||||||
resource.shortcutpromptdlg-wix-file=Shortcut prompt dialog 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.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=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.
|
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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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.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.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.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=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
|
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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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.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.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.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=\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
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final public AdditionalLauncher setLauncherAsService() {
|
||||||
|
return addRawProperties(LAUNCHER_AS_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
final public AdditionalLauncher addRawProperties(
|
final public AdditionalLauncher addRawProperties(
|
||||||
Map.Entry<String, String>... v) {
|
Map.Entry<String, String>... v) {
|
||||||
return addRawProperties(List.of(v));
|
return addRawProperties(List.of(v));
|
||||||
@ -338,7 +342,13 @@ public class AdditionalLauncher {
|
|||||||
"--java-options"))).stream().map(
|
"--java-options"))).stream().map(
|
||||||
str -> resolveVariables(cmd, str)).toList());
|
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 {
|
public static final class PropertyFile {
|
||||||
@ -394,4 +404,6 @@ public class AdditionalLauncher {
|
|||||||
private Boolean withShortcut;
|
private Boolean withShortcut;
|
||||||
|
|
||||||
private final static Path NO_ICON = Path.of("");
|
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;
|
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) {
|
private CfgFile(Map<String, Map<String, String>> data, String id) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.id = id;
|
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;
|
package jdk.jpackage.test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -80,6 +82,14 @@ public final class LinuxHelper {
|
|||||||
desktopFileName);
|
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) {
|
static String getBundleName(JPackageCommand cmd) {
|
||||||
cmd.verifyIsOfType(PackageType.LINUX);
|
cmd.verifyIsOfType(PackageType.LINUX);
|
||||||
|
|
||||||
@ -668,6 +678,31 @@ public final class LinuxHelper {
|
|||||||
return arch;
|
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(
|
static final Set<Path> CRITICAL_RUNTIME_FILES = Set.of(Path.of(
|
||||||
"lib/server/libjvm.so"));
|
"lib/server/libjvm.so"));
|
||||||
|
|
||||||
@ -677,4 +712,6 @@ public final class LinuxHelper {
|
|||||||
|
|
||||||
// Values grabbed from https://linux.die.net/man/1/xdg-icon-resource
|
// 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 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.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -225,10 +228,14 @@ public final class MacHelper {
|
|||||||
pkg.uninstallHandler = cmd -> {
|
pkg.uninstallHandler = cmd -> {
|
||||||
cmd.verifyIsOfType(PackageType.MAC_PKG);
|
cmd.verifyIsOfType(PackageType.MAC_PKG);
|
||||||
|
|
||||||
Executor.of("sudo", "rm", "-rf")
|
if (Files.exists(getUninstallCommand(cmd))) {
|
||||||
.addArgument(cmd.appInstallationDirectory())
|
Executor.of("sudo", "/bin/sh",
|
||||||
.execute();
|
getUninstallCommand(cmd).toString()).execute();
|
||||||
|
} else {
|
||||||
|
Executor.of("sudo", "rm", "-rf")
|
||||||
|
.addArgument(cmd.appInstallationDirectory())
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return pkg;
|
return pkg;
|
||||||
@ -247,10 +254,34 @@ public final class MacHelper {
|
|||||||
cmd.name() + (cmd.isRuntime() ? "" : ".app"));
|
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) {
|
private static String getPackageName(JPackageCommand cmd) {
|
||||||
return cmd.getArgumentValue("--mac-package-name", cmd::installerName);
|
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 static final class PListWrapper {
|
||||||
public String queryValue(String keyName) {
|
public String queryValue(String keyName) {
|
||||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||||
@ -314,6 +345,34 @@ public final class MacHelper {
|
|||||||
return dbf.newDocumentBuilder();
|
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(
|
static final Set<Path> CRITICAL_RUNTIME_FILES = Set.of(Path.of(
|
||||||
"Contents/Home/lib/server/libjvm.dylib"));
|
"Contents/Home/lib/server/libjvm.dylib"));
|
||||||
|
|
||||||
|
private final static Method getServicePListFileName = initGetServicePListFileName();
|
||||||
}
|
}
|
||||||
|
@ -324,6 +324,13 @@ public final class PackageTest extends RunnablePackageTest {
|
|||||||
return this;
|
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 final static class Group extends RunnablePackageTest {
|
||||||
public Group(PackageTest... tests) {
|
public Group(PackageTest... tests) {
|
||||||
handlers = Stream.of(tests)
|
handlers = Stream.of(tests)
|
||||||
@ -367,12 +374,6 @@ public final class PackageTest extends RunnablePackageTest {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addHelloAppInitializer(String javaAppDesc) {
|
|
||||||
addInitializer(
|
|
||||||
cmd -> new HelloApp(JavaAppDesc.parse(javaAppDesc)).addTo(cmd),
|
|
||||||
"HelloApp");
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Consumer<Action>> createPackageTypeHandlers() {
|
private List<Consumer<Action>> createPackageTypeHandlers() {
|
||||||
return NATIVE.stream()
|
return NATIVE.stream()
|
||||||
.map(type -> {
|
.map(type -> {
|
||||||
@ -600,6 +601,11 @@ public final class PackageTest extends RunnablePackageTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LauncherAsServiceVerifier.SUPPORTED_PACKAGES.contains(
|
||||||
|
cmd.packageType())) {
|
||||||
|
LauncherAsServiceVerifier.verify(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
cmd.assertAppLayout();
|
cmd.assertAppLayout();
|
||||||
|
|
||||||
installVerifiers.forEach(v -> v.accept(cmd));
|
installVerifiers.forEach(v -> v.accept(cmd));
|
||||||
@ -608,15 +614,24 @@ public final class PackageTest extends RunnablePackageTest {
|
|||||||
private void verifyRootCountInUnpackedPackage(JPackageCommand cmd,
|
private void verifyRootCountInUnpackedPackage(JPackageCommand cmd,
|
||||||
Path unpackedDir) {
|
Path unpackedDir) {
|
||||||
|
|
||||||
|
final boolean withServices = !cmd.isRuntime()
|
||||||
|
&& !LauncherAsServiceVerifier.getLaunchersAsServices(cmd).isEmpty();
|
||||||
|
|
||||||
final long expectedRootCount;
|
final long expectedRootCount;
|
||||||
if (WINDOWS.contains(cmd.packageType())) {
|
if (WINDOWS.contains(cmd.packageType())) {
|
||||||
// On Windows it is always two entries:
|
// On Windows it is always two entries:
|
||||||
// installation home directory and MSI file
|
// installation home directory and MSI file
|
||||||
expectedRootCount = 2;
|
expectedRootCount = 2;
|
||||||
|
} else if (withServices && MAC_PKG.equals(cmd.packageType())) {
|
||||||
|
expectedRootCount = 2;
|
||||||
} else if (LINUX.contains(cmd.packageType())) {
|
} else if (LINUX.contains(cmd.packageType())) {
|
||||||
Set<Path> roots = new HashSet<>();
|
Set<Path> roots = new HashSet<>();
|
||||||
roots.add(Path.of("/").resolve(Path.of(cmd.getArgumentValue(
|
roots.add(Path.of("/").resolve(Path.of(cmd.getArgumentValue(
|
||||||
"--install-dir", () -> "/opt")).getName(0)));
|
"--install-dir", () -> "/opt")).getName(0)));
|
||||||
|
if (withServices) {
|
||||||
|
// /lib/systemd
|
||||||
|
roots.add(Path.of("/lib"));
|
||||||
|
}
|
||||||
if (cmd.hasArgument("--license-file")) {
|
if (cmd.hasArgument("--license-file")) {
|
||||||
switch (cmd.packageType()) {
|
switch (cmd.packageType()) {
|
||||||
case LINUX_RPM -> {
|
case LINUX_RPM -> {
|
||||||
@ -673,6 +688,11 @@ public final class PackageTest extends RunnablePackageTest {
|
|||||||
TKit.assertPathExists(appInstallDir, false);
|
TKit.assertPathExists(appInstallDir, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LauncherAsServiceVerifier.SUPPORTED_PACKAGES.contains(
|
||||||
|
cmd.packageType())) {
|
||||||
|
LauncherAsServiceVerifier.verifyUninstalled(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
uninstallVerifiers.forEach(v -> v.accept(cmd));
|
uninstallVerifiers.forEach(v -> v.accept(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +237,13 @@ final public class TKit {
|
|||||||
trace("Done");
|
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,
|
public static void createPropertiesFile(Path propsFilename,
|
||||||
Map.Entry<String, String>... props) {
|
Map.Entry<String, String>... props) {
|
||||||
createPropertiesFile(propsFilename, List.of(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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -43,7 +43,7 @@ public class AppImageFileTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIdentity() throws IOException {
|
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.NAME.getId(), "Foo");
|
||||||
params.put(Arguments.CLIOptions.VERSION.getId(), "2.3");
|
params.put(Arguments.CLIOptions.VERSION.getId(), "2.3");
|
||||||
params.put(Arguments.CLIOptions.DESCRIPTION.getId(), "Duck is the King");
|
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.
|
// never create app image at both load/save phases.
|
||||||
// People would edit this file just because they can.
|
// People would edit this file just because they can.
|
||||||
// We should be ready to handle curious minds.
|
// 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("invalidParamName", "randomStringValue");
|
||||||
params.put(Arguments.CLIOptions.APPCLASS.getId(), "TestClass");
|
params.put(Arguments.CLIOptions.APPCLASS.getId(), "TestClass");
|
||||||
params.put(Arguments.CLIOptions.MAIN_JAR.getId(), "test.jar");
|
params.put(Arguments.CLIOptions.MAIN_JAR.getId(), "test.jar");
|
||||||
@ -74,12 +74,13 @@ public class AppImageFileTest {
|
|||||||
public void testInavlidXml() throws IOException {
|
public void testInavlidXml() throws IOException {
|
||||||
assertInvalid(createFromXml("<foo/>"));
|
assertInvalid(createFromXml("<foo/>"));
|
||||||
assertInvalid(createFromXml("<jpackage-state/>"));
|
assertInvalid(createFromXml("<jpackage-state/>"));
|
||||||
|
assertInvalid(createFromXml(JPACKAGE_STATE_OPEN, "</jpackage-state>"));
|
||||||
assertInvalid(createFromXml(
|
assertInvalid(createFromXml(
|
||||||
"<jpackage-state>",
|
JPACKAGE_STATE_OPEN,
|
||||||
"<main-launcher></main-launcher>",
|
"<main-launcher></main-launcher>",
|
||||||
"</jpackage-state>"));
|
"</jpackage-state>"));
|
||||||
assertInvalid(createFromXml(
|
assertInvalid(createFromXml(
|
||||||
"<jpackage-state>",
|
JPACKAGE_STATE_OPEN,
|
||||||
"<launcher>A</launcher>",
|
"<launcher>A</launcher>",
|
||||||
"<launcher>B</launcher>",
|
"<launcher>B</launcher>",
|
||||||
"</jpackage-state>"));
|
"</jpackage-state>"));
|
||||||
@ -88,18 +89,18 @@ public class AppImageFileTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testValidXml() throws IOException {
|
public void testValidXml() throws IOException {
|
||||||
Assert.assertEquals("Foo", (createFromXml(
|
Assert.assertEquals("Foo", (createFromXml(
|
||||||
"<jpackage-state>",
|
JPACKAGE_STATE_OPEN,
|
||||||
"<main-launcher>Foo</main-launcher>",
|
"<main-launcher>Foo</main-launcher>",
|
||||||
"</jpackage-state>")).getLauncherName());
|
"</jpackage-state>")).getLauncherName());
|
||||||
|
|
||||||
Assert.assertEquals("Boo", (createFromXml(
|
Assert.assertEquals("Boo", (createFromXml(
|
||||||
"<jpackage-state>",
|
JPACKAGE_STATE_OPEN,
|
||||||
"<main-launcher>Boo</main-launcher>",
|
"<main-launcher>Boo</main-launcher>",
|
||||||
"<main-launcher>Bar</main-launcher>",
|
"<main-launcher>Bar</main-launcher>",
|
||||||
"</jpackage-state>")).getLauncherName());
|
"</jpackage-state>")).getLauncherName());
|
||||||
|
|
||||||
var file = createFromXml(
|
var file = createFromXml(
|
||||||
"<jpackage-state>",
|
JPACKAGE_STATE_OPEN,
|
||||||
"<main-launcher>Foo</main-launcher>",
|
"<main-launcher>Foo</main-launcher>",
|
||||||
"<launcher></launcher>",
|
"<launcher></launcher>",
|
||||||
"</jpackage-state>");
|
"</jpackage-state>");
|
||||||
@ -110,7 +111,7 @@ public class AppImageFileTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMainLauncherName() throws IOException {
|
public void testMainLauncherName() throws IOException {
|
||||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
Map<String, Object> params = new LinkedHashMap<>();
|
||||||
params.put("name", "Foo");
|
params.put("name", "Foo");
|
||||||
params.put("description", "Duck App Description");
|
params.put("description", "Duck App Description");
|
||||||
AppImageFile aif = create(params);
|
AppImageFile aif = create(params);
|
||||||
@ -120,14 +121,14 @@ public class AppImageFileTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddLaunchers() throws IOException {
|
public void testAddLaunchers() throws IOException {
|
||||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
Map<String, Object> params = new LinkedHashMap<>();
|
||||||
List<Map<String, ? super Object>> launchersAsMap = new ArrayList<>();
|
List<Map<String, Object>> launchersAsMap = new ArrayList<>();
|
||||||
|
|
||||||
Map<String, ? super Object> addLauncher2Params = new LinkedHashMap();
|
Map<String, Object> addLauncher2Params = new LinkedHashMap<>();
|
||||||
addLauncher2Params.put("name", "Launcher2Name");
|
addLauncher2Params.put("name", "Launcher2Name");
|
||||||
launchersAsMap.add(addLauncher2Params);
|
launchersAsMap.add(addLauncher2Params);
|
||||||
|
|
||||||
Map<String, ? super Object> addLauncher3Params = new LinkedHashMap();
|
Map<String, Object> addLauncher3Params = new LinkedHashMap<>();
|
||||||
addLauncher3Params.put("name", "Launcher3Name");
|
addLauncher3Params.put("name", "Launcher3Name");
|
||||||
launchersAsMap.add(addLauncher3Params);
|
launchersAsMap.add(addLauncher3Params);
|
||||||
|
|
||||||
@ -138,7 +139,7 @@ public class AppImageFileTest {
|
|||||||
|
|
||||||
List<AppImageFile.LauncherInfo> addLaunchers = aif.getAddLaunchers();
|
List<AppImageFile.LauncherInfo> addLaunchers = aif.getAddLaunchers();
|
||||||
Assert.assertEquals(2, addLaunchers.size());
|
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(0).getName());
|
||||||
names.add(addLaunchers.get(1).getName());
|
names.add(addLaunchers.get(1).getName());
|
||||||
|
|
||||||
@ -163,7 +164,7 @@ public class AppImageFileTest {
|
|||||||
path.toFile().mkdirs();
|
path.toFile().mkdirs();
|
||||||
Files.delete(path);
|
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.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>");
|
||||||
data.addAll(List.of(xmlData));
|
data.addAll(List.of(xmlData));
|
||||||
|
|
||||||
@ -174,4 +175,8 @@ public class AppImageFileTest {
|
|||||||
return image;
|
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