8232281: jpackage is not always reporting an error when no main class specified
Reviewed-by: asemenyuk, asemenuk
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java Wed Oct 23 10:37:54 2019 -0400
@@ -69,7 +69,8 @@
.setCategory(I18N.getString("resource.menu-icon"))
.setExternal(customIconFile);
desktopFileResource = createResource("template.desktop", params)
- .setCategory(I18N.getString("resource.menu-shortcut-descriptor"));
+ .setCategory(I18N.getString("resource.menu-shortcut-descriptor"))
+ .setPublicName(APP_NAME.fetchFrom(params) + ".desktop");
// XDG recommends to use vendor prefix in desktop file names as xdg
// commands copy files to system directories.
@@ -89,8 +90,8 @@
// - custom icon specified
//
desktopFile = new DesktopFile(desktopFileName);
- iconFile = new DesktopFile(String.format("%s.png",
- APP_NAME.fetchFrom(params)));
+ iconFile = new DesktopFile(APP_NAME.fetchFrom(params)
+ + IOUtils.getSuffix(Path.of(DEFAULT_ICON)));
} else {
desktopFile = null;
iconFile = null;
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -26,14 +26,8 @@
package jdk.jpackage.internal;
import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-import java.util.ResourceBundle;
+import java.util.*;
import static jdk.jpackage.internal.StandardBundlerParam.*;
@@ -85,10 +79,7 @@
public boolean validate(Map<String, ? super Object> params)
throws ConfigException {
try {
- if (params == null) throw new ConfigException(
- I18N.getString("error.parameters-null"),
- I18N.getString("error.parameters-null.advice"));
-
+ Objects.requireNonNull(params);
return doValidate(params);
} catch (RuntimeException re) {
if (re.getCause() instanceof ConfigException) {
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java Wed Oct 23 10:37:54 2019 -0400
@@ -169,7 +169,8 @@
throws IOException {
Path iconTarget = appLayout.destktopIntegrationDirectory().resolve(
- APP_NAME.fetchFrom(params) + ".png");
+ APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of(
+ DEFAULT_ICON)));
createResource(DEFAULT_ICON, params)
.setCategory("icon")
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -365,9 +365,12 @@
debianFiles.add(new DebianFile(
configDir.resolve("postrm"),
"resource.deb-postrm-script").setExecutable());
- debianFiles.add(new DebianFile(
- getConfig_CopyrightFile(params).toPath(),
- "resource.copyright-file"));
+
+ if (!StandardBundlerParam.isRuntimeInstaller(params)) {
+ debianFiles.add(new DebianFile(
+ getConfig_CopyrightFile(params).toPath(),
+ "resource.copyright-file"));
+ }
for (DebianFile debianFile : debianFiles) {
debianFile.create(data, params);
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -29,6 +29,7 @@
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.*;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -99,18 +100,25 @@
PlatformPackage thePackage = createMetaPackage(params);
+ Function<File, ApplicationLayout> initAppImageLayout = imageRoot -> {
+ ApplicationLayout layout = appImageLayout(params);
+ layout.pathGroup().setPath(new Object(),
+ AppImageFile.getPathInAppImage(Path.of("")));
+ return layout.resolveAt(imageRoot.toPath());
+ };
+
try {
File appImage = StandardBundlerParam.getPredefinedAppImage(params);
// we either have an application image or need to build one
if (appImage != null) {
- appImageLayout(params).resolveAt(appImage.toPath()).copy(
+ initAppImageLayout.apply(appImage).copy(
thePackage.sourceApplicationLayout());
} else {
appImage = APP_BUNDLER.fetchFrom(params).doBundle(params,
thePackage.sourceRoot().toFile(), true);
- ApplicationLayout srcAppLayout = appImageLayout(params).resolveAt(
- appImage.toPath());
+ ApplicationLayout srcAppLayout = initAppImageLayout.apply(
+ appImage);
if (appImage.equals(PREDEFINED_RUNTIME_IMAGE.fetchFrom(params))) {
// Application image points to run-time image.
// Copy it.
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties Wed Oct 23 10:37:54 2019 -0400
@@ -40,9 +40,6 @@
resource.menu-icon=menu icon
resource.rpm-spec-file=RPM spec file
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map
-
error.tool-not-found.advice=Please install required packages
error.tool-old-version.advice=Please install required packages
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties Wed Oct 23 10:37:54 2019 -0400
@@ -40,9 +40,6 @@
resource.menu-icon=menu icon
resource.rpm-spec-file=RPM spec file
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map
-
error.tool-not-found.advice=Please install required packages
error.tool-old-version.advice=Please install required packages
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties Wed Oct 23 10:37:54 2019 -0400
@@ -40,9 +40,6 @@
resource.menu-icon=menu icon
resource.rpm-spec-file=RPM spec file
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map
-
error.tool-not-found.advice=Please install required packages
error.tool-old-version.advice=Please install required packages
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppStoreBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppStoreBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -28,11 +28,7 @@
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.ResourceBundle;
+import java.util.*;
import static jdk.jpackage.internal.StandardBundlerParam.*;
import static jdk.jpackage.internal.MacAppBundler.*;
@@ -235,11 +231,7 @@
public boolean validate(Map<String, ? super Object> params)
throws ConfigException {
try {
- if (params == null) {
- throw new ConfigException(
- I18N.getString("error.parameters-null"),
- I18N.getString("error.parameters-null.advice"));
- }
+ Objects.requireNonNull(params);
// hdiutil is always available so there's no need to test for
// availability.
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -429,9 +429,7 @@
public boolean validate(Map<String, ? super Object> params)
throws ConfigException {
try {
- if (params == null) throw new ConfigException(
- I18N.getString("error.parameters-null"),
- I18N.getString("error.parameters-null.advice"));
+ Objects.requireNonNull(params);
//run basic validation to ensure requirements are met
//we are not interested in return code, only possible exception
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -31,12 +31,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.ResourceBundle;
+import java.util.*;
import static jdk.jpackage.internal.StandardBundlerParam.*;
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
@@ -502,9 +497,7 @@
public boolean validate(Map<String, ? super Object> params)
throws ConfigException {
try {
- if (params == null) throw new ConfigException(
- I18N.getString("error.parameters-null"),
- I18N.getString("error.parameters-null.advice"));
+ Objects.requireNonNull(params);
// run basic validation to ensure requirements are met
// we are not interested in return code, only possible exception
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties Wed Oct 23 10:37:54 2019 -0400
@@ -33,8 +33,6 @@
error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map.
error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
error.no-app-signing-key=No Mac App Store App Signing Key
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties Wed Oct 23 10:37:54 2019 -0400
@@ -33,8 +33,6 @@
error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map.
error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
error.no-app-signing-key=No Mac App Store App Signing Key
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties Wed Oct 23 10:37:54 2019 -0400
@@ -33,8 +33,6 @@
error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map.
error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
error.no-app-signing-key=No Mac App Store App Signing Key
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java Wed Oct 23 10:37:54 2019 -0400
@@ -51,7 +51,7 @@
private final String launcherName;
private final List<String> addLauncherNames;
- public final static String FILENAME = ".jpackage.xml";
+ private final static String FILENAME = ".jpackage.xml";
private final static Map<Platform, String> PLATFORM_LABELS = Map.of(
Platform.LINUX, "linux", Platform.WINDOWS, "windows", Platform.MAC,
@@ -91,13 +91,21 @@
}
/**
+ * Returns path to application image info file.
+ * @param appImageDir - path to application image
+ */
+ public static Path getPathInAppImage(Path appImageDir) {
+ return appImageDir.resolve(FILENAME);
+ }
+
+ /**
* Saves file with application image info in application image.
* @param appImageDir - path to application image
* @throws IOException
*/
- static void save(Path appImage, Map<String, Object> params)
+ static void save(Path appImageDir, Map<String, Object> params)
throws IOException {
- IOUtils.createXml(appImage.resolve(FILENAME), xml -> {
+ IOUtils.createXml(getPathInAppImage(appImageDir), xml -> {
xml.writeStartElement("jpackage-state");
xml.writeAttribute("version", getVersion());
xml.writeAttribute("platform", getPlatform());
@@ -126,7 +134,7 @@
*/
static AppImageFile load(Path appImageDir) throws IOException {
try {
- Path path = appImageDir.resolve(FILENAME);
+ Path path = getPathInAppImage(appImageDir);
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newDefaultInstance();
dbf.setFeature(
@@ -177,7 +185,7 @@
/**
* Returns list of launcher names configured for the application.
- * The first item in the returned list is man launcher name.
+ * The first item in the returned list is main launcher name.
* Following items in the list are names of additional launchers.
*/
static List<String> getLauncherNames(Path appImageDir,
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java Wed Oct 23 10:37:54 2019 -0400
@@ -240,6 +240,11 @@
return parent != null ? parent.resolve(filename) : Path.of(filename);
}
+ public static String getSuffix(Path path) {
+ String filename = replaceSuffix(path.getFileName(), null).toString();
+ return path.getFileName().toString().substring(filename.length());
+ }
+
@FunctionalInterface
public static interface XmlConsumer {
void accept(XMLStreamWriter xml) throws IOException, XMLStreamException;
@@ -248,7 +253,7 @@
public static void createXml(Path dstFile, XmlConsumer xmlConsumer) throws
IOException {
XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance();
- try (Writer w = new BufferedWriter(new FileWriter(dstFile.toFile()))) {
+ try (Writer w = Files.newBufferedWriter(dstFile)) {
// Wrap with pretty print proxy
XMLStreamWriter xml = (XMLStreamWriter) Proxy.newProxyInstance(
XMLStreamWriter.class.getClassLoader(), new Class<?>[]{
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java Wed Oct 23 10:37:54 2019 -0400
@@ -81,10 +81,6 @@
return this;
}
- String getCategory() {
- return category;
- }
-
OverridableResource setResourceDir(Path v) {
resourceDir = v;
return this;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ScriptRunner.java Wed Oct 23 10:37:54 2019 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019, 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.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import static jdk.jpackage.internal.OverridableResource.createResource;
+import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
+import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
+
+/**
+ * Runs custom script from resource directory.
+ */
+class ScriptRunner {
+ ScriptRunner() {
+ environment = new ProcessBuilder().environment();
+ }
+
+ ScriptRunner setResourceCategoryId(String v) {
+ resourceCategoryId = v;
+ return this;
+ }
+
+ ScriptRunner setDirectory(Path v) {
+ directory = v;
+ return this;
+ }
+
+ ScriptRunner setScriptNameSuffix(String v) {
+ scriptNameSuffix = v;
+ return this;
+ }
+
+ ScriptRunner addEnvironment(Map<String, String> v) {
+ environment.putAll(v);
+ return this;
+ }
+
+ ScriptRunner setEnvironmentVariable(String envVarName, String envVarValue) {
+ Objects.requireNonNull(envVarName);
+ if (envVarValue == null) {
+ environment.remove(envVarName);
+ } else {
+ environment.put(envVarName, envVarValue);
+ }
+ return this;
+ }
+
+ public void run(Map<String, ? super Object> params) throws IOException {
+ String scriptName = String.format("%s-%s%s", APP_NAME.fetchFrom(params),
+ scriptNameSuffix, scriptSuffix());
+ Path scriptPath = CONFIG_ROOT.fetchFrom(params).toPath().resolve(
+ scriptName);
+ createResource(null, params)
+ .setCategory(I18N.getString(resourceCategoryId))
+ .saveToFile(scriptPath);
+ if (!Files.exists(scriptPath)) {
+ return;
+ }
+
+ ProcessBuilder pb = new ProcessBuilder(shell(),
+ scriptPath.toAbsolutePath().toString());
+ Map<String, String> workEnvironment = pb.environment();
+ workEnvironment.clear();
+ workEnvironment.putAll(environment);
+
+ if (directory != null) {
+ pb.directory(directory.toFile());
+ }
+
+ Executor.of(pb).executeExpectSuccess();
+ }
+
+ private static String shell() {
+ if (Platform.isWindows()) {
+ return "cscript";
+ }
+ return Optional.ofNullable(System.getenv("SHELL")).orElseGet(() -> "sh");
+ }
+
+ private static String scriptSuffix() {
+ if (Platform.isWindows()) {
+ return ".wsf";
+ }
+ return ".sh";
+ }
+
+ private String scriptNameSuffix;
+ private String resourceCategoryId;
+ private Path directory;
+ private Map<String, String> environment;
+}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinAppBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinAppBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -28,10 +28,7 @@
import java.io.File;
import java.nio.file.Path;
import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-import java.util.ResourceBundle;
+import java.util.*;
import static jdk.jpackage.internal.WindowsBundlerParam.*;
import static jdk.jpackage.internal.WinMsiBundler.WIN_APP_IMAGE;
@@ -60,10 +57,7 @@
public boolean validate(Map<String, ? super Object> params)
throws ConfigException {
try {
- if (params == null) throw new ConfigException(
- I18N.getString("error.parameters-null"),
- I18N.getString("error.parameters-null.advice"));
-
+ Objects.requireNonNull(params);
return doValidate(params);
} catch (RuntimeException re) {
if (re.getCause() instanceof ConfigException) {
@@ -80,21 +74,6 @@
throws ConfigException {
imageBundleValidation(p);
-
- if (StandardBundlerParam.getPredefinedAppImage(p) != null) {
- return true;
- }
-
- // Make sure that jpackage.exe exists.
- File tool = new File(
- System.getProperty("java.home") + "\\bin\\jpackage.exe");
-
- if (!tool.exists()) {
- throw new ConfigException(
- I18N.getString("error.no-windows-resources"),
- I18N.getString("error.no-windows-resources.advice"));
- }
-
return true;
}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -110,6 +110,13 @@
File msi = msiBundler.bundle(params, exeImageDir);
try {
+ new ScriptRunner()
+ .setDirectory(msi.toPath().getParent())
+ .setResourceCategoryId("resource.post-msi-script")
+ .setScriptNameSuffix("post-msi")
+ .setEnvironmentVariable("JpMsiFile", msi.getAbsolutePath().toString())
+ .run(params);
+
return buildEXE(msi, outdir);
} catch (IOException ex) {
Log.verbose(ex);
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java Wed Oct 23 10:37:54 2019 -0400
@@ -335,11 +335,6 @@
try {
Files.createDirectories(imageDir);
- Path postImageScript = imageDir.resolve(APP_NAME.fetchFrom(params) + "-post-image.wsf");
- createResource(null, params)
- .setCategory(I18N.getString("resource.post-install-script"))
- .saveToFile(postImageScript);
-
prepareProto(params);
wixSourcesBuilder
@@ -349,12 +344,13 @@
Map<String, String> wixVars = prepareMainProjectFile(params);
- if (Files.exists(postImageScript)) {
- Log.verbose(MessageFormat.format(I18N.getString(
- "message.running-wsh-script"),
- postImageScript.toAbsolutePath()));
- Executor.of("wscript", postImageScript.toString()).executeExpectSuccess();
- }
+ new ScriptRunner()
+ .setDirectory(imageDir)
+ .setResourceCategoryId("resource.post-app-image-script")
+ .setScriptNameSuffix("post-image")
+ .setEnvironmentVariable("JpAppImageDir", imageDir.toAbsolutePath().toString())
+ .run(params);
+
return buildMSI(params, wixVars, outdir);
} catch (IOException ex) {
Log.verbose(ex);
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java Wed Oct 23 10:37:54 2019 -0400
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
+import java.text.MessageFormat;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
@@ -75,7 +76,8 @@
// Don't want AppImageFile.FILENAME in installed application.
// Register it with app image at a role without a match in installed
// app layout to exclude it from layout transformation.
- layout.pathGroup().setPath(new Object(), Path.of(AppImageFile.FILENAME));
+ layout.pathGroup().setPath(new Object(),
+ AppImageFile.getPathInAppImage(Path.of("")));
// Want absolute paths to source files in generated WiX sources.
// This is to handle scenario if sources would be processed from
@@ -136,7 +138,8 @@
void logWixFeatures() {
if (wixVersion.compareTo("3.6") >= 0) {
- Log.verbose(I18N.getString("message.use-wix36-features"));
+ Log.verbose(MessageFormat.format(I18N.getString(
+ "message.use-wix36-features"), wixVersion));
}
}
@@ -148,6 +151,10 @@
fa.iconPath = null;
}
+ if (fa.iconPath != null) {
+ fa.iconPath = fa.iconPath.toAbsolutePath();
+ }
+
// Filter out empty extensions.
fa.extensions = fa.extensions.stream().filter(Predicate.not(
String::isEmpty)).collect(Collectors.toList());
@@ -277,6 +284,14 @@
return cfg.isFile;
}
+ static void startElement(XMLStreamWriter xml, String componentId,
+ String componentGuid) throws XMLStreamException, IOException {
+ xml.writeStartElement("Component");
+ xml.writeAttribute("Win64", "yes");
+ xml.writeAttribute("Id", componentId);
+ xml.writeAttribute("Guid", componentGuid);
+ }
+
private static final class Config {
Config withRegistryKeyPath() {
withRegistryKeyPath = true;
@@ -329,9 +344,8 @@
xml.writeAttribute("Id", Id.Folder.of(directoryRefPath));
final String componentId = "c" + role.idOf(path);
- xml.writeStartElement("Component");
- xml.writeAttribute("Id", componentId);
- xml.writeAttribute("Guid", String.format("{%s}", role.guidOf(path)));
+ Component.startElement(xml, componentId, String.format("{%s}",
+ role.guidOf(path)));
boolean isRegistryKeyPath = !systemWide || role.isRegistryKeyPath();
if (isRegistryKeyPath) {
@@ -716,9 +730,7 @@
xml.writeStartElement("DirectoryRef");
xml.writeAttribute("Id", INSTALLDIR.toString());
- xml.writeStartElement("Component");
- xml.writeAttribute("Id", componentId);
- xml.writeAttribute("Guid", "*");
+ Component.startElement(xml, componentId, "*");
addRegistryKeyPath(xml, INSTALLDIR, () -> propertyId, () -> {
// The following code converts a path to value to be saved in registry.
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java Wed Oct 23 10:37:54 2019 -0400
@@ -26,10 +26,7 @@
package jdk.jpackage.internal;
import java.io.IOException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.PathMatcher;
+import java.nio.file.*;
import java.text.MessageFormat;
import java.util.*;
import java.util.function.Supplier;
@@ -119,16 +116,39 @@
private final static String MINIMAL_VERSION = "3.0";
- private final static Path PROGRAM_FILES = Path.of("C:\\Program Files");
- private final static Path PROGRAM_FILES_X86 = Path.of("C:\\Program Files (x86)");
+ static Path getSystemDir(String envVar, String knownDir) {
+ return Optional
+ .ofNullable(getEnvVariableAsPath(envVar))
+ .orElseGet(() -> Optional
+ .ofNullable(getEnvVariableAsPath("SystemDrive"))
+ .orElseGet(() -> Path.of("C:")).resolve(knownDir));
+ }
+
+ private static Path getEnvVariableAsPath(String envVar) {
+ String path = System.getenv(envVar);
+ if (path != null) {
+ try {
+ return Path.of(path);
+ } catch (InvalidPathException ex) {
+ Log.error(MessageFormat.format(I18N.getString(
+ "error.invalid-envvar"), envVar));
+ return null;
+ }
+ }
+ return null;
+ }
private static List<Path> findWixInstallDirs() {
PathMatcher wixInstallDirMatcher = FileSystems.getDefault().getPathMatcher(
"glob:WiX Toolset v*");
+ Path programFiles = getSystemDir("ProgramFiles", "Program Files");
+ Path programFilesX86 = getSystemDir("ProgramFiles(X86)",
+ "Program Files (x86)");
+
// Returns list of WiX install directories ordered by WiX version number.
// Newer versions go first.
- return Stream.of(PROGRAM_FILES, PROGRAM_FILES_X86).map(path -> {
+ return Stream.of(programFiles, programFilesX86).map(path -> {
List<Path> result;
try (var paths = Files.walk(path, 1)) {
result = paths.collect(Collectors.toList());
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties Wed Oct 23 10:37:54 2019 -0400
@@ -32,16 +32,10 @@
resource.executable-properties-template=Template for creating executable properties file
resource.setup-icon=setup dialog icon
-resource.post-install-script=script to run after application image is populated
+resource.post-app-image-script=script to run after application image is populated
+resource.post-msi-script=script to run after msi file for exe installer is created
resource.wxl-file-name=MsiInstallerStrings_en.wxl
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map
-error.no-windows-resources=This copy of the JDK does not support Windows
-error.no-windows-resources.advice=Please use the Oracle JDK for Windows
-error.cannot-find-launcher=Cannot find cfg file in predefined app image directory {0}
-error.copyright-is-too-long=The copyright string is too long for InnoSetup
-error.copyright-is-too-long.advice=Provide a copyright string shorter than 100 characters.
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.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
@@ -50,28 +44,21 @@
error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
error.version-string-part-not-number=Failed to convert version component to int
-error.cannot-walk-directory=Can not walk [{0}] - it is not a valid directory
error.version-swap=Failed to update version information for {0}
-error.version-compare=Error: Failed to compare version {0} with {1.
+error.invalid-envvar=Invalid value of {0} environment variable
message.result-dir=Result application bundle: {0}.
message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
-message.multiple-launchers=Multiple launchers found in predefined app-image. {0} will be used as primary launcher.
message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
-message.tool-wrong-version=Detected [{0}] version {1} but version {2} is required.
message.outputting-to-location=Generating EXE for installer to: {0}.
message.output-location=Installer (.exe) saved to: {0}
message.tool-version=Detected [{0}] version [{1}].
-message.running-wsh-script=Running WSH script on application image [{0}].
message.creating-association-with-null-extension=Creating association with null extension.
message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
-message.truncating.id=Truncating Application ID to 126 chars for Inno Setup.
-message.use-wix36-features=WiX 3.6 detected. Enabling advanced cleanup action.
+message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
message.generated-product-guid=Generated product GUID: {0}.
message.preparing-msi-config=Preparing MSI config: {0}.
message.generating-msi=Generating MSI: {0}.
-message.light-file-string=WiX light tool set to {0}.
-message.candle-file-string=WiX candle tool set to {0}.
message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties Wed Oct 23 10:37:54 2019 -0400
@@ -32,16 +32,10 @@
resource.executable-properties-template=Template for creating executable properties file
resource.setup-icon=setup dialog icon
-resource.post-install-script=script to run after application image is populated
+resource.post-app-image-script=script to run after application image is populated
+resource.post-msi-script=script to run after msi file for exe installer is created
resource.wxl-file-name=MsiInstallerStrings_en.wxl
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map
-error.no-windows-resources=This copy of the JDK does not support Windows
-error.no-windows-resources.advice=Please use the Oracle JDK for Windows
-error.cannot-find-launcher=Cannot find cfg file in predefined app image directory {0}
-error.copyright-is-too-long=The copyright string is too long for InnoSetup
-error.copyright-is-too-long.advice=Provide a copyright string shorter than 100 characters.
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.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
@@ -50,28 +44,21 @@
error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
error.version-string-part-not-number=Failed to convert version component to int
-error.cannot-walk-directory=Can not walk [{0}] - it is not a valid directory
error.version-swap=Failed to update version information for {0}
-error.version-compare=Error: Failed to compare version {0} with {1.
+error.invalid-envvar=Invalid value of {0} environment variable
message.result-dir=Result application bundle: {0}.
message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
-message.multiple-launchers=Multiple launchers found in predefined app-image. {0} will be used as primary launcher.
message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
-message.tool-wrong-version=Detected [{0}] version {1} but version {2} is required.
message.outputting-to-location=Generating EXE for installer to: {0}.
message.output-location=Installer (.exe) saved to: {0}
message.tool-version=Detected [{0}] version [{1}].
-message.running-wsh-script=Running WSH script on application image [{0}].
message.creating-association-with-null-extension=Creating association with null extension.
message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
-message.truncating.id=Truncating Application ID to 126 chars for Inno Setup.
-message.use-wix36-features=WiX 3.6 detected. Enabling advanced cleanup action.
+message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
message.generated-product-guid=Generated product GUID: {0}.
message.preparing-msi-config=Preparing MSI config: {0}.
message.generating-msi=Generating MSI: {0}.
-message.light-file-string=WiX light tool set to {0}.
-message.candle-file-string=WiX candle tool set to {0}.
message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties Wed Oct 23 10:10:34 2019 -0400
+++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties Wed Oct 23 10:37:54 2019 -0400
@@ -32,16 +32,10 @@
resource.executable-properties-template=Template for creating executable properties file
resource.setup-icon=setup dialog icon
-resource.post-install-script=script to run after application image is populated
+resource.post-app-image-script=script to run after application image is populated
+resource.post-msi-script=script to run after msi file for exe installer is created
resource.wxl-file-name=MsiInstallerStrings_en.wxl
-error.parameters-null=Parameters map is null
-error.parameters-null.advice=Pass in a non-null parameters map
-error.no-windows-resources=This copy of the JDK does not support Windows
-error.no-windows-resources.advice=Please use the Oracle JDK for Windows
-error.cannot-find-launcher=Cannot find cfg file in predefined app image directory {0}
-error.copyright-is-too-long=The copyright string is too long for InnoSetup
-error.copyright-is-too-long.advice=Provide a copyright string shorter than 100 characters.
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.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
@@ -50,28 +44,21 @@
error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
error.version-string-part-not-number=Failed to convert version component to int
-error.cannot-walk-directory=Can not walk [{0}] - it is not a valid directory
error.version-swap=Failed to update version information for {0}
-error.version-compare=Error: Failed to compare version {0} with {1.
+error.invalid-envvar=Invalid value of {0} environment variable
message.result-dir=Result application bundle: {0}.
message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
-message.multiple-launchers=Multiple launchers found in predefined app-image. {0} will be used as primary launcher.
message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
-message.tool-wrong-version=Detected [{0}] version {1} but version {2} is required.
message.outputting-to-location=Generating EXE for installer to: {0}.
message.output-location=Installer (.exe) saved to: {0}
message.tool-version=Detected [{0}] version [{1}].
-message.running-wsh-script=Running WSH script on application image [{0}].
message.creating-association-with-null-extension=Creating association with null extension.
message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
-message.truncating.id=Truncating Application ID to 126 chars for Inno Setup.
-message.use-wix36-features=WiX 3.6 detected. Enabling advanced cleanup action.
+message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
message.generated-product-guid=Generated product GUID: {0}.
message.preparing-msi-config=Preparing MSI config: {0}.
message.generating-msi=Generating MSI: {0}.
-message.light-file-string=WiX light tool set to {0}.
-message.candle-file-string=WiX candle tool set to {0}.
message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java Wed Oct 23 10:37:54 2019 -0400
@@ -619,7 +619,7 @@
}
public void verifyIsOfType(PackageType ... types) {
- final Set<PackageType> typesSet = Set.of(types);
+ final var typesSet = Stream.of(types).collect(Collectors.toSet());
if (!hasArgument("--package-type")) {
if (!isImagePackageType()) {
if (TKit.isLinux() && typesSet.equals(PackageType.LINUX)) {
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java Wed Oct 23 10:37:54 2019 -0400
@@ -255,7 +255,8 @@
Function<List<String>, String> verifier = (lines) -> {
// Lookup for xdg commands
return lines.stream().filter(line -> {
- Set<String> words = Set.of(line.split("\\s+"));
+ Set<String> words = Stream.of(line.split("\\s+")).collect(
+ Collectors.toSet());
return words.contains("xdg-desktop-menu") || words.contains(
"xdg-mime") || words.contains("xdg-icon-resource");
}).findFirst().orElse(null);
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -351,8 +351,8 @@
}
}
- TKit.assertPathExists(cmd.appInstallationDirectory().resolve(
- AppImageFile.FILENAME), false);
+ TKit.assertPathExists(AppImageFile.getPathInAppImage(
+ cmd.appInstallationDirectory()), false);
installVerifiers.stream().forEach(v -> v.accept(cmd));
}
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java Wed Oct 23 10:37:54 2019 -0400
@@ -593,18 +593,32 @@
}
public static void assertTrue(boolean actual, String msg) {
+ assertTrue(actual, msg, null);
+ }
+
+ public static void assertFalse(boolean actual, String msg) {
+ assertFalse(actual, msg, null);
+ }
+
+ public static void assertTrue(boolean actual, String msg, Runnable onFail) {
currentTest.notifyAssert();
if (!actual) {
- error(concatMessages("Unexpected FALSE", msg));
+ if (onFail != null) {
+ onFail.run();
+ }
+ error(concatMessages("Failed", msg));
}
traceAssert(String.format("assertTrue(): %s", msg));
}
- public static void assertFalse(boolean actual, String msg) {
+ public static void assertFalse(boolean actual, String msg, Runnable onFail) {
currentTest.notifyAssert();
if (actual) {
- error(concatMessages("Unexpected TRUE", msg));
+ if (onFail != null) {
+ onFail.run();
+ }
+ error(concatMessages("Failed", msg));
}
traceAssert(String.format("assertFalse(): %s", msg));
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/AppImageFileTest.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/AppImageFileTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -154,7 +154,7 @@
private AppImageFile createFromXml(String... xmlData) throws IOException {
Path directory = tempFolder.getRoot().toPath();
- Path path = directory.resolve(AppImageFile.FILENAME);
+ Path path = AppImageFile.getPathInAppImage(directory);
path.toFile().mkdirs();
Files.delete(path);
--- a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -21,13 +21,18 @@
* questions.
*/
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.Map;
import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
import jdk.jpackage.test.FileAssociations;
import jdk.jpackage.test.PackageType;
import jdk.jpackage.test.PackageTest;
import jdk.jpackage.test.TKit;
import jdk.jpackage.test.Annotations.Test;
+import jdk.jpackage.test.*;
/**
* Test --linux-shortcut parameter. Output of the test should be
@@ -139,4 +144,42 @@
TKit.TEST_SRC_ROOT.resolve("apps/dukeplug.png").toString()));
}).run();
}
+
+ /**
+ * .desktop file from resource dir.
+ */
+ @Test
+ public static void testDesktopFileFromResourceDir() {
+ final String expectedVersionString = "Version=12345678";
+ TKit.withTempDirectory("resources", tempDir -> {
+ createTest().addInitializer(cmd -> {
+ cmd.setFakeRuntime();
+
+ cmd.addArgument("--linux-shortcut");
+ cmd.addArguments("--resource-dir", tempDir);
+
+ // Create custom .desktop file in resource directory
+ TKit.createTextFile(tempDir.resolve(cmd.name() + ".desktop"),
+ List.of(
+ "[Desktop Entry]",
+ "Name=APPLICATION_NAME",
+ "Exec=APPLICATION_LAUNCHER",
+ "Terminal=false",
+ "Type=Application",
+ "Categories=DEPLOY_BUNDLE_CATEGORY",
+ expectedVersionString
+ ));
+ })
+ .addInstallVerifier(cmd -> {
+ Path desktopFile = cmd.appLayout().destktopIntegrationDirectory().resolve(
+ String.format("%s-%s.desktop",
+ LinuxHelper.getPackageName(cmd), cmd.name()));
+ TKit.assertFileExists(desktopFile);
+ TKit.assertTextStream(expectedVersionString)
+ .label(String.format("[%s] file", desktopFile))
+ .predicate(String::equals)
+ .apply(Files.readAllLines(desktopFile).stream());
+ }).run();
+ });
+ }
}
--- a/test/jdk/tools/jpackage/share/FileAssociationsTest.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/share/FileAssociationsTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -71,6 +71,8 @@
Path icon = TKit.TEST_SRC_ROOT.resolve(Path.of("resources", "icon"
+ TKit.ICON_SUFFIX));
+ icon = TKit.createRelativePathCopy(icon);
+
applyFileAssociations(packageTest,
new FileAssociations("jptest2").setFilename("fa2").setIcon(icon));
packageTest.run();
--- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -21,11 +21,15 @@
* questions.
*/
+import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.HashSet;
import java.util.Optional;
-import jdk.jpackage.test.TKit;
-import jdk.jpackage.test.PackageTest;
-import jdk.jpackage.test.JPackageCommand;
+import java.util.Set;
+import java.util.stream.Collectors;
+import jdk.jpackage.test.*;
+import jdk.jpackage.test.Annotations.Test;
/**
* Test --runtime-image parameter.
@@ -49,23 +53,55 @@
* @comment Temporary disable for Linux and OSX until functionality implemented
* @requires (os.family != "mac")
* @modules jdk.jpackage/jdk.jpackage.internal
- * @run main/othervm/timeout=720 -Xmx512m RuntimePackageTest
+ * @compile RuntimePackageTest.java
+ * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
+ * --jpt-run=RuntimePackageTest
*/
public class RuntimePackageTest {
- public static void main(String[] args) {
- TKit.run(args, () -> {
- new PackageTest()
- .addInitializer(cmd -> {
- cmd.addArguments("--runtime-image", Optional.ofNullable(
- JPackageCommand.DEFAULT_RUNTIME_IMAGE).orElse(Path.of(
- System.getProperty("java.home"))));
- // Remove --input parameter from jpackage command line as we don't
- // create input directory in the test and jpackage fails
- // if --input references non existant directory.
- cmd.removeArgumentWithValue("--input");
- })
- .run();
+ @Test
+ public static void test() {
+ new PackageTest()
+ .addInitializer(cmd -> {
+ cmd.addArguments("--runtime-image", Optional.ofNullable(
+ JPackageCommand.DEFAULT_RUNTIME_IMAGE).orElse(Path.of(
+ System.getProperty("java.home"))));
+ // Remove --input parameter from jpackage command line as we don't
+ // create input directory in the test and jpackage fails
+ // if --input references non existant directory.
+ cmd.removeArgumentWithValue("--input");
+ })
+ .addInstallVerifier(cmd -> {
+ Set<Path> srcRuntime = listFiles(Path.of(cmd.getArgumentValue("--runtime-image")));
+ Set<Path> dstRuntime = listFiles(cmd.appRuntimeDirectory());
+
+ Set<Path> intersection = new HashSet<>(srcRuntime);
+ intersection.retainAll(dstRuntime);
+
+ srcRuntime.removeAll(intersection);
+ dstRuntime.removeAll(intersection);
+
+ assertFileListEmpty(srcRuntime, "Missing");
+ assertFileListEmpty(dstRuntime, "Unexpected");
+ })
+ .run();
+ }
+
+ private static Set<Path> listFiles(Path root) throws IOException {
+ try (var files = Files.walk(root)) {
+ return files.map(root::relativize).collect(Collectors.toSet());
+ }
+ }
+
+ private static void assertFileListEmpty(Set<Path> paths, String msg) {
+ TKit.assertTrue(paths.isEmpty(), String.format(
+ "Check there are no %s files in installed image",
+ msg.toLowerCase()), () -> {
+ String msg2 = String.format("%s %d files", msg, paths.size());
+ TKit.trace(msg2 + ":");
+ paths.stream().map(Path::toString).sorted().forEachOrdered(
+ TKit::trace);
+ TKit.trace("Done");
});
}
}
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -44,7 +44,7 @@
* @build jdk.jpackage.test.*
* @modules jdk.jpackage/jdk.jpackage.internal
* @compile BasicTest.java
- * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
+ * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.BasicTest
*/
@@ -116,6 +116,7 @@
}
@Test
+ @SuppressWarnings("unchecked")
public void testVerbose() {
JPackageCommand cmd = JPackageCommand.helloAppImage()
.setFakeRuntime().executePrerequisiteActions();
@@ -139,12 +140,19 @@
TKit.deleteDirectoryContentsRecursive(cmd.outputDir());
List<String> nonVerboseOutput = cmd.createExecutor().executeAndGetOutput();
+ List<String>[] verboseOutput = (List<String>[])new List<?>[1];
- TKit.deleteDirectoryContentsRecursive(cmd.outputDir());
- List<String> verboseOutput = cmd.createExecutor().addArgument(
- "--verbose").executeAndGetOutput();
+ // Directory clean up is not 100% reliable on Windows because of
+ // antivirus software that can lock .exe files. Setup
+ // diffreent output directory instead of cleaning the default one for
+ // verbose jpackage run.
+ TKit.withTempDirectory("verbose-output", tempDir -> {
+ cmd.setArgumentValue("--dest", tempDir);
+ verboseOutput[0] = cmd.createExecutor().addArgument(
+ "--verbose").executeAndGetOutput();
+ });
- TKit.assertTrue(nonVerboseOutput.size() < verboseOutput.size(),
+ TKit.assertTrue(nonVerboseOutput.size() < verboseOutput[0].size(),
"Check verbose output is longer than regular");
expectedVerboseOutputStrings.forEach(str -> {
@@ -155,7 +163,7 @@
expectedVerboseOutputStrings.forEach(str -> {
TKit.assertTextStream(str).label("verbose output")
- .apply(verboseOutput.stream());
+ .apply(verboseOutput[0].stream());
});
}
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java Wed Oct 23 10:10:34 2019 -0400
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -52,7 +52,6 @@
* @compile MainClassTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.MainClassTest
- * --jpt-space-subst=_
*/
public final class MainClassTest {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/windows/WinScriptTest.java Wed Oct 23 10:37:54 2019 -0400
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2018, 2019, 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.Path;
+import java.util.List;
+import java.util.ArrayList;
+import jdk.jpackage.internal.IOUtils;
+import jdk.jpackage.test.TKit;
+import jdk.jpackage.test.PackageTest;
+import jdk.jpackage.test.PackageType;
+import jdk.jpackage.test.Annotations.Test;
+import jdk.jpackage.test.Annotations.Parameter;
+import jdk.jpackage.test.Annotations.Parameters;
+import jdk.jpackage.test.JPackageCommand;
+
+/*
+ * @test usage of scripts from resource dir
+ * @summary jpackage with
+ * @library ../helpers
+ * @build jdk.jpackage.test.*
+ * @requires (os.family == "windows")
+ * @modules jdk.jpackage/jdk.jpackage.internal
+ * @compile WinScriptTest.java
+ * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
+ * --jpt-run=WinScriptTest
+ */
+
+public class WinScriptTest {
+
+ public WinScriptTest(PackageType type) {
+ this.packageType = type;
+
+ test = new PackageTest()
+ .forTypes(type)
+ .configureHelloApp()
+ .addInitializer(cmd -> {
+ cmd.setFakeRuntime().saveConsoleOutput(true);
+ });
+ }
+
+ @Parameters
+ public static List<Object[]> data() {
+ return List.of(new Object[][]{
+ {PackageType.WIN_MSI},
+ {PackageType.WIN_EXE}
+ });
+ }
+
+ @Test
+ @Parameter("0")
+ @Parameter("10")
+ public void test(int wsfExitCode) {
+ final ScriptData appImageScriptData;
+ if (wsfExitCode != 0 && packageType == PackageType.WIN_EXE) {
+ appImageScriptData = new ScriptData(PackageType.WIN_MSI, 0);
+ } else {
+ appImageScriptData = new ScriptData(PackageType.WIN_MSI, wsfExitCode);
+ }
+
+ final ScriptData msiScriptData = new ScriptData(PackageType.WIN_EXE, wsfExitCode);
+
+ test.setExpectedExitCode(wsfExitCode == 0 ? 0 : 1);
+ TKit.withTempDirectory("resources", tempDir -> {
+ test.addInitializer(cmd -> {
+ cmd.addArguments("--resource-dir", tempDir);
+
+ appImageScriptData.createScript(cmd);
+ msiScriptData.createScript(cmd);
+ });
+
+ if (packageType == PackageType.WIN_MSI) {
+ test.addBundleVerifier((cmd, result) -> {
+ appImageScriptData.assertJPackageOutput(result.getOutput());
+ });
+ }
+
+ if (packageType == PackageType.WIN_EXE) {
+ test.addBundleVerifier((cmd, result) -> {
+ appImageScriptData.assertJPackageOutput(result.getOutput());
+ msiScriptData.assertJPackageOutput(result.getOutput());
+ });
+ }
+
+ test.run();
+ });
+ }
+
+ private static class ScriptData {
+ ScriptData(PackageType scriptType, int wsfExitCode) {
+ if (scriptType == PackageType.WIN_MSI) {
+ echoText = "post app image wsf";
+ envVarName = "JpAppImageDir";
+ scriptSuffixName = "post-image";
+ } else {
+ echoText = "post msi wsf";
+ envVarName = "JpMsiFile";
+ scriptSuffixName = "post-msi";
+ }
+ this.wsfExitCode = wsfExitCode;
+ }
+
+ void assertJPackageOutput(List<String> output) {
+ TKit.assertTextStream(String.format("jp: %s", echoText))
+ .predicate(String::equals)
+ .apply(output.stream());
+
+ String cwdPattern = String.format("jp: CWD(%s)=", envVarName);
+ TKit.assertTextStream(cwdPattern)
+ .predicate(String::startsWith)
+ .apply(output.stream());
+ String cwd = output.stream().filter(line -> line.startsWith(
+ cwdPattern)).findFirst().get().substring(cwdPattern.length());
+
+ String envVarPattern = String.format("jp: %s=", envVarName);
+ TKit.assertTextStream(envVarPattern)
+ .predicate(String::startsWith)
+ .apply(output.stream());
+ String envVar = output.stream().filter(line -> line.startsWith(
+ envVarPattern)).findFirst().get().substring(envVarPattern.length());
+
+ TKit.assertTrue(envVar.startsWith(cwd), String.format(
+ "Check value of %s environment variable [%s] starts with the current directory [%s] set for %s script",
+ envVarName, envVar, cwd, echoText));
+ }
+
+ void createScript(JPackageCommand cmd) throws IOException {
+ IOUtils.createXml(Path.of(cmd.getArgumentValue("--resource-dir"),
+ String.format("%s-%s.wsf", cmd.name(), scriptSuffixName)), xml -> {
+ xml.writeStartElement("job");
+ xml.writeAttribute("id", "main");
+ xml.writeStartElement("script");
+ xml.writeAttribute("language", "JScript");
+ xml.writeCData(String.join("\n", List.of(
+ "var shell = new ActiveXObject('WScript.Shell')",
+ "WScript.Echo('jp: " + envVarName + "=' + shell.ExpandEnvironmentStrings('%" + envVarName + "%'))",
+ "WScript.Echo('jp: CWD(" + envVarName + ")=' + shell.CurrentDirectory)",
+ String.format("WScript.Echo('jp: %s')", echoText),
+ String.format("WScript.Quit(%d)", wsfExitCode)
+ )));
+ xml.writeEndElement();
+ xml.writeEndElement();
+ });
+ }
+
+ private final int wsfExitCode;
+ private final String scriptSuffixName;
+ private final String echoText;
+ private final String envVarName;
+ }
+
+ private final PackageType packageType;
+ private PackageTest test;
+}