8263155: Allow additional contents for DMG

Reviewed-by: asemenyuk, almatvee
This commit is contained in:
Andy Herrick 2021-10-22 12:17:45 +00:00
parent 1efe946db7
commit b2128a9667
8 changed files with 170 additions and 17 deletions

View File

@ -34,6 +34,7 @@ import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
@ -46,6 +47,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
import static jdk.jpackage.internal.StandardBundlerParam.TEMP_ROOT;
import static jdk.jpackage.internal.StandardBundlerParam.VERBOSE;
import static jdk.jpackage.internal.StandardBundlerParam.DMG_CONTENT;
public class MacDmgBundler extends MacBaseInstallerBundler {
@ -79,7 +81,7 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
try {
Path appLocation = prepareAppBundle(params);
if (appLocation != null && prepareConfigFiles(params)) {
if (appLocation != null && prepareConfigFiles(appLocation,params)) {
Path configScript = getConfig_Script(params);
if (IOUtils.exists(configScript)) {
IOUtils.run("bash", configScript);
@ -96,8 +98,8 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
private static final String hdiutil = "/usr/bin/hdiutil";
private void prepareDMGSetupScript(Map<String, ? super Object> params)
throws IOException {
private void prepareDMGSetupScript(Path appLocation,
Map<String, ? super Object> params) throws IOException {
Path dmgSetup = getConfig_VolumeScript(params);
Log.verbose(MessageFormat.format(
I18N.getString("message.preparing-dmg-setup"),
@ -125,7 +127,9 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
data.put("DEPLOY_BG_FILE", bgFile.toString());
data.put("DEPLOY_VOLUME_PATH", volumePath.toString());
data.put("DEPLOY_APPLICATION_NAME", APP_NAME.fetchFrom(params));
String targetItem = (StandardBundlerParam.isRuntimeInstaller(params)) ?
APP_NAME.fetchFrom(params) : appLocation.getFileName().toString();
data.put("DEPLOY_TARGET", targetItem);
data.put("DEPLOY_INSTALL_LOCATION", getInstallDir(params, true));
createResource(DEFAULT_DMG_SETUP_SCRIPT, params)
@ -181,8 +185,8 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
}
}
private boolean prepareConfigFiles(Map<String, ? super Object> params)
throws IOException {
private boolean prepareConfigFiles(Path appLocation,
Map<String, ? super Object> params) throws IOException {
createResource(DEFAULT_BACKGROUND_IMAGE, params)
.setCategory(I18N.getString("resource.dmg-background"))
@ -199,7 +203,7 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
prepareLicense(params);
prepareDMGSetupScript(params);
prepareDMGSetupScript(appLocation, params);
return true;
}
@ -313,7 +317,11 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
String hdiUtilVerbosityFlag = VERBOSE.fetchFrom(params) ?
"-verbose" : "-quiet";
List <String> dmgContent = DMG_CONTENT.fetchFrom(params);
for (String content : dmgContent) {
Path path = Path.of(content);
IOUtils.copyRecursive(path, srcFolder.resolve(path.getFileName()));
}
// create temp image
ProcessBuilder pb = new ProcessBuilder(
hdiutil,

View File

@ -20,17 +20,24 @@ tell application "Finder"
make new alias file at POSIX file "DEPLOY_VOLUME_PATH" to POSIX file "DEPLOY_INSTALL_LOCATION" with properties {name:"DEPLOY_INSTALL_LOCATION"}
set allTheFiles to the name of every item of theWindow
set xpos to 120
repeat with theFile in allTheFiles
set theFilePath to POSIX path of theFile
set appFilePath to POSIX path of "/DEPLOY_TARGET"
if theFilePath is "DEPLOY_INSTALL_LOCATION" then
-- Position install location
set position of item theFile of theWindow to {390, 130}
else
else if theFilePath ends with appFilePath then
-- Position application or runtime
set position of item theFile of theWindow to {120, 130}
else
-- Position all other items in a second row.
set position of item theFile of theWindow to {xpos, 290}
set xpos to xpos + 150
end if
end repeat
update theDisk without registering applications
delay 5
close (get window of theDisk)

View File

@ -179,6 +179,11 @@ public class Arguments {
setOptionValue("resource-dir", resourceDir);
}),
DMG_CONTENT ("mac-dmg-content", OptionCategories.PROPERTY, () -> {
List<String> content = getArgumentList(popArg());
content.forEach(a -> setOptionValue("mac-dmg-content", a));
}),
ARGUMENTS ("arguments", OptionCategories.PROPERTY, () -> {
List<String> arguments = getArgumentList(popArg());
setOptionValue("arguments", arguments);
@ -625,6 +630,11 @@ public class Arguments {
CLIOptions.JLINK_OPTIONS.getIdWithPrefix());
}
}
if (allOptions.contains(CLIOptions.DMG_CONTENT)
&& !("dmg".equals(type))) {
throw new PackagerException("ERR_InvalidTypeOption",
CLIOptions.DMG_CONTENT.getIdWithPrefix(), ptype);
}
if (hasMainJar && hasMainModule) {
throw new PackagerException("ERR_BothMainJarAndModule");
}

View File

@ -294,6 +294,7 @@ public class DeployParams {
StandardBundlerParam.ADD_MODULES.getID(),
StandardBundlerParam.LIMIT_MODULES.getID(),
StandardBundlerParam.FILE_ASSOCIATIONS.getID(),
StandardBundlerParam.DMG_CONTENT.getID(),
StandardBundlerParam.APP_CONTENT.getID(),
StandardBundlerParam.JLINK_OPTIONS.getID()
));
@ -307,8 +308,10 @@ public class DeployParams {
String delim = "\n\n";
if (key.equals(StandardBundlerParam.MODULE_PATH.getID())) {
delim = File.pathSeparator;
} else if (key.equals(StandardBundlerParam.ADD_MODULES.getID()) ||
key.equals(StandardBundlerParam.APP_CONTENT.getID())) {
} else if (
key.equals(StandardBundlerParam.DMG_CONTENT.getID()) ||
key.equals(StandardBundlerParam.APP_CONTENT.getID()) ||
key.equals(StandardBundlerParam.ADD_MODULES.getID())) {
delim = ",";
}
bundlerArguments.put(key, existingValue + delim + value);

View File

@ -404,6 +404,15 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
(s, p) -> Path.of(s)
);
@SuppressWarnings("unchecked")
static final BundlerParamInfo<List<String>> DMG_CONTENT =
new StandardBundlerParam<>(
Arguments.CLIOptions.DMG_CONTENT.getId(),
(Class<List<String>>) (Object)List.class,
p -> Collections.emptyList(),
(s, p) -> Arrays.asList(s.split(","))
);
@SuppressWarnings("unchecked")
static final StandardBundlerParam<List<String>> APP_CONTENT =
new StandardBundlerParam<>(
@ -411,7 +420,6 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
(Class<List<String>>) (Object)List.class,
p->Collections.emptyList(),
(s, p) -> Arrays.asList(s.split(","))
);
@SuppressWarnings("unchecked")

View File

@ -119,6 +119,7 @@ class ValidOptions {
options.put(CLIOptions.MAC_APP_STORE.getId(), USE.ALL);
options.put(CLIOptions.MAC_CATEGORY.getId(), USE.ALL);
options.put(CLIOptions.MAC_ENTITLEMENTS.getId(), USE.ALL);
options.put(CLIOptions.DMG_CONTENT.getId(), USE.INSTALL);
}
if (Platform.getPlatform() == Platform.LINUX) {

View File

@ -62,11 +62,16 @@ public class MacHelper {
final Path mountPoint = Path.of(plist.queryValue("mount-point"));
try {
Path dmgImage = mountPoint.resolve(cmd.name() +
(cmd.isRuntime() ? "" : ".app"));
TKit.trace(String.format("Exploded [%s] in [%s] directory",
cmd.outputBundle(), dmgImage));
ThrowingConsumer.toConsumer(consumer).accept(dmgImage);
// code here used to copy just <runtime name> or <app name>.app
// We now have option to include arbitrary content, so we copy
// everything in the mounted image.
String[] children = mountPoint.toFile().list();
for (String child : children) {
Path childPath = mountPoint.resolve(child);
TKit.trace(String.format("Exploded [%s] in [%s] directory",
cmd.outputBundle(), childPath));
ThrowingConsumer.toConsumer(consumer).accept(childPath);
}
} finally {
String cmdline[] = {
"/usr/bin/hdiutil",

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2019, 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.
*
* 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.JPackageCommand;
import jdk.jpackage.test.PackageTest;
import jdk.jpackage.test.PackageType;
import jdk.jpackage.test.MacHelper;
import jdk.jpackage.test.TKit;
import jdk.jpackage.test.Annotations.Parameter;
import jdk.jpackage.test.Annotations.Parameters;
import jdk.jpackage.test.Annotations.Test;
import java.util.Collection;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
/*
* @test
* @summary jpackage with --type dmg --mac-dmg-content
* @library ../helpers
* @library /test/lib
* @library base
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @build DmgContentTest
* @modules jdk.jpackage/jdk.jpackage.internal
* @requires (os.family == "mac")
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=DmgContentTest
*/
public class DmgContentTest {
private static final String TEST_JAVA = TKit.TEST_SRC_ROOT.resolve(
"apps/PrintEnv.java").toString();
private static final String TEST_DUKE = TKit.TEST_SRC_ROOT.resolve(
"apps/dukeplug.png").toString();
private static final String TEST_DIR = TKit.TEST_SRC_ROOT.resolve(
"apps").toString();
private static final String TEST_BAD = TKit.TEST_SRC_ROOT.resolve(
"non-existant").toString();
@Parameters
public static Collection input() {
List<Object[]> data = new ArrayList<>();
data.addAll(List.of(new Object[][] {
{"0", PackageType.MAC_DMG, new String[] {TEST_JAVA, TEST_DUKE}},
{"1", PackageType.MAC_PKG, new String[] {TEST_JAVA, TEST_DUKE}},
{"1", PackageType.MAC_DMG, new String[] {TEST_JAVA, TEST_BAD}},
{"0", PackageType.MAC_DMG,
new String[] {TEST_JAVA + "," + TEST_DUKE, TEST_DIR}}}));
return data;
}
public DmgContentTest(String expected, PackageType type, String[] content) {
this.expected = Integer.parseInt(expected);
this.type = type;
this.content = content;
}
@Test
public void test() {
new PackageTest()
.forTypes(type)
.configureHelloApp()
.addInitializer(cmd -> {
for (String arg : content) {
cmd.addArguments("--mac-dmg-content", arg);
}
})
.addInstallVerifier(DmgContentTest::verifyDMG)
.setExpectedExitCode(expected)
.run(PackageTest.Action.CREATE_AND_UNPACK);
}
private static void verifyDMG(JPackageCommand cmd) {
if (cmd.isPackageUnpacked()) {
Path installDir = cmd.appInstallationDirectory();
Path dmgRoot = cmd.pathToUnpackedPackageFile(installDir)
.toAbsolutePath().getParent();
TKit.assertFileExists(dmgRoot.resolve("PrintEnv.java"));
}
}
private final int expected;
private final PackageType type;
private final String[] content;
}