8246624: Refactor JLinkBundlerHelper and StandardBundlerParam classes
Reviewed-by: herrick, almatvee
This commit is contained in:
parent
086c5f1750
commit
045d61b5e0
src/jdk.incubator.jpackage
linux/classes/jdk/incubator/jpackage/internal
macosx/classes/jdk/incubator/jpackage/internal
MacAppImageBuilder.java
resources
share/classes/jdk/incubator/jpackage/internal
AbstractAppImageBuilder.javaAbstractImageBundler.javaArgAction.javaArguments.javaBundleParams.javaDeployParams.javaJLinkBundlerHelper.javaLauncherData.javaModFile.javaRelativeFileSet.javaStandardBundlerParam.java
resources
windows/classes/jdk/incubator/jpackage/internal
test/jdk/tools/jpackage
junit/jdk/incubator/jpackage/internal
share/jdk/jpackage/tests
15
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java
15
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java
@ -147,19 +147,4 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
iconResource.saveToFile(iconTarget);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyApplication(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
for (RelativeFileSet appResources :
|
||||
APP_RESOURCES_LIST.fetchFrom(params)) {
|
||||
if (appResources == null) {
|
||||
throw new RuntimeException("Null app resources?");
|
||||
}
|
||||
File srcdir = appResources.getBaseDirectory();
|
||||
for (String fname : appResources.getIncludedFiles()) {
|
||||
copyEntry(appLayout.appDirectory(), srcdir, fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
@ -118,7 +118,7 @@ public class LinuxDebBundler extends LinuxPackageBundler {
|
||||
|
||||
private static final BundlerParamInfo<String> MAINTAINER =
|
||||
new StandardBundlerParam<> (
|
||||
BundleParams.PARAM_MAINTAINER,
|
||||
Arguments.CLIOptions.LINUX_DEB_MAINTAINER.getId() + ".internal",
|
||||
String.class,
|
||||
params -> VENDOR.fetchFrom(params) + " <"
|
||||
+ EMAIL.fetchFrom(params) + ">",
|
||||
|
74
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java
74
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java
@ -218,7 +218,7 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
}
|
||||
|
||||
// Copy class path entries to Java folder
|
||||
copyClassPathEntries(appDir, params);
|
||||
copyApplication(params);
|
||||
|
||||
/*********** Take care of "config" files *******/
|
||||
|
||||
@ -312,11 +312,7 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
}
|
||||
|
||||
private static String getLauncherName(Map<String, ? super Object> params) {
|
||||
if (APP_NAME.fetchFrom(params) != null) {
|
||||
return APP_NAME.fetchFrom(params);
|
||||
} else {
|
||||
return MAIN_CLASS.fetchFrom(params);
|
||||
}
|
||||
return APP_NAME.fetchFrom(params);
|
||||
}
|
||||
|
||||
public static String getLauncherCfgName(
|
||||
@ -324,23 +320,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
return "Contents/app/" + APP_NAME.fetchFrom(params) + ".cfg";
|
||||
}
|
||||
|
||||
private void copyClassPathEntries(Path javaDirectory,
|
||||
Map<String, ? super Object> params) throws IOException {
|
||||
List<RelativeFileSet> resourcesList =
|
||||
APP_RESOURCES_LIST.fetchFrom(params);
|
||||
if (resourcesList == null) {
|
||||
throw new RuntimeException(
|
||||
I18N.getString("message.null-classpath"));
|
||||
}
|
||||
|
||||
for (RelativeFileSet classPath : resourcesList) {
|
||||
File srcdir = classPath.getBaseDirectory();
|
||||
for (String fname : classPath.getIncludedFiles()) {
|
||||
copyEntry(javaDirectory, srcdir, fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getBundleName(Map<String, ? super Object> params) {
|
||||
if (MAC_CF_BUNDLE_NAME.fetchFrom(params) != null) {
|
||||
String bn = MAC_CF_BUNDLE_NAME.fetchFrom(params);
|
||||
@ -399,50 +378,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
data.put("DEPLOY_BUNDLE_SHORT_VERSION", VERSION.fetchFrom(params));
|
||||
data.put("DEPLOY_BUNDLE_CFBUNDLE_VERSION", VERSION.fetchFrom(params));
|
||||
|
||||
boolean hasMainJar = MAIN_JAR.fetchFrom(params) != null;
|
||||
boolean hasMainModule =
|
||||
StandardBundlerParam.MODULE.fetchFrom(params) != null;
|
||||
|
||||
if (hasMainJar) {
|
||||
data.put("DEPLOY_MAIN_JAR_NAME", MAIN_JAR.fetchFrom(params).
|
||||
getIncludedFiles().iterator().next());
|
||||
}
|
||||
else if (hasMainModule) {
|
||||
data.put("DEPLOY_MODULE_NAME",
|
||||
StandardBundlerParam.MODULE.fetchFrom(params));
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<String> jvmOptions = JAVA_OPTIONS.fetchFrom(params);
|
||||
|
||||
String newline = ""; //So we don't add extra line after last append
|
||||
for (String o : jvmOptions) {
|
||||
sb.append(newline).append(
|
||||
" <string>").append(o).append("</string>");
|
||||
newline = "\n";
|
||||
}
|
||||
|
||||
data.put("DEPLOY_JAVA_OPTIONS", sb.toString());
|
||||
|
||||
sb = new StringBuilder();
|
||||
List<String> args = ARGUMENTS.fetchFrom(params);
|
||||
newline = "";
|
||||
// So we don't add unneccessary extra line after last append
|
||||
|
||||
for (String o : args) {
|
||||
sb.append(newline).append(" <string>").append(o).append(
|
||||
"</string>");
|
||||
newline = "\n";
|
||||
}
|
||||
data.put("DEPLOY_ARGUMENTS", sb.toString());
|
||||
|
||||
newline = "";
|
||||
|
||||
data.put("DEPLOY_LAUNCHER_CLASS", MAIN_CLASS.fetchFrom(params));
|
||||
|
||||
data.put("DEPLOY_APP_CLASSPATH",
|
||||
getCfgClassPath(CLASSPATH.fetchFrom(params)));
|
||||
|
||||
StringBuilder bundleDocumentTypes = new StringBuilder();
|
||||
StringBuilder exportedTypes = new StringBuilder();
|
||||
for (Map<String, ? super Object>
|
||||
@ -788,8 +723,9 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
|
||||
}
|
||||
Path frameworkPath = appLocation.resolve("Contents/Frameworks");
|
||||
if (Files.isDirectory(frameworkPath)) {
|
||||
Files.list(frameworkPath)
|
||||
.forEach(signIdentifiedByPList);
|
||||
try (var fileList = Files.list(frameworkPath)) {
|
||||
fileList.forEach(signIdentifiedByPList);
|
||||
}
|
||||
|
||||
ioe = toThrow.get();
|
||||
if (ioe != null) {
|
||||
|
@ -58,7 +58,6 @@ resource.pkg-background-image=pkg background image
|
||||
|
||||
|
||||
message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
|
||||
message.null-classpath=Null app resources?
|
||||
message.preparing-info-plist=Preparing Info.plist: {0}.
|
||||
message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place.
|
||||
message.version-string-too-many-components=Version sting may have between 1 and 3 numbers: 1, 1.2, 1.2.3.
|
||||
|
@ -59,7 +59,6 @@ resource.pkg-background-image=pkg\u80CC\u666F\u30A4\u30E1\u30FC\u30B8
|
||||
|
||||
|
||||
message.bundle-name-too-long-warning={0}\u304C16\u6587\u5B57\u3092\u8D85\u3048\u308B''{1}''\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\u3002Mac\u3067\u306E\u64CD\u4F5C\u6027\u3092\u3088\u308A\u826F\u304F\u3059\u308B\u305F\u3081\u306B\u77ED\u304F\u3059\u308B\u3053\u3068\u3092\u691C\u8A0E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
||||
message.null-classpath=Null\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u3067\u3059\u304B\u3002
|
||||
message.preparing-info-plist=Info.plist\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059: {0}\u3002
|
||||
message.icon-not-icns= \u6307\u5B9A\u3057\u305F\u30A2\u30A4\u30B3\u30F3"{0}"\u306FICNS\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.version-string-too-many-components=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306B\u306F\u30011\u30011.2\u30011.2.3\u306A\u30691\u304B\u30893\u306E\u6570\u5B57\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
|
||||
|
@ -59,7 +59,6 @@ resource.pkg-background-image=pkg \u80CC\u666F\u56FE\u50CF
|
||||
|
||||
|
||||
message.bundle-name-too-long-warning={0}\u5DF2\u8BBE\u7F6E\u4E3A ''{1}'', \u5176\u957F\u5EA6\u8D85\u8FC7\u4E86 16 \u4E2A\u5B57\u7B26\u3002\u4E3A\u4E86\u83B7\u5F97\u66F4\u597D\u7684 Mac \u4F53\u9A8C, \u8BF7\u8003\u8651\u5C06\u5176\u7F29\u77ED\u3002
|
||||
message.null-classpath=\u662F\u5426\u4E3A\u7A7A\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90?
|
||||
message.preparing-info-plist=\u6B63\u5728\u51C6\u5907 Info.plist: {0}\u3002
|
||||
message.icon-not-icns= \u6307\u5B9A\u7684\u56FE\u6807 "{0}" \u4E0D\u662F ICNS \u6587\u4EF6, \u4E0D\u4F1A\u4F7F\u7528\u3002\u5C06\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\u4EE3\u66FF\u3002
|
||||
message.version-string-too-many-components=\u7248\u672C\u5B57\u7B26\u4E32\u53EF\u4EE5\u5305\u542B 1 \u5230 3 \u4E2A\u6570\u5B57: 1, 1.2, 1.2.3\u3002
|
||||
|
@ -89,14 +89,9 @@ public abstract class AbstractAppImageBuilder {
|
||||
File cfgFileName) throws IOException {
|
||||
cfgFileName.getParentFile().mkdirs();
|
||||
cfgFileName.delete();
|
||||
File mainJar = JLinkBundlerHelper.getMainJar(params);
|
||||
ModFile.ModType mainJarType = ModFile.ModType.Unknown;
|
||||
|
||||
if (mainJar != null) {
|
||||
mainJarType = new ModFile(mainJar).getModType();
|
||||
}
|
||||
|
||||
String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
|
||||
LauncherData launcherData = StandardBundlerParam.LAUNCHER_DATA.fetchFrom(
|
||||
params);
|
||||
|
||||
try (PrintStream out = new PrintStream(cfgFileName)) {
|
||||
|
||||
@ -104,27 +99,26 @@ public abstract class AbstractAppImageBuilder {
|
||||
out.println("app.name=" + APP_NAME.fetchFrom(params));
|
||||
out.println("app.version=" + VERSION.fetchFrom(params));
|
||||
out.println("app.runtime=" + getCfgRuntimeDir());
|
||||
out.println("app.classpath="
|
||||
+ getCfgClassPath(CLASSPATH.fetchFrom(params)));
|
||||
|
||||
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 (mainModule != null &&
|
||||
(mainJarType == ModFile.ModType.Unknown ||
|
||||
mainJarType == ModFile.ModType.ModularJar)) {
|
||||
out.println("app.mainmodule=" + mainModule);
|
||||
if (launcherData.isModular()) {
|
||||
out.println("app.mainmodule=" + launcherData.moduleName() + "/"
|
||||
+ launcherData.qualifiedClassName());
|
||||
} else {
|
||||
String mainClass =
|
||||
StandardBundlerParam.MAIN_CLASS.fetchFrom(params);
|
||||
// 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 (mainJar != null) {
|
||||
if (launcherData.mainJarName() != null) {
|
||||
out.println("app.classpath=" + getCfgAppDir()
|
||||
+ mainJar.toPath().getFileName().toString());
|
||||
}
|
||||
if (mainClass != null) {
|
||||
out.println("app.mainclass=" + mainClass);
|
||||
+ launcherData.mainJarName().toString());
|
||||
}
|
||||
|
||||
out.println("app.mainclass=" + launcherData.qualifiedClassName());
|
||||
}
|
||||
|
||||
out.println();
|
||||
@ -149,6 +143,14 @@ public abstract class AbstractAppImageBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
protected void copyApplication(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
Path inputPath = StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
|
||||
if (inputPath != null) {
|
||||
IOUtils.copyRecursive(SOURCE_DIR.fetchFrom(params), getAppDir());
|
||||
}
|
||||
}
|
||||
|
||||
File getRuntimeImageDir(File runtimeImageTop) {
|
||||
return runtimeImageTop;
|
||||
}
|
||||
|
22
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractImageBundler.java
22
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractImageBundler.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -27,11 +27,7 @@ package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
||||
@ -49,13 +45,12 @@ import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
*/
|
||||
public abstract class AbstractImageBundler extends AbstractBundler {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.MainResources");
|
||||
|
||||
public void imageBundleValidation(Map<String, ? super Object> params)
|
||||
protected void imageBundleValidation(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
StandardBundlerParam.validateMainClassInfoFromAppResources(params);
|
||||
|
||||
if (!params.containsKey(PREDEFINED_APP_IMAGE.getID())
|
||||
&& !StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
StandardBundlerParam.LAUNCHER_DATA.fetchFrom(params);
|
||||
}
|
||||
}
|
||||
|
||||
protected File createRoot(Map<String, ? super Object> params,
|
||||
@ -70,11 +65,6 @@ public abstract class AbstractImageBundler extends AbstractBundler {
|
||||
name, outputDirectory.getAbsolutePath()));
|
||||
}
|
||||
|
||||
// NAME will default to CLASS, so the real problem is no MAIN_CLASS
|
||||
if (name == null) {
|
||||
throw new PackagerException("ERR_NoMainClass");
|
||||
}
|
||||
|
||||
// Create directory structure
|
||||
File rootDirectory = new File(outputDirectory, name);
|
||||
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. 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;
|
||||
|
||||
@FunctionalInterface
|
||||
interface ArgAction {
|
||||
void execute();
|
||||
}
|
@ -344,7 +344,7 @@ public class Arguments {
|
||||
private final String id;
|
||||
private final String shortId;
|
||||
private final OptionCategories category;
|
||||
private final ArgAction action;
|
||||
private final Runnable action;
|
||||
private static Arguments argContext;
|
||||
|
||||
private CLIOptions(String id, OptionCategories category) {
|
||||
@ -357,12 +357,12 @@ public class Arguments {
|
||||
}
|
||||
|
||||
private CLIOptions(String id,
|
||||
OptionCategories category, ArgAction action) {
|
||||
OptionCategories category, Runnable action) {
|
||||
this(id, null, category, action);
|
||||
}
|
||||
|
||||
private CLIOptions(String id, String shortId,
|
||||
OptionCategories category, ArgAction action) {
|
||||
OptionCategories category, Runnable action) {
|
||||
this.id = id;
|
||||
this.shortId = shortId;
|
||||
this.action = action;
|
||||
@ -395,7 +395,7 @@ public class Arguments {
|
||||
|
||||
void execute() {
|
||||
if (action != null) {
|
||||
action.execute();
|
||||
action.run();
|
||||
} else {
|
||||
defaultAction();
|
||||
}
|
||||
@ -471,8 +471,6 @@ public class Arguments {
|
||||
|
||||
validateArguments();
|
||||
|
||||
addResources(deployParams, input, mainJarPath);
|
||||
|
||||
List<Map<String, ? super Object>> launchersAsMap =
|
||||
new ArrayList<>();
|
||||
|
||||
@ -680,35 +678,6 @@ public class Arguments {
|
||||
}
|
||||
}
|
||||
|
||||
private void addResources(DeployParams deployParams,
|
||||
String inputdir, String mainJar) throws PackagerException {
|
||||
|
||||
if (inputdir == null || inputdir.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
File baseDir = new File(inputdir);
|
||||
|
||||
if (!baseDir.isDirectory()) {
|
||||
throw new PackagerException("ERR_InputNotDirectory", inputdir);
|
||||
}
|
||||
if (!baseDir.canRead()) {
|
||||
throw new PackagerException("ERR_CannotReadInputDir", inputdir);
|
||||
}
|
||||
|
||||
List<String> fileNames;
|
||||
fileNames = new ArrayList<>();
|
||||
try (Stream<Path> files = Files.list(baseDir.toPath())) {
|
||||
files.forEach(file -> fileNames.add(
|
||||
file.getFileName().toString()));
|
||||
} catch (IOException e) {
|
||||
Log.error("Unable to add resources: " + e.getMessage());
|
||||
}
|
||||
fileNames.forEach(file -> deployParams.addResource(baseDir, file));
|
||||
|
||||
deployParams.setClasspath(mainJar);
|
||||
}
|
||||
|
||||
static CLIOptions toCLIOption(String arg) {
|
||||
CLIOptions option;
|
||||
if ((option = argIds.get(arg)) == null) {
|
||||
|
@ -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
|
||||
@ -38,60 +38,6 @@ public class BundleParams {
|
||||
|
||||
final protected Map<String, ? super Object> params;
|
||||
|
||||
// RelativeFileSet
|
||||
public static final String PARAM_APP_RESOURCES = "appResources";
|
||||
|
||||
// String - Icon file name
|
||||
public static final String PARAM_ICON = "icon";
|
||||
|
||||
// String - Name of bundle file and native launcher
|
||||
public static final String PARAM_NAME = "name";
|
||||
|
||||
// String - application vendor, used by most of the bundlers
|
||||
public static final String PARAM_VENDOR = "vendor";
|
||||
|
||||
// String - email name and email, only used for debian */
|
||||
public static final String PARAM_EMAIL = "email";
|
||||
|
||||
// String - vendor <email>, only used for debian */
|
||||
public static final String PARAM_MAINTAINER = "maintainer";
|
||||
|
||||
/* String - Copyright. Used on Mac */
|
||||
public static final String PARAM_COPYRIGHT = "copyright";
|
||||
|
||||
// String - GUID on windows for MSI, CFBundleIdentifier on Mac
|
||||
// If not compatible with requirements then bundler either do not bundle
|
||||
// or autogenerate
|
||||
public static final String PARAM_IDENTIFIER = "identifier";
|
||||
|
||||
/* boolean - shortcut preferences */
|
||||
public static final String PARAM_SHORTCUT = "shortcutHint";
|
||||
// boolean - menu shortcut preference
|
||||
public static final String PARAM_MENU = "menuHint";
|
||||
|
||||
// String - Application version. Format may differ for different bundlers
|
||||
public static final String PARAM_VERSION = "appVersion";
|
||||
|
||||
// String - Application release. Used on Linux.
|
||||
public static final String PARAM_RELEASE = "appRelease";
|
||||
|
||||
// String - Optional application description. Used by MSI and on Linux
|
||||
public static final String PARAM_DESCRIPTION = "description";
|
||||
|
||||
// String - License type. Needed on Linux (rpm)
|
||||
public static final String PARAM_LICENSE_TYPE = "licenseType";
|
||||
|
||||
// String - File with license. Format is OS/bundler specific
|
||||
public static final String PARAM_LICENSE_FILE = "licenseFile";
|
||||
|
||||
// String Main application class.
|
||||
// Not used directly but used to derive default values
|
||||
public static final String PARAM_APPLICATION_CLASS = "applicationClass";
|
||||
|
||||
// boolean - Adds a dialog to let the user choose a directory
|
||||
// where the product will be installed.
|
||||
public static final String PARAM_INSTALLDIR_CHOOSER = "installdirChooser";
|
||||
|
||||
/**
|
||||
* create a new bundle with all default values
|
||||
*/
|
||||
@ -123,11 +69,6 @@ public class BundleParams {
|
||||
return APP_NAME.fetchFrom(params);
|
||||
}
|
||||
|
||||
public void setAppResourcesList(
|
||||
List<jdk.incubator.jpackage.internal.RelativeFileSet> rfs) {
|
||||
putUnlessNull(APP_RESOURCES_LIST.getID(), rfs);
|
||||
}
|
||||
|
||||
private void putUnlessNull(String param, Object value) {
|
||||
if (value != null) {
|
||||
params.put(param, value);
|
||||
|
@ -50,8 +50,6 @@ import java.util.TreeSet;
|
||||
*/
|
||||
public class DeployParams {
|
||||
|
||||
final List<RelativeFileSet> resources = new ArrayList<>();
|
||||
|
||||
String targetFormat = null; // means default type for this platform
|
||||
|
||||
File outdir = null;
|
||||
@ -98,44 +96,6 @@ public class DeployParams {
|
||||
return files;
|
||||
}
|
||||
|
||||
public void addResource(File baseDir, String path) {
|
||||
addResource(baseDir, new File(baseDir, path));
|
||||
}
|
||||
|
||||
public void addResource(File baseDir, File file) {
|
||||
// normalize initial file
|
||||
// to strip things like "." in the path
|
||||
// or it can confuse symlink detection logic
|
||||
file = file.getAbsoluteFile();
|
||||
|
||||
if (baseDir == null) {
|
||||
baseDir = file.getParentFile();
|
||||
}
|
||||
resources.add(new RelativeFileSet(
|
||||
baseDir, new LinkedHashSet<>(expandFileset(file))));
|
||||
}
|
||||
|
||||
void setClasspath(String mainJarPath) {
|
||||
String classpath;
|
||||
// we want main jar first on the classpath
|
||||
if (mainJarPath != null) {
|
||||
classpath = mainJarPath + File.pathSeparator;
|
||||
} else {
|
||||
classpath = "";
|
||||
}
|
||||
for (RelativeFileSet resource : resources) {
|
||||
for (String file : resource.getIncludedFiles()) {
|
||||
if (file.endsWith(".jar")) {
|
||||
if (!file.equals(mainJarPath)) {
|
||||
classpath += file + File.pathSeparator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addBundleArgument(
|
||||
StandardBundlerParam.CLASSPATH.getID(), classpath);
|
||||
}
|
||||
|
||||
static void validateName(String s, boolean forApp)
|
||||
throws PackagerException {
|
||||
|
||||
@ -230,14 +190,8 @@ public class DeployParams {
|
||||
|
||||
// if bundling non-modular image, or installer without app-image
|
||||
// then we need some resources and a main class
|
||||
if (!hasModule && !hasAppImage && !runtimeInstaller) {
|
||||
if (resources.isEmpty()) {
|
||||
throw new PackagerException("ERR_MissingAppResources");
|
||||
}
|
||||
if (!hasMain) {
|
||||
throw new PackagerException("ERR_MissingArgument",
|
||||
"--main-jar");
|
||||
}
|
||||
if (!hasModule && !hasAppImage && !runtimeInstaller && !hasMain) {
|
||||
throw new PackagerException("ERR_MissingArgument", "--main-jar");
|
||||
}
|
||||
|
||||
String name = (String)bundlerArguments.get(
|
||||
@ -364,9 +318,6 @@ public class DeployParams {
|
||||
BundleParams getBundleParams() {
|
||||
BundleParams bundleParams = new BundleParams();
|
||||
|
||||
// construct app resources relative to destination folder!
|
||||
bundleParams.setAppResourcesList(resources);
|
||||
|
||||
Map<String, String> unescapedHtmlParams = new TreeMap<>();
|
||||
Map<String, String> escapedHtmlParams = new TreeMap<>();
|
||||
|
||||
@ -386,8 +337,7 @@ public class DeployParams {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeployParams {" + "output: " + outdir
|
||||
+ " resources: {" + resources + "}}";
|
||||
return "DeployParams {" + "output: " + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
166
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JLinkBundlerHelper.java
166
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JLinkBundlerHelper.java
@ -27,28 +27,18 @@ package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.Optional;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.regex.Matcher;
|
||||
@ -64,77 +54,9 @@ import jdk.internal.module.ModulePath;
|
||||
|
||||
final class JLinkBundlerHelper {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.MainResources");
|
||||
|
||||
static final ToolProvider JLINK_TOOL =
|
||||
private static final ToolProvider JLINK_TOOL =
|
||||
ToolProvider.findFirst("jlink").orElseThrow();
|
||||
|
||||
static File getMainJar(Map<String, ? super Object> params) {
|
||||
File result = null;
|
||||
RelativeFileSet fileset =
|
||||
StandardBundlerParam.MAIN_JAR.fetchFrom(params);
|
||||
|
||||
if (fileset != null) {
|
||||
String filename = fileset.getIncludedFiles().iterator().next();
|
||||
result = fileset.getBaseDirectory().toPath().
|
||||
resolve(filename).toFile();
|
||||
|
||||
if (result == null || !result.exists()) {
|
||||
String srcdir =
|
||||
StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
|
||||
|
||||
if (srcdir != null) {
|
||||
result = new File(srcdir + File.separator + filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static String getMainClassFromModule(Map<String, ? super Object> params) {
|
||||
String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
|
||||
if (mainModule != null) {
|
||||
|
||||
int index = mainModule.indexOf("/");
|
||||
if (index > 0) {
|
||||
return mainModule.substring(index + 1);
|
||||
} else {
|
||||
ModuleDescriptor descriptor =
|
||||
JLinkBundlerHelper.getMainModuleDescription(params);
|
||||
if (descriptor != null) {
|
||||
Optional<String> mainClass = descriptor.mainClass();
|
||||
if (mainClass.isPresent()) {
|
||||
Log.verbose(MessageFormat.format(I18N.getString(
|
||||
"message.module-class"),
|
||||
mainClass.get(),
|
||||
JLinkBundlerHelper.getMainModule(params)));
|
||||
return mainClass.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static String getMainModule(Map<String, ? super Object> params) {
|
||||
String result = null;
|
||||
String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
|
||||
|
||||
if (mainModule != null) {
|
||||
int index = mainModule.indexOf("/");
|
||||
|
||||
if (index > 0) {
|
||||
result = mainModule.substring(0, index);
|
||||
} else {
|
||||
result = mainModule;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void execute(Map<String, ? super Object> params,
|
||||
AbstractAppImageBuilder imageBuilder)
|
||||
throws IOException, Exception {
|
||||
@ -148,38 +70,23 @@ final class JLinkBundlerHelper {
|
||||
List<String> options =
|
||||
StandardBundlerParam.JLINK_OPTIONS.fetchFrom(params);
|
||||
Path outputDir = imageBuilder.getRuntimeRoot();
|
||||
File mainJar = getMainJar(params);
|
||||
ModFile.ModType mainJarType = ModFile.ModType.Unknown;
|
||||
|
||||
if (mainJar != null) {
|
||||
mainJarType = new ModFile(mainJar).getModType();
|
||||
} else if (StandardBundlerParam.MODULE.fetchFrom(params) == null) {
|
||||
// user specified only main class, all jars will be on the classpath
|
||||
mainJarType = ModFile.ModType.UnnamedJar;
|
||||
}
|
||||
LauncherData launcherData = StandardBundlerParam.LAUNCHER_DATA.fetchFrom(
|
||||
params);
|
||||
|
||||
boolean bindServices =
|
||||
StandardBundlerParam.BIND_SERVICES.fetchFrom(params);
|
||||
|
||||
// Modules
|
||||
String mainModule = getMainModule(params);
|
||||
if (mainModule == null) {
|
||||
if (mainJarType == ModFile.ModType.UnnamedJar) {
|
||||
if (addModules.isEmpty()) {
|
||||
// The default for an unnamed jar is ALL_DEFAULT
|
||||
addModules.add(ModuleHelper.ALL_DEFAULT);
|
||||
}
|
||||
} else if (mainJarType == ModFile.ModType.Unknown ||
|
||||
mainJarType == ModFile.ModType.ModularJar) {
|
||||
addModules.add(ModuleHelper.ALL_DEFAULT);
|
||||
}
|
||||
if (!launcherData.isModular() && addModules.isEmpty()) {
|
||||
addModules.add(ModuleHelper.ALL_DEFAULT);
|
||||
}
|
||||
|
||||
Set<String> modules = new ModuleHelper(
|
||||
modulePath, addModules, limitModules).modules();
|
||||
|
||||
if (mainModule != null) {
|
||||
modules.add(mainModule);
|
||||
if (launcherData.isModular()) {
|
||||
modules.add(launcherData.moduleName());
|
||||
}
|
||||
|
||||
runJLink(outputDir, modulePath, modules, limitModules,
|
||||
@ -188,38 +95,6 @@ final class JLinkBundlerHelper {
|
||||
imageBuilder.prepareApplicationFiles(params);
|
||||
}
|
||||
|
||||
|
||||
// Returns the path to the JDK modules in the user defined module path.
|
||||
static Path findPathOfModule( List<Path> modulePath, String moduleName) {
|
||||
|
||||
for (Path path : modulePath) {
|
||||
Path moduleNamePath = path.resolve(moduleName);
|
||||
|
||||
if (Files.exists(moduleNamePath)) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static ModuleDescriptor getMainModuleDescription(Map<String, ? super Object> params) {
|
||||
boolean hasModule = params.containsKey(StandardBundlerParam.MODULE.getID());
|
||||
if (hasModule) {
|
||||
List<Path> modulePath = StandardBundlerParam.MODULE_PATH.fetchFrom(params);
|
||||
if (!modulePath.isEmpty()) {
|
||||
ModuleFinder finder = ModuleFinder.of(modulePath.toArray(new Path[0]));
|
||||
String mainModule = JLinkBundlerHelper.getMainModule(params);
|
||||
Optional<ModuleReference> omref = finder.find(mainModule);
|
||||
if (omref.isPresent()) {
|
||||
return omref.get().descriptor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the set of modules that would be visible by default for
|
||||
* a non-modular-aware application consisting of the given elements.
|
||||
@ -255,7 +130,7 @@ final class JLinkBundlerHelper {
|
||||
.anyMatch(e -> !e.isQualified());
|
||||
}
|
||||
|
||||
private static ModuleFinder createModuleFinder(Collection<Path> modulePath) {
|
||||
static ModuleFinder createModuleFinder(Collection<Path> modulePath) {
|
||||
return ModuleFinder.compose(
|
||||
ModulePath.of(JarFile.runtimeVersion(), true,
|
||||
modulePath.toArray(Path[]::new)),
|
||||
@ -373,27 +248,14 @@ final class JLinkBundlerHelper {
|
||||
}
|
||||
|
||||
private static String getPathList(List<Path> pathList) {
|
||||
String ret = null;
|
||||
for (Path p : pathList) {
|
||||
String s = Matcher.quoteReplacement(p.toString());
|
||||
if (ret == null) {
|
||||
ret = s;
|
||||
} else {
|
||||
ret += File.pathSeparator + s;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return pathList.stream()
|
||||
.map(Path::toString)
|
||||
.map(Matcher::quoteReplacement)
|
||||
.collect(Collectors.joining(File.pathSeparator));
|
||||
}
|
||||
|
||||
private static String getStringList(Set<String> strings) {
|
||||
String ret = null;
|
||||
for (String s : strings) {
|
||||
if (ret == null) {
|
||||
ret = s;
|
||||
} else {
|
||||
ret += "," + s;
|
||||
}
|
||||
}
|
||||
return (ret == null) ? null : Matcher.quoteReplacement(ret);
|
||||
return Matcher.quoteReplacement(strings.stream().collect(
|
||||
Collectors.joining(",")));
|
||||
}
|
||||
}
|
||||
|
281
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java
Normal file
281
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* 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.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Extracts data needed to run application from parameters.
|
||||
*/
|
||||
final class LauncherData {
|
||||
boolean isModular() {
|
||||
return moduleDescriptor != null;
|
||||
}
|
||||
|
||||
String qualifiedClassName() {
|
||||
return qualifiedClassName;
|
||||
}
|
||||
|
||||
String packageName() {
|
||||
int sepIdx = qualifiedClassName.lastIndexOf('.');
|
||||
if (sepIdx < 0) {
|
||||
return "";
|
||||
}
|
||||
return qualifiedClassName.substring(sepIdx + 1);
|
||||
}
|
||||
|
||||
String moduleName() {
|
||||
verifyIsModular(true);
|
||||
return moduleDescriptor.name();
|
||||
}
|
||||
|
||||
List<Path> modulePath() {
|
||||
verifyIsModular(true);
|
||||
return modulePath;
|
||||
}
|
||||
|
||||
Path mainJarName() {
|
||||
verifyIsModular(false);
|
||||
return mainJarName;
|
||||
}
|
||||
|
||||
List<Path> classPath() {
|
||||
return classPath;
|
||||
}
|
||||
|
||||
String getAppVersion() {
|
||||
if (isModular()) {
|
||||
ModuleDescriptor.Version ver = moduleDescriptor.version().orElse(null);
|
||||
if (ver != null) {
|
||||
return ver.toString();
|
||||
}
|
||||
return moduleDescriptor.rawVersion().orElse(null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private LauncherData() {
|
||||
}
|
||||
|
||||
private void verifyIsModular(boolean isModular) {
|
||||
if ((moduleDescriptor != null) != isModular) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
static LauncherData create(Map<String, ? super Object> params) throws
|
||||
ConfigException, IOException {
|
||||
|
||||
final String mainModule = getMainModule(params);
|
||||
if (mainModule == null) {
|
||||
return createNonModular(params);
|
||||
}
|
||||
|
||||
LauncherData launcherData = new LauncherData();
|
||||
|
||||
final int sepIdx = mainModule.indexOf("/");
|
||||
final String moduleName;
|
||||
if (sepIdx > 0) {
|
||||
launcherData.qualifiedClassName = mainModule.substring(sepIdx + 1);
|
||||
moduleName = mainModule.substring(0, sepIdx);
|
||||
} else {
|
||||
moduleName = mainModule;
|
||||
}
|
||||
launcherData.modulePath = getModulePath(params);
|
||||
|
||||
launcherData.moduleDescriptor = JLinkBundlerHelper.createModuleFinder(
|
||||
launcherData.modulePath).find(moduleName).orElseThrow(
|
||||
() -> new ConfigException(MessageFormat.format(I18N.getString(
|
||||
"error.no-module-in-path"), moduleName), null)).descriptor();
|
||||
|
||||
if (launcherData.qualifiedClassName == null) {
|
||||
launcherData.qualifiedClassName = launcherData.moduleDescriptor.mainClass().orElseThrow(
|
||||
() -> new ConfigException(I18N.getString("ERR_NoMainClass"),
|
||||
null));
|
||||
}
|
||||
|
||||
launcherData.initClasspath(params);
|
||||
return launcherData;
|
||||
}
|
||||
|
||||
private static LauncherData createNonModular(
|
||||
Map<String, ? super Object> params) throws ConfigException, IOException {
|
||||
LauncherData launcherData = new LauncherData();
|
||||
|
||||
launcherData.qualifiedClassName = getMainClass(params);
|
||||
|
||||
launcherData.mainJarName = getMainJarName(params);
|
||||
if (launcherData.mainJarName == null && launcherData.qualifiedClassName
|
||||
== null) {
|
||||
throw new ConfigException(I18N.getString("error.no-main-jar-parameter"),
|
||||
null);
|
||||
}
|
||||
|
||||
Path mainJarDir = StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
|
||||
if (mainJarDir == null && launcherData.qualifiedClassName == null) {
|
||||
throw new ConfigException(I18N.getString("error.no-input-parameter"),
|
||||
null);
|
||||
}
|
||||
|
||||
final Path mainJarPath;
|
||||
if (launcherData.mainJarName != null && mainJarDir != null) {
|
||||
mainJarPath = mainJarDir.resolve(launcherData.mainJarName);
|
||||
if (!Files.exists(mainJarPath)) {
|
||||
throw new ConfigException(MessageFormat.format(I18N.getString(
|
||||
"error.main-jar-does-not-exist"),
|
||||
launcherData.mainJarName), I18N.getString(
|
||||
"error.main-jar-does-not-exist.advice"));
|
||||
}
|
||||
} else {
|
||||
mainJarPath = null;
|
||||
}
|
||||
|
||||
if (launcherData.qualifiedClassName == null) {
|
||||
if (mainJarPath == null) {
|
||||
throw new ConfigException(I18N.getString("error.no-main-class"),
|
||||
I18N.getString("error.no-main-class.advice"));
|
||||
}
|
||||
|
||||
try (JarFile jf = new JarFile(mainJarPath.toFile())) {
|
||||
Manifest m = jf.getManifest();
|
||||
Attributes attrs = (m != null) ? m.getMainAttributes() : null;
|
||||
if (attrs != null) {
|
||||
launcherData.qualifiedClassName = attrs.getValue(
|
||||
Attributes.Name.MAIN_CLASS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (launcherData.qualifiedClassName == null) {
|
||||
throw new ConfigException(MessageFormat.format(I18N.getString(
|
||||
"error.no-main-class-with-main-jar"),
|
||||
launcherData.mainJarName), MessageFormat.format(
|
||||
I18N.getString(
|
||||
"error.no-main-class-with-main-jar.advice"),
|
||||
launcherData.mainJarName));
|
||||
}
|
||||
|
||||
launcherData.initClasspath(params);
|
||||
return launcherData;
|
||||
}
|
||||
|
||||
private void initClasspath(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
Path inputDir = StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
|
||||
if (inputDir == null) {
|
||||
classPath = Collections.emptyList();
|
||||
} else {
|
||||
try (Stream<Path> walk = Files.walk(inputDir, 1)) {
|
||||
Set<Path> jars = walk.filter(Files::isRegularFile)
|
||||
.filter(file -> file.toString().endsWith(".jar"))
|
||||
.map(Path::getFileName)
|
||||
.collect(Collectors.toSet());
|
||||
jars.remove(mainJarName);
|
||||
classPath = jars.stream().sorted().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getMainClass(Map<String, ? super Object> params) {
|
||||
return getStringParam(params, Arguments.CLIOptions.APPCLASS.getId());
|
||||
}
|
||||
|
||||
private static Path getMainJarName(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
return getPathParam(params, Arguments.CLIOptions.MAIN_JAR.getId());
|
||||
}
|
||||
|
||||
private static String getMainModule(Map<String, ? super Object> params) {
|
||||
return getStringParam(params, Arguments.CLIOptions.MODULE.getId());
|
||||
}
|
||||
|
||||
private static String getStringParam(Map<String, ? super Object> params,
|
||||
String paramName) {
|
||||
Optional<Object> value = Optional.ofNullable(params.get(paramName));
|
||||
if (value.isPresent()) {
|
||||
return value.get().toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <T> T getPathParam(Map<String, ? super Object> params,
|
||||
String paramName, Supplier<T> func) throws ConfigException {
|
||||
try {
|
||||
return func.get();
|
||||
} catch (InvalidPathException ex) {
|
||||
throw new ConfigException(MessageFormat.format(I18N.getString(
|
||||
"error.not-path-parameter"), paramName,
|
||||
ex.getLocalizedMessage()), null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static Path getPathParam(Map<String, ? super Object> params,
|
||||
String paramName) throws ConfigException {
|
||||
return getPathParam(params, paramName, () -> {
|
||||
String value = getStringParam(params, paramName);
|
||||
Path result = null;
|
||||
if (value != null) {
|
||||
result = Path.of(value);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private static List<Path> getModulePath(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
return getPathListParameter(Arguments.CLIOptions.MODULE_PATH.getId(),
|
||||
params);
|
||||
}
|
||||
|
||||
private static List<Path> getPathListParameter(String paramName,
|
||||
Map<String, ? super Object> params) throws ConfigException {
|
||||
return getPathParam(params, paramName, () -> {
|
||||
String value = params.getOrDefault(paramName, "").toString();
|
||||
return List.of(value.split(File.pathSeparator)).stream()
|
||||
.map(Path::of)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
});
|
||||
}
|
||||
|
||||
private String qualifiedClassName;
|
||||
private Path mainJarName;
|
||||
private List<Path> classPath;
|
||||
private List<Path> modulePath;
|
||||
private ModuleDescriptor moduleDescriptor;
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
final class ModFile {
|
||||
private final String filename;
|
||||
private final ModType moduleType;
|
||||
|
||||
enum JarType {All, UnnamedJar, ModularJar}
|
||||
enum ModType {
|
||||
Unknown, UnnamedJar, ModularJar, Jmod, ExplodedModule}
|
||||
|
||||
ModFile(File aFile) {
|
||||
super();
|
||||
filename = aFile.getPath();
|
||||
moduleType = getModType(aFile);
|
||||
}
|
||||
|
||||
String getModName() {
|
||||
File file = new File(getFileName());
|
||||
// do not try to remove extension for directories
|
||||
return moduleType == ModType.ExplodedModule ?
|
||||
file.getName() : getFileWithoutExtension(file.getName());
|
||||
}
|
||||
|
||||
String getFileName() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
ModType getModType() {
|
||||
return moduleType;
|
||||
}
|
||||
|
||||
private static ModType getModType(File aFile) {
|
||||
ModType result = ModType.Unknown;
|
||||
String filename = aFile.getAbsolutePath();
|
||||
|
||||
if (aFile.isFile()) {
|
||||
if (filename.endsWith(".jmod")) {
|
||||
result = ModType.Jmod;
|
||||
}
|
||||
else if (filename.endsWith(".jar")) {
|
||||
JarType status = isModularJar(filename);
|
||||
|
||||
if (status == JarType.ModularJar) {
|
||||
result = ModType.ModularJar;
|
||||
}
|
||||
else if (status == JarType.UnnamedJar) {
|
||||
result = ModType.UnnamedJar;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (aFile.isDirectory()) {
|
||||
File moduleInfo = new File(
|
||||
filename + File.separator + "module-info.class");
|
||||
|
||||
if (moduleInfo.exists()) {
|
||||
result = ModType.ExplodedModule;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JarType isModularJar(String FileName) {
|
||||
JarType result = JarType.All;
|
||||
|
||||
try (ZipInputStream zip =
|
||||
new ZipInputStream(new FileInputStream(FileName))) {
|
||||
result = JarType.UnnamedJar;
|
||||
|
||||
for (ZipEntry entry = zip.getNextEntry(); entry != null;
|
||||
entry = zip.getNextEntry()) {
|
||||
if (entry.getName().matches("module-info.class")) {
|
||||
result = JarType.ModularJar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String getFileWithoutExtension(String FileName) {
|
||||
return FileName.replaceFirst("[.][^.]+$", "");
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* RelativeFileSet
|
||||
*
|
||||
* A class encapsulating a directory and a set of files within it.
|
||||
*/
|
||||
class RelativeFileSet {
|
||||
|
||||
private File basedir;
|
||||
private Set<String> files = new LinkedHashSet<>();
|
||||
|
||||
RelativeFileSet(File base, Collection<File> files) {
|
||||
basedir = base;
|
||||
String baseAbsolute = basedir.getAbsolutePath();
|
||||
for (File f: files) {
|
||||
String absolute = f.getAbsolutePath();
|
||||
if (!absolute.startsWith(baseAbsolute)) {
|
||||
throw new RuntimeException("File " + f.getAbsolutePath() +
|
||||
" does not belong to " + baseAbsolute);
|
||||
}
|
||||
if (!absolute.equals(baseAbsolute)) {
|
||||
// possible in jpackage case
|
||||
this.files.add(absolute.substring(baseAbsolute.length()+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RelativeFileSet(File base, Set<File> files) {
|
||||
this(base, (Collection<File>) files);
|
||||
}
|
||||
|
||||
File getBaseDirectory() {
|
||||
return basedir;
|
||||
}
|
||||
|
||||
Set<String> getIncludedFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (files.size() == 1) {
|
||||
return "" + basedir + File.pathSeparator + files;
|
||||
}
|
||||
return "RelativeFileSet {basedir:" + basedir
|
||||
+ ", files: {" + files + "}";
|
||||
}
|
||||
|
||||
}
|
380
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java
380
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java
@ -65,8 +65,6 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
|
||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||
"jdk.incubator.jpackage.internal.resources.MainResources");
|
||||
private static final String JAVABASEJMOD = "java.base.jmod";
|
||||
private final static String DEFAULT_VERSION = "1.0";
|
||||
private final static String DEFAULT_RELEASE = "1";
|
||||
@ -86,67 +84,36 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
this.stringConverter = stringConverter;
|
||||
}
|
||||
|
||||
static final StandardBundlerParam<RelativeFileSet> APP_RESOURCES =
|
||||
static final StandardBundlerParam<LauncherData> LAUNCHER_DATA =
|
||||
new StandardBundlerParam<>(
|
||||
BundleParams.PARAM_APP_RESOURCES,
|
||||
RelativeFileSet.class,
|
||||
null, // no default. Required parameter
|
||||
null // no string translation,
|
||||
// tool must provide complex type
|
||||
"launcherData",
|
||||
LauncherData.class,
|
||||
params -> {
|
||||
try {
|
||||
return LauncherData.create(params);
|
||||
} catch (ConfigException | IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
},
|
||||
null
|
||||
);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final
|
||||
StandardBundlerParam<List<RelativeFileSet>> APP_RESOURCES_LIST =
|
||||
new StandardBundlerParam<>(
|
||||
BundleParams.PARAM_APP_RESOURCES + "List",
|
||||
(Class<List<RelativeFileSet>>) (Object) List.class,
|
||||
// Default is appResources, as a single item list
|
||||
p -> new ArrayList<>(Collections.singletonList(
|
||||
APP_RESOURCES.fetchFrom(p))),
|
||||
StandardBundlerParam::createAppResourcesListFromString
|
||||
);
|
||||
|
||||
static final StandardBundlerParam<String> SOURCE_DIR =
|
||||
static final StandardBundlerParam<Path> SOURCE_DIR =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.INPUT.getId(),
|
||||
String.class,
|
||||
Path.class,
|
||||
p -> null,
|
||||
(s, p) -> {
|
||||
String value = String.valueOf(s);
|
||||
if (value.charAt(value.length() - 1) ==
|
||||
File.separatorChar) {
|
||||
return value.substring(0, value.length() - 1);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
(s, p) -> Path.of(s)
|
||||
);
|
||||
|
||||
// note that each bundler is likely to replace this one with
|
||||
// their own converter
|
||||
static final StandardBundlerParam<RelativeFileSet> MAIN_JAR =
|
||||
static final StandardBundlerParam<Path> MAIN_JAR =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.MAIN_JAR.getId(),
|
||||
RelativeFileSet.class,
|
||||
params -> {
|
||||
extractMainClassInfoFromAppResources(params);
|
||||
return (RelativeFileSet) params.get("mainJar");
|
||||
},
|
||||
(s, p) -> getMainJar(s, p)
|
||||
);
|
||||
|
||||
static final StandardBundlerParam<String> CLASSPATH =
|
||||
new StandardBundlerParam<>(
|
||||
"classpath",
|
||||
String.class,
|
||||
params -> {
|
||||
extractMainClassInfoFromAppResources(params);
|
||||
String cp = (String) params.get("classpath");
|
||||
return cp == null ? "" : cp;
|
||||
},
|
||||
(s, p) -> s
|
||||
Path.class,
|
||||
params -> LAUNCHER_DATA.fetchFrom(params).mainJarName(),
|
||||
null
|
||||
);
|
||||
|
||||
static final StandardBundlerParam<String> MAIN_CLASS =
|
||||
@ -157,14 +124,7 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
if (isRuntimeInstaller(params)) {
|
||||
return null;
|
||||
}
|
||||
extractMainClassInfoFromAppResources(params);
|
||||
String s = (String) params.get(
|
||||
BundleParams.PARAM_APPLICATION_CLASS);
|
||||
if (s == null) {
|
||||
s = JLinkBundlerHelper.getMainClassFromModule(
|
||||
params);
|
||||
}
|
||||
return s;
|
||||
return LAUNCHER_DATA.fetchFrom(params).qualifiedClassName();
|
||||
},
|
||||
(s, p) -> s
|
||||
);
|
||||
@ -253,13 +213,11 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
(s, p) -> Arrays.asList(s.split("\n\n"))
|
||||
);
|
||||
|
||||
// note that each bundler is likely to replace this one with
|
||||
// their own converter
|
||||
static final StandardBundlerParam<String> VERSION =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.VERSION.getId(),
|
||||
String.class,
|
||||
params -> getDefaultAppVersion(params),
|
||||
StandardBundlerParam::getDefaultAppVersion,
|
||||
(s, p) -> s
|
||||
);
|
||||
|
||||
@ -414,19 +372,12 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.MODULE_PATH.getId(),
|
||||
(Class<List<Path>>) (Object)List.class,
|
||||
p -> { return getDefaultModulePath(); },
|
||||
p -> getDefaultModulePath(),
|
||||
(s, p) -> {
|
||||
List<Path> modulePath = Arrays.asList(s
|
||||
.split(File.pathSeparator)).stream()
|
||||
.map(ss -> new File(ss).toPath())
|
||||
List<Path> modulePath = Stream.of(s.split(File.pathSeparator))
|
||||
.map(Path::of)
|
||||
.collect(Collectors.toList());
|
||||
Path javaBasePath = null;
|
||||
if (modulePath != null) {
|
||||
javaBasePath = JLinkBundlerHelper
|
||||
.findPathOfModule(modulePath, JAVABASEJMOD);
|
||||
} else {
|
||||
modulePath = new ArrayList<Path>();
|
||||
}
|
||||
Path javaBasePath = findPathOfModule(modulePath, JAVABASEJMOD);
|
||||
|
||||
// Add the default JDK module path to the module path.
|
||||
if (javaBasePath == null) {
|
||||
@ -434,9 +385,7 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
|
||||
if (jdkModulePath != null) {
|
||||
modulePath.addAll(jdkModulePath);
|
||||
javaBasePath =
|
||||
JLinkBundlerHelper.findPathOfModule(
|
||||
modulePath, JAVABASEJMOD);
|
||||
javaBasePath = findPathOfModule(modulePath, JAVABASEJMOD);
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,6 +398,20 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
return modulePath;
|
||||
});
|
||||
|
||||
// Returns the path to the JDK modules in the user defined module path.
|
||||
private static Path findPathOfModule( List<Path> modulePath, String moduleName) {
|
||||
|
||||
for (Path path : modulePath) {
|
||||
Path moduleNamePath = path.resolve(moduleName);
|
||||
|
||||
if (Files.exists(moduleNamePath)) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static final BundlerParamInfo<String> MODULE =
|
||||
new StandardBundlerParam<>(
|
||||
Arguments.CLIOptions.MODULE.getId(),
|
||||
@ -496,16 +459,13 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
}
|
||||
|
||||
static File getPredefinedAppImage(Map<String, ? super Object> params) {
|
||||
File applicationImage = null;
|
||||
if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) {
|
||||
applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params);
|
||||
if (!applicationImage.exists()) {
|
||||
throw new RuntimeException(
|
||||
MessageFormat.format(I18N.getString(
|
||||
"message.app-image-dir-does-not-exist"),
|
||||
PREDEFINED_APP_IMAGE.getID(),
|
||||
applicationImage.toString()));
|
||||
}
|
||||
File applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params);
|
||||
if (applicationImage != null && !applicationImage.exists()) {
|
||||
throw new RuntimeException(
|
||||
MessageFormat.format(I18N.getString(
|
||||
"message.app-image-dir-does-not-exist"),
|
||||
PREDEFINED_APP_IMAGE.getID(),
|
||||
applicationImage.toString()));
|
||||
}
|
||||
return applicationImage;
|
||||
}
|
||||
@ -548,236 +508,36 @@ class StandardBundlerParam<T> extends BundlerParamInfo<T> {
|
||||
appBuilder.prepareApplicationFiles(params);
|
||||
}
|
||||
|
||||
static void extractMainClassInfoFromAppResources(
|
||||
Map<String, ? super Object> params) {
|
||||
boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
|
||||
boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
|
||||
boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
|
||||
boolean hasModule = params.containsKey(MODULE.getID());
|
||||
|
||||
if (hasMainClass && hasMainJar && hasMainJarClassPath || hasModule ||
|
||||
isRuntimeInstaller(params)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// it's a pair.
|
||||
// The [0] is the srcdir [1] is the file relative to sourcedir
|
||||
List<String[]> filesToCheck = new ArrayList<>();
|
||||
|
||||
if (hasMainJar) {
|
||||
RelativeFileSet rfs = MAIN_JAR.fetchFrom(params);
|
||||
for (String s : rfs.getIncludedFiles()) {
|
||||
filesToCheck.add(
|
||||
new String[] {rfs.getBaseDirectory().toString(), s});
|
||||
}
|
||||
} else if (hasMainJarClassPath) {
|
||||
for (String s : CLASSPATH.fetchFrom(params).split("\\s+")) {
|
||||
if (APP_RESOURCES.fetchFrom(params) != null) {
|
||||
filesToCheck.add(
|
||||
new String[] {APP_RESOURCES.fetchFrom(params)
|
||||
.getBaseDirectory().toString(), s});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<RelativeFileSet> rfsl = APP_RESOURCES_LIST.fetchFrom(params);
|
||||
if (rfsl == null || rfsl.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (RelativeFileSet rfs : rfsl) {
|
||||
if (rfs == null) continue;
|
||||
|
||||
for (String s : rfs.getIncludedFiles()) {
|
||||
filesToCheck.add(
|
||||
new String[]{rfs.getBaseDirectory().toString(), s});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// presume the set iterates in-order
|
||||
for (String[] fnames : filesToCheck) {
|
||||
try {
|
||||
// only sniff jars
|
||||
if (!fnames[1].toLowerCase().endsWith(".jar")) continue;
|
||||
|
||||
File file = new File(fnames[0], fnames[1]);
|
||||
// that actually exist
|
||||
if (!file.exists()) continue;
|
||||
|
||||
try (JarFile jf = new JarFile(file)) {
|
||||
Manifest m = jf.getManifest();
|
||||
Attributes attrs = (m != null) ?
|
||||
m.getMainAttributes() : null;
|
||||
|
||||
if (attrs != null) {
|
||||
if (!hasMainJar) {
|
||||
if (fnames[0] == null) {
|
||||
fnames[0] = file.getParentFile().toString();
|
||||
}
|
||||
params.put(MAIN_JAR.getID(), new RelativeFileSet(
|
||||
new File(fnames[0]),
|
||||
new LinkedHashSet<>(Collections
|
||||
.singletonList(file))));
|
||||
}
|
||||
if (!hasMainJarClassPath) {
|
||||
String cp =
|
||||
attrs.getValue(Attributes.Name.CLASS_PATH);
|
||||
params.put(CLASSPATH.getID(),
|
||||
cp == null ? "" : cp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
ignore.printStackTrace();
|
||||
}
|
||||
}
|
||||
private static List<Path> getDefaultModulePath() {
|
||||
return List.of(
|
||||
Path.of(System.getProperty("java.home"), "jmods").toAbsolutePath());
|
||||
}
|
||||
|
||||
static void validateMainClassInfoFromAppResources(
|
||||
Map<String, ? super Object> params) throws ConfigException {
|
||||
boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
|
||||
boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
|
||||
boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
|
||||
boolean hasModule = params.containsKey(MODULE.getID());
|
||||
boolean hasAppImage = params.containsKey(PREDEFINED_APP_IMAGE.getID());
|
||||
|
||||
if (hasMainClass && hasMainJar && hasMainJarClassPath ||
|
||||
hasAppImage || isRuntimeInstaller(params)) {
|
||||
return;
|
||||
}
|
||||
if (hasModule) {
|
||||
if (JLinkBundlerHelper.getMainClassFromModule(params) == null) {
|
||||
throw new ConfigException(
|
||||
I18N.getString("ERR_NoMainClass"), null);
|
||||
}
|
||||
} else {
|
||||
extractMainClassInfoFromAppResources(params);
|
||||
|
||||
if (!params.containsKey(MAIN_CLASS.getID())) {
|
||||
if (hasMainJar) {
|
||||
throw new ConfigException(
|
||||
MessageFormat.format(I18N.getString(
|
||||
"error.no-main-class-with-main-jar"),
|
||||
MAIN_JAR.fetchFrom(params)),
|
||||
MessageFormat.format(I18N.getString(
|
||||
"error.no-main-class-with-main-jar.advice"),
|
||||
MAIN_JAR.fetchFrom(params)));
|
||||
} else {
|
||||
throw new ConfigException(
|
||||
I18N.getString("error.no-main-class"),
|
||||
I18N.getString("error.no-main-class.advice"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<RelativeFileSet>
|
||||
createAppResourcesListFromString(String s,
|
||||
Map<String, ? super Object> objectObjectMap) {
|
||||
List<RelativeFileSet> result = new ArrayList<>();
|
||||
for (String path : s.split("[:;]")) {
|
||||
File f = new File(path);
|
||||
if (f.getName().equals("*") || path.endsWith("/") ||
|
||||
path.endsWith("\\")) {
|
||||
if (f.getName().equals("*")) {
|
||||
f = f.getParentFile();
|
||||
}
|
||||
Set<File> theFiles = new HashSet<>();
|
||||
try {
|
||||
try (Stream<Path> stream = Files.walk(f.toPath())) {
|
||||
stream.filter(Files::isRegularFile)
|
||||
.forEach(p -> theFiles.add(p.toFile()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
result.add(new RelativeFileSet(f, theFiles));
|
||||
} else {
|
||||
result.add(new RelativeFileSet(f.getParentFile(),
|
||||
Collections.singleton(f)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static RelativeFileSet getMainJar(
|
||||
String mainJarValue, Map<String, ? super Object> params) {
|
||||
for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(params)) {
|
||||
File appResourcesRoot = rfs.getBaseDirectory();
|
||||
File mainJarFile = new File(appResourcesRoot, mainJarValue);
|
||||
|
||||
if (mainJarFile.exists()) {
|
||||
return new RelativeFileSet(appResourcesRoot,
|
||||
new LinkedHashSet<>(Collections.singletonList(
|
||||
mainJarFile)));
|
||||
}
|
||||
mainJarFile = new File(mainJarValue);
|
||||
if (mainJarFile.exists()) {
|
||||
// absolute path for main-jar may fail is not legal
|
||||
// below contains explicit error message.
|
||||
} else {
|
||||
List<Path> modulePath = MODULE_PATH.fetchFrom(params);
|
||||
modulePath.removeAll(getDefaultModulePath());
|
||||
if (!modulePath.isEmpty()) {
|
||||
Path modularJarPath = JLinkBundlerHelper.findPathOfModule(
|
||||
modulePath, mainJarValue);
|
||||
if (modularJarPath != null &&
|
||||
Files.exists(modularJarPath)) {
|
||||
return new RelativeFileSet(appResourcesRoot,
|
||||
new LinkedHashSet<>(Collections.singletonList(
|
||||
modularJarPath.toFile())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
new ConfigException(MessageFormat.format(I18N.getString(
|
||||
"error.main-jar-does-not-exist"),
|
||||
mainJarValue), I18N.getString(
|
||||
"error.main-jar-does-not-exist.advice")));
|
||||
}
|
||||
|
||||
static List<Path> getDefaultModulePath() {
|
||||
List<Path> result = new ArrayList<Path>();
|
||||
Path jdkModulePath = Paths.get(
|
||||
System.getProperty("java.home"), "jmods").toAbsolutePath();
|
||||
|
||||
if (jdkModulePath != null && Files.exists(jdkModulePath)) {
|
||||
result.add(jdkModulePath);
|
||||
}
|
||||
else {
|
||||
// On a developer build the JDK Home isn't where we expect it
|
||||
// relative to the jmods directory. Do some extra
|
||||
// processing to find it.
|
||||
Map<String, String> env = System.getenv();
|
||||
|
||||
if (env.containsKey("JDK_HOME")) {
|
||||
jdkModulePath = Paths.get(env.get("JDK_HOME"),
|
||||
".." + File.separator + "images"
|
||||
+ File.separator + "jmods").toAbsolutePath();
|
||||
|
||||
if (jdkModulePath != null && Files.exists(jdkModulePath)) {
|
||||
result.add(jdkModulePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static String getDefaultAppVersion(Map<String, ? super Object> params) {
|
||||
private static String getDefaultAppVersion(Map<String, ? super Object> params) {
|
||||
String appVersion = DEFAULT_VERSION;
|
||||
|
||||
ModuleDescriptor descriptor = JLinkBundlerHelper.getMainModuleDescription(params);
|
||||
if (descriptor != null) {
|
||||
Optional<Version> oversion = descriptor.version();
|
||||
if (oversion.isPresent()) {
|
||||
if (isRuntimeInstaller(params)) {
|
||||
return appVersion;
|
||||
}
|
||||
|
||||
LauncherData launcherData = null;
|
||||
try {
|
||||
launcherData = LAUNCHER_DATA.fetchFrom(params);
|
||||
} catch (RuntimeException ex) {
|
||||
if (ex.getCause() instanceof ConfigException) {
|
||||
return appVersion;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (launcherData.isModular()) {
|
||||
String moduleVersion = launcherData.getAppVersion();
|
||||
if (moduleVersion != null) {
|
||||
Log.verbose(MessageFormat.format(I18N.getString(
|
||||
"message.module-version"),
|
||||
oversion.get().toString(),
|
||||
JLinkBundlerHelper.getMainModule(params)));
|
||||
appVersion = oversion.get().toString();
|
||||
moduleVersion,
|
||||
launcherData.moduleName()));
|
||||
appVersion = moduleVersion;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,10 @@ error.no-main-class=A main class was not specified nor was one found in the supp
|
||||
error.no-main-class.advice=Please specify a application class or ensure that the appResources has a jar containing one in the manifest
|
||||
error.main-jar-does-not-exist=The configured main jar does not exist {0} in the input directory
|
||||
error.main-jar-does-not-exist.advice=The main jar must be specified relative to the input directory (not an absolute path), and must exist within that directory
|
||||
error.no-module-in-path="Failed to find {0} module in module path"
|
||||
error.not-path-parameter="Invalid value of {0} parameter: {1}"
|
||||
error.no-input-parameter="Missing --input parameter for non modular application"
|
||||
error.no-main-jar-parameter="Missing --main-jar parameter for non modular application"
|
||||
|
||||
error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
|
||||
error.no-content-types-for-file-association.advice=Specify MIME type for File Association number {0}
|
||||
@ -69,7 +73,6 @@ error.tool-old-version.advice=Please install {0} {1} or newer
|
||||
error.jlink.failed=jlink failed with: {0}
|
||||
error.blocked.option=jlink option [{0}] is not permitted in --jlink-options
|
||||
|
||||
warning.module.does.not.exist=Module [{0}] does not exist
|
||||
warning.no.jdk.modules.found=Warning: No JDK Modules found
|
||||
warning.deprecation=Warning: Option "{0}" is deprecated and may be removed in a future release
|
||||
|
||||
|
@ -56,6 +56,10 @@ error.no-main-class=\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u304C\u6307\u5B9A
|
||||
error.no-main-class.advice=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30AF\u30E9\u30B9\u3092\u6307\u5B9A\u3059\u308B\u304B\u3001\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u3067appResources\u306B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30AF\u30E9\u30B9\u3092\u542B\u3080jar\u304C\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044
|
||||
error.main-jar-does-not-exist=\u5165\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u3001\u69CB\u6210\u3055\u308C\u305F\u30E1\u30A4\u30F3jar\u304C{0}\u306B\u5B58\u5728\u3057\u307E\u305B\u3093
|
||||
error.main-jar-does-not-exist.advice=\u5165\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5BFE\u3057\u3066\u76F8\u5BFE\u7684\u306B(\u7D76\u5BFE\u30D1\u30B9\u3067\u306F\u306A\u3044)\u30E1\u30A4\u30F3jar\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u3001\u305D\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u5185\u306B\u5B58\u5728\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
|
||||
error.no-module-in-path="Failed to find {0} module in module path"
|
||||
error.not-path-parameter="Invalid value of {0} parameter: {1}"
|
||||
error.no-input-parameter="Missing --input parameter for non modular application"
|
||||
error.no-main-jar-parameter="Missing --main-jar parameter for non modular application"
|
||||
|
||||
error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
|
||||
error.no-content-types-for-file-association.advice=Specify MIME type for File Association number {0}
|
||||
@ -69,7 +73,6 @@ error.tool-old-version.advice={0} {1}\u4EE5\u964D\u3092\u30A4\u30F3\u30B9\u30C8\
|
||||
error.jlink.failed=jlink\u304C\u6B21\u3067\u5931\u6557\u3057\u307E\u3057\u305F: {0}
|
||||
error.blocked.option=jlink option [{0}] is not permitted in --jlink-options
|
||||
|
||||
warning.module.does.not.exist=\u30E2\u30B8\u30E5\u30FC\u30EB[{0}]\u306F\u5B58\u5728\u3057\u307E\u305B\u3093
|
||||
warning.no.jdk.modules.found=\u8B66\u544A: JDK\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
|
||||
warning.deprecation=Warning: Option "{0}" is deprecated and may be removed in a future release
|
||||
|
||||
|
@ -56,6 +56,10 @@ error.no-main-class=\u672A\u6307\u5B9A\u4E3B\u7C7B\uFF0C\u5728\u63D0\u4F9B\u7684
|
||||
error.no-main-class.advice=\u8BF7\u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u7C7B\uFF0C\u6216\u8005\u786E\u4FDD appResources \u4E2D\u6709\u4E00\u4E2A jar \u5728\u6E05\u5355\u4E2D\u5305\u542B\u5E94\u7528\u7A0B\u5E8F\u7C7B\u3002
|
||||
error.main-jar-does-not-exist=\u914D\u7F6E\u7684\u4E3B jar \u5728\u8F93\u5165\u76EE\u5F55\u4E2D\u4E0D\u5B58\u5728 {0}
|
||||
error.main-jar-does-not-exist.advice=\u5FC5\u987B\u4F7F\u7528\u76F8\u5BF9\u4E8E\u8F93\u5165\u76EE\u5F55\u7684\u8DEF\u5F84\uFF08\u4E0D\u4F7F\u7528\u7EDD\u5BF9\u8DEF\u5F84\uFF09\u6307\u5B9A\u4E3B jar \uFF0C\u5E76\u4E14\u8BE5\u76EE\u5F55\u4E2D\u5B58\u5728\u4E3B jar
|
||||
error.no-module-in-path="Failed to find {0} module in module path"
|
||||
error.not-path-parameter="Invalid value of {0} parameter: {1}"
|
||||
error.no-input-parameter="Missing --input parameter for non modular application"
|
||||
error.no-main-jar-parameter="Missing --main-jar parameter for non modular application"
|
||||
|
||||
error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
|
||||
error.no-content-types-for-file-association.advice=Specify MIME type for File Association number {0}
|
||||
@ -69,7 +73,6 @@ error.tool-old-version.advice=\u8BF7\u5B89\u88C5 {0} {1}\u6216\u66F4\u65B0\u7248
|
||||
error.jlink.failed=jlink \u5931\u8D25\uFF0C\u51FA\u73B0 {0}
|
||||
error.blocked.option=jlink option [{0}] is not permitted in --jlink-options
|
||||
|
||||
warning.module.does.not.exist=\u6A21\u5757 [{0}] \u4E0D\u5B58\u5728
|
||||
warning.no.jdk.modules.found=\u8B66\u544A: \u672A\u627E\u5230 JDK \u6A21\u5757
|
||||
warning.deprecation=Warning: Option "{0}" is deprecated and may be removed in a future release
|
||||
|
||||
|
@ -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
|
||||
@ -226,6 +226,8 @@ public class WinMsiBundler extends AbstractBundler {
|
||||
public boolean validate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
try {
|
||||
APP_BUNDLER.fetchFrom(params).validate(params);
|
||||
|
||||
if (wixToolset == null) {
|
||||
wixToolset = WixTool.toolset();
|
||||
}
|
||||
|
@ -192,22 +192,4 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
executableFile.toFile().setExecutable(true);
|
||||
executableFile.toFile().setReadOnly();
|
||||
}
|
||||
|
||||
private void copyApplication(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
List<RelativeFileSet> appResourcesList =
|
||||
APP_RESOURCES_LIST.fetchFrom(params);
|
||||
if (appResourcesList == null) {
|
||||
throw new RuntimeException("Null app resources?");
|
||||
}
|
||||
for (RelativeFileSet appResources : appResourcesList) {
|
||||
if (appResources == null) {
|
||||
throw new RuntimeException("Null app resources?");
|
||||
}
|
||||
File srcdir = appResources.getBaseDirectory();
|
||||
for (String fname : appResources.getIncludedFiles()) {
|
||||
copyEntry(appDir, srcdir, fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -45,9 +45,9 @@ public class AppImageFileTest {
|
||||
@Test
|
||||
public void testIdentity() throws IOException {
|
||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
||||
params.put("name", "Foo");
|
||||
params.put("app-version", "2.3");
|
||||
params.put("description", "Duck is the King");
|
||||
params.put(Arguments.CLIOptions.NAME.getId(), "Foo");
|
||||
params.put(Arguments.CLIOptions.VERSION.getId(), "2.3");
|
||||
params.put(Arguments.CLIOptions.DESCRIPTION.getId(), "Duck is the King");
|
||||
AppImageFile aif = create(params);
|
||||
|
||||
Assert.assertEquals("Foo", aif.getLauncherName());
|
||||
@ -61,11 +61,13 @@ public class AppImageFileTest {
|
||||
// We should be ready to handle curious minds.
|
||||
Map<String, ? super Object> params = new LinkedHashMap<>();
|
||||
params.put("invalidParamName", "randomStringValue");
|
||||
params.put(Arguments.CLIOptions.APPCLASS.getId(), "TestClass");
|
||||
params.put(Arguments.CLIOptions.MAIN_JAR.getId(), "test.jar");
|
||||
create(params);
|
||||
|
||||
params = new LinkedHashMap<>();
|
||||
params.put("name", "foo");
|
||||
params.put("app-version", "");
|
||||
params.put(Arguments.CLIOptions.NAME.getId(), "foo");
|
||||
params.put(Arguments.CLIOptions.VERSION.getId(), "");
|
||||
create(params);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
@ -119,7 +119,6 @@ public class DeployParamsTest {
|
||||
params = new DeployParams();
|
||||
|
||||
params.setOutput(testRoot);
|
||||
params.addResource(testRoot, new File(testRoot, "test.jar"));
|
||||
params.addBundleArgument(Arguments.CLIOptions.APPCLASS.getId(),
|
||||
"TestClass");
|
||||
params.addBundleArgument(Arguments.CLIOptions.MAIN_JAR.getId(),
|
||||
|
@ -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
|
||||
@ -123,7 +123,7 @@ public final class ModulePathTest {
|
||||
expectedErrorMessage = "Error: Missing argument: --runtime-image or --module-path";
|
||||
} else {
|
||||
expectedErrorMessage = String.format(
|
||||
"Error: Module %s not found", appDesc.moduleName());
|
||||
"Failed to find %s module in module path", appDesc.moduleName());
|
||||
}
|
||||
|
||||
List<String> output = cmd
|
||||
|
Loading…
x
Reference in New Issue
Block a user