--- old/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsAppImageBuilder.java 2019-11-18 21:10:20.591064100 -0500 +++ /dev/null 2019-11-18 21:10:22.000000000 -0500 @@ -1,444 +0,0 @@ -/* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jpackage.internal; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UncheckedIOException; -import java.io.Writer; -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.PosixFilePermission; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.ResourceBundle; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import static jdk.jpackage.internal.StandardBundlerParam.*; - -public class WindowsAppImageBuilder extends AbstractAppImageBuilder { - - static { - System.loadLibrary("jpackage"); - } - - private static final ResourceBundle I18N = ResourceBundle.getBundle( - "jdk.jpackage.internal.resources.WinResources"); - - private final static String LIBRARY_NAME = "applauncher.dll"; - private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll"; - private final static String REDIST_MSVCP = "msvcpVS_VER.dll"; - - private final static String TEMPLATE_APP_ICON ="javalogo_white_48.ico"; - - private static final String EXECUTABLE_PROPERTIES_TEMPLATE = - "WinLauncher.template"; - - private final Path root; - private final Path appDir; - private final Path appModsDir; - private final Path runtimeDir; - private final Path mdir; - - private final Map params; - - public static final BundlerParamInfo REBRAND_EXECUTABLE = - new WindowsBundlerParam<>( - "win.launcher.rebrand", - Boolean.class, - params -> Boolean.TRUE, - (s, p) -> Boolean.valueOf(s)); - - public static final BundlerParamInfo ICON_ICO = - new StandardBundlerParam<>( - "icon.ico", - File.class, - params -> { - File f = ICON.fetchFrom(params); - if (f != null && !f.getName().toLowerCase().endsWith(".ico")) { - Log.error(MessageFormat.format( - I18N.getString("message.icon-not-ico"), f)); - return null; - } - return f; - }, - (s, p) -> new File(s)); - - public static final StandardBundlerParam CONSOLE_HINT = - new WindowsBundlerParam<>( - Arguments.CLIOptions.WIN_CONSOLE_HINT.getId(), - Boolean.class, - params -> false, - // valueOf(null) is false, - // and we actually do want null in some cases - (s, p) -> (s == null - || "null".equalsIgnoreCase(s)) ? true : Boolean.valueOf(s)); - - public WindowsAppImageBuilder(Map config, Path imageOutDir) - throws IOException { - super(config, - imageOutDir.resolve(APP_NAME.fetchFrom(config) + "/runtime")); - - Objects.requireNonNull(imageOutDir); - - this.params = config; - - this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params)); - this.appDir = root.resolve("app"); - this.appModsDir = appDir.resolve("mods"); - this.runtimeDir = root.resolve("runtime"); - this.mdir = runtimeDir.resolve("lib"); - Files.createDirectories(appDir); - Files.createDirectories(runtimeDir); - } - - public WindowsAppImageBuilder(String jreName, Path imageOutDir) - throws IOException { - super(null, imageOutDir.resolve(jreName)); - - Objects.requireNonNull(imageOutDir); - - this.params = null; - this.root = imageOutDir.resolve(jreName); - this.appDir = null; - this.appModsDir = null; - this.runtimeDir = root; - this.mdir = runtimeDir.resolve("lib"); - Files.createDirectories(runtimeDir); - } - - private Path destFile(String dir, String filename) { - return runtimeDir.resolve(dir).resolve(filename); - } - - private void writeEntry(InputStream in, Path dstFile) throws IOException { - Files.createDirectories(dstFile.getParent()); - Files.copy(in, dstFile); - } - - private void writeSymEntry(Path dstFile, Path target) throws IOException { - Files.createDirectories(dstFile.getParent()); - Files.createLink(dstFile, target); - } - - /** - * chmod ugo+x file - */ - private void setExecutable(Path file) { - try { - Set perms = - Files.getPosixFilePermissions(file); - perms.add(PosixFilePermission.OWNER_EXECUTE); - perms.add(PosixFilePermission.GROUP_EXECUTE); - perms.add(PosixFilePermission.OTHERS_EXECUTE); - Files.setPosixFilePermissions(file, perms); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - } - - private static void createUtf8File(File file, String content) - throws IOException { - try (OutputStream fout = new FileOutputStream(file); - Writer output = new OutputStreamWriter(fout, "UTF-8")) { - output.write(content); - } - } - - public static String getLauncherName(Map p) { - return APP_NAME.fetchFrom(p) + ".exe"; - } - - // Returns launcher resource name for launcher we need to use. - public static String getLauncherResourceName( - Map p) { - if (CONSOLE_HINT.fetchFrom(p)) { - return "jpackageapplauncher.exe"; - } else { - return "jpackageapplauncherw.exe"; - } - } - - public static String getLauncherCfgName(Map p) { - return "app/" + APP_NAME.fetchFrom(p) +".cfg"; - } - - private File getConfig_AppIcon(Map params) { - return new File(getConfigRoot(params), - APP_NAME.fetchFrom(params) + ".ico"); - } - - private File getConfig_ExecutableProperties( - Map params) { - return new File(getConfigRoot(params), - APP_NAME.fetchFrom(params) + ".properties"); - } - - File getConfigRoot(Map params) { - return CONFIG_ROOT.fetchFrom(params); - } - - @Override - public Path getAppDir() { - return appDir; - } - - @Override - public Path getAppModsDir() { - return appModsDir; - } - - @Override - public void prepareApplicationFiles() throws IOException { - Map originalParams = new HashMap<>(params); - File rootFile = root.toFile(); - if (!rootFile.isDirectory() && !rootFile.mkdirs()) { - throw new RuntimeException(MessageFormat.format(I18N.getString( - "error.cannot-create-output-dir"), rootFile.getAbsolutePath())); - } - if (!rootFile.canWrite()) { - throw new RuntimeException(MessageFormat.format( - I18N.getString("error.cannot-write-to-output-dir"), - rootFile.getAbsolutePath())); - } - // create the .exe launchers - createLauncherForEntryPoint(params); - - // copy the jars - copyApplication(params); - - // copy in the needed libraries - try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) { - Files.copy(is_lib, root.resolve(LIBRARY_NAME)); - } - - copyMSVCDLLs(); - - // create the additional launcher(s), if any - List> entryPoints = - StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); - for (Map entryPoint : entryPoints) { - createLauncherForEntryPoint( - AddLauncherArguments.merge(originalParams, entryPoint)); - } - } - - @Override - public void prepareJreFiles() throws IOException {} - - private void copyMSVCDLLs() throws IOException { - AtomicReference ioe = new AtomicReference<>(); - try (Stream files = Files.list(runtimeDir.resolve("bin"))) { - files.filter(p -> Pattern.matches( - "^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$", - p.toFile().getName().toLowerCase())) - .forEach(p -> { - try { - Files.copy(p, root.resolve((p.toFile().getName()))); - } catch (IOException e) { - ioe.set(e); - } - }); - } - - IOException e = ioe.get(); - if (e != null) { - throw e; - } - } - - // TODO: do we still need this? - private boolean copyMSVCDLLs(String VS_VER) throws IOException { - final InputStream REDIST_MSVCR_URL = getResourceAsStream( - REDIST_MSVCR.replaceAll("VS_VER", VS_VER)); - final InputStream REDIST_MSVCP_URL = getResourceAsStream( - REDIST_MSVCP.replaceAll("VS_VER", VS_VER)); - - if (REDIST_MSVCR_URL != null && REDIST_MSVCP_URL != null) { - Files.copy( - REDIST_MSVCR_URL, - root.resolve(REDIST_MSVCR.replaceAll("VS_VER", VS_VER))); - Files.copy( - REDIST_MSVCP_URL, - root.resolve(REDIST_MSVCP.replaceAll("VS_VER", VS_VER))); - return true; - } - - return false; - } - - private void validateValueAndPut( - Map data, String key, - BundlerParamInfo param, - Map params) { - String value = param.fetchFrom(params); - if (value.contains("\r") || value.contains("\n")) { - Log.error("Configuration Parameter " + param.getID() - + " contains multiple lines of text, ignore it"); - data.put(key, ""); - return; - } - data.put(key, value); - } - - protected void prepareExecutableProperties( - Map params) throws IOException { - Map data = new HashMap<>(); - - // mapping Java parameters in strings for version resource - 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("ORIGINAL_FILENAME", getLauncherName(params)); - validateValueAndPut(data, "PRODUCT_NAME", APP_NAME, params); - validateValueAndPut(data, "PRODUCT_VERSION", VERSION, params); - - try (Writer w = Files.newBufferedWriter( - getConfig_ExecutableProperties(params).toPath(), - StandardCharsets.UTF_8)) { - String content = preprocessTextResource( - getConfig_ExecutableProperties(params).getName(), - I18N.getString("resource.executable-properties-template"), - EXECUTABLE_PROPERTIES_TEMPLATE, data, - VERBOSE.fetchFrom(params), - RESOURCE_DIR.fetchFrom(params)); - w.write(content); - } - } - - private void createLauncherForEntryPoint( - Map p) throws IOException { - - File launcherIcon = ICON_ICO.fetchFrom(p); - File icon = launcherIcon != null ? - launcherIcon : ICON_ICO.fetchFrom(params); - File iconTarget = getConfig_AppIcon(p); - - InputStream in = locateResource( - APP_NAME.fetchFrom(params) + ".ico", - "icon", - TEMPLATE_APP_ICON, - icon, - VERBOSE.fetchFrom(params), - RESOURCE_DIR.fetchFrom(params)); - - Files.copy(in, iconTarget.toPath(), - StandardCopyOption.REPLACE_EXISTING); - - writeCfgFile(p, root.resolve( - getLauncherCfgName(p)).toFile(), "$APPDIR\\runtime"); - - prepareExecutableProperties(p); - - // Copy executable root folder - Path executableFile = root.resolve(getLauncherName(p)); - try (InputStream is_launcher = - getResourceAsStream(getLauncherResourceName(p))) { - writeEntry(is_launcher, executableFile); - } - - File launcher = executableFile.toFile(); - launcher.setWritable(true, true); - - // Update branding of EXE file - if (REBRAND_EXECUTABLE.fetchFrom(p)) { - try { - String tempDirectory = WindowsDefender.getUserTempDirectory(); - if (Arguments.CLIOptions.context().userProvidedBuildRoot) { - tempDirectory = TEMP_ROOT.fetchFrom(p).getAbsolutePath(); - } - if (WindowsDefender.isThereAPotentialWindowsDefenderIssue( - tempDirectory)) { - Log.error(MessageFormat.format(I18N.getString( - "message.potential.windows.defender.issue"), - tempDirectory)); - } - - launcher.setWritable(true); - - if (iconTarget.exists()) { - iconSwap(iconTarget.getAbsolutePath(), - launcher.getAbsolutePath()); - } - - File executableProperties = getConfig_ExecutableProperties(p); - - if (executableProperties.exists()) { - if (versionSwap(executableProperties.getAbsolutePath(), - launcher.getAbsolutePath()) != 0) { - throw new RuntimeException(MessageFormat.format( - I18N.getString("error.version-swap"), - executableProperties.getAbsolutePath())); - } - } - } finally { - executableFile.toFile().setReadOnly(); - } - } - - Files.copy(iconTarget.toPath(), - root.resolve(APP_NAME.fetchFrom(p) + ".ico")); - } - - private void copyApplication(Map params) - throws IOException { - List 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); - } - } - } - - private static native int iconSwap(String iconTarget, String launcher); - - private static native int versionSwap(String executableProperties, String launcher); - -} --- /dev/null 2019-11-18 21:10:22.000000000 -0500 +++ new/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java 2019-11-18 21:10:17.143449800 -0500 @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2015, 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.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UncheckedIOException; +import java.io.Writer; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.PosixFilePermission; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import static jdk.incubator.jpackage.internal.OverridableResource.createResource; + +import static jdk.incubator.jpackage.internal.StandardBundlerParam.*; + +public class WindowsAppImageBuilder extends AbstractAppImageBuilder { + + static { + System.loadLibrary("jpackage"); + } + + private static final ResourceBundle I18N = ResourceBundle.getBundle( + "jdk.incubator.jpackage.internal.resources.WinResources"); + + private final static String LIBRARY_NAME = "applauncher.dll"; + private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll"; + private final static String REDIST_MSVCP = "msvcpVS_VER.dll"; + + private final static String TEMPLATE_APP_ICON ="java48.ico"; + + private static final String EXECUTABLE_PROPERTIES_TEMPLATE = + "WinLauncher.template"; + + private final Path root; + private final Path appDir; + private final Path appModsDir; + private final Path runtimeDir; + private final Path mdir; + private final Path binDir; + + public static final BundlerParamInfo REBRAND_EXECUTABLE = + new WindowsBundlerParam<>( + "win.launcher.rebrand", + Boolean.class, + params -> Boolean.TRUE, + (s, p) -> Boolean.valueOf(s)); + + public static final BundlerParamInfo ICON_ICO = + new StandardBundlerParam<>( + "icon.ico", + File.class, + params -> { + File f = ICON.fetchFrom(params); + if (f != null && !f.getName().toLowerCase().endsWith(".ico")) { + Log.error(MessageFormat.format( + I18N.getString("message.icon-not-ico"), f)); + return null; + } + return f; + }, + (s, p) -> new File(s)); + + public static final StandardBundlerParam CONSOLE_HINT = + new WindowsBundlerParam<>( + Arguments.CLIOptions.WIN_CONSOLE_HINT.getId(), + Boolean.class, + params -> false, + // valueOf(null) is false, + // and we actually do want null in some cases + (s, p) -> (s == null + || "null".equalsIgnoreCase(s)) ? true : Boolean.valueOf(s)); + + public WindowsAppImageBuilder(Map params, Path imageOutDir) + throws IOException { + super(params, + imageOutDir.resolve(APP_NAME.fetchFrom(params) + "/runtime")); + + Objects.requireNonNull(imageOutDir); + + this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params)); + this.appDir = root.resolve("app"); + this.appModsDir = appDir.resolve("mods"); + this.runtimeDir = root.resolve("runtime"); + this.mdir = runtimeDir.resolve("lib"); + this.binDir = root; + Files.createDirectories(appDir); + Files.createDirectories(runtimeDir); + } + + private void writeEntry(InputStream in, Path dstFile) throws IOException { + Files.createDirectories(dstFile.getParent()); + Files.copy(in, dstFile); + } + + private static String getLauncherName(Map params) { + return APP_NAME.fetchFrom(params) + ".exe"; + } + + // Returns launcher resource name for launcher we need to use. + public static String getLauncherResourceName( + Map params) { + if (CONSOLE_HINT.fetchFrom(params)) { + return "jpackageapplauncher.exe"; + } else { + return "jpackageapplauncherw.exe"; + } + } + + public static String getLauncherCfgName( + Map params) { + return "app/" + APP_NAME.fetchFrom(params) +".cfg"; + } + + private File getConfig_AppIcon(Map params) { + return new File(getConfigRoot(params), + APP_NAME.fetchFrom(params) + ".ico"); + } + + private File getConfig_ExecutableProperties( + Map params) { + return new File(getConfigRoot(params), + APP_NAME.fetchFrom(params) + ".properties"); + } + + File getConfigRoot(Map params) { + return CONFIG_ROOT.fetchFrom(params); + } + + @Override + public Path getAppDir() { + return appDir; + } + + @Override + public Path getAppModsDir() { + return appModsDir; + } + + @Override + public void prepareApplicationFiles(Map params) + throws IOException { + Map originalParams = new HashMap<>(params); + + try { + IOUtils.writableOutputDir(root); + IOUtils.writableOutputDir(binDir); + } catch (PackagerException pe) { + throw new RuntimeException(pe); + } + AppImageFile.save(root, params); + + // create the .exe launchers + createLauncherForEntryPoint(params); + + // copy the jars + copyApplication(params); + + // copy in the needed libraries + try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) { + Files.copy(is_lib, binDir.resolve(LIBRARY_NAME)); + } + + copyMSVCDLLs(); + + // create the additional launcher(s), if any + List> entryPoints = + StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); + for (Map entryPoint : entryPoints) { + createLauncherForEntryPoint( + AddLauncherArguments.merge(originalParams, entryPoint)); + } + } + + @Override + public void prepareJreFiles(Map params) + throws IOException {} + + private void copyMSVCDLLs() throws IOException { + AtomicReference ioe = new AtomicReference<>(); + try (Stream files = Files.list(runtimeDir.resolve("bin"))) { + files.filter(p -> Pattern.matches( + "^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$", + p.toFile().getName().toLowerCase())) + .forEach(p -> { + try { + Files.copy(p, binDir.resolve((p.toFile().getName()))); + } catch (IOException e) { + ioe.set(e); + } + }); + } + + IOException e = ioe.get(); + if (e != null) { + throw e; + } + } + + private void validateValueAndPut( + Map data, String key, + BundlerParamInfo param, + Map params) { + String value = param.fetchFrom(params); + if (value.contains("\r") || value.contains("\n")) { + Log.error("Configuration Parameter " + param.getID() + + " contains multiple lines of text, ignore it"); + data.put(key, ""); + return; + } + data.put(key, value); + } + + protected void prepareExecutableProperties( + Map params) throws IOException { + + Map data = new HashMap<>(); + + // mapping Java parameters in strings for version resource + 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("ORIGINAL_FILENAME", getLauncherName(params)); + validateValueAndPut(data, "PRODUCT_NAME", APP_NAME, params); + validateValueAndPut(data, "PRODUCT_VERSION", VERSION, params); + + createResource(EXECUTABLE_PROPERTIES_TEMPLATE, params) + .setCategory(I18N.getString("resource.executable-properties-template")) + .setSubstitutionData(data) + .saveToFile(getConfig_ExecutableProperties(params)); + } + + private void createLauncherForEntryPoint( + Map params) throws IOException { + + File iconTarget = getConfig_AppIcon(params); + + createResource(TEMPLATE_APP_ICON, params) + .setCategory("icon") + .setExternal(ICON_ICO.fetchFrom(params)) + .saveToFile(iconTarget); + + writeCfgFile(params, root.resolve( + getLauncherCfgName(params)).toFile()); + + prepareExecutableProperties(params); + + // Copy executable to bin folder + Path executableFile = binDir.resolve(getLauncherName(params)); + + try (InputStream is_launcher = + getResourceAsStream(getLauncherResourceName(params))) { + writeEntry(is_launcher, executableFile); + } + + File launcher = executableFile.toFile(); + launcher.setWritable(true, true); + + // Update branding of EXE file + if (REBRAND_EXECUTABLE.fetchFrom(params)) { + try { + String tempDirectory = WindowsDefender.getUserTempDirectory(); + if (Arguments.CLIOptions.context().userProvidedBuildRoot) { + tempDirectory = + TEMP_ROOT.fetchFrom(params).getAbsolutePath(); + } + if (WindowsDefender.isThereAPotentialWindowsDefenderIssue( + tempDirectory)) { + Log.verbose(MessageFormat.format(I18N.getString( + "message.potential.windows.defender.issue"), + tempDirectory)); + } + + launcher.setWritable(true); + + if (iconTarget.exists()) { + iconSwap(iconTarget.getAbsolutePath(), + launcher.getAbsolutePath()); + } + + File executableProperties = + getConfig_ExecutableProperties(params); + + if (executableProperties.exists()) { + if (versionSwap(executableProperties.getAbsolutePath(), + launcher.getAbsolutePath()) != 0) { + throw new RuntimeException(MessageFormat.format( + I18N.getString("error.version-swap"), + executableProperties.getAbsolutePath())); + } + } + } finally { + executableFile.toFile().setExecutable(true); + executableFile.toFile().setReadOnly(); + } + } + + Files.copy(iconTarget.toPath(), + binDir.resolve(APP_NAME.fetchFrom(params) + ".ico")); + } + + private void copyApplication(Map params) + throws IOException { + List 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); + } + } + } + + private static native int iconSwap(String iconTarget, String launcher); + + private static native int versionSwap(String executableProperties, + String launcher); + +}