Skip to content

Commit 52da771

Browse files
committed
Rename old launcher after upgrading
Discourage the use of the ImageJ* launchers which do not use Jaunch and cannot handle modern JVM's (e.g. 21)
1 parent 060f50c commit 52da771

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

src/main/java/net/imagej/ui/swing/updater/LauncherMigrator.java

+83
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ private void switchToNewLauncher() {
392392
return;
393393
}
394394
// New process seems to be up and running; we are done. Whew!
395+
startExeRenameProcess(appDir.toPath());
395396
appService.getContext().dispose();
396397
System.exit(0);
397398
}
@@ -400,6 +401,88 @@ private void switchToNewLauncher() {
400401
}
401402
}
402403

404+
/**
405+
* Helper method to rename the current exe to a backup version, to discourage
406+
* accidental use of a launcher that is incompatible with Java 21, for example
407+
*/
408+
private static void startExeRenameProcess(Path appDir) throws IOException {
409+
Path originalExe;
410+
if (OS_WIN) {
411+
if (ARCH.equals("x32")) {
412+
originalExe = appDir.resolve("ImageJ-win32.exe");
413+
} else {
414+
originalExe = appDir.resolve("ImageJ-win64.exe");
415+
}
416+
} else if (OS_LINUX) {
417+
originalExe = appDir.resolve("ImageJ-linux64");
418+
} else if (OS_MACOS) {
419+
originalExe = appDir.resolve("Contents").resolve("MacOS").resolve("ImageJ-macosx");
420+
} else {
421+
throw new RuntimeException("Unknown operating system");
422+
}
423+
424+
Path renamedExe = Paths.get(originalExe + ".old");
425+
// Copy the previous executable to a backup .old version
426+
Files.copy(originalExe, renamedExe);
427+
428+
// We can't actually remove the previous executable while this process is
429+
// running, since it was used to launch this JVM. So we need to start a
430+
// sub-process that will continually try to delete the file until it
431+
// succeeds.
432+
final int checkIntervalMs = 1000;
433+
final int numTries = 20;
434+
ProcessBuilder pb;
435+
String pathToDelete = originalExe.toFile().getAbsolutePath();
436+
437+
if (OS_WIN) {
438+
// Windows implementation using PowerShell
439+
pb = new ProcessBuilder(
440+
"powershell.exe",
441+
"-Command",
442+
"$tries = 0; " +
443+
"while ((Test-Path '" + pathToDelete + "') -and ($tries -lt " + numTries + ")) { " +
444+
"try { " +
445+
" Remove-Item -Path '" + pathToDelete + "' -Force -ErrorAction Stop; " +
446+
" Write-Host 'File deleted successfully.'; " +
447+
" break;" +
448+
"} catch { " +
449+
" $tries++; " +
450+
" Write-Host \"Attempt $tries of " + numTries + " failed...\"; " +
451+
" if ($tries -eq " + numTries + ") { Write-Host 'Max attempts reached. Exiting.'; break; } " +
452+
" Start-Sleep -Milliseconds " + checkIntervalMs + " " +
453+
"} }"
454+
);
455+
} else {
456+
// Unix/Linux/Mac implementation using bash
457+
pb = new ProcessBuilder(
458+
"bash",
459+
"-c",
460+
"tries=0; " +
461+
"while [ -f \"" + pathToDelete + "\" ] && [$tries -lt " + numTries + " ]; do " +
462+
" if rm -f \"" + pathToDelete + "\" 2>/dev/null; then " +
463+
" echo \"File deleted successfully.\";" +
464+
" break; " +
465+
" else " +
466+
" tries=$((tries+1)); " +
467+
" echo \"Attempt $tries of " + numTries + " failed...\";" +
468+
" if [ $tries -eq " + numTries + " ]; then " +
469+
" echo \"Max attempts reached. Exiting.\"; " +
470+
" break; " +
471+
" fi; " +
472+
" fi; " +
473+
" sleep " + (checkIntervalMs / 1000.0) + "; " +
474+
"done"
475+
);
476+
}
477+
478+
// Redirect process output (optional - for debugging)
479+
// pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
480+
// pb.redirectError(ProcessBuilder.Redirect.INHERIT);
481+
482+
// Start the process
483+
Process process = pb.start();
484+
}
485+
403486
/** Implores the user to report a bug relating to new launcher switch-over. */
404487
private void askForBugReport(
405488
Logger log, String appTitle, String appSlug, Exception exc)

0 commit comments

Comments
 (0)