24 */ 25 26 package com.sun.javafx.tools.packager.bundlers; 27 28 import com.oracle.bundlers.AbstractBundler; 29 import com.oracle.bundlers.BundlerParamInfo; 30 import com.oracle.bundlers.StandardBundlerParam; 31 import com.oracle.bundlers.windows.WindowsBundlerParam; 32 import com.sun.javafx.tools.packager.Log; 33 import com.sun.javafx.tools.resource.windows.WinResources; 34 35 import java.io.File; 36 import java.io.FileNotFoundException; 37 import java.io.IOException; 38 import java.io.PrintStream; 39 import java.net.MalformedURLException; 40 import java.net.URL; 41 import java.text.MessageFormat; 42 import java.util.*; 43 44 import static com.oracle.bundlers.StandardBundlerParam.*; 45 import static com.oracle.bundlers.windows.WindowsBundlerParam.BIT_ARCH_64; 46 import static com.oracle.bundlers.windows.WindowsBundlerParam.BIT_ARCH_64_RUNTIME; 47 48 public class WinAppBundler extends AbstractBundler { 49 50 private static final ResourceBundle I18N = 51 ResourceBundle.getBundle("com.oracle.bundlers.windows.WinAppBundler"); 52 53 public static final BundlerParamInfo<File> CONFIG_ROOT = new WindowsBundlerParam<>( 54 I18N.getString("param.config-root.name"), 55 I18N.getString("param.config-root.description"), 56 "configRoot", //KEY 57 File.class, null, params -> { 58 File imagesRoot = new File(StandardBundlerParam.BUILD_ROOT.fetchFrom(params), "windows"); 59 imagesRoot.mkdirs(); 60 return imagesRoot; 61 }, false, s -> null); 62 63 private final static String EXECUTABLE_NAME = "WinLauncher.exe"; 64 private static final String TOOL_ICON_SWAP="IconSwap.exe"; 65 66 public static final BundlerParamInfo<URL> RAW_EXECUTABLE_URL = new WindowsBundlerParam<>( 67 I18N.getString("param.raw-executable-url.name"), 68 I18N.getString("param.raw-executable-url.description"), 69 "win.launcher.url", //KEY 70 URL.class, null, params -> WinResources.class.getResource(EXECUTABLE_NAME), 71 false, s -> { 72 try { 73 return new URL(s); 74 } catch (MalformedURLException e) { 75 Log.info(e.toString()); 76 return null; 77 } 78 }); 79 80 public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE = new WindowsBundlerParam<>( 81 I18N.getString("param.rebrand-executable.name"), 82 I18N.getString("param.rebrand-executable.description"), 83 "win.launcher.rebrand", //KEY 84 Boolean.class, null, params -> Boolean.TRUE, 85 false, Boolean::valueOf); 86 87 public WinAppBundler() { 88 super(); 89 baseResourceLoader = WinResources.class; 90 } 91 92 public final static String WIN_BUNDLER_PREFIX = 93 BUNDLER_PREFIX + "windows/"; 94 95 File getConfigRoot(Map<String, ? super Object> params) { 96 return CONFIG_ROOT.fetchFrom(params); 97 } 98 99 @Override 100 public boolean validate(Map<String, ? super Object> params) throws UnsupportedPlatformException, ConfigException { 101 if (params == null) throw new ConfigException( 102 I18N.getString("error.parameters-null"), 103 I18N.getString("error.parameters-null.advice")); 104 105 return doValidate(params); 106 } 107 108 //to be used by chained bundlers, e.g. by EXE bundler to avoid 109 // skipping validation if p.type does not include "image" 110 boolean doValidate(Map<String, ? super Object> p) throws UnsupportedPlatformException, ConfigException { 111 if (!System.getProperty("os.name").toLowerCase().startsWith("win")) { 112 throw new UnsupportedPlatformException(); 113 } 114 115 if (WinResources.class.getResource(TOOL_ICON_SWAP) == null) { 116 throw new ConfigException( 117 I18N.getString("error.no-windows-resources"), 118 I18N.getString("error.no-windows-resources.advice")); 119 } 120 121 if (StandardBundlerParam.MAIN_JAR.fetchFrom(p) == null) { 122 throw new ConfigException( 123 I18N.getString("error.no-application-jar"), 124 I18N.getString("error.no-application-jar.advice")); 125 } 126 127 //validate required inputs 128 if (USE_FX_PACKAGING.fetchFrom(p)) { 129 testRuntime(p, new String[] {"lib/ext/jfxrt.jar", "lib/jfxrt.jar"}); 130 } 131 132 //validate runtime bit-architectire 133 testRuntimeBitArchitecture(p); 134 135 return true; 136 } 137 138 private static void testRuntimeBitArchitecture(Map<String, ? super Object> params) throws ConfigException { 139 if ("true".equalsIgnoreCase(System.getProperty("fxpackager.disableBitArchitectureMismatchCheck"))) { 140 Log.debug(I18N.getString("message.disable-bit-architecture-check")); 141 return; 142 } 143 144 if (BIT_ARCH_64.fetchFrom(params) != BIT_ARCH_64_RUNTIME.fetchFrom(params)) { 145 throw new ConfigException( 146 I18N.getString("error.bit-architecture-mismatch"), 147 I18N.getString("error.bit-architecture-mismatch.advice")); 148 } 149 } 150 151 static String getAppName(Map<String, ? super Object> p) { 152 return StandardBundlerParam.APP_NAME.fetchFrom(p); 153 } 154 155 //it is static for the sake of sharing with "Exe" bundles 156 // that may skip calls to validate/bundle in this class! 157 private static File getRootDir(File outDir, Map<String, ? super Object> p) { 158 return new File(outDir, getAppName(p)); 159 } 160 161 public static File getLauncher(File outDir, Map<String, ? super Object> p) { 162 return new File(getRootDir(outDir, p), getAppName(p)+".exe"); 163 } 164 165 private File getConfig_AppIcon(Map<String, ? super Object> params) { 166 return new File(getConfigRoot(params), getAppName(params) + ".ico"); 167 } 168 169 private final static String TEMPLATE_APP_ICON ="javalogo_white_48.ico"; 170 171 //remove 172 protected void cleanupConfigFiles(Map<String, ? super Object> params) { 173 if (getConfig_AppIcon(params) != null) { 174 getConfig_AppIcon(params).delete(); 175 } 176 } 177 178 private void prepareConfigFiles(Map<String, ? super Object> params) throws IOException { 179 File iconTarget = getConfig_AppIcon(params); 180 181 File icon = ICON.fetchFrom(params); 182 if (icon != null && icon.exists()) { 183 fetchResource(WIN_BUNDLER_PREFIX + iconTarget.getName(), 184 I18N.getString("resource.application-icon"), 185 icon, 186 iconTarget); 187 } else { 188 fetchResource(WIN_BUNDLER_PREFIX + iconTarget.getName(), 189 I18N.getString("resource.application-icon"), 190 WinAppBundler.TEMPLATE_APP_ICON, 191 iconTarget); 192 } 193 } 194 195 public boolean bundle(Map<String, ? super Object> p, File outputDirectory) { 196 return doBundle(p, outputDirectory, false) != null; 197 } 198 199 File doBundle(Map<String, ? super Object> p, File outputDirectory, boolean dependentTask) { 200 try { 201 outputDirectory.mkdirs(); 202 203 if (!dependentTask) { 204 Log.info(MessageFormat.format(I18N.getString("message.creating-app-bundle"), getAppName(p), outputDirectory.getAbsolutePath())); 205 } 206 207 prepareConfigFiles(p); 208 209 // Create directory structure 210 File rootDirectory = getRootDir(outputDirectory, p); 211 IOUtils.deleteRecursive(rootDirectory); 212 rootDirectory.mkdirs(); 213 214 File appDirectory = new File(rootDirectory, "app"); 215 appDirectory.mkdirs(); 216 copyApplication(p, appDirectory); 217 218 // Generate PkgInfo 219 File pkgInfoFile = new File(appDirectory, "package.cfg"); 220 pkgInfoFile.createNewFile(); 221 writePkgInfo(p, pkgInfoFile); 222 223 // Copy executable root folder 224 File executableFile = getLauncher(outputDirectory, p); 225 IOUtils.copyFromURL( 226 RAW_EXECUTABLE_URL.fetchFrom(p), 227 executableFile); 228 executableFile.setExecutable(true, false); 229 230 //Update branding of exe file 231 if (REBRAND_EXECUTABLE.fetchFrom(p) && getConfig_AppIcon(p).exists()) { 232 //extract helper tool 233 File iconSwapTool = File.createTempFile("iconswap", ".exe"); 234 iconSwapTool.delete(); 235 IOUtils.copyFromURL( 236 WinResources.class.getResource(TOOL_ICON_SWAP), 237 iconSwapTool); 238 iconSwapTool.setExecutable(true, false); 239 iconSwapTool.deleteOnExit(); 240 241 //run it on launcher file 242 executableFile.setWritable(true); 243 ProcessBuilder pb = new ProcessBuilder( 244 iconSwapTool.getAbsolutePath(), 245 getConfig_AppIcon(p).getAbsolutePath(), 246 executableFile.getAbsolutePath()); 247 IOUtils.exec(pb, verbose); 248 executableFile.setReadOnly(); 249 iconSwapTool.delete(); 250 } 251 252 // Copy runtime to PlugIns folder 253 File runtimeDirectory = new File(rootDirectory, "runtime"); 254 copyRuntime(p, runtimeDirectory); 255 256 IOUtils.copyFile(getConfig_AppIcon(p), 257 new File(getRootDir(outputDirectory, p), getAppName(p) + ".ico")); 258 259 if (!dependentTask) { 260 Log.info(MessageFormat.format(I18N.getString("message.result-dir"), outputDirectory.getAbsolutePath())); 261 } 262 263 return rootDirectory; 264 } catch (IOException ex) { 265 System.out.println("Exception: "+ex); 266 ex.printStackTrace(); 267 return null; 268 } finally { 269 if (verbose) { 270 Log.info(MessageFormat.format(I18N.getString("message.config-save-location"), getConfigRoot(p).getAbsolutePath())); 271 } else { 272 cleanupConfigFiles(p); 273 } 274 } 275 276 } 277 278 @Override 279 public String toString() { 280 return "Windows Application Bundler"; 281 } 282 283 private void copyApplication(Map<String, ? super Object> params, File appDirectory) throws IOException { 284 RelativeFileSet appResource = APP_RESOURCES.fetchFrom(params); 285 if (appResource == null) { 286 throw new RuntimeException("Null app resources?"); 287 } 288 File srcdir = appResource.getBaseDirectory(); 289 for (String fname : appResource.getIncludedFiles()) { 324 idx++; 325 } 326 327 328 Map<String, String> overridableJVMOptions = USER_JVM_OPTIONS.fetchFrom(params); 329 idx = 1; 330 for (Map.Entry<String, String> arg: overridableJVMOptions.entrySet()) { 331 if (arg.getKey() == null || arg.getValue() == null) { 332 Log.info(I18N.getString("message.jvm-user-arg-is-null")); 333 } 334 else { 335 out.println("jvmuserarg."+idx+".name="+arg.getKey()); 336 out.println("jvmuserarg."+idx+".value="+arg.getValue()); 337 } 338 idx++; 339 } 340 out.close(); 341 } 342 343 private void copyRuntime(Map<String, ? super Object> params, File runtimeDirectory) throws IOException { 344 RelativeFileSet runtime = RUNTIME.fetchFrom(params); 345 if (runtime == null) { 346 //its ok, request to use system JRE 347 return; 348 } 349 runtimeDirectory.mkdirs(); 350 351 File srcdir = runtime.getBaseDirectory(); 352 File destDir = new File(runtimeDirectory, srcdir.getName()); 353 Set<String> filesToCopy = runtime.getIncludedFiles(); 354 for (String fname : filesToCopy) { 355 IOUtils.copyFile( 356 new File(srcdir, fname), new File(destDir, fname)); 357 } 358 } 359 360 @Override 361 public String getName() { 362 return I18N.getString("bundler.name"); 363 } 364 365 @Override 366 public String getDescription() { 367 return I18N.getString("bundler.description"); 368 } 369 370 @Override 371 public String getID() { 372 return "windows.app"; //KEY 373 } 374 375 @Override 376 public BundleType getBundleType() { 377 return BundleType.IMAGE; 378 } 379 380 @Override 381 public Collection<BundlerParamInfo<?>> getBundleParameters() { 382 return getAppBundleParameters(); 383 } 384 385 public static Collection<BundlerParamInfo<?>> getAppBundleParameters() { 386 return Arrays.asList( 387 APP_NAME, 388 APP_RESOURCES, 389 BUILD_ROOT, 390 CONFIG_ROOT, 391 ICON, 392 IDENTIFIER, 393 JVM_OPTIONS, 394 JVM_PROPERTIES, 395 MAIN_CLASS, 396 MAIN_JAR, 397 MAIN_JAR_CLASSPATH, 398 PREFERENCES_ID, 399 RAW_EXECUTABLE_URL, 400 RUNTIME, 401 USE_FX_PACKAGING, 402 USER_JVM_OPTIONS, 403 VERSION 404 ); 405 } 406 407 @Override 408 public File execute(Map<String, ? super Object> params, File outputParentDir) { 409 return doBundle(params, outputParentDir, false); 410 } 411 } | 24 */ 25 26 package com.sun.javafx.tools.packager.bundlers; 27 28 import com.oracle.bundlers.AbstractBundler; 29 import com.oracle.bundlers.BundlerParamInfo; 30 import com.oracle.bundlers.StandardBundlerParam; 31 import com.oracle.bundlers.windows.WindowsBundlerParam; 32 import com.sun.javafx.tools.packager.Log; 33 import com.sun.javafx.tools.resource.windows.WinResources; 34 35 import java.io.File; 36 import java.io.FileNotFoundException; 37 import java.io.IOException; 38 import java.io.PrintStream; 39 import java.net.MalformedURLException; 40 import java.net.URL; 41 import java.text.MessageFormat; 42 import java.util.*; 43 44 import static com.oracle.bundlers.JreUtils.*; 45 import static com.oracle.bundlers.StandardBundlerParam.*; 46 import static com.oracle.bundlers.windows.WindowsBundlerParam.BIT_ARCH_64; 47 import static com.oracle.bundlers.windows.WindowsBundlerParam.BIT_ARCH_64_RUNTIME; 48 49 public class WinAppBundler extends AbstractBundler { 50 51 private static final ResourceBundle I18N = 52 ResourceBundle.getBundle("com.oracle.bundlers.windows.WinAppBundler"); 53 54 public static final BundlerParamInfo<File> CONFIG_ROOT = new WindowsBundlerParam<>( 55 I18N.getString("param.config-root.name"), 56 I18N.getString("param.config-root.description"), 57 "configRoot", 58 File.class, null, params -> { 59 File imagesRoot = new File(BUILD_ROOT.fetchFrom(params), "windows"); 60 imagesRoot.mkdirs(); 61 return imagesRoot; 62 }, false, (s, p) -> null); 63 64 //Subsetting of JRE is restricted. 65 //JRE README defines what is allowed to strip: 66 // http://www.oracle.com/technetwork/java/javase/jre-7-readme-430162.html //TODO update when 8 goes GA 67 public static final BundlerParamInfo<Rule[]> WIN_JRE_RULES = new StandardBundlerParam<>( 68 "", 69 "", 70 ".win.runtime.rules", 71 Rule[].class, 72 null, 73 params -> new Rule[]{ 74 Rule.prefixNeg("\\bin\\new_plugin"), 75 Rule.prefixNeg("\\lib\\deploy"), 76 Rule.suffixNeg(".pdb"), 77 Rule.suffixNeg(".map"), 78 Rule.suffixNeg("axbridge.dll"), 79 Rule.suffixNeg("eula.dll"), 80 Rule.substrNeg("javacpl"), 81 Rule.suffixNeg("wsdetect.dll"), 82 Rule.substrNeg("eployjava1.dll"), //NP and IE versions 83 Rule.substrNeg("bin\\jp2"), 84 Rule.substrNeg("bin\\jpi"), 85 //Rule.suffixNeg("lib\\ext"), //need some of jars there for https to work 86 Rule.suffixNeg("ssv.dll"), 87 Rule.substrNeg("npjpi"), 88 Rule.substrNeg("npoji"), 89 Rule.suffixNeg(".exe"), 90 //keep core deploy files as JavaFX APIs use them 91 //Rule.suffixNeg("deploy.dll"), 92 Rule.suffixNeg("deploy.jar"), 93 //Rule.suffixNeg("javaws.jar"), 94 //Rule.suffixNeg("plugin.jar"), 95 Rule.suffix(".jar") 96 }, 97 false, 98 (s, p) -> null 99 ); 100 101 public static final BundlerParamInfo<RelativeFileSet> WIN_RUNTIME = new StandardBundlerParam<>( 102 RUNTIME.getName(), 103 RUNTIME.getDescription(), 104 RUNTIME.getID(), 105 RelativeFileSet.class, 106 null, 107 params -> extractJreAsRelativeFileSet(System.getProperty("java.home"), 108 WIN_JRE_RULES.fetchFrom(params)), 109 false, 110 (s, p) -> extractJreAsRelativeFileSet(s, 111 WIN_JRE_RULES.fetchFrom(p)) 112 ); 113 114 private final static String EXECUTABLE_NAME = "WinLauncher.exe"; 115 private final static String EXECUTABLE_SVC_NAME = "WinLauncherSvc.exe"; 116 117 private static final String TOOL_ICON_SWAP="IconSwap.exe"; 118 119 public static final BundlerParamInfo<URL> RAW_EXECUTABLE_URL = new WindowsBundlerParam<>( 120 I18N.getString("param.raw-executable-url.name"), 121 I18N.getString("param.raw-executable-url.description"), 122 "win.launcher.url", 123 URL.class, null, params -> WinResources.class.getResource(EXECUTABLE_NAME), 124 false, (s, p) -> { 125 try { 126 return new URL(s); 127 } catch (MalformedURLException e) { 128 Log.info(e.toString()); 129 return null; 130 } 131 }); 132 133 public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE = new WindowsBundlerParam<>( 134 I18N.getString("param.rebrand-executable.name"), 135 I18N.getString("param.rebrand-executable.description"), 136 "win.launcher.rebrand", 137 Boolean.class, null, params -> Boolean.TRUE, 138 false, (s, p) -> Boolean.valueOf(s)); 139 140 public WinAppBundler() { 141 super(); 142 baseResourceLoader = WinResources.class; 143 } 144 145 public final static String WIN_BUNDLER_PREFIX = 146 BUNDLER_PREFIX + "windows/"; 147 148 File getConfigRoot(Map<String, ? super Object> params) { 149 return CONFIG_ROOT.fetchFrom(params); 150 } 151 152 @Override 153 public boolean validate(Map<String, ? super Object> params) throws UnsupportedPlatformException, ConfigException { 154 try { 155 if (params == null) throw new ConfigException( 156 I18N.getString("error.parameters-null"), 157 I18N.getString("error.parameters-null.advice")); 158 159 return doValidate(params); 160 } catch (RuntimeException re) { 161 throw new ConfigException(re); 162 } 163 } 164 165 //to be used by chained bundlers, e.g. by EXE bundler to avoid 166 // skipping validation if p.type does not include "image" 167 boolean doValidate(Map<String, ? super Object> p) throws UnsupportedPlatformException, ConfigException { 168 if (!System.getProperty("os.name").toLowerCase().startsWith("win")) { 169 throw new UnsupportedPlatformException(); 170 } 171 172 if (WinResources.class.getResource(TOOL_ICON_SWAP) == null) { 173 throw new ConfigException( 174 I18N.getString("error.no-windows-resources"), 175 I18N.getString("error.no-windows-resources.advice")); 176 } 177 178 if (SERVICE_HINT.fetchFrom(p) && WinResources.class.getResource(EXECUTABLE_SVC_NAME) == null) { 179 throw new ConfigException( 180 I18N.getString("error.no-windows-resources"), 181 I18N.getString("error.no-windows-resources.advice")); 182 } 183 184 if (MAIN_JAR.fetchFrom(p) == null) { 185 throw new ConfigException( 186 I18N.getString("error.no-application-jar"), 187 I18N.getString("error.no-application-jar.advice")); 188 } 189 190 //validate required inputs 191 if (USE_FX_PACKAGING.fetchFrom(p)) { 192 testRuntime(p, new String[] {"lib/ext/jfxrt.jar", "lib/jfxrt.jar"}); 193 } 194 195 //validate runtime bit-architectire 196 testRuntimeBitArchitecture(p); 197 198 return true; 199 } 200 201 private static void testRuntimeBitArchitecture(Map<String, ? super Object> params) throws ConfigException { 202 if ("true".equalsIgnoreCase(System.getProperty("fxpackager.disableBitArchitectureMismatchCheck"))) { 203 Log.debug(I18N.getString("message.disable-bit-architecture-check")); 204 return; 205 } 206 207 if (BIT_ARCH_64.fetchFrom(params) != BIT_ARCH_64_RUNTIME.fetchFrom(params)) { 208 throw new ConfigException( 209 I18N.getString("error.bit-architecture-mismatch"), 210 I18N.getString("error.bit-architecture-mismatch.advice")); 211 } 212 } 213 214 static String getAppName(Map<String, ? super Object> p) { 215 return APP_NAME.fetchFrom(p); 216 } 217 218 static String getAppSvcName(Map<String, ? super Object> p) { 219 return APP_NAME.fetchFrom(p) + "Svc"; 220 } 221 222 //it is static for the sake of sharing with "Exe" bundles 223 // that may skip calls to validate/bundle in this class! 224 private static File getRootDir(File outDir, Map<String, ? super Object> p) { 225 return new File(outDir, getAppName(p)); 226 } 227 228 public static File getLauncher(File outDir, Map<String, ? super Object> p) { 229 return new File(getRootDir(outDir, p), getAppName(p)+".exe"); 230 } 231 232 public static File getLauncherSvc(File outDir, Map<String, ? super Object> p) { 233 return new File(getRootDir(outDir, p), getAppName(p)+"Svc.exe"); 234 } 235 236 private File getConfig_AppIcon(Map<String, ? super Object> params) { 237 return new File(getConfigRoot(params), getAppName(params) + ".ico"); 238 } 239 240 private final static String TEMPLATE_APP_ICON ="javalogo_white_48.ico"; 241 242 //remove 243 protected void cleanupConfigFiles(Map<String, ? super Object> params) { 244 if (getConfig_AppIcon(params) != null) { 245 getConfig_AppIcon(params).delete(); 246 } 247 } 248 249 private void prepareConfigFiles(Map<String, ? super Object> params) throws IOException { 250 File iconTarget = getConfig_AppIcon(params); 251 252 File icon = ICON.fetchFrom(params); 253 if (icon != null && icon.exists()) { 254 fetchResource(WIN_BUNDLER_PREFIX + iconTarget.getName(), 255 I18N.getString("resource.application-icon"), 256 icon, 257 iconTarget, 258 VERBOSE.fetchFrom(params)); 259 } else { 260 fetchResource(WIN_BUNDLER_PREFIX + iconTarget.getName(), 261 I18N.getString("resource.application-icon"), 262 WinAppBundler.TEMPLATE_APP_ICON, 263 iconTarget, 264 VERBOSE.fetchFrom(params)); 265 } 266 } 267 268 public boolean bundle(Map<String, ? super Object> p, File outputDirectory) { 269 return doBundle(p, outputDirectory, false) != null; 270 } 271 272 File doBundle(Map<String, ? super Object> p, File outputDirectory, boolean dependentTask) { 273 try { 274 outputDirectory.mkdirs(); 275 276 if (!dependentTask) { 277 Log.info(MessageFormat.format(I18N.getString("message.creating-app-bundle"), getAppName(p), outputDirectory.getAbsolutePath())); 278 } 279 280 prepareConfigFiles(p); 281 282 // Create directory structure 283 File rootDirectory = getRootDir(outputDirectory, p); 284 IOUtils.deleteRecursive(rootDirectory); 285 rootDirectory.mkdirs(); 286 287 File appDirectory = new File(rootDirectory, "app"); 288 appDirectory.mkdirs(); 289 copyApplication(p, appDirectory); 290 291 // Generate PkgInfo 292 File pkgInfoFile = new File(appDirectory, "package.cfg"); 293 pkgInfoFile.createNewFile(); 294 writePkgInfo(p, pkgInfoFile); 295 296 // Copy executable root folder 297 File executableFile = getLauncher(outputDirectory, p); 298 IOUtils.copyFromURL( 299 RAW_EXECUTABLE_URL.fetchFrom(p), 300 executableFile); 301 executableFile.setExecutable(true, false); 302 303 // Copy executable to install application as service 304 if (SERVICE_HINT.fetchFrom(p)) { 305 File executableSvcFile = getLauncherSvc(outputDirectory, p); 306 IOUtils.copyFromURL( 307 WinResources.class.getResource(EXECUTABLE_SVC_NAME), 308 executableSvcFile); 309 executableSvcFile.setExecutable(true, false); 310 } 311 312 //Update branding of exe file 313 if (REBRAND_EXECUTABLE.fetchFrom(p) && getConfig_AppIcon(p).exists()) { 314 //extract helper tool 315 File iconSwapTool = File.createTempFile("iconswap", ".exe"); 316 iconSwapTool.delete(); 317 IOUtils.copyFromURL( 318 WinResources.class.getResource(TOOL_ICON_SWAP), 319 iconSwapTool); 320 iconSwapTool.setExecutable(true, false); 321 iconSwapTool.deleteOnExit(); 322 323 //run it on launcher file 324 executableFile.setWritable(true); 325 ProcessBuilder pb = new ProcessBuilder( 326 iconSwapTool.getAbsolutePath(), 327 getConfig_AppIcon(p).getAbsolutePath(), 328 executableFile.getAbsolutePath()); 329 IOUtils.exec(pb, VERBOSE.fetchFrom(p)); 330 executableFile.setReadOnly(); 331 iconSwapTool.delete(); 332 } 333 334 // Copy runtime to PlugIns folder 335 File runtimeDirectory = new File(rootDirectory, "runtime"); 336 copyRuntime(p, runtimeDirectory); 337 338 IOUtils.copyFile(getConfig_AppIcon(p), 339 new File(getRootDir(outputDirectory, p), getAppName(p) + ".ico")); 340 341 if (!dependentTask) { 342 Log.info(MessageFormat.format(I18N.getString("message.result-dir"), outputDirectory.getAbsolutePath())); 343 } 344 345 return rootDirectory; 346 } catch (IOException ex) { 347 System.out.println("Exception: "+ex); 348 ex.printStackTrace(); 349 return null; 350 } finally { 351 if (VERBOSE.fetchFrom(p)) { 352 Log.info(MessageFormat.format(I18N.getString("message.config-save-location"), getConfigRoot(p).getAbsolutePath())); 353 } else { 354 cleanupConfigFiles(p); 355 } 356 } 357 358 } 359 360 @Override 361 public String toString() { 362 return "Windows Application Bundler"; 363 } 364 365 private void copyApplication(Map<String, ? super Object> params, File appDirectory) throws IOException { 366 RelativeFileSet appResource = APP_RESOURCES.fetchFrom(params); 367 if (appResource == null) { 368 throw new RuntimeException("Null app resources?"); 369 } 370 File srcdir = appResource.getBaseDirectory(); 371 for (String fname : appResource.getIncludedFiles()) { 406 idx++; 407 } 408 409 410 Map<String, String> overridableJVMOptions = USER_JVM_OPTIONS.fetchFrom(params); 411 idx = 1; 412 for (Map.Entry<String, String> arg: overridableJVMOptions.entrySet()) { 413 if (arg.getKey() == null || arg.getValue() == null) { 414 Log.info(I18N.getString("message.jvm-user-arg-is-null")); 415 } 416 else { 417 out.println("jvmuserarg."+idx+".name="+arg.getKey()); 418 out.println("jvmuserarg."+idx+".value="+arg.getValue()); 419 } 420 idx++; 421 } 422 out.close(); 423 } 424 425 private void copyRuntime(Map<String, ? super Object> params, File runtimeDirectory) throws IOException { 426 RelativeFileSet runtime = WIN_RUNTIME.fetchFrom(params); 427 if (runtime == null) { 428 //its ok, request to use system JRE 429 return; 430 } 431 runtimeDirectory.mkdirs(); 432 433 File srcdir = runtime.getBaseDirectory(); 434 File destDir = new File(runtimeDirectory, srcdir.getName()); 435 Set<String> filesToCopy = runtime.getIncludedFiles(); 436 for (String fname : filesToCopy) { 437 IOUtils.copyFile( 438 new File(srcdir, fname), new File(destDir, fname)); 439 } 440 } 441 442 @Override 443 public String getName() { 444 return I18N.getString("bundler.name"); 445 } 446 447 @Override 448 public String getDescription() { 449 return I18N.getString("bundler.description"); 450 } 451 452 @Override 453 public String getID() { 454 return "windows.app"; 455 } 456 457 @Override 458 public BundleType getBundleType() { 459 return BundleType.IMAGE; 460 } 461 462 @Override 463 public Collection<BundlerParamInfo<?>> getBundleParameters() { 464 return getAppBundleParameters(); 465 } 466 467 public static Collection<BundlerParamInfo<?>> getAppBundleParameters() { 468 return Arrays.asList( 469 APP_NAME, 470 APP_RESOURCES, 471 BUILD_ROOT, 472 CONFIG_ROOT, 473 ICON, 474 IDENTIFIER, 475 JVM_OPTIONS, 476 JVM_PROPERTIES, 477 MAIN_CLASS, 478 MAIN_JAR, 479 MAIN_JAR_CLASSPATH, 480 PREFERENCES_ID, 481 RAW_EXECUTABLE_URL, 482 WIN_RUNTIME, 483 USE_FX_PACKAGING, 484 USER_JVM_OPTIONS, 485 VERSION 486 ); 487 } 488 489 @Override 490 public File execute(Map<String, ? super Object> params, File outputParentDir) { 491 return doBundle(params, outputParentDir, false); 492 } 493 } |