< prev index next >
modules/fxpackager/src/main/java/com/oracle/tools/packager/windows/WinAppBundler.java
Print this page
rev 9619 : imported patch 9-jake-fxpackager.patch
*** 25,106 ****
package com.oracle.tools.packager.windows;
import com.oracle.tools.packager.AbstractImageBundler;
import com.oracle.tools.packager.BundlerParamInfo;
- import com.oracle.tools.packager.StandardBundlerParam;
- import com.oracle.tools.packager.Log;
import com.oracle.tools.packager.ConfigException;
import com.oracle.tools.packager.IOUtils;
import com.oracle.tools.packager.RelativeFileSet;
import com.oracle.tools.packager.UnsupportedPlatformException;
! import java.io.*;
! import java.net.MalformedURLException;
! import java.net.URL;
! import java.nio.file.Files;
import java.text.MessageFormat;
! import java.util.*;
! import java.util.concurrent.atomic.AtomicReference;
! import java.util.regex.Pattern;
import static com.oracle.tools.packager.StandardBundlerParam.*;
! import static com.oracle.tools.packager.windows.WindowsBundlerParam.BIT_ARCH_64;
! import static com.oracle.tools.packager.windows.WindowsBundlerParam.BIT_ARCH_64_RUNTIME;
! import static com.oracle.tools.packager.windows.WindowsBundlerParam.WIN_RUNTIME;
public class WinAppBundler extends AbstractImageBundler {
private static final ResourceBundle I18N =
ResourceBundle.getBundle(WinAppBundler.class.getName());
- public static final BundlerParamInfo<File> CONFIG_ROOT = new WindowsBundlerParam<>(
- I18N.getString("param.config-root.name"),
- I18N.getString("param.config-root.description"),
- "configRoot",
- File.class,
- params -> {
- File imagesRoot = new File(BUILD_ROOT.fetchFrom(params), "windows");
- imagesRoot.mkdirs();
- return imagesRoot;
- },
- (s, p) -> null);
-
- private final static String EXECUTABLE_NAME = "WinLauncher.exe";
- private final static String LIBRARY_NAME = "packager.dll";
-
- private final static String[] VS_VERS = {"100", "110", "120"};
- private final static String REDIST_MSVCR = "msvcrVS_VER.dll";
- private final static String REDIST_MSVCP = "msvcpVS_VER.dll";
-
private static final String TOOL_ICON_SWAP="IconSwap.exe";
- private static final String TOOL_VERSION_INFO_SWAP="VersionInfoSwap.exe";
-
- private static final String EXECUTABLE_PROPERTIES_TEMPLATE = "WinLauncher.properties";
-
- public static final BundlerParamInfo<URL> RAW_EXECUTABLE_URL = new WindowsBundlerParam<>(
- I18N.getString("param.raw-executable-url.name"),
- I18N.getString("param.raw-executable-url.description"),
- "win.launcher.url",
- URL.class,
- params -> WinResources.class.getResource(EXECUTABLE_NAME),
- (s, p) -> {
- try {
- return new URL(s);
- } catch (MalformedURLException e) {
- Log.info(e.toString());
- return null;
- }
- });
-
- public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE = new WindowsBundlerParam<>(
- I18N.getString("param.rebrand-executable.name"),
- I18N.getString("param.rebrand-executable.description"),
- "win.launcher.rebrand",
- Boolean.class,
- params -> Boolean.TRUE,
- (s, p) -> Boolean.valueOf(s));
public static final BundlerParamInfo<File> ICON_ICO = new StandardBundlerParam<>(
I18N.getString("param.icon-ico.name"),
I18N.getString("param.icon-ico.description"),
"icon.ico",
--- 25,63 ----
package com.oracle.tools.packager.windows;
import com.oracle.tools.packager.AbstractImageBundler;
import com.oracle.tools.packager.BundlerParamInfo;
import com.oracle.tools.packager.ConfigException;
import com.oracle.tools.packager.IOUtils;
+ import com.oracle.tools.packager.JLinkBundlerHelper;
+ import com.oracle.tools.packager.Log;
import com.oracle.tools.packager.RelativeFileSet;
+ import com.oracle.tools.packager.StandardBundlerParam;
import com.oracle.tools.packager.UnsupportedPlatformException;
+ import jdk.packager.builders.windows.WindowsAppImageBuilder;
+ import jdk.tools.jlink.builder.ImageBuilder;
! import java.io.ByteArrayOutputStream;
! import java.io.File;
! import java.io.IOException;
! import java.io.PrintStream;
import java.text.MessageFormat;
! import java.util.Arrays;
! import java.util.Collection;
! import java.util.Map;
! import java.util.ResourceBundle;
import static com.oracle.tools.packager.StandardBundlerParam.*;
! import static com.oracle.tools.packager.windows.WindowsBundlerParam.*;
public class WinAppBundler extends AbstractImageBundler {
private static final ResourceBundle I18N =
ResourceBundle.getBundle(WinAppBundler.class.getName());
private static final String TOOL_ICON_SWAP="IconSwap.exe";
public static final BundlerParamInfo<File> ICON_ICO = new StandardBundlerParam<>(
I18N.getString("param.icon-ico.name"),
I18N.getString("param.icon-ico.description"),
"icon.ico",
*** 121,134 ****
}
public final static String WIN_BUNDLER_PREFIX =
BUNDLER_PREFIX + "windows/";
- File getConfigRoot(Map<String, ? super Object> params) {
- return CONFIG_ROOT.fetchFrom(params);
- }
-
@Override
public boolean validate(Map<String, ? super Object> params) throws UnsupportedPlatformException, ConfigException {
try {
if (params == null) throw new ConfigException(
I18N.getString("error.parameters-null"),
--- 78,87 ----
*** 151,177 ****
throw new UnsupportedPlatformException();
}
imageBundleValidation(p);
! if (WinResources.class.getResource(TOOL_ICON_SWAP) == null ||
! WinResources.class.getResource(TOOL_VERSION_INFO_SWAP) == null)
! {
throw new ConfigException(
I18N.getString("error.no-windows-resources"),
I18N.getString("error.no-windows-resources.advice"));
}
- //validate required inputs
- testRuntime(WIN_RUNTIME.fetchFrom(p), new String[] {
- "bin\\\\[^\\\\]+\\\\jvm.dll", // most reliable
- "lib\\\\rt.jar", // fallback canary for JDK 8
- });
- if (USE_FX_PACKAGING.fetchFrom(p)) {
- testRuntime(WIN_RUNTIME.fetchFrom(p), new String[] {"lib\\\\ext\\\\jfxrt.jar", "lib\\\\jfxrt.jar"});
- }
-
//validate runtime bit-architectire
testRuntimeBitArchitecture(p);
return true;
}
--- 104,119 ----
throw new UnsupportedPlatformException();
}
imageBundleValidation(p);
! if (WinResources.class.getResource(TOOL_ICON_SWAP) == null) {
throw new ConfigException(
I18N.getString("error.no-windows-resources"),
I18N.getString("error.no-windows-resources.advice"));
}
//validate runtime bit-architectire
testRuntimeBitArchitecture(p);
return true;
}
*** 201,296 ****
public static String getLauncherCfgName(Map<String, ? super Object> p) {
return "app\\" + APP_NAME.fetchFrom(p) +".cfg";
}
- private File getConfig_AppIcon(Map<String, ? super Object> params) {
- return new File(getConfigRoot(params), APP_NAME.fetchFrom(params) + ".ico");
- }
-
- private File getConfig_ExecutableProperties(Map<String, ? super Object> params) {
- return new File(getConfigRoot(params), APP_NAME.fetchFrom(params) + ".properties");
- }
-
- private final static String TEMPLATE_APP_ICON ="javalogo_white_48.ico";
-
- //remove
- protected void cleanupConfigFiles(Map<String, ? super Object> params) {
- getConfig_AppIcon(params).delete();
- getConfig_ExecutableProperties(params).delete();
- }
-
- private void validateValueAndPut(Map<String, String> data, String key,
- BundlerParamInfo<String> param, Map<String, ? super Object> params)
- {
- String value = param.fetchFrom(params);
- if (value.contains("\r") || value.contains("\n")) {
- Log.info("Configuration Parameter " + param.getID() + " contains multiple lines of text, ignore it");
- data.put(key, "");
- return;
- }
- data.put(key, value);
- }
-
- protected void prepareExecutableProperties(Map<String, ? super Object> params)
- throws IOException
- {
- Map<String, String> data = new HashMap<>();
-
- // mapping Java parameters in strings for version resource
- data.put("COMMENTS", "");
- validateValueAndPut(data, "COMPANY_NAME", VENDOR, params);
- validateValueAndPut(data, "FILE_DESCRIPTION", DESCRIPTION, params);
- validateValueAndPut(data, "FILE_VERSION", VERSION, params);
- data.put("INTERNAL_NAME", getLauncherName(params));
- validateValueAndPut(data, "LEGAL_COPYRIGHT", COPYRIGHT, params);
- data.put("LEGAL_TRADEMARK", "");
- data.put("ORIGINAL_FILENAME", getLauncherName(params));
- data.put("PRIVATE_BUILD", "");
- validateValueAndPut(data, "PRODUCT_NAME", APP_NAME, params);
- validateValueAndPut(data, "PRODUCT_VERSION", VERSION, params);
- data.put("SPECIAL_BUILD", "");
-
- Writer w = new BufferedWriter(new FileWriter(getConfig_ExecutableProperties(params)));
- String content = preprocessTextResource(
- WinAppBundler.WIN_BUNDLER_PREFIX + getConfig_ExecutableProperties(params).getName(),
- I18N.getString("resource.executable-properties-template"), EXECUTABLE_PROPERTIES_TEMPLATE, data,
- VERBOSE.fetchFrom(params),
- DROP_IN_RESOURCES_ROOT.fetchFrom(params));
- w.write(content);
- w.close();
- }
-
- private void prepareConfigFiles(Map<String, ? super Object> params) throws IOException {
- File iconTarget = getConfig_AppIcon(params);
-
- File icon = ICON_ICO.fetchFrom(params);
- if (icon != null && icon.exists()) {
- fetchResource(WIN_BUNDLER_PREFIX + iconTarget.getName(),
- I18N.getString("resource.application-icon"),
- icon,
- iconTarget,
- VERBOSE.fetchFrom(params),
- DROP_IN_RESOURCES_ROOT.fetchFrom(params));
- } else {
- fetchResource(WIN_BUNDLER_PREFIX + iconTarget.getName(),
- I18N.getString("resource.application-icon"),
- WinAppBundler.TEMPLATE_APP_ICON,
- iconTarget,
- VERBOSE.fetchFrom(params),
- DROP_IN_RESOURCES_ROOT.fetchFrom(params));
- }
-
- prepareExecutableProperties(params);
- }
-
public boolean bundle(Map<String, ? super Object> p, File outputDirectory) {
return doBundle(p, outputDirectory, false) != null;
}
File doBundle(Map<String, ? super Object> p, File outputDirectory, boolean dependentTask) {
- Map<String, ? super Object> originalParams = new HashMap<>(p);
if (!outputDirectory.isDirectory() && !outputDirectory.mkdirs()) {
throw new RuntimeException(MessageFormat.format(I18N.getString("error.cannot-create-output-dir"), outputDirectory.getAbsolutePath()));
}
if (!outputDirectory.canWrite()) {
throw new RuntimeException(MessageFormat.format(I18N.getString("error.cannot-write-to-output-dir"), outputDirectory.getAbsolutePath()));
--- 143,157 ----
*** 303,581 ****
// Create directory structure
File rootDirectory = getRootDir(outputDirectory, p);
IOUtils.deleteRecursive(rootDirectory);
rootDirectory.mkdirs();
! File appDirectory = new File(rootDirectory, "app");
! appDirectory.mkdirs();
!
! // create the .exe launchers
! createLauncherForEntryPoint(p, rootDirectory);
!
! // copy the jars
! copyApplication(p, appDirectory);
!
! // Copy runtime
! File runtimeDirectory = new File(rootDirectory, "runtime");
! copyRuntime(p, runtimeDirectory);
!
! // copy in the needed libraries
! IOUtils.copyFromURL(
! WinResources.class.getResource(LIBRARY_NAME),
! new File(rootDirectory, LIBRARY_NAME));
!
! copyMSVCDLLs(rootDirectory, runtimeDirectory);
!
! // create the secondary launchers, if any
! List<Map<String, ? super Object>> entryPoints = StandardBundlerParam.SECONDARY_LAUNCHERS.fetchFrom(p);
! for (Map<String, ? super Object> entryPoint : entryPoints) {
! Map<String, ? super Object> tmp = new HashMap<>(originalParams);
! tmp.putAll(entryPoint);
! createLauncherForEntryPoint(tmp, rootDirectory);
}
if (!dependentTask) {
Log.info(MessageFormat.format(I18N.getString("message.result-dir"), outputDirectory.getAbsolutePath()));
}
return rootDirectory;
} catch (IOException ex) {
! Log.info("Exception: "+ex);
! Log.debug(ex);
return null;
- } finally {
- if (VERBOSE.fetchFrom(p)) {
- Log.info(MessageFormat.format(I18N.getString("message.config-save-location"), getConfigRoot(p).getAbsolutePath()));
- } else {
- cleanupConfigFiles(p);
- }
- }
-
}
-
- private void copyMSVCDLLs(File rootDirectory, File jreDir) throws IOException {
- String vsVer = null;
- if (jreDir == null || !jreDir.isDirectory()) {
- jreDir = new File(System.getProperty("java.home"));
}
- // first copy the ones needed for the launcher
- for (String thisVer : VS_VERS) {
- if (copyMSVCDLLs(rootDirectory, thisVer)) {
- vsVer = thisVer;
- break;
- }
- }
- if (vsVer == null) {
- throw new RuntimeException("Not found MSVC dlls");
- }
-
- AtomicReference<IOException> ioe = new AtomicReference<>();
- final String finalVsVer = vsVer;
- Files.list(jreDir.toPath().resolve("bin"))
- .filter(p -> Pattern.matches("msvc(r|p)\\d\\d\\d.dll", p.toFile().getName().toLowerCase()))
- .filter(p -> !p.toString().toLowerCase().endsWith(finalVsVer + ".dll"))
- .forEach(p -> {
- try {
- IOUtils.copyFile(p.toFile(), new File(rootDirectory, p.toFile().getName()));
- } catch (IOException e) {
- ioe.set(e);
- }
- });
-
- IOException e = ioe.get();
- if (e != null) {
- throw e;
- }
- }
-
- private boolean copyMSVCDLLs(File rootDirectory, String VS_VER) throws IOException {
- final URL REDIST_MSVCR_URL = WinResources.class.getResource(
- REDIST_MSVCR.replaceAll("VS_VER", VS_VER));
- final URL REDIST_MSVCP_URL = WinResources.class.getResource(
- REDIST_MSVCP.replaceAll("VS_VER", VS_VER));
-
- if (REDIST_MSVCR_URL != null && REDIST_MSVCP_URL != null) {
- IOUtils.copyFromURL(
- REDIST_MSVCR_URL,
- new File(rootDirectory, REDIST_MSVCR.replaceAll("VS_VER", VS_VER)));
- IOUtils.copyFromURL(
- REDIST_MSVCP_URL,
- new File(rootDirectory, REDIST_MSVCP.replaceAll("VS_VER", VS_VER)));
- return true;
- }
-
- return false; // not found
- }
-
- private void createLauncherForEntryPoint(Map<String, ? super Object> p, File rootDirectory) throws IOException {
- prepareConfigFiles(p);
-
- // Generate launcher .cfg file
- if (LAUNCHER_CFG_FORMAT.fetchFrom(p).equals(CFG_FORMAT_PROPERTIES)) {
- writeCfgFile(p, rootDirectory);
- } else {
- writeCfgFile(p, new File(rootDirectory, getLauncherCfgName(p)), getRuntimeLocation(p));
- }
-
- // Copy executable root folder
- File executableFile = new File(rootDirectory, getLauncherName(p));
- IOUtils.copyFromURL(
- RAW_EXECUTABLE_URL.fetchFrom(p),
- executableFile);
- executableFile.setExecutable(true, false);
-
- //Update branding of exe file
- if (REBRAND_EXECUTABLE.fetchFrom(p) && getConfig_AppIcon(p).exists()) {
- //extract IconSwap helper tool
- File iconSwapTool = File.createTempFile("iconswap", ".exe");
- IOUtils.copyFromURL(
- WinResources.class.getResource(TOOL_ICON_SWAP),
- iconSwapTool,
- true);
- iconSwapTool.setExecutable(true, false);
- iconSwapTool.deleteOnExit();
-
- //run it on launcher file
- executableFile.setWritable(true);
- ProcessBuilder pb = new ProcessBuilder(
- iconSwapTool.getAbsolutePath(),
- getConfig_AppIcon(p).getAbsolutePath(),
- executableFile.getAbsolutePath());
- IOUtils.exec(pb, VERBOSE.fetchFrom(p));
- executableFile.setReadOnly();
- iconSwapTool.delete();
- }
-
- IOUtils.copyFile(getConfig_AppIcon(p),
- new File(rootDirectory, APP_NAME.fetchFrom(p) + ".ico"));
-
- if (REBRAND_EXECUTABLE.fetchFrom(p) && getConfig_ExecutableProperties(p).exists()) {
- // extract VersionInfoHelper tool
- File versionInfoTool = File.createTempFile("versioninfoswap", ".exe");
- IOUtils.copyFromURL(
- WinResources.class.getResource(TOOL_VERSION_INFO_SWAP),
- versionInfoTool,
- true);
- versionInfoTool.setExecutable(true, false);
- versionInfoTool.deleteOnExit();
-
- // run it on launcher file
- executableFile.setWritable(true);
- ProcessBuilder pb = new ProcessBuilder(
- versionInfoTool.getAbsolutePath(),
- getConfig_ExecutableProperties(p).getAbsolutePath(),
- executableFile.getAbsolutePath());
- IOUtils.exec(pb, VERBOSE.fetchFrom(p));
- executableFile.setReadOnly();
- versionInfoTool.delete();
- }
- }
-
- private void copyApplication(Map<String, ? super Object> params, File appDirectory) 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()) {
- IOUtils.copyFile(
- new File(srcdir, fname), new File(appDirectory, fname));
- }
- }
- }
-
- private String getRuntimeLocation(Map<String, ? super Object> params) {
- if (WIN_RUNTIME.fetchFrom(params) == null) {
- return "";
- } else {
- return "$APPDIR\\runtime";
- }
- }
-
- private void writeCfgFile(Map<String, ? super Object> params, File rootDir) throws FileNotFoundException {
- File cfgFile = new File(rootDir, getLauncherCfgName(params));
-
- cfgFile.delete();
-
- PrintStream out = new PrintStream(cfgFile);
- out.println("app.runtime=" + getRuntimeLocation(params));
- out.println("app.mainjar=" + MAIN_JAR.fetchFrom(params).getIncludedFiles().iterator().next());
- out.println("app.version=" + VERSION.fetchFrom(params));
- //for future AU support (to be able to find app in the registry)
- out.println("app.id=" + IDENTIFIER.fetchFrom(params));
- out.println("app.preferences.id=" + PREFERENCES_ID.fetchFrom(params));
- out.println("app.identifier=" + IDENTIFIER.fetchFrom(params));
-
- out.println("app.mainclass=" +
- MAIN_CLASS.fetchFrom(params).replaceAll("\\.", "/"));
- out.println("app.classpath=" + CLASSPATH.fetchFrom(params));
-
- List<String> jvmargs = JVM_OPTIONS.fetchFrom(params);
- int idx = 1;
- for (String a : jvmargs) {
- out.println("jvmarg."+idx+"="+a);
- idx++;
- }
- Map<String, String> jvmProps = JVM_PROPERTIES.fetchFrom(params);
- for (Map.Entry<String, String> entry : jvmProps.entrySet()) {
- out.println("jvmarg."+idx+"=-D"+entry.getKey()+"="+entry.getValue());
- idx++;
- }
-
- String preloader = PRELOADER_CLASS.fetchFrom(params);
- if (preloader != null) {
- out.println("jvmarg."+idx+"=-Djavafx.preloader="+preloader);
- }
-
- Map<String, String> overridableJVMOptions = USER_JVM_OPTIONS.fetchFrom(params);
- idx = 1;
- for (Map.Entry<String, String> arg: overridableJVMOptions.entrySet()) {
- if (arg.getKey() == null || arg.getValue() == null) {
- Log.info(I18N.getString("message.jvm-user-arg-is-null"));
- }
- else {
- out.println("jvmuserarg."+idx+".name="+arg.getKey());
- out.println("jvmuserarg."+idx+".value="+arg.getValue());
- }
- idx++;
- }
-
- // add command line args
- List<String> args = ARGUMENTS.fetchFrom(params);
- idx = 1;
- for (String a : args) {
- out.println("arg."+idx+"="+a);
- idx++;
- }
-
- out.close();
- }
-
- private void copyRuntime(Map<String, ? super Object> params, File runtimeDirectory) throws IOException {
- RelativeFileSet runtime = WIN_RUNTIME.fetchFrom(params);
- if (runtime == null) {
- //its ok, request to use system JRE
- return;
- }
- runtimeDirectory.mkdirs();
-
- File srcdir = runtime.getBaseDirectory();
- Set<String> filesToCopy = runtime.getIncludedFiles();
- for (String fname : filesToCopy) {
- IOUtils.copyFile(
- new File(srcdir, fname), new File(runtimeDirectory, fname));
- }
- }
-
- public void extractRuntimeFlags(Map<String, ? super Object> params) {
- extractFlagsFromRuntime(params);
- }
public static void extractFlagsFromRuntime(Map<String, ? super Object> params) {
if (params.containsKey(".runtime.autodetect")) return;
params.put(".runtime.autodetect", "attempted");
--- 164,192 ----
// Create directory structure
File rootDirectory = getRootDir(outputDirectory, p);
IOUtils.deleteRecursive(rootDirectory);
rootDirectory.mkdirs();
! if (!p.containsKey(JLinkBundlerHelper.JLINK_BUILDER.getID())) {
! p.put(JLinkBundlerHelper.JLINK_BUILDER.getID(), "windowsapp-image-builder");
}
+ ImageBuilder imageBuilder = new WindowsAppImageBuilder(p, outputDirectory.toPath());
+ JLinkBundlerHelper.execute(p, outputDirectory, imageBuilder);
+
if (!dependentTask) {
Log.info(MessageFormat.format(I18N.getString("message.result-dir"), outputDirectory.getAbsolutePath()));
}
return rootDirectory;
} catch (IOException ex) {
! Log.info(ex.toString());
! Log.verbose(ex);
return null;
}
}
public static void extractFlagsFromRuntime(Map<String, ? super Object> params) {
if (params.containsKey(".runtime.autodetect")) return;
params.put(".runtime.autodetect", "attempted");
*** 653,663 ****
@Override
public File execute(Map<String, ? super Object> params, File outputParentDir) {
return doBundle(params, outputParentDir, false);
}
-
- @Override
- protected String getCacheLocation(Map<String, ? super Object> params) {
- return "$CACHEDIR/";
- }
}
--- 264,269 ----
< prev index next >