modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/WinExeBundler.java
Print this page
@@ -36,69 +36,65 @@
import java.text.MessageFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import static com.oracle.bundlers.StandardBundlerParam.VERBOSE;
import static com.oracle.bundlers.windows.WindowsBundlerParam.*;
public class WinExeBundler extends AbstractBundler {
private static final ResourceBundle I18N =
ResourceBundle.getBundle("com.oracle.bundlers.windows.WinExeBundler");
public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER = new WindowsBundlerParam<>(
I18N.getString("param.app-bundler.name"),
I18N.getString("param.app-bundler.description"),
- "winAppBundler", //KEY
+ "win.app.bundler",
WinAppBundler.class, null, params -> new WinAppBundler(), false, null);
public static final BundlerParamInfo<File> CONFIG_ROOT = new WindowsBundlerParam<>(
I18N.getString("param.config-root.name"),
I18N.getString("param.config-root.description"),
- "configRoot", //KEY
+ "configRoot",
File.class, null,params -> {
- File imagesRoot = new File(StandardBundlerParam.BUILD_ROOT.fetchFrom(params), "windows");
+ File imagesRoot = new File(BUILD_ROOT.fetchFrom(params), "windows");
imagesRoot.mkdirs();
return imagesRoot;
- }, false, s -> null);
+ }, false, (s, p) -> null);
//default for .exe is user level installation
// only do system wide if explicitly requested
public static final StandardBundlerParam<Boolean> EXE_SYSTEM_WIDE =
new StandardBundlerParam<>(
I18N.getString("param.system-wide.name"),
I18N.getString("param.system-wide.description"),
- "winexe" + BundleParams.PARAM_SYSTEM_WIDE, //KEY
+ "win.exe." + BundleParams.PARAM_SYSTEM_WIDE,
Boolean.class,
new String[] {BundleParams.PARAM_SYSTEM_WIDE},
params -> false, // EXEs default to user local install
false,
- s -> (s == null || "null".equalsIgnoreCase(s))? null : Boolean.valueOf(s) // valueOf(null) is false, and we actually do want null
+ (s, p) -> (s == null || "null".equalsIgnoreCase(s))? null : Boolean.valueOf(s) // valueOf(null) is false, and we actually do want null
);
- public static final BundlerParamInfo<File> IMAGE_DIR = new WindowsBundlerParam<>(
+ public static final BundlerParamInfo<File> EXE_IMAGE_DIR = new WindowsBundlerParam<>(
I18N.getString("param.image-dir.name"),
I18N.getString("param.image-dir.description"),
- "imageDir", //KEY
+ "win.exe.imageDir",
File.class, null, params -> {
File imagesRoot = IMAGES_ROOT.fetchFrom(params);
- return new File(imagesRoot, "win-app.image");
- }, false, s -> null);
-
- public static final BundlerParamInfo<File> OUT_DIR = new WindowsBundlerParam<>(
- I18N.getString("param.out-dir.name"),
- I18N.getString("param.out-dir.description"),
- "outDir", //KEY
- File.class, null, params -> null, false, s -> null);
+ if (!imagesRoot.exists()) imagesRoot.mkdirs();
+ return new File(imagesRoot, "win-exe.image");
+ }, false, (s, p) -> null);
private final static String DEFAULT_EXE_PROJECT_TEMPLATE = "template.iss";
private static final String TOOL_INNO_SETUP_COMPILER = "iscc.exe";
public static final BundlerParamInfo<String> TOOL_INNO_SETUP_COMPILER_EXECUTABLE = new WindowsBundlerParam<>(
I18N.getString("param.iscc-path.name"),
I18N.getString("param.iscc-path.description"),
- "win.iscc.exe", //KEY
+ "win.exe.iscc.exe",
String.class, null, params -> {
for (String dirString : (System.getenv("PATH") + ";C:\\Program Files (x86)\\Inno Setup 5;C:\\Program Files\\Inno Setup 5").split(";")) {
File f = new File(dirString.replace("\"", ""), TOOL_INNO_SETUP_COMPILER);
if (f.isFile()) {
return f.toString();
@@ -122,11 +118,11 @@
return I18N.getString("bundler.description");
}
@Override
public String getID() {
- return "exe"; //KEY
+ return "exe";
}
@Override
public BundleType getBundleType() {
return BundleType.INSTALLER;
@@ -144,14 +140,15 @@
return Arrays.asList(
APP_BUNDLER,
APP_RESOURCES,
BUILD_ROOT,
//CONFIG_ROOT, // duplicate from getAppBundleParameters
+ DESCRIPTION,
COPYRIGHT,
EXE_SYSTEM_WIDE,
IDENTIFIER,
- IMAGE_DIR,
+ EXE_IMAGE_DIR,
IMAGES_ROOT,
LICENSE_FILES,
MENU_GROUP,
MENU_HINT,
SHORTCUT_HINT,
@@ -207,10 +204,11 @@
}
}
@Override
public boolean validate(Map<String, ? super Object> p) throws UnsupportedPlatformException, ConfigException {
+ try {
if (p == null) throw new ConfigException(I18N.getString("error.parameters-null"), I18N.getString("error.parameters-null.advice"));
//run basic validation to ensure requirements are met
//we are not interested in return code, only possible exception
APP_BUNDLER.fetchFrom(p).validate(p);
@@ -226,14 +224,17 @@
I18N.getString("error.iscc-not-found"),
I18N.getString("error.iscc-not-found.advice"));
}
return true;
+ } catch (RuntimeException re) {
+ throw new ConfigException(re);
+ }
}
private boolean prepareProto(Map<String, ? super Object> params) throws IOException {
- File imageDir = IMAGE_DIR.fetchFrom(params);
+ File imageDir = EXE_IMAGE_DIR.fetchFrom(params);
File appOutputDir = APP_BUNDLER.fetchFrom(params).doBundle(params, imageDir, true);
if (appOutputDir == null) {
return false;
}
List<String> licenseFiles = LICENSE_FILES.fetchFrom(params);
@@ -247,13 +248,20 @@
}
return true;
}
public File bundle(Map<String, ? super Object> p, File outputDirectory) {
- File imageDir = IMAGE_DIR.fetchFrom(p);
- try {
+ // validate we have valid tools before continuing
+ String iscc = TOOL_INNO_SETUP_COMPILER_EXECUTABLE.fetchFrom(p);
+ if (iscc == null || !new File(iscc).isFile()) {
+ Log.info(I18N.getString("error.iscc-not-found"));
+ Log.info(MessageFormat.format(I18N.getString("message.iscc-file-string"), iscc));
+ return null;
+ }
+ File imageDir = EXE_IMAGE_DIR.fetchFrom(p);
+ try {
imageDir.mkdirs();
boolean menuShortcut = MENU_HINT.fetchFrom(p);
boolean desktopShortcut = SHORTCUT_HINT.fetchFrom(p);
if (!menuShortcut && !desktopShortcut) {
@@ -264,21 +272,21 @@
if (prepareProto(p) && prepareProjectConfig(p)) {
File configScript = getConfig_Script(p);
if (configScript.exists()) {
Log.info(MessageFormat.format(I18N.getString("message.running-wsh-script"), configScript.getAbsolutePath()));
- IOUtils.run("wscript", configScript, verbose);
+ IOUtils.run("wscript", configScript, VERBOSE.fetchFrom(p));
}
return buildEXE(p, outputDirectory);
}
return null;
} catch (IOException ex) {
ex.printStackTrace();
return null;
} finally {
try {
- if (verbose) {
+ if (VERBOSE.fetchFrom(p)) {
saveConfigFiles(p);
}
if (imageDir != null && !Log.isDebug()) {
IOUtils.deleteRecursive(imageDir);
} else if (imageDir != null) {
@@ -291,17 +299,16 @@
}
}
//name of post-image script
private File getConfig_Script(Map<String, ? super Object> params) {
- return new File(IMAGE_DIR.fetchFrom(params), WinAppBundler.getAppName(params) + "-post-image.wsf");
+ return new File(EXE_IMAGE_DIR.fetchFrom(params), WinAppBundler.getAppName(params) + "-post-image.wsf");
}
protected void saveConfigFiles(Map<String, ? super Object> params) {
try {
File configRoot = CONFIG_ROOT.fetchFrom(params);
- File imagesRoot = IMAGES_ROOT.fetchFrom(params);
if (getConfig_ExeProjectFile(params).exists()) {
IOUtils.copyFile(getConfig_ExeProjectFile(params),
new File(configRoot, getConfig_ExeProjectFile(params).getName()));
}
if (getConfig_Script(params).exists()) {
@@ -350,11 +357,11 @@
data.put("APPLICATION_NAME", WinAppBundler.getAppName(params));
data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
data.put("APPLICATION_VERSION", VERSION.fetchFrom(params)); // TODO make our own version paraminfo?
data.put("APPLICATION_LAUNCHER_FILENAME",
- WinAppBundler.getLauncher(IMAGE_DIR.fetchFrom(params), params).getName());
+ WinAppBundler.getLauncher(EXE_IMAGE_DIR.fetchFrom(params), params).getName());
data.put("APPLICATION_DESKTOP_SHORTCUT", SHORTCUT_HINT.fetchFrom(params) ? "returnTrue" : "returnFalse");
data.put("APPLICATION_MENU_SHORTCUT", MENU_HINT.fetchFrom(params) ? "returnTrue" : "returnFalse");
data.put("APPLICATION_GROUP", MENU_GROUP.fetchFrom(params));
data.put("APPLICATION_COMMENTS", TITLE.fetchFrom(params)); // TODO this seems strange, at least in name
data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
@@ -373,16 +380,27 @@
data.put("ARCHITECTURE_BIT_MODE", "x64");
} else {
data.put("ARCHITECTURE_BIT_MODE", "");
}
-
+ if (SERVICE_HINT.fetchFrom(params)) {
+ data.put("RUN_FILENAME", WinAppBundler.getAppSvcName(params));
+ } else {
+ data.put("RUN_FILENAME", WinAppBundler.getAppName(params));
+ }
+ data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
+ data.put("APPLICATION_SERVICE", SERVICE_HINT.fetchFrom(params) ? "returnTrue" : "returnFalse");
+ data.put("APPLICATION_NOT_SERVICE", SERVICE_HINT.fetchFrom(params) ? "returnFalse" : "returnTrue");
+ data.put("START_ON_INSTALL", START_ON_INSTALL.fetchFrom(params) ? "-startOnInstall" : "");
+ data.put("STOP_ON_UNINSTALL", STOP_ON_UNINSTALL.fetchFrom(params) ? "-stopOnUninstall" : "");
+ data.put("RUN_AT_STARTUP", RUN_AT_STARTUP.fetchFrom(params) ? "-runAtStartup" : "");
Writer w = new BufferedWriter(new FileWriter(getConfig_ExeProjectFile(params)));
String content = preprocessTextResource(
WinAppBundler.WIN_BUNDLER_PREFIX + getConfig_ExeProjectFile(params).getName(),
- I18N.getString("resource.inno-setup-project-file"), DEFAULT_EXE_PROJECT_TEMPLATE, data);
+ I18N.getString("resource.inno-setup-project-file"), DEFAULT_EXE_PROJECT_TEMPLATE, data,
+ VERBOSE.fetchFrom(params));
w.write(content);
w.close();
return true;
}
@@ -394,26 +412,28 @@
//prepare installer icon
File iconTarget = getConfig_SmallInnoSetupIcon(params);
fetchResource(WinAppBundler.WIN_BUNDLER_PREFIX + iconTarget.getName(),
I18N.getString("resource.setup-icon"),
DEFAULT_INNO_SETUP_ICON,
- iconTarget);
+ iconTarget,
+ VERBOSE.fetchFrom(params));
fetchResource(WinAppBundler.WIN_BUNDLER_PREFIX + getConfig_Script(params).getName(),
I18N.getString("resource.post-install-script"),
(String) null,
- getConfig_Script(params));
+ getConfig_Script(params),
+ VERBOSE.fetchFrom(params));
return true;
}
private File getConfig_SmallInnoSetupIcon(Map<String, ? super Object> params) {
- return new File(IMAGE_DIR.fetchFrom(params),
+ return new File(EXE_IMAGE_DIR.fetchFrom(params),
WinAppBundler.getAppName(params) + "-setup-icon.bmp");
}
private File getConfig_ExeProjectFile(Map<String, ? super Object> params) {
- return new File(IMAGE_DIR.fetchFrom(params),
+ return new File(EXE_IMAGE_DIR.fetchFrom(params),
WinAppBundler.getAppName(params) + ".iss");
}
private File buildEXE(Map<String, ? super Object> params, File outdir) throws IOException {
@@ -424,14 +444,27 @@
//run candle
ProcessBuilder pb = new ProcessBuilder(
TOOL_INNO_SETUP_COMPILER_EXECUTABLE.fetchFrom(params),
"/o"+outdir.getAbsolutePath(),
getConfig_ExeProjectFile(params).getAbsolutePath());
- pb = pb.directory(IMAGE_DIR.fetchFrom(params));
- IOUtils.exec(pb, verbose);
+ pb = pb.directory(EXE_IMAGE_DIR.fetchFrom(params));
+ IOUtils.exec(pb, VERBOSE.fetchFrom(params));
Log.info(MessageFormat.format(I18N.getString("message.output-location"), outdir.getAbsolutePath()));
- return outdir;
+ // presume the result is the ".exe" file with the newest modified time
+ // not the best solution, but it is the most reliable
+ File result = null;
+ long lastModified = 0;
+ File[] list = outdir.listFiles();
+ if (list != null) {
+ for (File f : list) {
+ if (f.getName().endsWith(".exe") && f.lastModified() > lastModified) {
+ result = f;
+ lastModified = f.lastModified();
+ }
+ }
}
-}
+ return result;
+ }
+}