com.sun.javafx.tools.packager.bundlers.WinExeBundler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openjfx-78-backport Show documentation
Show all versions of openjfx-78-backport Show documentation
This is a backport of OpenJFX 8 to run on Java 7.
The newest version!
/*
* Copyright (c) 2012, 2013, 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 com.sun.javafx.tools.packager.bundlers;
import com.sun.javafx.tools.packager.Log;
import com.sun.javafx.tools.resource.windows.WinResources;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WinExeBundler extends Bundler {
WinAppBundler appBundler = new WinAppBundler();
BundleParams params;
private File configRoot = null;
File imageDir = null;
private boolean menuShortcut = false;
private boolean desktopShortcut = false;
private final static String DEFAULT_EXE_PROJECT_TEMPLATE = "template.iss";
private static final String TOOL_INNO_SETUP_COMPILER = "iscc.exe";
public WinExeBundler() {
super();
baseResourceLoader = WinResources.class;
}
@Override
protected void setBuildRoot(File dir) {
super.setBuildRoot(dir);
configRoot = new File(dir, "windows");
configRoot.mkdirs();
appBundler.setBuildRoot(dir);
}
@Override
public void setVerbose(boolean m) {
super.setVerbose(m);
appBundler.setVerbose(m);
}
static class VersionExtractor extends PrintStream {
double version = 0f;
public VersionExtractor() {
super(new ByteArrayOutputStream());
}
double getVersion() {
if (version == 0f) {
String content = new String(((ByteArrayOutputStream) out).toByteArray());
Pattern pattern = Pattern.compile("Inno Setup (\\d+.?\\d*)");
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
String v = matcher.group(1);
version = new Double(v);
}
}
return version;
}
}
private static double findTool(String toolName) {
try {
ProcessBuilder pb = new ProcessBuilder(
toolName,
"/?");
VersionExtractor ve = new VersionExtractor();
IOUtils.exec(pb, Log.isDebug(), true, ve); //not interested in the output
double version = ve.getVersion();
Log.verbose(" Detected ["+toolName+"] version [" + version + "]");
return version;
} catch (Exception e) {
if (Log.isDebug()) {
e.printStackTrace();
}
return 0f;
}
}
@Override
boolean validate(BundleParams p) throws Bundler.UnsupportedPlatformException, Bundler.ConfigException {
if (!(p.type == Bundler.BundleType.ALL || p.type == Bundler.BundleType.INSTALLER)
|| !(p.bundleFormat == null || "exe".equals(p.bundleFormat))) {
return false;
}
//run basic validation to ensure requirements are met
//we are not interested in return code, only possible exception
appBundler.doValidate(p);
double innoVersion = findTool(TOOL_INNO_SETUP_COMPILER);
//Inno Setup 5+ is required
double minVersion = 5.0f;
if (innoVersion < minVersion) {
Log.info("Detected ["+TOOL_INNO_SETUP_COMPILER+"] version "+innoVersion +
" but version "+minVersion+" is required.");
throw new Bundler.ConfigException(
"Can not find Inno Setup Compiler (iscc.exe).",
" Download Inno Setup 5 or later from http://www.jrsoftware.org and add it to the PATH.");
}
return true;
}
private boolean prepareProto() throws IOException {
if (!appBundler.doBundle(params, imageDir, true)) {
return false;
}
if (!params.licenseFile.isEmpty()) {
//need to copy license file to the root of win-app.image
File lfile = new File(params.appResources.getBaseDirectory(),
params.licenseFile.get(0));
IOUtils.copyFile(lfile, new File(imageDir, lfile.getName()));
}
return true;
}
@Override
public boolean bundle(BundleParams p, File outdir) {
imageDir = new File(imagesRoot, "win-app.image");
try {
params = p;
imageDir.mkdirs();
menuShortcut = params.needMenu;
desktopShortcut = params.needShortcut;
if (!menuShortcut && !desktopShortcut) {
//both can not be false - user will not find the app
Log.verbose("At least one type of shortcut is required. Enabling menu shortcut.");
menuShortcut = true;
}
if (prepareProto() && prepareProjectConfig()) {
File configScript = getConfig_Script();
if (configScript.exists()) {
Log.info("Running WSH script on application image [" +
configScript.getAbsolutePath() + "]");
IOUtils.run("wscript", configScript, verbose);
}
return buildEXE(outdir);
}
return false;
} catch (IOException ex) {
ex.printStackTrace();
return false;
} finally {
try {
if (verbose) {
saveConfigFiles();
}
if (imageDir != null && !Log.isDebug()) {
IOUtils.deleteRecursive(imageDir);
} else if (imageDir != null) {
Log.info("Kept working directory for debug: "
+ imageDir.getAbsolutePath());
}
} catch (FileNotFoundException ex) {
return false;
}
}
}
//name of post-image script
private File getConfig_Script() {
return new File(imageDir, WinAppBundler.getAppName(params) + "-post-image.wsf");
}
protected void saveConfigFiles() {
try {
if (getConfig_ExeProjectFile().exists()) {
IOUtils.copyFile(getConfig_ExeProjectFile(),
new File(configRoot, getConfig_ExeProjectFile().getName()));
}
if (getConfig_Script().exists()) {
IOUtils.copyFile(getConfig_Script(),
new File(configRoot, getConfig_Script().getName()));
}
if (getConfig_SmallInnoSetupIcon().exists()) {
IOUtils.copyFile(getConfig_SmallInnoSetupIcon(),
new File(configRoot, getConfig_SmallInnoSetupIcon().getName()));
}
Log.info(" Config files are saved to "
+ configRoot.getAbsolutePath()
+ ". Use them to customize package.");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
@Override
public String toString() {
return "Exe Bundler (based on Inno Setup)";
}
private String getAppIdentifier() {
String nm = null;
if (params.identifier != null) {
nm = params.identifier;
} else {
nm = params.getMainClassName();
}
//limitation of innosetup
if (nm.length() > 126)
nm = nm.substring(0, 126);
return nm;
}
private String getGroup() {
if (params.applicationCategory != null) {
return params.applicationCategory;
} else {
if (params.vendor != null) {
return params.vendor;
} else {
return "Unknown";
}
}
}
private String getLicenseFile() {
if (params.licenseFile.isEmpty()) {
return "";
}
return params.licenseFile.get(0);
}
private String getDescription() {
if (params.description != null) {
//strip quotes if any
return params.description.replaceAll("\"", "'");
}
return "none";
}
boolean prepareMainProjectFile(File imageDir) throws IOException {
Map data = new HashMap();
data.put("PRODUCT_APP_IDENTIFIER", getAppIdentifier());
data.put("APPLICATION_NAME", WinAppBundler.getAppName(params));
data.put("APPLICATION_VENDOR",
params.vendor != null ? params.vendor : "Unknown");
data.put("APPLICATION_VERSION",
params.appVersion != null ? params.appVersion : "1.0");
data.put("APPLICATION_LAUNCHER_FILENAME",
appBundler.getLauncher(imageDir, params).getName());
data.put("APPLICATION_DESKTOP_SHORTCUT",
desktopShortcut ? "returnTrue" : "returnFalse");
data.put("APPLICATION_MENU_SHORTCUT",
menuShortcut ? "returnTrue" : "returnFalse");
data.put("APPLICATION_GROUP", getGroup());
data.put("APPLICATION_COMMENTS",
params.title != null ? params.title : "");
data.put("APPLICATION_COPYRIGHT",
params.copyright != null ? params.copyright : "");
data.put("APPLICATION_LICENSE_FILE", getLicenseFile());
//default for .exe is user level installation
// only do system wide if explicitly requested
if (params.systemWide != null && params.systemWide) {
data.put("APPLICATION_INSTALL_ROOT", "{pf}");
data.put("APPLICATION_INSTALL_PRIVILEGE", "admin");
} else {
data.put("APPLICATION_INSTALL_ROOT", "{localappdata}");
data.put("APPLICATION_INSTALL_PRIVILEGE", "lowest");
}
Writer w = new BufferedWriter(new FileWriter(getConfig_ExeProjectFile()));
String content = preprocessTextResource(
WinAppBundler.WIN_BUNDLER_PREFIX + getConfig_ExeProjectFile().getName(),
"Inno Setup project file", DEFAULT_EXE_PROJECT_TEMPLATE, data);
w.write(content);
w.close();
return true;
}
private final static String DEFAULT_INNO_SETUP_ICON = "icon_inno_setup.bmp";
private boolean prepareProjectConfig() throws IOException {
prepareMainProjectFile(imageDir);
//prepare installer icon
File iconTarget = getConfig_SmallInnoSetupIcon();
fetchResource(WinAppBundler.WIN_BUNDLER_PREFIX + iconTarget.getName(),
"setup dialog icon",
DEFAULT_INNO_SETUP_ICON,
iconTarget);
fetchResource(WinAppBundler.WIN_BUNDLER_PREFIX + getConfig_Script().getName(),
"script to run after application image is populated",
(String) null,
getConfig_Script());
return true;
}
private File getConfig_SmallInnoSetupIcon() {
return new File(imageDir,
WinAppBundler.getAppName(params) + "-setup-icon.bmp");
}
private File getConfig_ExeProjectFile() {
return new File(imageDir,
WinAppBundler.getAppName(params) + ".iss");
}
private boolean buildEXE(File outdir) throws IOException {
Log.verbose("Generating EXE for installer to: " + outdir.getAbsolutePath());
outdir.mkdirs();
//run candle
ProcessBuilder pb = new ProcessBuilder(
TOOL_INNO_SETUP_COMPILER,
"/o"+outdir.getAbsolutePath(),
getConfig_ExeProjectFile().getAbsolutePath());
pb = pb.directory(imageDir);
IOUtils.exec(pb, verbose);
Log.info("Installer (.exe) saved to: " + outdir.getAbsolutePath());
return true;
}
}