8246627: Consolidate app image bundlers
Reviewed-by: herrick, almatvee
This commit is contained in:
parent
045d61b5e0
commit
28d2cdf99a
src/jdk.incubator.jpackage
linux/classes/jdk/incubator/jpackage/internal
DesktopIntegration.javaLinuxAppBundler.javaLinuxAppImageBuilder.javaLinuxDebBundler.javaLinuxPackageBundler.javaLinuxRpmBundler.java
macosx
classes/jdk/incubator/jpackage/internal
MacAppBundler.javaMacAppImageBuilder.javaMacBaseInstallerBundler.javaMacDmgBundler.javaMacPkgBundler.java
native/applauncher
share/classes/jdk/incubator/jpackage/internal
AbstractAppImageBuilder.javaAbstractImageBundler.javaAppImageBundler.javaAppImageFile.javaApplicationLayout.javaCfgFile.javaJLinkBundlerHelper.javaStandardBundlerParam.java
windows/classes/jdk/incubator/jpackage/internal
test/jdk/tools/jpackage
helpers/jdk/jpackage/test
share/jdk/jpackage/tests
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,19 +25,34 @@
|
||||
package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppBundler.ICON_PNG;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppImageBuilder.DEFAULT_ICON;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppImageBuilder.ICON_PNG;
|
||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.ADD_LAUNCHERS;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.DESCRIPTION;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.FILE_ASSOCIATIONS;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.ICON;
|
||||
|
||||
/**
|
||||
* Helper to create files for desktop integration.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,140 +25,8 @@
|
||||
|
||||
package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
||||
public class LinuxAppBundler extends AbstractImageBundler {
|
||||
|
||||
static final BundlerParamInfo<File> ICON_PNG =
|
||||
new StandardBundlerParam<>(
|
||||
"icon.png",
|
||||
File.class,
|
||||
params -> {
|
||||
File f = ICON.fetchFrom(params);
|
||||
if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
|
||||
Log.error(MessageFormat.format(
|
||||
I18N.getString("message.icon-not-png"), f));
|
||||
return null;
|
||||
}
|
||||
return f;
|
||||
},
|
||||
(s, p) -> new File(s));
|
||||
|
||||
static final BundlerParamInfo<String> LINUX_INSTALL_DIR =
|
||||
new StandardBundlerParam<>(
|
||||
"linux-install-dir",
|
||||
String.class,
|
||||
params -> {
|
||||
String dir = INSTALL_DIR.fetchFrom(params);
|
||||
if (dir != null) {
|
||||
if (dir.endsWith("/")) {
|
||||
dir = dir.substring(0, dir.length()-1);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
return "/opt";
|
||||
},
|
||||
(s, p) -> s
|
||||
);
|
||||
|
||||
static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
|
||||
String.class,
|
||||
params -> {
|
||||
return "";
|
||||
},
|
||||
(s, p) -> s
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean validate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
try {
|
||||
Objects.requireNonNull(params);
|
||||
return doValidate(params);
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() instanceof ConfigException) {
|
||||
throw (ConfigException) re.getCause();
|
||||
} else {
|
||||
throw new ConfigException(re);
|
||||
}
|
||||
}
|
||||
public class LinuxAppBundler extends AppImageBundler {
|
||||
public LinuxAppBundler() {
|
||||
setAppImageSupplier(LinuxAppImageBuilder::new);
|
||||
}
|
||||
|
||||
private boolean doValidate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
|
||||
imageBundleValidation(params);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
File doBundle(Map<String, ? super Object> params, File outputDirectory,
|
||||
boolean dependentTask) throws PackagerException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
|
||||
} else {
|
||||
return doAppBundle(params, outputDirectory, dependentTask);
|
||||
}
|
||||
}
|
||||
|
||||
private File doAppBundle(Map<String, ? super Object> params,
|
||||
File outputDirectory, boolean dependentTask)
|
||||
throws PackagerException {
|
||||
try {
|
||||
File rootDirectory = createRoot(params, outputDirectory,
|
||||
dependentTask, APP_NAME.fetchFrom(params));
|
||||
AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(
|
||||
params, outputDirectory.toPath());
|
||||
if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ) {
|
||||
JLinkBundlerHelper.execute(params, appBuilder);
|
||||
} else {
|
||||
StandardBundlerParam.copyPredefinedRuntimeImage(
|
||||
params, appBuilder);
|
||||
}
|
||||
return rootDirectory;
|
||||
} catch (PackagerException pe) {
|
||||
throw pe;
|
||||
} catch (Exception ex) {
|
||||
Log.verbose(ex);
|
||||
throw new PackagerException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return I18N.getString("app.bundler.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "linux.app";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBundleType() {
|
||||
return "IMAGE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public File execute(Map<String, ? super Object> params,
|
||||
File outputParentDir) throws PackagerException {
|
||||
return doBundle(params, outputParentDir, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supported(boolean runtimeInstaller) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
72
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java
72
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java
@ -30,31 +30,33 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppBundler.ICON_PNG;
|
||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.ICON;
|
||||
|
||||
public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
|
||||
static final BundlerParamInfo<File> ICON_PNG =
|
||||
new StandardBundlerParam<>(
|
||||
"icon.png",
|
||||
File.class,
|
||||
params -> {
|
||||
File f = ICON.fetchFrom(params);
|
||||
if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
|
||||
Log.error(MessageFormat.format(
|
||||
I18N.getString("message.icon-not-png"), f));
|
||||
return null;
|
||||
}
|
||||
return f;
|
||||
},
|
||||
(s, p) -> new File(s));
|
||||
|
||||
final static String DEFAULT_ICON = "java32.png";
|
||||
|
||||
private final ApplicationLayout appLayout;
|
||||
|
||||
private static ApplicationLayout createAppLayout(Map<String, Object> params,
|
||||
Path imageOutDir) {
|
||||
return ApplicationLayout.linuxAppImage().resolveAt(
|
||||
imageOutDir.resolve(APP_NAME.fetchFrom(params)));
|
||||
}
|
||||
|
||||
public LinuxAppImageBuilder(Map<String, Object> params, Path imageOutDir)
|
||||
throws IOException {
|
||||
super(params, createAppLayout(params, imageOutDir).runtimeDirectory());
|
||||
|
||||
appLayout = createAppLayout(params, imageOutDir);
|
||||
LinuxAppImageBuilder(Path imageOutDir) {
|
||||
super(imageOutDir);
|
||||
}
|
||||
|
||||
private void writeEntry(InputStream in, Path dstFile) throws IOException {
|
||||
@ -66,34 +68,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
return APP_NAME.fetchFrom(params);
|
||||
}
|
||||
|
||||
private Path getLauncherCfgPath(Map<String, ? super Object> params) {
|
||||
return appLayout.appDirectory().resolve(
|
||||
APP_NAME.fetchFrom(params) + ".cfg");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getAppDir() {
|
||||
return appLayout.appDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getAppModsDir() {
|
||||
return appLayout.appModsDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCfgAppDir() {
|
||||
return Path.of("$ROOTDIR").resolve(
|
||||
ApplicationLayout.linuxAppImage().appDirectory()).toString()
|
||||
+ File.separator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCfgRuntimeDir() {
|
||||
return Path.of("$ROOTDIR").resolve(
|
||||
ApplicationLayout.linuxAppImage().runtimeDirectory()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
@ -120,10 +94,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
copyApplication(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareJreFiles(Map<String, ? super Object> params)
|
||||
throws IOException {}
|
||||
|
||||
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
|
||||
Map<String, ? super Object> mainParams) throws IOException {
|
||||
// Copy executable to launchers folder
|
||||
@ -136,7 +106,7 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
executableFile.toFile().setExecutable(true, false);
|
||||
executableFile.toFile().setWritable(true, true);
|
||||
|
||||
writeCfgFile(params, getLauncherCfgPath(params).toFile());
|
||||
writeCfgFile(params);
|
||||
|
||||
var iconResource = createIconResource(DEFAULT_ICON, ICON_PNG, params,
|
||||
mainParams);
|
||||
|
@ -40,7 +40,6 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
|
||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
42
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java
42
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, 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,8 +34,6 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import static jdk.incubator.jpackage.internal.DesktopIntegration.*;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
||||
|
||||
@ -43,6 +41,7 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
|
||||
LinuxPackageBundler(BundlerParamInfo<String> packageName) {
|
||||
this.packageName = packageName;
|
||||
appImageBundler = new LinuxAppBundler().setDependentTask(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -51,7 +50,7 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
|
||||
// run basic validation to ensure requirements are met
|
||||
// we are not interested in return code, only possible exception
|
||||
APP_BUNDLER.fetchFrom(params).validate(params);
|
||||
appImageBundler.validate(params);
|
||||
|
||||
validateInstallDir(LINUX_INSTALL_DIR.fetchFrom(params));
|
||||
|
||||
@ -115,8 +114,8 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
initAppImageLayout.apply(appImage).copy(
|
||||
thePackage.sourceApplicationLayout());
|
||||
} else {
|
||||
appImage = APP_BUNDLER.fetchFrom(params).doBundle(params,
|
||||
thePackage.sourceRoot().toFile(), true);
|
||||
appImage = appImageBundler.execute(params,
|
||||
thePackage.sourceRoot().toFile());
|
||||
ApplicationLayout srcAppLayout = initAppImageLayout.apply(
|
||||
appImage);
|
||||
if (appImage.equals(PREDEFINED_RUNTIME_IMAGE.fetchFrom(params))) {
|
||||
@ -314,15 +313,32 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
}
|
||||
|
||||
private final BundlerParamInfo<String> packageName;
|
||||
private final Bundler appImageBundler;
|
||||
private boolean withFindNeededPackages;
|
||||
private DesktopIntegration desktopIntegration;
|
||||
|
||||
private static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER =
|
||||
new StandardBundlerParam<>(
|
||||
"linux.app.bundler",
|
||||
LinuxAppBundler.class,
|
||||
(params) -> new LinuxAppBundler(),
|
||||
null
|
||||
);
|
||||
private static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
|
||||
String.class,
|
||||
params -> "",
|
||||
(s, p) -> s
|
||||
);
|
||||
|
||||
static final BundlerParamInfo<String> LINUX_INSTALL_DIR =
|
||||
new StandardBundlerParam<>(
|
||||
"linux-install-dir",
|
||||
String.class,
|
||||
params -> {
|
||||
String dir = INSTALL_DIR.fetchFrom(params);
|
||||
if (dir != null) {
|
||||
if (dir.endsWith("/")) {
|
||||
dir = dir.substring(0, dir.length()-1);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
return "/opt";
|
||||
},
|
||||
(s, p) -> s
|
||||
);
|
||||
}
|
||||
|
@ -32,10 +32,8 @@ import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
|
||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,22 +25,21 @@
|
||||
|
||||
package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
|
||||
import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.MAIN_CLASS;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERBOSE;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.*;
|
||||
|
||||
public class MacAppBundler extends AbstractImageBundler {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.MacResources");
|
||||
public class MacAppBundler extends AppImageBundler {
|
||||
public MacAppBundler() {
|
||||
setAppImageSupplier(MacAppImageBuilder::new);
|
||||
setParamsValidator(MacAppBundler::doValidate);
|
||||
}
|
||||
|
||||
private static final String TEMPLATE_BUNDLE_ICON = "java.icns";
|
||||
|
||||
@ -99,27 +98,11 @@ public class MacAppBundler extends AbstractImageBundler {
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(Map<String, ? super Object> params)
|
||||
private static void doValidate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
try {
|
||||
return doValidate(params);
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() instanceof ConfigException) {
|
||||
throw (ConfigException) re.getCause();
|
||||
} else {
|
||||
throw new ConfigException(re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doValidate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
|
||||
imageBundleValidation(params);
|
||||
|
||||
if (StandardBundlerParam.getPredefinedAppImage(params) != null) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// validate short version
|
||||
@ -156,74 +139,5 @@ public class MacAppBundler extends AbstractImageBundler {
|
||||
throw new ConfigException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
File doBundle(Map<String, ? super Object> params, File outputDirectory,
|
||||
boolean dependentTask) throws PackagerException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
|
||||
} else {
|
||||
return doAppBundle(params, outputDirectory, dependentTask);
|
||||
}
|
||||
}
|
||||
|
||||
File doAppBundle(Map<String, ? super Object> params, File outputDirectory,
|
||||
boolean dependentTask) throws PackagerException {
|
||||
try {
|
||||
File rootDirectory = createRoot(params, outputDirectory,
|
||||
dependentTask, APP_NAME.fetchFrom(params) + ".app");
|
||||
AbstractAppImageBuilder appBuilder =
|
||||
new MacAppImageBuilder(params, outputDirectory.toPath());
|
||||
if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ) {
|
||||
JLinkBundlerHelper.execute(params, appBuilder);
|
||||
} else {
|
||||
StandardBundlerParam.copyPredefinedRuntimeImage(
|
||||
params, appBuilder);
|
||||
}
|
||||
return rootDirectory;
|
||||
} catch (PackagerException pe) {
|
||||
throw pe;
|
||||
} catch (Exception ex) {
|
||||
Log.verbose(ex);
|
||||
throw new PackagerException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Implement Bundler
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return I18N.getString("app.bundler.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "mac.app";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBundleType() {
|
||||
return "IMAGE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public File execute(Map<String, ? super Object> params,
|
||||
File outputParentDir) throws PackagerException {
|
||||
return doBundle(params, outputParentDir, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supported(boolean runtimeInstaller) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
98
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java
98
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java
@ -30,10 +30,8 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Writer;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
@ -42,7 +40,6 @@ import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
@ -54,11 +51,22 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.*;
|
||||
import static jdk.incubator.jpackage.internal.MacAppBundler.*;
|
||||
import static jdk.incubator.jpackage.internal.MacAppBundler.BUNDLE_ID_SIGNING_PREFIX;
|
||||
import static jdk.incubator.jpackage.internal.MacAppBundler.DEVELOPER_ID_APP_SIGNING_KEY;
|
||||
import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
|
||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.COPYRIGHT;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.FA_CONTENT_TYPE;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.FA_DESCRIPTION;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.FA_EXTENSIONS;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.FA_ICON;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.FILE_ASSOCIATIONS;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.ICON;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.MAIN_CLASS;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
|
||||
public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
|
||||
@ -74,13 +82,10 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
|
||||
private final Path root;
|
||||
private final Path contentsDir;
|
||||
private final Path appDir;
|
||||
private final Path javaModsDir;
|
||||
private final Path resourcesDir;
|
||||
private final Path macOSDir;
|
||||
private final Path runtimeDir;
|
||||
private final Path runtimeRoot;
|
||||
private final Path mdir;
|
||||
|
||||
private static List<String> keyChains;
|
||||
|
||||
@ -139,26 +144,15 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
null : Boolean.valueOf(s)
|
||||
);
|
||||
|
||||
public MacAppImageBuilder(Map<String, Object> params, Path imageOutDir)
|
||||
throws IOException {
|
||||
super(params, imageOutDir.resolve(APP_NAME.fetchFrom(params)
|
||||
+ ".app/Contents/runtime/Contents/Home"));
|
||||
public MacAppImageBuilder(Path imageOutDir) {
|
||||
super(imageOutDir);
|
||||
|
||||
Objects.requireNonNull(imageOutDir);
|
||||
|
||||
this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params) + ".app");
|
||||
this.root = imageOutDir;
|
||||
this.contentsDir = root.resolve("Contents");
|
||||
this.appDir = contentsDir.resolve("app");
|
||||
this.javaModsDir = appDir.resolve("mods");
|
||||
this.resourcesDir = contentsDir.resolve("Resources");
|
||||
this.macOSDir = contentsDir.resolve("MacOS");
|
||||
this.runtimeDir = contentsDir.resolve("runtime");
|
||||
this.runtimeRoot = runtimeDir.resolve("Contents/Home");
|
||||
this.mdir = runtimeRoot.resolve("lib");
|
||||
Files.createDirectories(appDir);
|
||||
Files.createDirectories(resourcesDir);
|
||||
Files.createDirectories(macOSDir);
|
||||
Files.createDirectories(runtimeDir);
|
||||
this.resourcesDir = appLayout.destktopIntegrationDirectory();
|
||||
this.macOSDir = appLayout.launchersDirectory();
|
||||
this.runtimeDir = appLayout.runtimeDirectory();
|
||||
this.runtimeRoot = appLayout.runtimeHomeDirectory();
|
||||
}
|
||||
|
||||
private void writeEntry(InputStream in, Path dstFile) throws IOException {
|
||||
@ -166,19 +160,11 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
Files.copy(in, dstFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getAppDir() {
|
||||
return appDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getAppModsDir() {
|
||||
return javaModsDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
Files.createDirectories(macOSDir);
|
||||
|
||||
Map<String, ? super Object> originalParams = new HashMap<>(params);
|
||||
// Generate PkgInfo
|
||||
File pkgInfoFile = new File(contentsDir.toFile(), "PkgInfo");
|
||||
@ -195,8 +181,7 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
}
|
||||
executable.toFile().setExecutable(true, false);
|
||||
// generate main app launcher config file
|
||||
File cfg = new File(root.toFile(), getLauncherCfgName(params));
|
||||
writeCfgFile(params, cfg);
|
||||
writeCfgFile(params);
|
||||
|
||||
// create additional app launcher(s) and config file(s)
|
||||
List<Map<String, ? super Object>> entryPoints =
|
||||
@ -213,8 +198,7 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
addExecutable.toFile().setExecutable(true, false);
|
||||
|
||||
// add config file for add launcher
|
||||
cfg = new File(root.toFile(), getLauncherCfgName(tmp));
|
||||
writeCfgFile(tmp, cfg);
|
||||
writeCfgFile(tmp);
|
||||
}
|
||||
|
||||
// Copy class path entries to Java folder
|
||||
@ -244,19 +228,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
sign(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareJreFiles(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
copyRuntimeFiles(params);
|
||||
sign(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
File getRuntimeImageDir(File runtimeImageTop) {
|
||||
File home = new File(runtimeImageTop, "Contents/Home");
|
||||
return (home.exists() ? home : runtimeImageTop);
|
||||
}
|
||||
|
||||
private void copyRuntimeFiles(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
// Generate Info.plist
|
||||
@ -265,18 +236,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
// generate java runtime info.plist
|
||||
writeRuntimeInfoPlist(
|
||||
runtimeDir.resolve("Contents/Info.plist").toFile(), params);
|
||||
|
||||
// copy library
|
||||
Path runtimeMacOSDir = Files.createDirectories(
|
||||
runtimeDir.resolve("Contents/MacOS"));
|
||||
|
||||
// JDK 9, 10, and 11 have extra '/jli/' subdir
|
||||
Path jli = runtimeRoot.resolve("lib/libjli.dylib");
|
||||
if (!Files.exists(jli)) {
|
||||
jli = runtimeRoot.resolve("lib/jli/libjli.dylib");
|
||||
}
|
||||
|
||||
Files.copy(jli, runtimeMacOSDir.resolve("libjli.dylib"));
|
||||
}
|
||||
|
||||
private void sign(Map<String, ? super Object> params) throws IOException {
|
||||
@ -315,11 +274,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
return APP_NAME.fetchFrom(params);
|
||||
}
|
||||
|
||||
public static String getLauncherCfgName(
|
||||
Map<String, ? super Object> params) {
|
||||
return "Contents/app/" + APP_NAME.fetchFrom(params) + ".cfg";
|
||||
}
|
||||
|
||||
private String getBundleName(Map<String, ? super Object> params) {
|
||||
if (MAC_CF_BUNDLE_NAME.fetchFrom(params) != null) {
|
||||
String bn = MAC_CF_BUNDLE_NAME.fetchFrom(params);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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,25 +34,15 @@ import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
|
||||
public abstract class MacBaseInstallerBundler extends AbstractBundler {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.MacResources");
|
||||
|
||||
// This could be generalized more to be for any type of Image Bundler
|
||||
public static final BundlerParamInfo<MacAppBundler> APP_BUNDLER =
|
||||
new StandardBundlerParam<>(
|
||||
"mac.app.bundler",
|
||||
MacAppBundler.class,
|
||||
params -> new MacAppBundler(),
|
||||
(s, p) -> null);
|
||||
|
||||
public final BundlerParamInfo<File> APP_IMAGE_TEMP_ROOT =
|
||||
new StandardBundlerParam<>(
|
||||
"mac.app.imageRoot",
|
||||
@ -113,6 +103,10 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler {
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public MacBaseInstallerBundler() {
|
||||
appImageBundler = new MacAppBundler().setDependentTask(true);
|
||||
}
|
||||
|
||||
protected void validateAppImageAndBundeler(
|
||||
Map<String, ? super Object> params) throws ConfigException {
|
||||
if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) {
|
||||
@ -134,7 +128,7 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler {
|
||||
"message.app-image-requires-app-name.advice"));
|
||||
}
|
||||
} else {
|
||||
APP_BUNDLER.fetchFrom(params).validate(params);
|
||||
appImageBundler.validate(params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,8 +141,7 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler {
|
||||
}
|
||||
File appImageRoot = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
|
||||
|
||||
return APP_BUNDLER.fetchFrom(params).doBundle(
|
||||
params, appImageRoot, true);
|
||||
return appImageBundler.execute(params, appImageRoot);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -197,4 +190,6 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final Bundler appImageBundler;
|
||||
}
|
||||
|
@ -25,16 +25,27 @@
|
||||
|
||||
package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import static jdk.incubator.jpackage.internal.MacAppImageBuilder.ICON_ICNS;
|
||||
import static jdk.incubator.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
|
||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.TEMP_ROOT;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERBOSE;
|
||||
|
||||
public class MacDmgBundler extends MacBaseInstallerBundler {
|
||||
|
||||
@ -65,9 +76,7 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
|
||||
|
||||
IOUtils.writableOutputDir(outdir.toPath());
|
||||
|
||||
File appImageDir = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
|
||||
try {
|
||||
appImageDir.mkdirs();
|
||||
File appLocation = prepareAppBundle(params);
|
||||
|
||||
if (appLocation != null && prepareConfigFiles(params)) {
|
||||
@ -327,6 +336,10 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
|
||||
File mountedRoot = new File(imagesRoot.getAbsolutePath(),
|
||||
APP_NAME.fetchFrom(params));
|
||||
try {
|
||||
Files.deleteIfExists(AppImageFile.getPathInAppImage(
|
||||
mountedRoot.toPath().resolve(APP_NAME.fetchFrom(params)
|
||||
+ ".app")));
|
||||
|
||||
// background image
|
||||
File bgdir = new File(mountedRoot, BACKGROUND_IMAGE_FOLDER);
|
||||
bgdir.mkdirs();
|
||||
|
@ -407,6 +407,8 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
root,
|
||||
"--install-location",
|
||||
getInstallDir(params),
|
||||
"--filter",
|
||||
AppImageFile.getPathInAppImage(Path.of("")).toString(),
|
||||
"--analyze",
|
||||
cpl.getAbsolutePath());
|
||||
|
||||
@ -422,6 +424,8 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
|
||||
root,
|
||||
"--install-location",
|
||||
getInstallDir(params),
|
||||
"--filter",
|
||||
AppImageFile.getPathInAppImage(Path.of("")).toString(),
|
||||
"--component-plist",
|
||||
cpl.getAbsolutePath(),
|
||||
"--scripts",
|
||||
|
@ -45,18 +45,16 @@ void initJvmLauncher() {
|
||||
const tstring launcherPath = SysInfo::getProcessModulePath();
|
||||
|
||||
// Launcher should be in "Contents/MacOS" subdirectory of app image.
|
||||
// However, don't strip "Contents" folder from launcher path, so that app
|
||||
// image root directory would be set to "Contents" subfolder of app image.
|
||||
const tstring appImageRoot = FileUtils::dirname(
|
||||
FileUtils::dirname(launcherPath));
|
||||
const tstring appImageRoot = FileUtils::dirname(FileUtils::dirname(
|
||||
FileUtils::dirname(launcherPath)));
|
||||
|
||||
// Create JVM launcher and save in global variable.
|
||||
jvmLauncher = AppLauncher()
|
||||
.setImageRoot(appImageRoot)
|
||||
.addJvmLibName(_T("Contents/Home/lib/libjli.dylib"))
|
||||
.setAppDir(FileUtils::mkpath() << appImageRoot << _T("app"))
|
||||
.setAppDir(FileUtils::mkpath() << appImageRoot << _T("Contents/app"))
|
||||
.setDefaultRuntimePath(FileUtils::mkpath() << appImageRoot
|
||||
<< _T("runtime"))
|
||||
<< _T("Contents/runtime"))
|
||||
.createJvmLauncher();
|
||||
|
||||
// Kick start JVM launching. The function wouldn't return!
|
||||
|
@ -28,19 +28,14 @@ package jdk.incubator.jpackage.internal;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.ICON;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.SOURCE_DIR;
|
||||
import jdk.incubator.jpackage.internal.resources.ResourceLocator;
|
||||
|
||||
|
||||
/*
|
||||
* AbstractAppImageBuilder
|
||||
* This is sub-classed by each of the platform dependent AppImageBuilder
|
||||
@ -49,13 +44,12 @@ import jdk.incubator.jpackage.internal.resources.ResourceLocator;
|
||||
|
||||
public abstract class AbstractAppImageBuilder {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.MainResources");
|
||||
|
||||
private final Path root;
|
||||
protected final ApplicationLayout appLayout;
|
||||
|
||||
public AbstractAppImageBuilder(Map<String, Object> unused, Path root) {
|
||||
public AbstractAppImageBuilder(Path root) {
|
||||
this.root = root;
|
||||
appLayout = ApplicationLayout.platformAppImage().resolveAt(root);
|
||||
}
|
||||
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
@ -64,121 +58,24 @@ public abstract class AbstractAppImageBuilder {
|
||||
|
||||
public abstract void prepareApplicationFiles(
|
||||
Map<String, ? super Object> params) throws IOException;
|
||||
public abstract void prepareJreFiles(
|
||||
Map<String, ? super Object> params) throws IOException;
|
||||
public abstract Path getAppDir();
|
||||
public abstract Path getAppModsDir();
|
||||
|
||||
public Path getRuntimeRoot() {
|
||||
return this.root;
|
||||
protected void writeCfgFile(Map<String, ? super Object> params) throws
|
||||
IOException {
|
||||
new CfgFile().initFromParams(params).create(root);
|
||||
}
|
||||
|
||||
protected void copyEntry(Path appDir, File srcdir, String fname)
|
||||
throws IOException {
|
||||
Path dest = appDir.resolve(fname);
|
||||
Files.createDirectories(dest.getParent());
|
||||
File src = new File(srcdir, fname);
|
||||
if (src.isDirectory()) {
|
||||
IOUtils.copyRecursive(src.toPath(), dest);
|
||||
} else {
|
||||
Files.copy(src.toPath(), dest);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeCfgFile(Map<String, ? super Object> params,
|
||||
File cfgFileName) throws IOException {
|
||||
cfgFileName.getParentFile().mkdirs();
|
||||
cfgFileName.delete();
|
||||
|
||||
LauncherData launcherData = StandardBundlerParam.LAUNCHER_DATA.fetchFrom(
|
||||
params);
|
||||
|
||||
try (PrintStream out = new PrintStream(cfgFileName)) {
|
||||
|
||||
out.println("[Application]");
|
||||
out.println("app.name=" + APP_NAME.fetchFrom(params));
|
||||
out.println("app.version=" + VERSION.fetchFrom(params));
|
||||
out.println("app.runtime=" + getCfgRuntimeDir());
|
||||
|
||||
for (var path : launcherData.classPath()) {
|
||||
out.println("app.classpath=" + getCfgAppDir()
|
||||
+ path.toString().replace("\\", "/"));
|
||||
}
|
||||
|
||||
// The main app is required to be a jar, modular or unnamed.
|
||||
if (launcherData.isModular()) {
|
||||
out.println("app.mainmodule=" + launcherData.moduleName() + "/"
|
||||
+ launcherData.qualifiedClassName());
|
||||
} else {
|
||||
// If the app is contained in an unnamed jar then launch it the
|
||||
// legacy way and the main class string must be
|
||||
// of the format com/foo/Main
|
||||
if (launcherData.mainJarName() != null) {
|
||||
out.println("app.classpath=" + getCfgAppDir()
|
||||
+ launcherData.mainJarName().toString());
|
||||
}
|
||||
|
||||
out.println("app.mainclass=" + launcherData.qualifiedClassName());
|
||||
}
|
||||
|
||||
out.println();
|
||||
out.println("[JavaOptions]");
|
||||
List<String> jvmargs = JAVA_OPTIONS.fetchFrom(params);
|
||||
for (String arg : jvmargs) {
|
||||
out.println("java-options=" + arg);
|
||||
}
|
||||
Path modsDir = getAppModsDir();
|
||||
|
||||
if (modsDir != null && modsDir.toFile().exists()) {
|
||||
out.println("java-options=" + "--module-path");
|
||||
out.println("java-options=" + getCfgAppDir().replace("\\","/") + "mods");
|
||||
}
|
||||
|
||||
out.println();
|
||||
out.println("[ArgOptions]");
|
||||
List<String> args = ARGUMENTS.fetchFrom(params);
|
||||
for (String arg : args) {
|
||||
out.println("arguments=" + arg);
|
||||
}
|
||||
}
|
||||
ApplicationLayout getAppLayout() {
|
||||
return appLayout;
|
||||
}
|
||||
|
||||
protected void copyApplication(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
Path inputPath = StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
|
||||
Path inputPath = SOURCE_DIR.fetchFrom(params);
|
||||
if (inputPath != null) {
|
||||
IOUtils.copyRecursive(SOURCE_DIR.fetchFrom(params), getAppDir());
|
||||
IOUtils.copyRecursive(SOURCE_DIR.fetchFrom(params),
|
||||
appLayout.appDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
File getRuntimeImageDir(File runtimeImageTop) {
|
||||
return runtimeImageTop;
|
||||
}
|
||||
|
||||
protected String getCfgAppDir() {
|
||||
return "$ROOTDIR" + File.separator
|
||||
+ getAppDir().getFileName() + File.separator;
|
||||
}
|
||||
|
||||
protected String getCfgRuntimeDir() {
|
||||
return "$ROOTDIR" + File.separator + "runtime";
|
||||
}
|
||||
|
||||
String getCfgClassPath(String classpath) {
|
||||
String cfgAppDir = getCfgAppDir();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String path : classpath.split("[:;]")) {
|
||||
if (path.length() > 0) {
|
||||
sb.append(cfgAppDir);
|
||||
sb.append(path);
|
||||
sb.append(File.pathSeparator);
|
||||
}
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
return sb.toString();
|
||||
AppImageFile.save(root, params);
|
||||
}
|
||||
|
||||
public static OverridableResource createIconResource(String defaultIconName,
|
||||
|
81
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractImageBundler.java
81
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractImageBundler.java
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2020, 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.incubator.jpackage.internal;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
import java.io.File;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
||||
/**
|
||||
* AbstractImageBundler
|
||||
*
|
||||
* This is the base class for each of the Application Image Bundlers.
|
||||
*
|
||||
* It contains methods and parameters common to all Image Bundlers.
|
||||
*
|
||||
* Application Image Bundlers are created in "create-app-image" mode,
|
||||
* or as an intermediate step in "create-installer" mode.
|
||||
*
|
||||
* The concrete implementations are in the platform specific Bundlers.
|
||||
*/
|
||||
public abstract class AbstractImageBundler extends AbstractBundler {
|
||||
|
||||
protected void imageBundleValidation(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
if (!params.containsKey(PREDEFINED_APP_IMAGE.getID())
|
||||
&& !StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
StandardBundlerParam.LAUNCHER_DATA.fetchFrom(params);
|
||||
}
|
||||
}
|
||||
|
||||
protected File createRoot(Map<String, ? super Object> params,
|
||||
File outputDirectory, boolean dependentTask, String name)
|
||||
throws PackagerException {
|
||||
|
||||
IOUtils.writableOutputDir(outputDirectory.toPath());
|
||||
|
||||
if (!dependentTask) {
|
||||
Log.verbose(MessageFormat.format(
|
||||
I18N.getString("message.creating-app-bundle"),
|
||||
name, outputDirectory.getAbsolutePath()));
|
||||
}
|
||||
|
||||
// Create directory structure
|
||||
File rootDirectory = new File(outputDirectory, name);
|
||||
|
||||
if (rootDirectory.exists()) {
|
||||
throw new PackagerException("error.root-exists",
|
||||
rootDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
rootDirectory.mkdirs();
|
||||
|
||||
return rootDirectory;
|
||||
}
|
||||
|
||||
}
|
178
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageBundler.java
Normal file
178
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageBundler.java
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2020, 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.incubator.jpackage.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.PREDEFINED_RUNTIME_IMAGE;
|
||||
|
||||
|
||||
class AppImageBundler extends AbstractBundler {
|
||||
|
||||
@Override
|
||||
final public String getName() {
|
||||
return I18N.getString("app.bundler.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
final public String getID() {
|
||||
return "app";
|
||||
}
|
||||
|
||||
@Override
|
||||
final public String getBundleType() {
|
||||
return "IMAGE";
|
||||
}
|
||||
|
||||
@Override
|
||||
final public boolean validate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
try {
|
||||
Objects.requireNonNull(params);
|
||||
|
||||
if (!params.containsKey(PREDEFINED_APP_IMAGE.getID())
|
||||
&& !StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
StandardBundlerParam.LAUNCHER_DATA.fetchFrom(params);
|
||||
}
|
||||
|
||||
if (paramsValidator != null) {
|
||||
paramsValidator.validate(params);
|
||||
}
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() instanceof ConfigException) {
|
||||
throw (ConfigException) re.getCause();
|
||||
} else {
|
||||
throw new ConfigException(re);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public File execute(Map<String, ? super Object> params,
|
||||
File outputParentDir) throws PackagerException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
|
||||
}
|
||||
|
||||
try {
|
||||
return createAppBundle(params, outputParentDir.toPath()).toFile();
|
||||
} catch (PackagerException pe) {
|
||||
throw pe;
|
||||
} catch (RuntimeException|IOException|ConfigException ex) {
|
||||
Log.verbose(ex);
|
||||
throw new PackagerException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
final public boolean supported(boolean runtimeInstaller) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public boolean isDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
final AppImageBundler setDependentTask(boolean v) {
|
||||
dependentTask = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
final AppImageBundler setAppImageSupplier(
|
||||
Function<Path, AbstractAppImageBuilder> v) {
|
||||
appImageSupplier = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
final AppImageBundler setParamsValidator(ParamsValidator v) {
|
||||
paramsValidator = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ParamsValidator {
|
||||
void validate(Map<String, ? super Object> params) throws ConfigException;
|
||||
}
|
||||
|
||||
private Path createRoot(Map<String, ? super Object> params,
|
||||
Path outputDirectory) throws PackagerException, IOException {
|
||||
|
||||
IOUtils.writableOutputDir(outputDirectory);
|
||||
|
||||
String imageName = StandardBundlerParam.APP_NAME.fetchFrom(params);
|
||||
if (Platform.isMac()) {
|
||||
imageName = imageName + ".app";
|
||||
}
|
||||
|
||||
if (!dependentTask) {
|
||||
Log.verbose(MessageFormat.format(
|
||||
I18N.getString("message.creating-app-bundle"),
|
||||
imageName, outputDirectory.toAbsolutePath()));
|
||||
}
|
||||
|
||||
// Create directory structure
|
||||
Path rootDirectory = outputDirectory.resolve(imageName);
|
||||
if (Files.exists(rootDirectory)) {
|
||||
throw new PackagerException("error.root-exists",
|
||||
rootDirectory.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
Files.createDirectories(rootDirectory);
|
||||
|
||||
return rootDirectory;
|
||||
}
|
||||
|
||||
private Path createAppBundle(Map<String, ? super Object> params,
|
||||
Path outputDirectory) throws PackagerException, IOException,
|
||||
ConfigException {
|
||||
|
||||
Path rootDirectory = createRoot(params, outputDirectory);
|
||||
AbstractAppImageBuilder appBuilder = appImageSupplier.apply(rootDirectory);
|
||||
if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ) {
|
||||
JLinkBundlerHelper.execute(params,
|
||||
appBuilder.getAppLayout().runtimeHomeDirectory());
|
||||
} else {
|
||||
StandardBundlerParam.copyPredefinedRuntimeImage(
|
||||
params, appBuilder.getAppLayout());
|
||||
}
|
||||
appBuilder.prepareApplicationFiles(params);
|
||||
return rootDirectory;
|
||||
}
|
||||
|
||||
private boolean dependentTask;
|
||||
private ParamsValidator paramsValidator;
|
||||
private Function<Path, AbstractAppImageBuilder> appImageSupplier;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, 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
|
||||
@ -110,6 +110,10 @@ public class AppImageFile {
|
||||
xml.writeAttribute("version", getVersion());
|
||||
xml.writeAttribute("platform", getPlatform());
|
||||
|
||||
xml.writeStartElement("app-version");
|
||||
xml.writeCharacters(VERSION.fetchFrom(params));
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.writeStartElement("main-launcher");
|
||||
xml.writeCharacters(APP_NAME.fetchFrom(params));
|
||||
xml.writeEndElement();
|
||||
@ -134,14 +138,7 @@ public class AppImageFile {
|
||||
*/
|
||||
static AppImageFile load(Path appImageDir) throws IOException {
|
||||
try {
|
||||
Path path = getPathInAppImage(appImageDir);
|
||||
DocumentBuilderFactory dbf =
|
||||
DocumentBuilderFactory.newDefaultInstance();
|
||||
dbf.setFeature(
|
||||
"http://apache.org/xml/features/nonvalidating/load-external-dtd",
|
||||
false);
|
||||
DocumentBuilder b = dbf.newDocumentBuilder();
|
||||
Document doc = b.parse(new FileInputStream(path.toFile()));
|
||||
Document doc = readXml(appImageDir);
|
||||
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
@ -174,15 +171,29 @@ public class AppImageFile {
|
||||
file = new AppImageFile();
|
||||
}
|
||||
return file;
|
||||
} catch (ParserConfigurationException | SAXException ex) {
|
||||
// Let caller sort this out
|
||||
throw new IOException(ex);
|
||||
} catch (XPathExpressionException ex) {
|
||||
// This should never happen as XPath expressions should be correct
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Document readXml(Path appImageDir) throws IOException {
|
||||
try {
|
||||
Path path = getPathInAppImage(appImageDir);
|
||||
|
||||
DocumentBuilderFactory dbf =
|
||||
DocumentBuilderFactory.newDefaultInstance();
|
||||
dbf.setFeature(
|
||||
"http://apache.org/xml/features/nonvalidating/load-external-dtd",
|
||||
false);
|
||||
DocumentBuilder b = dbf.newDocumentBuilder();
|
||||
return b.parse(new FileInputStream(path.toFile()));
|
||||
} catch (ParserConfigurationException | SAXException ex) {
|
||||
// Let caller sort this out
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of launcher names configured for the application.
|
||||
* The first item in the returned list is main launcher name.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,7 +33,35 @@ import java.util.Map;
|
||||
*/
|
||||
public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayout> {
|
||||
enum PathRole {
|
||||
RUNTIME, APP, LAUNCHERS, DESKTOP, APP_MODS, DLLS, RELEASE
|
||||
/**
|
||||
* Java run-time directory.
|
||||
*/
|
||||
RUNTIME,
|
||||
|
||||
/**
|
||||
* Java run-time home directory.
|
||||
*/
|
||||
RUNTIME_HOME,
|
||||
|
||||
/**
|
||||
* Application data directory.
|
||||
*/
|
||||
APP,
|
||||
|
||||
/**
|
||||
* Directory with application launchers.
|
||||
*/
|
||||
LAUNCHERS,
|
||||
|
||||
/**
|
||||
* Directory for files for desktop integration.
|
||||
*/
|
||||
DESKTOP,
|
||||
|
||||
/**
|
||||
* Directory with application Java modules.
|
||||
*/
|
||||
MODULES,
|
||||
}
|
||||
|
||||
ApplicationLayout(Map<Object, Path> paths) {
|
||||
@ -61,13 +89,6 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
return pathGroup().getPath(PathRole.LAUNCHERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to directory with dynamic libraries.
|
||||
*/
|
||||
public Path dllDirectory() {
|
||||
return pathGroup().getPath(PathRole.DLLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to application data directory.
|
||||
*/
|
||||
@ -76,17 +97,24 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to Java runtime directory.
|
||||
* Path to Java run-time directory.
|
||||
*/
|
||||
public Path runtimeDirectory() {
|
||||
return pathGroup().getPath(PathRole.RUNTIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to Java run-time home directory.
|
||||
*/
|
||||
public Path runtimeHomeDirectory() {
|
||||
return pathGroup().getPath(PathRole.RUNTIME_HOME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to application mods directory.
|
||||
*/
|
||||
public Path appModsDirectory() {
|
||||
return pathGroup().getPath(PathRole.APP_MODS);
|
||||
return pathGroup().getPath(PathRole.MODULES);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,22 +124,14 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
return pathGroup().getPath(PathRole.DESKTOP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to release file in the Java runtime directory.
|
||||
*/
|
||||
public Path runtimeRelease() {
|
||||
return pathGroup().getPath(PathRole.RELEASE);
|
||||
}
|
||||
|
||||
static ApplicationLayout linuxAppImage() {
|
||||
return new ApplicationLayout(Map.of(
|
||||
PathRole.LAUNCHERS, Path.of("bin"),
|
||||
PathRole.APP, Path.of("lib/app"),
|
||||
PathRole.RUNTIME, Path.of("lib/runtime"),
|
||||
PathRole.RUNTIME_HOME, Path.of("lib/runtime"),
|
||||
PathRole.DESKTOP, Path.of("lib"),
|
||||
PathRole.DLLS, Path.of("lib"),
|
||||
PathRole.APP_MODS, Path.of("lib/app/mods"),
|
||||
PathRole.RELEASE, Path.of("lib/runtime/release")
|
||||
PathRole.MODULES, Path.of("lib/app/mods")
|
||||
));
|
||||
}
|
||||
|
||||
@ -120,10 +140,9 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
PathRole.LAUNCHERS, Path.of(""),
|
||||
PathRole.APP, Path.of("app"),
|
||||
PathRole.RUNTIME, Path.of("runtime"),
|
||||
PathRole.RUNTIME_HOME, Path.of("runtime"),
|
||||
PathRole.DESKTOP, Path.of(""),
|
||||
PathRole.DLLS, Path.of(""),
|
||||
PathRole.APP_MODS, Path.of("app/mods"),
|
||||
PathRole.RELEASE, Path.of("runtime/release")
|
||||
PathRole.MODULES, Path.of("app/mods")
|
||||
));
|
||||
}
|
||||
|
||||
@ -132,10 +151,9 @@ public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayo
|
||||
PathRole.LAUNCHERS, Path.of("Contents/MacOS"),
|
||||
PathRole.APP, Path.of("Contents/app"),
|
||||
PathRole.RUNTIME, Path.of("Contents/runtime"),
|
||||
PathRole.RUNTIME_HOME, Path.of("Contents/runtime/Contents/Home"),
|
||||
PathRole.DESKTOP, Path.of("Contents/Resources"),
|
||||
PathRole.DLLS, Path.of("Contents/MacOS"),
|
||||
PathRole.APP_MODS, Path.of("Contents/app/mods"),
|
||||
PathRole.RELEASE, Path.of("Contents/runtime/Contents/Home/release")
|
||||
PathRole.MODULES, Path.of("Contents/app/mods")
|
||||
));
|
||||
}
|
||||
|
||||
|
133
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/CfgFile.java
Normal file
133
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/CfgFile.java
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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.incubator.jpackage.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
||||
/**
|
||||
* App launcher's config file.
|
||||
*/
|
||||
final class CfgFile {
|
||||
CfgFile() {
|
||||
appLayout = ApplicationLayout.platformAppImage();
|
||||
}
|
||||
|
||||
CfgFile initFromParams(Map<String, ? super Object> params) {
|
||||
launcherData = StandardBundlerParam.LAUNCHER_DATA.fetchFrom(params);
|
||||
launcherName = StandardBundlerParam.APP_NAME.fetchFrom(params);
|
||||
javaOptions = JAVA_OPTIONS.fetchFrom(params);
|
||||
arguments = ARGUMENTS.fetchFrom(params);
|
||||
return this;
|
||||
}
|
||||
|
||||
void create(Path appImage) throws IOException {
|
||||
List<Map.Entry<String, Object>> content = new ArrayList<>();
|
||||
|
||||
ApplicationLayout appCfgLayout = createAppCfgLayout();
|
||||
|
||||
content.add(Map.entry("[Application]", SECTION_TAG));
|
||||
content.add(Map.entry("app.runtime", appCfgLayout.runtimeDirectory()));
|
||||
|
||||
if (launcherData.isModular()) {
|
||||
content.add(Map.entry("app.mainmodule", launcherData.moduleName()
|
||||
+ "/" + launcherData.qualifiedClassName()));
|
||||
} else {
|
||||
// If the app is contained in an unnamed jar then launch it the
|
||||
// legacy way and the main class string must be
|
||||
// of the format com/foo/Main
|
||||
if (launcherData.mainJarName() != null) {
|
||||
content.add(Map.entry("app.classpath",
|
||||
appCfgLayout.appDirectory().resolve(
|
||||
launcherData.mainJarName())));
|
||||
}
|
||||
content.add(Map.entry("app.mainclass",
|
||||
launcherData.qualifiedClassName()));
|
||||
}
|
||||
|
||||
for (var value : launcherData.classPath()) {
|
||||
content.add(Map.entry("app.classpath",
|
||||
appCfgLayout.appDirectory().resolve(value).toString()));
|
||||
}
|
||||
|
||||
ApplicationLayout appImagelayout = appLayout.resolveAt(appImage);
|
||||
Path modsDir = appImagelayout.appModsDirectory();
|
||||
if (!javaOptions.isEmpty() || Files.isDirectory(modsDir)) {
|
||||
content.add(Map.entry("[JavaOptions]", SECTION_TAG));
|
||||
for (var value : javaOptions) {
|
||||
content.add(Map.entry("java-options", value));
|
||||
}
|
||||
content.add(Map.entry("java-options", "--module-path"));
|
||||
content.add(Map.entry("java-options",
|
||||
appCfgLayout.appModsDirectory()));
|
||||
}
|
||||
|
||||
if (!arguments.isEmpty()) {
|
||||
content.add(Map.entry("[ArgOptions]", SECTION_TAG));
|
||||
for (var value : arguments) {
|
||||
content.add(Map.entry("arguments", value));
|
||||
}
|
||||
}
|
||||
|
||||
Path cfgFile = appImagelayout.appDirectory().resolve(launcherName + ".cfg");
|
||||
Files.createDirectories(cfgFile.getParent());
|
||||
|
||||
boolean[] addLineBreakAtSection = new boolean[1];
|
||||
Stream<String> lines = content.stream().map(entry -> {
|
||||
if (entry.getValue() == SECTION_TAG) {
|
||||
if (!addLineBreakAtSection[0]) {
|
||||
addLineBreakAtSection[0] = true;
|
||||
return entry.getKey();
|
||||
}
|
||||
return "\n" + entry.getKey();
|
||||
}
|
||||
return entry.getKey() + "=" + entry.getValue();
|
||||
});
|
||||
Files.write(cfgFile, (Iterable<String>) lines::iterator);
|
||||
}
|
||||
|
||||
private ApplicationLayout createAppCfgLayout() {
|
||||
ApplicationLayout appCfgLayout = appLayout.resolveAt(Path.of("$ROOTDIR"));
|
||||
appCfgLayout.pathGroup().setPath(ApplicationLayout.PathRole.APP,
|
||||
Path.of("$APPDIR"));
|
||||
appCfgLayout.pathGroup().setPath(ApplicationLayout.PathRole.MODULES,
|
||||
appCfgLayout.appDirectory().resolve(appCfgLayout.appModsDirectory().getFileName()));
|
||||
return appCfgLayout;
|
||||
}
|
||||
|
||||
private String launcherName;
|
||||
private LauncherData launcherData;
|
||||
List<String> arguments;
|
||||
List<String> javaOptions;
|
||||
private final ApplicationLayout appLayout;
|
||||
|
||||
private final static Object SECTION_TAG = new Object();
|
||||
}
|
139
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JLinkBundlerHelper.java
139
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JLinkBundlerHelper.java
@ -29,37 +29,32 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.spi.ToolProvider;
|
||||
import java.util.jar.JarFile;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.spi.ToolProvider;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.internal.module.ModulePath;
|
||||
|
||||
|
||||
final class JLinkBundlerHelper {
|
||||
|
||||
private static final ToolProvider JLINK_TOOL =
|
||||
ToolProvider.findFirst("jlink").orElseThrow();
|
||||
|
||||
static void execute(Map<String, ? super Object> params,
|
||||
AbstractAppImageBuilder imageBuilder)
|
||||
throws IOException, Exception {
|
||||
static void execute(Map<String, ? super Object> params, Path outputDir)
|
||||
throws IOException, PackagerException {
|
||||
|
||||
List<Path> modulePath =
|
||||
StandardBundlerParam.MODULE_PATH.fetchFrom(params);
|
||||
@ -69,7 +64,6 @@ final class JLinkBundlerHelper {
|
||||
StandardBundlerParam.LIMIT_MODULES.fetchFrom(params);
|
||||
List<String> options =
|
||||
StandardBundlerParam.JLINK_OPTIONS.fetchFrom(params);
|
||||
Path outputDir = imageBuilder.getRuntimeRoot();
|
||||
|
||||
LauncherData launcherData = StandardBundlerParam.LAUNCHER_DATA.fetchFrom(
|
||||
params);
|
||||
@ -79,11 +73,10 @@ final class JLinkBundlerHelper {
|
||||
|
||||
// Modules
|
||||
if (!launcherData.isModular() && addModules.isEmpty()) {
|
||||
addModules.add(ModuleHelper.ALL_DEFAULT);
|
||||
addModules.add(ALL_DEFAULT);
|
||||
}
|
||||
|
||||
Set<String> modules = new ModuleHelper(
|
||||
modulePath, addModules, limitModules).modules();
|
||||
Set<String> modules = createModuleList(modulePath, addModules, limitModules);
|
||||
|
||||
if (launcherData.isModular()) {
|
||||
modules.add(launcherData.moduleName());
|
||||
@ -91,8 +84,6 @@ final class JLinkBundlerHelper {
|
||||
|
||||
runJLink(outputDir, modulePath, modules, limitModules,
|
||||
options, bindServices);
|
||||
|
||||
imageBuilder.prepareApplicationFiles(params);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -137,72 +128,41 @@ final class JLinkBundlerHelper {
|
||||
ModuleFinder.ofSystem());
|
||||
}
|
||||
|
||||
private static class ModuleHelper {
|
||||
// The token for "all modules on the module path".
|
||||
private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
|
||||
private static Set<String> createModuleList(List<Path> paths,
|
||||
Set<String> addModules, Set<String> limitModules) {
|
||||
|
||||
// The token for "all valid runtime modules".
|
||||
static final String ALL_DEFAULT = "ALL-DEFAULT";
|
||||
final Set<String> modules = new HashSet<>();
|
||||
|
||||
private final Set<String> modules = new HashSet<>();
|
||||
ModuleHelper(List<Path> paths, Set<String> addModules,
|
||||
Set<String> limitModules) {
|
||||
boolean addAllModulePath = false;
|
||||
boolean addDefaultMods = false;
|
||||
final Map<String, Supplier<Collection<String>>> phonyModules = Map.of(
|
||||
ALL_MODULE_PATH,
|
||||
() -> createModuleFinder(paths)
|
||||
.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.collect(Collectors.toSet()),
|
||||
ALL_DEFAULT,
|
||||
() -> getDefaultModules(paths, modules));
|
||||
|
||||
for (Iterator<String> iterator = addModules.iterator();
|
||||
iterator.hasNext();) {
|
||||
String module = iterator.next();
|
||||
|
||||
switch (module) {
|
||||
case ALL_MODULE_PATH:
|
||||
iterator.remove();
|
||||
addAllModulePath = true;
|
||||
break;
|
||||
case ALL_DEFAULT:
|
||||
iterator.remove();
|
||||
addDefaultMods = true;
|
||||
break;
|
||||
default:
|
||||
this.modules.add(module);
|
||||
}
|
||||
}
|
||||
|
||||
if (addAllModulePath) {
|
||||
this.modules.addAll(getModuleNamesFromPath(paths));
|
||||
} else if (addDefaultMods) {
|
||||
this.modules.addAll(getDefaultModules(
|
||||
paths, addModules));
|
||||
Supplier<Collection<String>> phonyModule = null;
|
||||
for (var module : addModules) {
|
||||
phonyModule = phonyModules.get(module);
|
||||
if (phonyModule == null) {
|
||||
modules.add(module);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> modules() {
|
||||
return modules;
|
||||
if (phonyModule != null) {
|
||||
modules.addAll(phonyModule.get());
|
||||
}
|
||||
|
||||
private static Set<String> getModuleNamesFromPath(List<Path> paths) {
|
||||
|
||||
return createModuleFinder(paths)
|
||||
.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
||||
private static void runJLink(Path output, List<Path> modulePath,
|
||||
Set<String> modules, Set<String> limitModules,
|
||||
List<String> options, boolean bindServices)
|
||||
throws PackagerException {
|
||||
|
||||
// This is just to ensure jlink is given a non-existant directory
|
||||
// The passed in output path should be non-existant or empty directory
|
||||
try {
|
||||
IOUtils.deleteRecursive(output.toFile());
|
||||
} catch (IOException ioe) {
|
||||
throw new PackagerException(ioe);
|
||||
}
|
||||
throws PackagerException, IOException {
|
||||
|
||||
ArrayList<String> args = new ArrayList<String>();
|
||||
args.add("--output");
|
||||
@ -237,14 +197,14 @@ final class JLinkBundlerHelper {
|
||||
PrintWriter pw = new PrintWriter(writer);
|
||||
|
||||
Log.verbose("jlink arguments: " + args);
|
||||
int retVal = JLINK_TOOL.run(pw, pw, args.toArray(new String[0]));
|
||||
int retVal = LazyLoad.JLINK_TOOL.run(pw, pw, args.toArray(new String[0]));
|
||||
String jlinkOut = writer.toString();
|
||||
|
||||
if (retVal != 0) {
|
||||
throw new PackagerException("error.jlink.failed" , jlinkOut);
|
||||
} else if (jlinkOut.length() > 0) {
|
||||
Log.verbose("jlink output: " + jlinkOut);
|
||||
}
|
||||
|
||||
Log.verbose("jlink output: " + jlinkOut);
|
||||
}
|
||||
|
||||
private static String getPathList(List<Path> pathList) {
|
||||
@ -258,4 +218,15 @@ final class JLinkBundlerHelper {
|
||||
return Matcher.quoteReplacement(strings.stream().collect(
|
||||
Collectors.joining(",")));
|
||||
}
|
||||
|
||||
// The token for "all modules on the module path".
|
||||
private final static String ALL_MODULE_PATH = "ALL-MODULE-PATH";
|
||||
|
||||
// The token for "all valid runtime modules".
|
||||
private final static String ALL_DEFAULT = "ALL-DEFAULT";
|
||||
|
||||
private static class LazyLoad {
|
||||
static final ToolProvider JLINK_TOOL = ToolProvider.findFirst(
|
||||
"jlink").orElseThrow();
|
||||
};
|
||||
}
|
||||
|
15
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java
15
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java
@ -470,10 +470,8 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
return applicationImage;
|
||||
}
|
||||
|
||||
static void copyPredefinedRuntimeImage(
|
||||
Map<String, ? super Object> params,
|
||||
AbstractAppImageBuilder appBuilder)
|
||||
throws IOException , ConfigException {
|
||||
static void copyPredefinedRuntimeImage(Map<String, ? super Object> params,
|
||||
ApplicationLayout appLayout) throws IOException, ConfigException {
|
||||
File topImage = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
|
||||
if (!topImage.exists()) {
|
||||
throw new ConfigException(
|
||||
@ -485,16 +483,17 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
"message.runtime-image-dir-does-not-exist.advice"),
|
||||
PREDEFINED_RUNTIME_IMAGE.getID()));
|
||||
}
|
||||
File image = appBuilder.getRuntimeImageDir(topImage);
|
||||
|
||||
// copy whole runtime, need to skip jmods and src.zip
|
||||
final List<String> excludes = Arrays.asList("jmods", "src.zip");
|
||||
IOUtils.copyRecursive(image.toPath(), appBuilder.getRuntimeRoot(), excludes);
|
||||
IOUtils.copyRecursive(topImage.toPath(),
|
||||
appLayout.runtimeHomeDirectory(), excludes);
|
||||
|
||||
// if module-path given - copy modules to appDir/mods
|
||||
List<Path> modulePath =
|
||||
StandardBundlerParam.MODULE_PATH.fetchFrom(params);
|
||||
List<Path> defaultModulePath = getDefaultModulePath();
|
||||
Path dest = appBuilder.getAppModsDir();
|
||||
Path dest = appLayout.appModsDirectory();
|
||||
|
||||
if (dest != null) {
|
||||
for (Path mp : modulePath) {
|
||||
@ -504,8 +503,6 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appBuilder.prepareApplicationFiles(params);
|
||||
}
|
||||
|
||||
private static List<Path> getDefaultModulePath() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,111 +25,8 @@
|
||||
|
||||
package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.WindowsBundlerParam.*;
|
||||
|
||||
public class WinAppBundler extends AbstractImageBundler {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.WinResources");
|
||||
|
||||
@Override
|
||||
public boolean validate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
try {
|
||||
Objects.requireNonNull(params);
|
||||
return doValidate(params);
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() instanceof ConfigException) {
|
||||
throw (ConfigException) re.getCause();
|
||||
} else {
|
||||
throw new ConfigException(re);
|
||||
}
|
||||
}
|
||||
public class WinAppBundler extends AppImageBundler {
|
||||
public WinAppBundler() {
|
||||
setAppImageSupplier(WindowsAppImageBuilder::new);
|
||||
}
|
||||
|
||||
// to be used by chained bundlers, e.g. by EXE bundler to avoid
|
||||
// skipping validation if p.type does not include "image"
|
||||
private boolean doValidate(Map<String, ? super Object> p)
|
||||
throws ConfigException {
|
||||
|
||||
imageBundleValidation(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean bundle(Map<String, ? super Object> p, File outputDirectory)
|
||||
throws PackagerException {
|
||||
return doBundle(p, outputDirectory, false) != null;
|
||||
}
|
||||
|
||||
File doBundle(Map<String, ? super Object> p, File outputDirectory,
|
||||
boolean dependentTask) throws PackagerException {
|
||||
if (StandardBundlerParam.isRuntimeInstaller(p)) {
|
||||
return PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
|
||||
} else {
|
||||
return doAppBundle(p, outputDirectory, dependentTask);
|
||||
}
|
||||
}
|
||||
|
||||
File doAppBundle(Map<String, ? super Object> p, File outputDirectory,
|
||||
boolean dependentTask) throws PackagerException {
|
||||
try {
|
||||
File rootDirectory = createRoot(p, outputDirectory, dependentTask,
|
||||
APP_NAME.fetchFrom(p));
|
||||
AbstractAppImageBuilder appBuilder =
|
||||
new WindowsAppImageBuilder(p, outputDirectory.toPath());
|
||||
if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
|
||||
JLinkBundlerHelper.execute(p, appBuilder);
|
||||
} else {
|
||||
StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
|
||||
}
|
||||
if (!dependentTask) {
|
||||
Log.verbose(MessageFormat.format(
|
||||
I18N.getString("message.result-dir"),
|
||||
outputDirectory.getAbsolutePath()));
|
||||
}
|
||||
return rootDirectory;
|
||||
} catch (PackagerException pe) {
|
||||
throw pe;
|
||||
} catch (Exception e) {
|
||||
Log.verbose(e);
|
||||
throw new PackagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return I18N.getString("app.bundler.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "windows.app";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBundleType() {
|
||||
return "IMAGE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public File execute(Map<String, ? super Object> params,
|
||||
File outputParentDir) throws PackagerException {
|
||||
return doBundle(params, outputParentDir, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supported(boolean platformInstaller) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -37,18 +37,8 @@ public class WinExeBundler extends AbstractBundler {
|
||||
System.loadLibrary("jpackage");
|
||||
}
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.WinResources");
|
||||
|
||||
public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER
|
||||
= new WindowsBundlerParam<>(
|
||||
"win.app.bundler",
|
||||
WinAppBundler.class,
|
||||
params -> new WinAppBundler(),
|
||||
null);
|
||||
|
||||
public static final BundlerParamInfo<File> EXE_IMAGE_DIR
|
||||
= new WindowsBundlerParam<>(
|
||||
= new StandardBundlerParam<>(
|
||||
"win.exe.imageDir",
|
||||
File.class,
|
||||
params -> {
|
||||
@ -107,7 +97,7 @@ public class WinExeBundler extends AbstractBundler {
|
||||
File exeImageDir = EXE_IMAGE_DIR.fetchFrom(params);
|
||||
|
||||
// Write msi to temporary directory.
|
||||
File msi = msiBundler.bundle(params, exeImageDir);
|
||||
File msi = msiBundler.execute(params, exeImageDir);
|
||||
|
||||
try {
|
||||
new ScriptRunner()
|
||||
|
@ -54,8 +54,6 @@ import static jdk.incubator.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.TEMP_ROOT;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VENDOR;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERSION;
|
||||
import static jdk.incubator.jpackage.internal.WindowsBundlerParam.INSTALLDIR_CHOOSER;
|
||||
import static jdk.incubator.jpackage.internal.WindowsBundlerParam.INSTALLER_FILE_NAME;
|
||||
|
||||
/**
|
||||
* WinMsiBundler
|
||||
@ -105,15 +103,8 @@ import static jdk.incubator.jpackage.internal.WindowsBundlerParam.INSTALLER_FILE
|
||||
*/
|
||||
public class WinMsiBundler extends AbstractBundler {
|
||||
|
||||
public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER =
|
||||
new WindowsBundlerParam<>(
|
||||
"win.app.bundler",
|
||||
WinAppBundler.class,
|
||||
params -> new WinAppBundler(),
|
||||
null);
|
||||
|
||||
public static final BundlerParamInfo<File> MSI_IMAGE_DIR =
|
||||
new WindowsBundlerParam<>(
|
||||
new StandardBundlerParam<>(
|
||||
"win.msi.imageDir",
|
||||
File.class,
|
||||
params -> {
|
||||
@ -124,7 +115,7 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
(s, p) -> null);
|
||||
|
||||
public static final BundlerParamInfo<File> WIN_APP_IMAGE =
|
||||
new WindowsBundlerParam<>(
|
||||
new StandardBundlerParam<>(
|
||||
"win.app.image",
|
||||
File.class,
|
||||
null,
|
||||
@ -151,12 +142,41 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
);
|
||||
|
||||
private static final BundlerParamInfo<String> UPGRADE_UUID =
|
||||
new WindowsBundlerParam<>(
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.WIN_UPGRADE_UUID.getId(),
|
||||
String.class,
|
||||
null,
|
||||
(s, p) -> s);
|
||||
|
||||
private static final BundlerParamInfo<String> INSTALLER_FILE_NAME =
|
||||
new StandardBundlerParam<> (
|
||||
"win.installerName",
|
||||
String.class,
|
||||
params -> {
|
||||
String nm = APP_NAME.fetchFrom(params);
|
||||
if (nm == null) return null;
|
||||
|
||||
String version = VERSION.fetchFrom(params);
|
||||
if (version == null) {
|
||||
return nm;
|
||||
} else {
|
||||
return nm + "-" + version;
|
||||
}
|
||||
},
|
||||
(s, p) -> s);
|
||||
|
||||
private static final BundlerParamInfo<Boolean> INSTALLDIR_CHOOSER =
|
||||
new StandardBundlerParam<> (
|
||||
Arguments.CLIOptions.WIN_DIR_CHOOSER.getId(),
|
||||
Boolean.class,
|
||||
params -> Boolean.FALSE,
|
||||
(s, p) -> Boolean.valueOf(s)
|
||||
);
|
||||
|
||||
public WinMsiBundler() {
|
||||
appImageBundler = new WinAppBundler().setDependentTask(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return I18N.getString("msi.bundler.name");
|
||||
@ -172,12 +192,6 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
return "INSTALLER";
|
||||
}
|
||||
|
||||
@Override
|
||||
public File execute(Map<String, ? super Object> params,
|
||||
File outputParentDir) throws PackagerException {
|
||||
return bundle(params, outputParentDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supported(boolean platformInstaller) {
|
||||
try {
|
||||
@ -226,7 +240,7 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
public boolean validate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
try {
|
||||
APP_BUNDLER.fetchFrom(params).validate(params);
|
||||
appImageBundler.validate(params);
|
||||
|
||||
if (wixToolset == null) {
|
||||
wixToolset = WixTool.toolset();
|
||||
@ -282,8 +296,8 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
// copy everything from appImage dir into appDir/name
|
||||
IOUtils.copyRecursive(appImage.toPath(), appDir.toPath());
|
||||
} else {
|
||||
appDir = APP_BUNDLER.fetchFrom(params).doBundle(params,
|
||||
MSI_IMAGE_DIR.fetchFrom(params), true);
|
||||
appDir = appImageBundler.execute(params, MSI_IMAGE_DIR.fetchFrom(
|
||||
params));
|
||||
}
|
||||
|
||||
// Configure installer icon
|
||||
@ -317,10 +331,11 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
}
|
||||
}
|
||||
|
||||
public File bundle(Map<String, ? super Object> params, File outdir)
|
||||
throws PackagerException {
|
||||
@Override
|
||||
public File execute(Map<String, ? super Object> params,
|
||||
File outputParentDir) throws PackagerException {
|
||||
|
||||
IOUtils.writableOutputDir(outdir.toPath());
|
||||
IOUtils.writableOutputDir(outputParentDir.toPath());
|
||||
|
||||
Path imageDir = MSI_IMAGE_DIR.fetchFrom(params).toPath();
|
||||
try {
|
||||
@ -342,14 +357,14 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
.setEnvironmentVariable("JpAppImageDir", imageDir.toAbsolutePath().toString())
|
||||
.run(params);
|
||||
|
||||
return buildMSI(params, wixVars, outdir);
|
||||
return buildMSI(params, wixVars, outputParentDir);
|
||||
} catch (IOException ex) {
|
||||
Log.verbose(ex);
|
||||
throw new PackagerException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> prepareMainProjectFile(
|
||||
private Map<String, String> prepareMainProjectFile(
|
||||
Map<String, ? super Object> params) throws IOException {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
|
||||
@ -467,7 +482,7 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
return msiOut;
|
||||
}
|
||||
|
||||
public static void ensureByMutationFileIsRTF(File f) {
|
||||
private static void ensureByMutationFileIsRTF(File f) {
|
||||
if (f == null || !f.isFile()) return;
|
||||
|
||||
try {
|
||||
@ -540,6 +555,7 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
|
||||
private Path installerIcon;
|
||||
private Map<WixTool, WixTool.ToolInfo> wixToolset;
|
||||
private AppImageBundler appImageBundler;
|
||||
private WixSourcesBuilder wixSourcesBuilder = new WixSourcesBuilder();
|
||||
|
||||
}
|
||||
|
@ -49,13 +49,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
|
||||
private static final String TEMPLATE_APP_ICON ="java48.ico";
|
||||
|
||||
private final Path root;
|
||||
private final Path appDir;
|
||||
private final Path appModsDir;
|
||||
private final Path runtimeDir;
|
||||
private final Path mdir;
|
||||
private final Path binDir;
|
||||
|
||||
public static final BundlerParamInfo<File> ICON_ICO =
|
||||
new StandardBundlerParam<>(
|
||||
"icon.ico",
|
||||
@ -72,7 +65,7 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
(s, p) -> new File(s));
|
||||
|
||||
public static final StandardBundlerParam<Boolean> CONSOLE_HINT =
|
||||
new WindowsBundlerParam<>(
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.WIN_CONSOLE_HINT.getId(),
|
||||
Boolean.class,
|
||||
params -> false,
|
||||
@ -81,21 +74,8 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
(s, p) -> (s == null
|
||||
|| "null".equalsIgnoreCase(s)) ? true : Boolean.valueOf(s));
|
||||
|
||||
public WindowsAppImageBuilder(Map<String, Object> params, Path imageOutDir)
|
||||
throws IOException {
|
||||
super(params,
|
||||
imageOutDir.resolve(APP_NAME.fetchFrom(params) + "/runtime"));
|
||||
|
||||
Objects.requireNonNull(imageOutDir);
|
||||
|
||||
this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params));
|
||||
this.appDir = root.resolve("app");
|
||||
this.appModsDir = appDir.resolve("mods");
|
||||
this.runtimeDir = root.resolve("runtime");
|
||||
this.mdir = runtimeDir.resolve("lib");
|
||||
this.binDir = root;
|
||||
Files.createDirectories(appDir);
|
||||
Files.createDirectories(runtimeDir);
|
||||
WindowsAppImageBuilder(Path imageOutDir) {
|
||||
super(imageOutDir);
|
||||
}
|
||||
|
||||
private void writeEntry(InputStream in, Path dstFile) throws IOException {
|
||||
@ -117,32 +97,9 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getLauncherCfgName(
|
||||
Map<String, ? super Object> params) {
|
||||
return "app/" + APP_NAME.fetchFrom(params) +".cfg";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getAppDir() {
|
||||
return appDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getAppModsDir() {
|
||||
return appModsDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
try {
|
||||
IOUtils.writableOutputDir(root);
|
||||
IOUtils.writableOutputDir(binDir);
|
||||
} catch (PackagerException pe) {
|
||||
throw new RuntimeException(pe);
|
||||
}
|
||||
AppImageFile.save(root, params);
|
||||
|
||||
// create the .exe launchers
|
||||
createLauncherForEntryPoint(params, null);
|
||||
|
||||
@ -158,10 +115,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareJreFiles(Map<String, ? super Object> params)
|
||||
throws IOException {}
|
||||
|
||||
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
|
||||
Map<String, ? super Object> mainParams) throws IOException {
|
||||
|
||||
@ -169,17 +122,18 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
mainParams);
|
||||
Path iconTarget = null;
|
||||
if (iconResource != null) {
|
||||
iconTarget = binDir.resolve(APP_NAME.fetchFrom(params) + ".ico");
|
||||
iconTarget = appLayout.destktopIntegrationDirectory().resolve(
|
||||
APP_NAME.fetchFrom(params) + ".ico");
|
||||
if (null == iconResource.saveToFile(iconTarget)) {
|
||||
iconTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
writeCfgFile(params, root.resolve(
|
||||
getLauncherCfgName(params)).toFile());
|
||||
writeCfgFile(params);
|
||||
|
||||
// Copy executable to bin folder
|
||||
Path executableFile = binDir.resolve(getLauncherName(params));
|
||||
Path executableFile = appLayout.launchersDirectory().resolve(
|
||||
getLauncherName(params));
|
||||
|
||||
try (InputStream is_launcher =
|
||||
getResourceAsStream(getLauncherResourceName(params))) {
|
||||
|
104
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsBundlerParam.java
104
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsBundlerParam.java
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.incubator.jpackage.internal;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
class WindowsBundlerParam<T> extends StandardBundlerParam<T> {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.WinResources");
|
||||
|
||||
WindowsBundlerParam(String id, Class<T> valueType,
|
||||
Function<Map<String, ? super Object>, T> defaultValueFunction,
|
||||
BiFunction<String,
|
||||
Map<String, ? super Object>, T> stringConverter) {
|
||||
super(id, valueType, defaultValueFunction, stringConverter);
|
||||
}
|
||||
|
||||
static final BundlerParamInfo<String> INSTALLER_FILE_NAME =
|
||||
new StandardBundlerParam<> (
|
||||
"win.installerName",
|
||||
String.class,
|
||||
params -> {
|
||||
String nm = APP_NAME.fetchFrom(params);
|
||||
if (nm == null) return null;
|
||||
|
||||
String version = VERSION.fetchFrom(params);
|
||||
if (version == null) {
|
||||
return nm;
|
||||
} else {
|
||||
return nm + "-" + version;
|
||||
}
|
||||
},
|
||||
(s, p) -> s);
|
||||
|
||||
static final StandardBundlerParam<String> MENU_GROUP =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.WIN_MENU_GROUP.getId(),
|
||||
String.class,
|
||||
params -> I18N.getString("param.menu-group.default"),
|
||||
(s, p) -> s
|
||||
);
|
||||
|
||||
static final BundlerParamInfo<Boolean> INSTALLDIR_CHOOSER =
|
||||
new StandardBundlerParam<> (
|
||||
Arguments.CLIOptions.WIN_DIR_CHOOSER.getId(),
|
||||
Boolean.class,
|
||||
params -> Boolean.FALSE,
|
||||
(s, p) -> Boolean.valueOf(s)
|
||||
);
|
||||
|
||||
static final BundlerParamInfo<String> WINDOWS_INSTALL_DIR =
|
||||
new StandardBundlerParam<>(
|
||||
"windows-install-dir",
|
||||
String.class,
|
||||
params -> {
|
||||
String dir = INSTALL_DIR.fetchFrom(params);
|
||||
if (dir != null) {
|
||||
if (dir.contains(":") || dir.contains("..")) {
|
||||
Log.error(MessageFormat.format(I18N.getString(
|
||||
"message.invalid.install.dir"), dir,
|
||||
APP_NAME.fetchFrom(params)));
|
||||
} else {
|
||||
if (dir.startsWith("\\")) {
|
||||
dir = dir.substring(1);
|
||||
}
|
||||
if (dir.endsWith("\\")) {
|
||||
dir = dir.substring(0, dir.length() - 1);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
return APP_NAME.fetchFrom(params); // Default to app name
|
||||
},
|
||||
(s, p) -> s
|
||||
);
|
||||
}
|
42
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java
42
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,8 +38,6 @@ import javax.xml.stream.XMLStreamWriter;
|
||||
import jdk.incubator.jpackage.internal.IOUtils.XmlConsumer;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
import static jdk.incubator.jpackage.internal.WinMsiBundler.*;
|
||||
import static jdk.incubator.jpackage.internal.WindowsBundlerParam.MENU_GROUP;
|
||||
import static jdk.incubator.jpackage.internal.WindowsBundlerParam.WINDOWS_INSTALL_DIR;
|
||||
|
||||
/**
|
||||
* Creates application WiX source files.
|
||||
@ -824,7 +822,7 @@ class WixSourcesBuilder {
|
||||
PROGRAM_MENU_PATH, DESKTOP_PATH);
|
||||
|
||||
private static final StandardBundlerParam<Boolean> MENU_HINT =
|
||||
new WindowsBundlerParam<>(
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.WIN_MENU_HINT.getId(),
|
||||
Boolean.class,
|
||||
params -> false,
|
||||
@ -835,7 +833,7 @@ class WixSourcesBuilder {
|
||||
);
|
||||
|
||||
private static final StandardBundlerParam<Boolean> SHORTCUT_HINT =
|
||||
new WindowsBundlerParam<>(
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.WIN_SHORTCUT_HINT.getId(),
|
||||
Boolean.class,
|
||||
params -> false,
|
||||
@ -844,4 +842,38 @@ class WixSourcesBuilder {
|
||||
(s, p) -> (s == null ||
|
||||
"null".equalsIgnoreCase(s))? false : Boolean.valueOf(s)
|
||||
);
|
||||
|
||||
private static final StandardBundlerParam<String> MENU_GROUP =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.WIN_MENU_GROUP.getId(),
|
||||
String.class,
|
||||
params -> I18N.getString("param.menu-group.default"),
|
||||
(s, p) -> s
|
||||
);
|
||||
|
||||
private static final BundlerParamInfo<String> WINDOWS_INSTALL_DIR =
|
||||
new StandardBundlerParam<>(
|
||||
"windows-install-dir",
|
||||
String.class,
|
||||
params -> {
|
||||
String dir = INSTALL_DIR.fetchFrom(params);
|
||||
if (dir != null) {
|
||||
if (dir.contains(":") || dir.contains("..")) {
|
||||
Log.error(MessageFormat.format(I18N.getString(
|
||||
"message.invalid.install.dir"), dir,
|
||||
APP_NAME.fetchFrom(params)));
|
||||
} else {
|
||||
if (dir.startsWith("\\")) {
|
||||
dir = dir.substring(1);
|
||||
}
|
||||
if (dir.endsWith("\\")) {
|
||||
dir = dir.substring(0, dir.length() - 1);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
return APP_NAME.fetchFrom(params); // Default to app name
|
||||
},
|
||||
(s, p) -> s
|
||||
);
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ error.version-swap=Failed to update version information for {0}
|
||||
error.invalid-envvar=Invalid value of {0} environment variable
|
||||
error.lock-resource=Failed to lock: {0}
|
||||
|
||||
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.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.outputting-to-location=Generating EXE for installer to: {0}.
|
||||
|
@ -47,9 +47,8 @@ error.msi-product-version-build-out-of-range=\u30D0\u30FC\u30B8\u30E7\u30F3\u306
|
||||
error.msi-product-version-minor-out-of-range=\u30DE\u30A4\u30CA\u30FC\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u306F\u7BC4\u56F2[0, 255]\u5185\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
|
||||
error.version-swap={0}\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F
|
||||
error.invalid-envvar={0}\u74B0\u5883\u5909\u6570\u306E\u5024\u304C\u7121\u52B9\u3067\u3059
|
||||
+error.lock-resource=Failed to lock: {0}
|
||||
error.lock-resource=Failed to lock: {0}
|
||||
|
||||
message.result-dir=\u7D50\u679C\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB: {0}
|
||||
message.icon-not-ico=\u6307\u5B9A\u3057\u305F\u30A2\u30A4\u30B3\u30F3"{0}"\u306FICO\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u306A\u304F\u3001\u4F7F\u7528\u3055\u308C\u307E\u305B\u3093\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u304C\u305D\u306E\u4F4D\u7F6E\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
|
||||
message.potential.windows.defender.issue=\u8B66\u544A: Windows Defender\u304C\u539F\u56E0\u3067jpackage\u304C\u6A5F\u80FD\u3057\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\u554F\u984C\u304C\u767A\u751F\u3057\u305F\u5834\u5408\u306F\u3001\u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30FB\u30E2\u30CB\u30BF\u30EA\u30F3\u30B0\u3092\u7121\u52B9\u306B\u3059\u308B\u304B\u3001\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{0}"\u306E\u9664\u5916\u3092\u8FFD\u52A0\u3059\u308B\u3053\u3068\u306B\u3088\u308A\u3001\u554F\u984C\u306B\u5BFE\u51E6\u3067\u304D\u307E\u3059\u3002
|
||||
message.outputting-to-location=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u306EEXE\u3092\u6B21\u306B\u751F\u6210\u3057\u3066\u3044\u307E\u3059: {0}
|
||||
|
@ -47,9 +47,8 @@ error.msi-product-version-build-out-of-range=\u7248\u672C\u7684\u5DE5\u4F5C\u724
|
||||
error.msi-product-version-minor-out-of-range=\u6B21\u7248\u672C\u5FC5\u987B\u4F4D\u4E8E [0, 255] \u8303\u56F4\u4E2D
|
||||
error.version-swap=\u65E0\u6CD5\u66F4\u65B0 {0} \u7684\u7248\u672C\u4FE1\u606F
|
||||
error.invalid-envvar={0} \u73AF\u5883\u53D8\u91CF\u7684\u503C\u65E0\u6548
|
||||
+error.lock-resource=Failed to lock: {0}
|
||||
error.lock-resource=Failed to lock: {0}
|
||||
|
||||
message.result-dir=\u751F\u6210\u7684\u5E94\u7528\u7A0B\u5E8F\u5305: {0}\u3002
|
||||
message.icon-not-ico=\u6307\u5B9A\u7684\u56FE\u6807 "{0}" \u4E0D\u662F ICO \u6587\u4EF6, \u4E0D\u4F1A\u4F7F\u7528\u3002\u5C06\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\u4EE3\u66FF\u3002
|
||||
message.potential.windows.defender.issue=\u8B66\u544A\uFF1AWindows Defender \u53EF\u80FD\u4F1A\u963B\u6B62 jpackage \u6B63\u5E38\u5DE5\u4F5C\u3002\u5982\u679C\u5B58\u5728\u95EE\u9898\uFF0C\u53EF\u4EE5\u901A\u8FC7\u7981\u7528\u5B9E\u65F6\u76D1\u89C6\u6216\u8005\u4E3A\u76EE\u5F55 "{0}" \u6DFB\u52A0\u6392\u9664\u9879\u6765\u89E3\u51B3\u3002
|
||||
message.outputting-to-location=\u6B63\u5728\u4E3A\u5B89\u88C5\u7A0B\u5E8F\u751F\u6210 EXE, \u4F4D\u7F6E: {0}\u3002
|
||||
|
@ -729,10 +729,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
|
||||
public List<String> readRuntimeReleaseFile() {
|
||||
verifyIsOfType(PackageType.IMAGE);
|
||||
if (isRuntime()) {
|
||||
return null;
|
||||
}
|
||||
Path release = appLayout().runtimeRelease();
|
||||
Path release = appLayout().runtimeHomeDirectory().resolve("release");
|
||||
try {
|
||||
return Files.readAllLines(release);
|
||||
} catch (IOException ioe) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, 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,14 +23,21 @@
|
||||
|
||||
package jdk.jpackage.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import jdk.incubator.jpackage.internal.AppImageFile;
|
||||
import jdk.jpackage.test.Annotations.Parameters;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.incubator.jpackage.internal.AppImageFile;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/*
|
||||
* @test
|
||||
@ -93,7 +100,7 @@ public final class AppVersionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
public void test() throws XPathExpressionException, IOException {
|
||||
if (expectedVersion == null) {
|
||||
new PackageTest()
|
||||
.setExpectedExitCode(1)
|
||||
@ -110,8 +117,11 @@ public final class AppVersionTest {
|
||||
cmd.addArguments(jpackageArgs);
|
||||
}
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
String actualVersion = cmd.readLaunherCfgFile().getValue("Application",
|
||||
"app.version");
|
||||
|
||||
Document xml = AppImageFile.readXml(cmd.outputBundle());
|
||||
String actualVersion = XPathFactory.newInstance().newXPath().evaluate(
|
||||
"/jpackage-state/app-version/text()", xml, XPathConstants.STRING).toString();
|
||||
|
||||
TKit.assertEquals(expectedVersion, actualVersion,
|
||||
"Check application version");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, 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
|
||||
@ -129,7 +129,6 @@ public final class BasicTest {
|
||||
List<String> expectedVerboseOutputStrings = new ArrayList<>();
|
||||
expectedVerboseOutputStrings.add("Creating app package:");
|
||||
if (TKit.isWindows()) {
|
||||
expectedVerboseOutputStrings.add("Result application bundle:");
|
||||
expectedVerboseOutputStrings.add(
|
||||
"Succeeded in building Windows Application Image package");
|
||||
} else if (TKit.isLinux()) {
|
||||
|
@ -115,10 +115,10 @@ public final class JLinkOptionsTest {
|
||||
public JLinkOptionsTest(String javaAppDesc, String[] jpackageArgs, String[] required, String[] prohibited) {
|
||||
this.required = required;
|
||||
this.prohibited = prohibited;
|
||||
cmd = JPackageCommand.helloAppImage(javaAppDesc);
|
||||
if (jpackageArgs != null) {
|
||||
cmd.addArguments(jpackageArgs);
|
||||
}
|
||||
cmd = JPackageCommand
|
||||
.helloAppImage(javaAppDesc)
|
||||
.ignoreDefaultRuntime(true)
|
||||
.addArguments(jpackageArgs);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user