8301856: Generated .spec file for RPM installers uninstalls desktop launcher on update
Reviewed-by: almatvee
This commit is contained in:
parent
726f854b14
commit
7848ed779b
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2023, 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
|
||||
@ -63,9 +63,10 @@ final class DesktopIntegration extends ShellCustomAction {
|
||||
private static final String COMMANDS_INSTALL = "DESKTOP_COMMANDS_INSTALL";
|
||||
private static final String COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
|
||||
private static final String SCRIPTS = "DESKTOP_SCRIPTS";
|
||||
private static final String COMMON_SCRIPTS = "COMMON_SCRIPTS";
|
||||
|
||||
private static final List<String> REPLACEMENT_STRING_IDS = List.of(
|
||||
COMMANDS_INSTALL, COMMANDS_UNINSTALL, SCRIPTS);
|
||||
COMMANDS_INSTALL, COMMANDS_UNINSTALL, SCRIPTS, COMMON_SCRIPTS);
|
||||
|
||||
private DesktopIntegration(PlatformPackage thePackage,
|
||||
Map<String, ? super Object> params,
|
||||
@ -229,8 +230,6 @@ final class DesktopIntegration extends ShellCustomAction {
|
||||
shellCommands.applyTo(data);
|
||||
}
|
||||
|
||||
boolean needCleanupScripts = !associations.isEmpty();
|
||||
|
||||
// Take care of additional launchers if there are any.
|
||||
// Process every additional launcher as the main application launcher.
|
||||
// Collect shell commands to install/uninstall integration with desktop
|
||||
@ -241,10 +240,6 @@ final class DesktopIntegration extends ShellCustomAction {
|
||||
List<String> uninstallShellCmds = new ArrayList<>(Arrays.asList(
|
||||
data.get(COMMANDS_UNINSTALL)));
|
||||
for (var integration: nestedIntegrations) {
|
||||
if (!integration.associations.isEmpty()) {
|
||||
needCleanupScripts = true;
|
||||
}
|
||||
|
||||
Map<String, String> launcherData = integration.create();
|
||||
|
||||
installShellCmds.add(launcherData.get(COMMANDS_INSTALL));
|
||||
@ -254,10 +249,8 @@ final class DesktopIntegration extends ShellCustomAction {
|
||||
data.put(COMMANDS_INSTALL, stringifyShellCommands(installShellCmds));
|
||||
data.put(COMMANDS_UNINSTALL, stringifyShellCommands(uninstallShellCmds));
|
||||
|
||||
if (needCleanupScripts) {
|
||||
// Pull in desktop_utils.sh scrips library.
|
||||
data.put(SCRIPTS, stringifyTextFile("desktop_utils.sh"));
|
||||
}
|
||||
data.put(COMMON_SCRIPTS, stringifyTextFile("common_utils.sh"));
|
||||
data.put(SCRIPTS, stringifyTextFile("desktop_utils.sh"));
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -295,7 +288,9 @@ final class DesktopIntegration extends ShellCustomAction {
|
||||
|
||||
registerDesktopFileCmd = String.join(" ", "xdg-desktop-menu",
|
||||
"install", desktopFile.installPath().toString());
|
||||
unregisterDesktopFileCmd = String.join(" ", "xdg-desktop-menu",
|
||||
unregisterDesktopFileCmd = String.join(" ",
|
||||
"do_if_file_belongs_to_single_package", desktopFile.
|
||||
installPath().toString(), "xdg-desktop-menu",
|
||||
"uninstall", desktopFile.installPath().toString());
|
||||
}
|
||||
|
||||
@ -303,8 +298,10 @@ final class DesktopIntegration extends ShellCustomAction {
|
||||
registerFileAssociationsCmd = String.join(" ", "xdg-mime",
|
||||
"install",
|
||||
mimeInfoFile.installPath().toString());
|
||||
unregisterFileAssociationsCmd = String.join(" ", "xdg-mime",
|
||||
"uninstall", mimeInfoFile.installPath().toString());
|
||||
unregisterFileAssociationsCmd = String.join(" ",
|
||||
"do_if_file_belongs_to_single_package", mimeInfoFile.
|
||||
installPath().toString(), "xdg-mime", "uninstall",
|
||||
mimeInfoFile.installPath().toString());
|
||||
|
||||
//
|
||||
// Add manual cleanup of system files to get rid of
|
||||
@ -320,26 +317,26 @@ final class DesktopIntegration extends ShellCustomAction {
|
||||
// of non-existing desktop file.
|
||||
//
|
||||
String cleanUpCommand = String.join(" ",
|
||||
"uninstall_default_mime_handler",
|
||||
desktopFile.installPath().getFileName().toString(),
|
||||
String.join(" ", getMimeTypeNamesFromFileAssociations()));
|
||||
"do_if_file_belongs_to_single_package", desktopFile.
|
||||
installPath().toString(),
|
||||
"desktop_uninstall_default_mime_handler", desktopFile.
|
||||
installPath().getFileName().toString(), String.join(
|
||||
" ", getMimeTypeNamesFromFileAssociations()));
|
||||
|
||||
unregisterFileAssociationsCmd = stringifyShellCommands(
|
||||
unregisterFileAssociationsCmd, cleanUpCommand);
|
||||
}
|
||||
|
||||
void addIcon(String mimeType, Path iconFile) {
|
||||
addIcon(mimeType, iconFile, getSquareSizeOfImage(iconFile.toFile()));
|
||||
}
|
||||
|
||||
void addIcon(String mimeType, Path iconFile, int imgSize) {
|
||||
imgSize = normalizeIconSize(imgSize);
|
||||
final String dashMime = mimeType.replace('/', '-');
|
||||
registerIconCmds.add(String.join(" ", "xdg-icon-resource",
|
||||
"install", "--context", "mimetypes", "--size",
|
||||
Integer.toString(imgSize), iconFile.toString(), dashMime));
|
||||
unregisterIconCmds.add(String.join(" ", "xdg-icon-resource",
|
||||
"uninstall", dashMime, "--size", Integer.toString(imgSize)));
|
||||
unregisterIconCmds.add(String.join(" ",
|
||||
"do_if_file_belongs_to_single_package", iconFile.toString(),
|
||||
"xdg-icon-resource", "uninstall", dashMime, "--size",
|
||||
Integer.toString(imgSize)));
|
||||
}
|
||||
|
||||
void applyTo(Map<String, String> data) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2023, 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
|
||||
@ -26,6 +26,8 @@ package jdk.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import static jdk.jpackage.internal.OverridableResource.createResource;
|
||||
@ -42,10 +44,24 @@ public final class LinuxLaunchersAsServices extends UnixLaunchersAsServices {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> replacementStringIds() {
|
||||
return LINUX_REPLACEMENT_STRING_IDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> createImpl() throws IOException {
|
||||
var data = super.createImpl();
|
||||
if (!data.isEmpty()) {
|
||||
data.put(COMMON_SCRIPTS, stringifyTextFile("common_utils.sh"));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static ShellCustomAction create(PlatformPackage thePackage,
|
||||
Map<String, Object> params) throws IOException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
return ShellCustomAction.nop(REPLACEMENT_STRING_IDS);
|
||||
return ShellCustomAction.nop(LINUX_REPLACEMENT_STRING_IDS);
|
||||
}
|
||||
return new LinuxLaunchersAsServices(thePackage, params);
|
||||
}
|
||||
@ -84,4 +100,16 @@ public final class LinuxLaunchersAsServices extends UnixLaunchersAsServices {
|
||||
|
||||
private final static List<String> REQUIRED_PACKAGES = List.of("systemd",
|
||||
"coreutils" /* /usr/bin/wc */, "grep");
|
||||
|
||||
private static final String COMMON_SCRIPTS = "COMMON_SCRIPTS";
|
||||
|
||||
private static final List<String> LINUX_REPLACEMENT_STRING_IDS;
|
||||
|
||||
static {
|
||||
ArrayList<String> buf = new ArrayList<>();
|
||||
buf.addAll(UnixLaunchersAsServices.REPLACEMENT_STRING_IDS);
|
||||
buf.add(COMMON_SCRIPTS);
|
||||
|
||||
LINUX_REPLACEMENT_STRING_IDS = Collections.unmodifiableList(buf);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2023, 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
|
||||
@ -155,7 +155,8 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
Map<String, String> data = createDefaultReplacementData(params);
|
||||
|
||||
for (var ca : customActions) {
|
||||
data.putAll(ca.instance.create());
|
||||
ShellCustomAction.mergeReplacementData(data, ca.instance.
|
||||
create());
|
||||
}
|
||||
|
||||
data.putAll(createReplacementData(params));
|
||||
|
@ -0,0 +1,23 @@
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
do_if_file_belongs_to_single_package ()
|
||||
{
|
||||
local file="$1"
|
||||
shift
|
||||
|
||||
if file_belongs_to_single_package "$file"; then
|
||||
"$@"
|
||||
fi
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
# Remove $1 desktop file from the list of default handlers for $2 mime type
|
||||
# in $3 file dumping output to stdout.
|
||||
#
|
||||
_filter_out_default_mime_handler ()
|
||||
desktop_filter_out_default_mime_handler ()
|
||||
{
|
||||
local defaults_list="$3"
|
||||
|
||||
@ -50,7 +50,7 @@ EOF
|
||||
# in $1 file.
|
||||
# Result is saved in $1 file.
|
||||
#
|
||||
_uninstall_default_mime_handler ()
|
||||
desktop_uninstall_default_mime_handler_0 ()
|
||||
{
|
||||
local defaults_list=$1
|
||||
shift
|
||||
@ -66,20 +66,20 @@ _uninstall_default_mime_handler ()
|
||||
local v
|
||||
local update=
|
||||
for mime in "$@"; do
|
||||
_filter_out_default_mime_handler "$desktop_file" "$mime" "$tmpfile1" > "$tmpfile2"
|
||||
desktop_filter_out_default_mime_handler "$desktop_file" "$mime" "$tmpfile1" > "$tmpfile2"
|
||||
v="$tmpfile2"
|
||||
tmpfile2="$tmpfile1"
|
||||
tmpfile1="$v"
|
||||
|
||||
if ! diff -q "$tmpfile1" "$tmpfile2" > /dev/null; then
|
||||
update=yes
|
||||
trace Remove $desktop_file default handler for $mime mime type from $defaults_list file
|
||||
desktop_trace Remove $desktop_file default handler for $mime mime type from $defaults_list file
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$update" ]; then
|
||||
cat "$tmpfile1" > "$defaults_list"
|
||||
trace "$defaults_list" file updated
|
||||
desktop_trace "$defaults_list" file updated
|
||||
fi
|
||||
|
||||
rm -f "$tmpfile1" "$tmpfile2"
|
||||
@ -90,15 +90,15 @@ _uninstall_default_mime_handler ()
|
||||
# Remove $1 desktop file from the list of default handlers for $@ mime types
|
||||
# in all known system defaults lists.
|
||||
#
|
||||
uninstall_default_mime_handler ()
|
||||
desktop_uninstall_default_mime_handler ()
|
||||
{
|
||||
for f in /usr/share/applications/defaults.list /usr/local/share/applications/defaults.list; do
|
||||
_uninstall_default_mime_handler "$f" "$@"
|
||||
desktop_uninstall_default_mime_handler_0 "$f" "$@"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
trace ()
|
||||
desktop_trace ()
|
||||
{
|
||||
echo "$@"
|
||||
}
|
||||
|
@ -23,16 +23,3 @@ unregister_services ()
|
||||
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
|
||||
}
|
||||
|
@ -14,12 +14,13 @@ set -e
|
||||
# the debian-policy package
|
||||
|
||||
package_type=deb
|
||||
COMMON_SCRIPTS
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
if [ -n "$2" ]; then
|
||||
true; LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
:; LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
fi
|
||||
;;
|
||||
|
||||
|
@ -18,6 +18,7 @@ set -e
|
||||
|
||||
|
||||
package_type=deb
|
||||
COMMON_SCRIPTS
|
||||
DESKTOP_SCRIPTS
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
|
||||
|
@ -83,13 +83,15 @@ LAUNCHER_AS_SERVICE_COMMANDS_INSTALL
|
||||
|
||||
%pre
|
||||
package_type=rpm
|
||||
COMMON_SCRIPTS
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
if [ "$1" = 2 ]; then
|
||||
true; LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
if [ "$1" -gt 1 ]; then
|
||||
:; LAUNCHER_AS_SERVICE_COMMANDS_UNINSTALL
|
||||
fi
|
||||
|
||||
%preun
|
||||
package_type=rpm
|
||||
COMMON_SCRIPTS
|
||||
DESKTOP_SCRIPTS
|
||||
LAUNCHER_AS_SERVICE_SCRIPTS
|
||||
DESKTOP_COMMANDS_UNINSTALL
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,6 +34,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -74,6 +75,26 @@ abstract class ShellCustomAction {
|
||||
};
|
||||
}
|
||||
|
||||
static void mergeReplacementData(Map<String, String> target,
|
||||
Map<String, String> newValues) {
|
||||
Objects.requireNonNull(target);
|
||||
Objects.requireNonNull(newValues);
|
||||
|
||||
for (var kvp : newValues.entrySet()) {
|
||||
String newValue = kvp.getValue();
|
||||
String existingValue = target.putIfAbsent(kvp.getKey(), newValue);
|
||||
if (existingValue != null) {
|
||||
if (existingValue.isEmpty()) {
|
||||
target.replace(kvp.getKey(), newValue);
|
||||
} else if (!newValue.isEmpty() && !newValue.
|
||||
equals(existingValue)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Key [%s] value mismatch", kvp.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static String stringifyShellCommands(String... commands) {
|
||||
return stringifyShellCommands(Arrays.asList(commands));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2023, 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
|
||||
@ -65,12 +65,12 @@ class UnixLaunchersAsServices extends ShellCustomAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected List<String> replacementStringIds() {
|
||||
return List.of(COMMANDS_INSTALL, COMMANDS_UNINSTALL, SCRIPTS);
|
||||
protected List<String> replacementStringIds() {
|
||||
return REPLACEMENT_STRING_IDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected Map<String, String> createImpl() throws IOException {
|
||||
protected Map<String, String> createImpl() throws IOException {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
|
||||
if (launchers.isEmpty()) {
|
||||
@ -87,11 +87,7 @@ class UnixLaunchersAsServices extends ShellCustomAction {
|
||||
Collectors.joining(" ")));
|
||||
};
|
||||
|
||||
try {
|
||||
data.put(SCRIPTS, stringifyTextFile("services_utils.sh"));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
data.put(SCRIPTS, stringifyTextFile("services_utils.sh"));
|
||||
|
||||
data.put(COMMANDS_INSTALL, strigifier.apply("register_services"));
|
||||
data.put(COMMANDS_UNINSTALL, strigifier.apply("unregister_services"));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -76,6 +76,11 @@ public class AdditionalLauncher {
|
||||
return this;
|
||||
}
|
||||
|
||||
final public AdditionalLauncher setVerifyUninstalled(boolean value) {
|
||||
verifyUninstalled = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
final public AdditionalLauncher setLauncherAsService() {
|
||||
return addRawProperties(LAUNCHER_AS_SERVICE);
|
||||
}
|
||||
@ -141,6 +146,13 @@ public class AdditionalLauncher {
|
||||
final public void applyTo(PackageTest test) {
|
||||
test.addInitializer(this::initialize);
|
||||
test.addInstallVerifier(this::verify);
|
||||
if (verifyUninstalled) {
|
||||
test.addUninstallVerifier(this::verifyUninstalled);
|
||||
}
|
||||
}
|
||||
|
||||
final public void verifyRemovedInUpgrade(PackageTest test) {
|
||||
test.addInstallVerifier(this::verifyUninstalled);
|
||||
}
|
||||
|
||||
static void forEachAdditionalLauncher(JPackageCommand cmd,
|
||||
@ -318,10 +330,40 @@ public class AdditionalLauncher {
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyInstalled(JPackageCommand cmd, boolean installed) throws IOException {
|
||||
if (TKit.isLinux() && !cmd.isImagePackageType() && !cmd.
|
||||
isPackageUnpacked(String.format(
|
||||
"Not verifying package and system .desktop files for [%s] launcher",
|
||||
cmd.appLauncherPath(name)))) {
|
||||
Path packageDesktopFile = LinuxHelper.getDesktopFile(cmd, name);
|
||||
Path systemDesktopFile = LinuxHelper.getSystemDesktopFilesFolder().
|
||||
resolve(packageDesktopFile.getFileName());
|
||||
if (Files.exists(packageDesktopFile) && installed) {
|
||||
TKit.assertFileExists(systemDesktopFile);
|
||||
TKit.assertStringListEquals(Files.readAllLines(
|
||||
packageDesktopFile),
|
||||
Files.readAllLines(systemDesktopFile), String.format(
|
||||
"Check [%s] and [%s] files are equal",
|
||||
packageDesktopFile,
|
||||
systemDesktopFile));
|
||||
} else {
|
||||
TKit.assertPathExists(packageDesktopFile, false);
|
||||
TKit.assertPathExists(systemDesktopFile, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void verifyUninstalled(JPackageCommand cmd) throws IOException {
|
||||
verifyInstalled(cmd, false);
|
||||
Path launcherPath = cmd.appLauncherPath(name);
|
||||
TKit.assertPathExists(launcherPath, false);
|
||||
}
|
||||
|
||||
protected void verify(JPackageCommand cmd) throws IOException {
|
||||
verifyIcon(cmd);
|
||||
verifyShortcuts(cmd);
|
||||
verifyDescription(cmd);
|
||||
verifyInstalled(cmd, true);
|
||||
|
||||
Path launcherPath = cmd.appLauncherPath(name);
|
||||
|
||||
@ -394,6 +436,7 @@ public class AdditionalLauncher {
|
||||
return str;
|
||||
}
|
||||
|
||||
private boolean verifyUninstalled;
|
||||
private List<String> javaOptions;
|
||||
private List<String> defaultArguments;
|
||||
private Path icon;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2023, 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
|
||||
@ -23,6 +23,7 @@
|
||||
package jdk.jpackage.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystemException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -30,6 +31,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -58,10 +60,16 @@ public final class LauncherAsServiceVerifier {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAdditionalLauncherCallback(Consumer<AdditionalLauncher> v) {
|
||||
additionalLauncherCallback = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LauncherAsServiceVerifier create() {
|
||||
Objects.requireNonNull(expectedValue);
|
||||
return new LauncherAsServiceVerifier(launcherName, appOutputFileName,
|
||||
expectedValue);
|
||||
expectedValue,
|
||||
launcherName != null ? additionalLauncherCallback : null);
|
||||
}
|
||||
|
||||
public Builder applyTo(PackageTest pkg) {
|
||||
@ -72,6 +80,7 @@ public final class LauncherAsServiceVerifier {
|
||||
private String launcherName;
|
||||
private String expectedValue;
|
||||
private String appOutputFileName = "launcher-as-service.txt";
|
||||
private Consumer<AdditionalLauncher> additionalLauncherCallback;
|
||||
}
|
||||
|
||||
public static Builder build() {
|
||||
@ -80,10 +89,12 @@ public final class LauncherAsServiceVerifier {
|
||||
|
||||
private LauncherAsServiceVerifier(String launcherName,
|
||||
String appOutputFileName,
|
||||
String expectedArgValue) {
|
||||
String expectedArgValue,
|
||||
Consumer<AdditionalLauncher> additionalLauncherCallback) {
|
||||
this.expectedValue = expectedArgValue;
|
||||
this.launcherName = launcherName;
|
||||
this.appOutputFileName = Path.of(appOutputFileName);
|
||||
this.additionalLauncherCallback = additionalLauncherCallback;
|
||||
}
|
||||
|
||||
public void applyTo(PackageTest pkg) {
|
||||
@ -233,7 +244,7 @@ public final class LauncherAsServiceVerifier {
|
||||
outputFilePath.toString())
|
||||
.addDefaultArguments(expectedValue)
|
||||
.verifyOutput();
|
||||
TKit.deleteIfExists(outputFilePath);
|
||||
deleteOutputFile(outputFilePath);
|
||||
}
|
||||
});
|
||||
pkg.addInstallVerifier(cmd -> {
|
||||
@ -242,13 +253,13 @@ public final class LauncherAsServiceVerifier {
|
||||
}
|
||||
|
||||
private void applyToAdditionalLauncher(PackageTest pkg) {
|
||||
new AdditionalLauncher(launcherName) {
|
||||
AdditionalLauncher al = new AdditionalLauncher(launcherName) {
|
||||
@Override
|
||||
protected void verify(JPackageCommand cmd) throws IOException {
|
||||
if (canVerifyInstall(cmd)) {
|
||||
delayInstallVerify();
|
||||
super.verify(cmd);
|
||||
TKit.deleteIfExists(appOutputFilePathVerify(cmd));
|
||||
deleteOutputFile(appOutputFilePathVerify(cmd));
|
||||
}
|
||||
LauncherAsServiceVerifier.verify(cmd, launcherName);
|
||||
}
|
||||
@ -256,8 +267,26 @@ public final class LauncherAsServiceVerifier {
|
||||
.addJavaOptions("-Djpackage.test.appOutput="
|
||||
+ appOutputFilePathInitialize().toString())
|
||||
.addJavaOptions("-Djpackage.test.noexit=true")
|
||||
.addDefaultArguments(expectedValue)
|
||||
.applyTo(pkg);
|
||||
.addDefaultArguments(expectedValue);
|
||||
|
||||
Optional.ofNullable(additionalLauncherCallback).ifPresent(v -> v.accept(al));
|
||||
|
||||
al.applyTo(pkg);
|
||||
}
|
||||
|
||||
private static void deleteOutputFile(Path file) throws IOException {
|
||||
try {
|
||||
TKit.deleteIfExists(file);
|
||||
} catch (FileSystemException ex) {
|
||||
if (TKit.isLinux() || TKit.isOSX()) {
|
||||
// Probably "Operation no permitted" error. Try with "sudo" as the
|
||||
// file is created by a launcher started under root account.
|
||||
Executor.of("sudo", "rm", "-f").addArgument(file.toString()).
|
||||
execute();
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void verify(JPackageCommand cmd, String launcherName) throws
|
||||
@ -337,6 +366,7 @@ public final class LauncherAsServiceVerifier {
|
||||
private final String expectedValue;
|
||||
private final String launcherName;
|
||||
private final Path appOutputFileName;
|
||||
private final Consumer<AdditionalLauncher> additionalLauncherCallback;
|
||||
|
||||
final static Set<PackageType> SUPPORTED_PACKAGES = Stream.of(LINUX, WINDOWS,
|
||||
Set.of(MAC_PKG)).flatMap(x -> x.stream()).collect(Collectors.toSet());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2023, 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
|
||||
@ -464,7 +464,7 @@ public final class LinuxHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private static Path getSystemDesktopFilesFolder() {
|
||||
static Path getSystemDesktopFilesFolder() {
|
||||
return Stream.of("/usr/share/applications",
|
||||
"/usr/local/share/applications").map(Path::of).filter(dir -> {
|
||||
return Files.exists(dir.resolve("defaults.list"));
|
||||
@ -558,12 +558,17 @@ public final class LinuxHelper {
|
||||
final String xdgCmdName = "xdg-icon-resource";
|
||||
|
||||
Stream<String> scriptletBodyStream = scriptletBody.stream()
|
||||
.filter(str -> str.startsWith(xdgCmdName))
|
||||
.filter(str -> Pattern.compile(
|
||||
"\\b" + dashMime + "\\b").matcher(str).find());
|
||||
if (scriptletType == Scriptlet.PostInstall) {
|
||||
scriptletBodyStream = scriptletBodyStream.filter(str -> str.
|
||||
startsWith(xdgCmdName));
|
||||
scriptletBodyStream = scriptletBodyStream.filter(str -> List.of(
|
||||
str.split("\\s+")).contains(iconPathInPackage.toString()));
|
||||
} else {
|
||||
scriptletBodyStream = scriptletBodyStream.filter(str -> str.
|
||||
contains(xdgCmdName)).filter(str -> str.startsWith(
|
||||
"do_if_file_belongs_to_single_package"));
|
||||
}
|
||||
|
||||
scriptletBodyStream.peek(xdgCmd -> {
|
||||
|
74
test/jdk/tools/jpackage/linux/ServiceAndDesktopTest.java
Normal file
74
test/jdk/tools/jpackage/linux/ServiceAndDesktopTest.java
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.nio.file.Path;
|
||||
import jdk.jpackage.test.AdditionalLauncher;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.LauncherAsServiceVerifier;
|
||||
import jdk.jpackage.test.TKit;
|
||||
|
||||
/**
|
||||
* Test how services and desktop integration align together in the same package.
|
||||
* On Linux these features share common code in custom actions (common_utils.sh).
|
||||
* Test correctness of integration of this code.
|
||||
*
|
||||
* The test is not intended to be executed by SQE. It is for internal use only
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary jpackage with desktop integration and services on Linux
|
||||
* @library ../helpers
|
||||
* @key jpackagePlatformPackage
|
||||
* @requires jpackage.test.SQETest == null
|
||||
* @build jdk.jpackage.test.*
|
||||
* @requires (os.family == "linux")
|
||||
* @modules jdk.jpackage/jdk.jpackage.internal
|
||||
* @compile ServiceAndDesktopTest.java
|
||||
* @run main/othervm/timeout=720 jdk.jpackage.test.Main
|
||||
* --jpt-run=ServiceAndDesktopTest
|
||||
*/
|
||||
|
||||
public class ServiceAndDesktopTest {
|
||||
|
||||
@Test
|
||||
public static void test() {
|
||||
var pkg = new PackageTest()
|
||||
.configureHelloApp()
|
||||
.addBundleDesktopIntegrationVerifier(true)
|
||||
.addInitializer(cmd -> {
|
||||
// Want a .desktop file for the main launcher
|
||||
cmd.addArguments("--icon", GOLDEN_ICON.toString());
|
||||
});
|
||||
LauncherAsServiceVerifier.build().setLauncherName("foo").
|
||||
setExpectedValue("Fun").setAdditionalLauncherCallback(al -> {
|
||||
// Don't want .desktop file for service launcher
|
||||
al.setNoIcon();
|
||||
}).applyTo(pkg);
|
||||
pkg.run();
|
||||
}
|
||||
|
||||
private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of(
|
||||
"resources", "icon" + TKit.ICON_SUFFIX));
|
||||
}
|
94
test/jdk/tools/jpackage/linux/UpgradeTest.java
Normal file
94
test/jdk/tools/jpackage/linux/UpgradeTest.java
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.util.Map;
|
||||
import java.nio.file.Path;
|
||||
import jdk.jpackage.test.AdditionalLauncher;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.TKit;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Linux upgrade testing
|
||||
* @library ../helpers
|
||||
* @key jpackagePlatformPackage
|
||||
* @build jdk.jpackage.test.*
|
||||
* @requires (os.family == "linux")
|
||||
* @modules jdk.jpackage/jdk.jpackage.internal
|
||||
* @compile UpgradeTest.java
|
||||
* @run main/othervm/timeout=360 jdk.jpackage.test.Main
|
||||
* --jpt-run=UpgradeTest
|
||||
*/
|
||||
public class UpgradeTest {
|
||||
|
||||
@Test
|
||||
public void testDesktopFiles() {
|
||||
// Create two packages with the same name but different versions.
|
||||
// The first will have `launcherA`, and `launcherB` additional launchers.
|
||||
// The second will have `launcherB`, and `launcherC` additional launchers.
|
||||
// Launchers are configured in a way to have correpsonding .desktop files.
|
||||
// These files will be installed in system directories.
|
||||
// After the upgrade `launcherA`-related files must be deleted and
|
||||
// `launcherB`-related files from the first package must be replaced with
|
||||
// the files from the second package.
|
||||
// Checks that correct files are installed in system directories
|
||||
// encapsulated in AdditionalLauncher class.
|
||||
|
||||
var pkg = createPackageTest().disablePackageUninstaller();
|
||||
|
||||
var alA = createAdditionalLauncher("launcherA");
|
||||
|
||||
alA.applyTo(pkg);
|
||||
createAdditionalLauncher("launcherB").addRawProperties(Map.entry(
|
||||
"description", "Foo")).applyTo(pkg);
|
||||
|
||||
var pkg2 = createPackageTest().addInitializer(cmd -> {
|
||||
cmd.addArguments("--app-version", "2.0");
|
||||
});
|
||||
|
||||
alA.verifyRemovedInUpgrade(pkg2);
|
||||
createAdditionalLauncher("launcherB").addRawProperties(Map.entry(
|
||||
"description", "Bar")).applyTo(pkg2);
|
||||
createAdditionalLauncher("launcherC").applyTo(pkg2);
|
||||
|
||||
new PackageTest.Group(pkg, pkg2).run();
|
||||
}
|
||||
|
||||
private static PackageTest createPackageTest() {
|
||||
return new PackageTest().configureHelloApp().addInitializer(
|
||||
JPackageCommand::setInputToEmptyDirectory).addInitializer(
|
||||
JPackageCommand::setFakeRuntime).
|
||||
addBundleDesktopIntegrationVerifier(true);
|
||||
}
|
||||
|
||||
private static AdditionalLauncher createAdditionalLauncher(String name) {
|
||||
// Configure additionl launcher in a way to trigger jpackage create
|
||||
// corresponding .desktop file.
|
||||
return new AdditionalLauncher(name).setIcon(GOLDEN_ICON);
|
||||
}
|
||||
|
||||
private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of(
|
||||
"resources", "icon" + TKit.ICON_SUFFIX));
|
||||
}
|
Loading…
Reference in New Issue
Block a user