63
64 private final static String LIBRARY_NAME = "applauncher.dll";
65 private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll";
66 private final static String REDIST_MSVCP = "msvcpVS_VER.dll";
67
68 private final static String TEMPLATE_APP_ICON ="javalogo_white_48.ico";
69
70 private static final String EXECUTABLE_PROPERTIES_TEMPLATE =
71 "WinLauncher.template";
72
73 private final Path root;
74 private final Path appDir;
75 private final Path appModsDir;
76 private final Path runtimeDir;
77 private final Path mdir;
78
79 private final Map<String, ? super Object> params;
80
81 public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE =
82 new WindowsBundlerParam<>(
83 I18N.getString("param.rebrand-executable.name"),
84 I18N.getString("param.rebrand-executable.description"),
85 "win.launcher.rebrand",
86 Boolean.class,
87 params -> Boolean.TRUE,
88 (s, p) -> Boolean.valueOf(s));
89
90 public static final BundlerParamInfo<File> ICON_ICO =
91 new StandardBundlerParam<>(
92 I18N.getString("param.icon-ico.name"),
93 I18N.getString("param.icon-ico.description"),
94 "icon.ico",
95 File.class,
96 params -> {
97 File f = ICON.fetchFrom(params);
98 if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
99 Log.error(MessageFormat.format(
100 I18N.getString("message.icon-not-ico"), f));
101 return null;
102 }
103 return f;
104 },
105 (s, p) -> new File(s));
106
107 public static final StandardBundlerParam<Boolean> CONSOLE_HINT =
108 new WindowsBundlerParam<>(
109 I18N.getString("param.console-hint.name"),
110 I18N.getString("param.console-hint.description"),
111 Arguments.CLIOptions.WIN_CONSOLE_HINT.getId(),
112 Boolean.class,
113 params -> false,
114 // valueOf(null) is false,
115 // and we actually do want null in some cases
116 (s, p) -> (s == null
117 || "null".equalsIgnoreCase(s)) ? true : Boolean.valueOf(s));
118
119 public WindowsAppImageBuilder(Map<String, Object> config, Path imageOutDir)
120 throws IOException {
121 super(config,
122 imageOutDir.resolve(APP_NAME.fetchFrom(config) + "/runtime"));
123
124 Objects.requireNonNull(imageOutDir);
125
126 this.params = config;
127
128 this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params));
129 this.appDir = root.resolve("app");
130 this.appModsDir = appDir.resolve("mods");
239 "error.cannot-create-output-dir"), rootFile.getAbsolutePath()));
240 }
241 if (!rootFile.canWrite()) {
242 throw new RuntimeException(MessageFormat.format(
243 I18N.getString("error.cannot-write-to-output-dir"),
244 rootFile.getAbsolutePath()));
245 }
246 // create the .exe launchers
247 createLauncherForEntryPoint(params);
248
249 // copy the jars
250 copyApplication(params);
251
252 // copy in the needed libraries
253 try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
254 Files.copy(is_lib, root.resolve(LIBRARY_NAME));
255 }
256
257 copyMSVCDLLs();
258
259 // create the secondary launchers, if any
260 List<Map<String, ? super Object>> entryPoints =
261 StandardBundlerParam.SECONDARY_LAUNCHERS.fetchFrom(params);
262 for (Map<String, ? super Object> entryPoint : entryPoints) {
263 Map<String, ? super Object> tmp = new HashMap<>(originalParams);
264 tmp.putAll(entryPoint);
265 createLauncherForEntryPoint(tmp);
266 }
267 }
268
269 @Override
270 public void prepareJreFiles() throws IOException {}
271
272 private void copyMSVCDLLs() throws IOException {
273 AtomicReference<IOException> ioe = new AtomicReference<>();
274 try (Stream<Path> files = Files.list(runtimeDir.resolve("bin"))) {
275 files.filter(p -> Pattern.matches(
276 "^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$",
277 p.toFile().getName().toLowerCase()))
278 .forEach(p -> {
279 try {
280 Files.copy(p, root.resolve((p.toFile().getName())));
281 } catch (IOException e) {
372 writeCfgFile(p, root.resolve(
373 getLauncherCfgName(p)).toFile(), "$APPDIR\\runtime");
374
375 prepareExecutableProperties(p);
376
377 // Copy executable root folder
378 Path executableFile = root.resolve(getLauncherName(p));
379 try (InputStream is_launcher =
380 getResourceAsStream(getLauncherResourceName(p))) {
381 writeEntry(is_launcher, executableFile);
382 }
383
384 File launcher = executableFile.toFile();
385 launcher.setWritable(true, true);
386
387 // Update branding of EXE file
388 if (REBRAND_EXECUTABLE.fetchFrom(p)) {
389 try {
390 String tempDirectory = WindowsDefender.getUserTempDirectory();
391 if (Arguments.CLIOptions.context().userProvidedBuildRoot) {
392 tempDirectory = BUILD_ROOT.fetchFrom(p).getAbsolutePath();
393 }
394 if (WindowsDefender.isThereAPotentialWindowsDefenderIssue(
395 tempDirectory)) {
396 Log.error(MessageFormat.format(I18N.getString(
397 "message.potential.windows.defender.issue"),
398 tempDirectory));
399 }
400
401 launcher.setWritable(true);
402
403 if (iconTarget.exists()) {
404 iconSwap(iconTarget.getAbsolutePath(),
405 launcher.getAbsolutePath());
406 }
407
408 File executableProperties = getConfig_ExecutableProperties(p);
409
410 if (executableProperties.exists()) {
411 if (versionSwap(executableProperties.getAbsolutePath(),
412 launcher.getAbsolutePath()) != 0) {
|
63
64 private final static String LIBRARY_NAME = "applauncher.dll";
65 private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll";
66 private final static String REDIST_MSVCP = "msvcpVS_VER.dll";
67
68 private final static String TEMPLATE_APP_ICON ="javalogo_white_48.ico";
69
70 private static final String EXECUTABLE_PROPERTIES_TEMPLATE =
71 "WinLauncher.template";
72
73 private final Path root;
74 private final Path appDir;
75 private final Path appModsDir;
76 private final Path runtimeDir;
77 private final Path mdir;
78
79 private final Map<String, ? super Object> params;
80
81 public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE =
82 new WindowsBundlerParam<>(
83 "win.launcher.rebrand",
84 Boolean.class,
85 params -> Boolean.TRUE,
86 (s, p) -> Boolean.valueOf(s));
87
88 public static final BundlerParamInfo<File> ICON_ICO =
89 new StandardBundlerParam<>(
90 "icon.ico",
91 File.class,
92 params -> {
93 File f = ICON.fetchFrom(params);
94 if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
95 Log.error(MessageFormat.format(
96 I18N.getString("message.icon-not-ico"), f));
97 return null;
98 }
99 return f;
100 },
101 (s, p) -> new File(s));
102
103 public static final StandardBundlerParam<Boolean> CONSOLE_HINT =
104 new WindowsBundlerParam<>(
105 Arguments.CLIOptions.WIN_CONSOLE_HINT.getId(),
106 Boolean.class,
107 params -> false,
108 // valueOf(null) is false,
109 // and we actually do want null in some cases
110 (s, p) -> (s == null
111 || "null".equalsIgnoreCase(s)) ? true : Boolean.valueOf(s));
112
113 public WindowsAppImageBuilder(Map<String, Object> config, Path imageOutDir)
114 throws IOException {
115 super(config,
116 imageOutDir.resolve(APP_NAME.fetchFrom(config) + "/runtime"));
117
118 Objects.requireNonNull(imageOutDir);
119
120 this.params = config;
121
122 this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params));
123 this.appDir = root.resolve("app");
124 this.appModsDir = appDir.resolve("mods");
233 "error.cannot-create-output-dir"), rootFile.getAbsolutePath()));
234 }
235 if (!rootFile.canWrite()) {
236 throw new RuntimeException(MessageFormat.format(
237 I18N.getString("error.cannot-write-to-output-dir"),
238 rootFile.getAbsolutePath()));
239 }
240 // create the .exe launchers
241 createLauncherForEntryPoint(params);
242
243 // copy the jars
244 copyApplication(params);
245
246 // copy in the needed libraries
247 try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
248 Files.copy(is_lib, root.resolve(LIBRARY_NAME));
249 }
250
251 copyMSVCDLLs();
252
253 // create the additional launcher(s), if any
254 List<Map<String, ? super Object>> entryPoints =
255 StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
256 for (Map<String, ? super Object> entryPoint : entryPoints) {
257 Map<String, ? super Object> tmp = new HashMap<>(originalParams);
258 tmp.putAll(entryPoint);
259 createLauncherForEntryPoint(tmp);
260 }
261 }
262
263 @Override
264 public void prepareJreFiles() throws IOException {}
265
266 private void copyMSVCDLLs() throws IOException {
267 AtomicReference<IOException> ioe = new AtomicReference<>();
268 try (Stream<Path> files = Files.list(runtimeDir.resolve("bin"))) {
269 files.filter(p -> Pattern.matches(
270 "^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$",
271 p.toFile().getName().toLowerCase()))
272 .forEach(p -> {
273 try {
274 Files.copy(p, root.resolve((p.toFile().getName())));
275 } catch (IOException e) {
366 writeCfgFile(p, root.resolve(
367 getLauncherCfgName(p)).toFile(), "$APPDIR\\runtime");
368
369 prepareExecutableProperties(p);
370
371 // Copy executable root folder
372 Path executableFile = root.resolve(getLauncherName(p));
373 try (InputStream is_launcher =
374 getResourceAsStream(getLauncherResourceName(p))) {
375 writeEntry(is_launcher, executableFile);
376 }
377
378 File launcher = executableFile.toFile();
379 launcher.setWritable(true, true);
380
381 // Update branding of EXE file
382 if (REBRAND_EXECUTABLE.fetchFrom(p)) {
383 try {
384 String tempDirectory = WindowsDefender.getUserTempDirectory();
385 if (Arguments.CLIOptions.context().userProvidedBuildRoot) {
386 tempDirectory = TEMP_ROOT.fetchFrom(p).getAbsolutePath();
387 }
388 if (WindowsDefender.isThereAPotentialWindowsDefenderIssue(
389 tempDirectory)) {
390 Log.error(MessageFormat.format(I18N.getString(
391 "message.potential.windows.defender.issue"),
392 tempDirectory));
393 }
394
395 launcher.setWritable(true);
396
397 if (iconTarget.exists()) {
398 iconSwap(iconTarget.getAbsolutePath(),
399 launcher.getAbsolutePath());
400 }
401
402 File executableProperties = getConfig_ExecutableProperties(p);
403
404 if (executableProperties.exists()) {
405 if (versionSwap(executableProperties.getAbsolutePath(),
406 launcher.getAbsolutePath()) != 0) {
|