Skip to content

Commit 4c8fa46

Browse files
committed
toying with automatic restart
1 parent ecb0fcd commit 4c8fa46

File tree

4 files changed

+180
-22
lines changed

4 files changed

+180
-22
lines changed

app/src/processing/app/Base.java

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,10 @@ public JMenu initDefaultFileMenu() {
600600
item.addActionListener(e -> thinkDifferentExamples());
601601
defaultFileMenu.add(item);
602602

603+
item = new JMenuItem("Restart");
604+
item.addActionListener(e -> handleRestart());
605+
defaultFileMenu.add(item);
606+
603607
return defaultFileMenu;
604608
}
605609

@@ -858,16 +862,15 @@ public void rebuildToolList() {
858862
if (internalTools == null) {
859863
internalTools = new ArrayList<>();
860864

861-
initInternalTool("processing.app.tools.Archiver");
862-
initInternalTool("processing.app.tools.ColorSelector");
863-
initInternalTool("processing.app.tools.CreateFont");
865+
initInternalTool(processing.app.tools.Archiver.class);
866+
initInternalTool(processing.app.tools.ColorSelector.class);
867+
initInternalTool(processing.app.tools.CreateFont.class);
864868

865869
if (Platform.isMacOS()) {
866-
initInternalTool("processing.app.tools.InstallCommander");
870+
initInternalTool(processing.app.tools.InstallCommander.class);
867871
}
868872

869-
initInternalTool("processing.app.tools.ThemeSelector");
870-
//initInternalTool("processing.app.tools.UpdateTheme");
873+
initInternalTool(processing.app.tools.ThemeSelector.class);
871874
}
872875

873876
// Only init() these the first time they're loaded
@@ -913,9 +916,8 @@ public void rebuildToolList() {
913916
}
914917

915918

916-
protected void initInternalTool(String className) {
919+
protected void initInternalTool(Class<?> toolClass) {
917920
try {
918-
Class<?> toolClass = Class.forName(className);
919921
final Tool tool = (Tool)
920922
toolClass.getDeclaredConstructor().newInstance();
921923

@@ -1681,18 +1683,6 @@ public boolean handleClose(Editor editor, boolean preventQuit) {
16811683
}
16821684
}
16831685

1684-
/*
1685-
// wow, this is wrong (should only be called after the last window)
1686-
// but also outdated, because it's instance_server.* not server.*
1687-
// and Preferences.save() is also about restoring sketches.
1688-
1689-
Preferences.unset("server.port"); //$NON-NLS-1$
1690-
Preferences.unset("server.key"); //$NON-NLS-1$
1691-
1692-
// Save out the current prefs state
1693-
Preferences.save();
1694-
*/
1695-
16961686
if (defaultFileMenu == null) {
16971687
if (preventQuit) {
16981688
// need to close this editor, ever so temporarily
@@ -1724,7 +1714,10 @@ public boolean handleClose(Editor editor, boolean preventQuit) {
17241714

17251715

17261716
/**
1727-
* Handler for File &rarr; Quit.
1717+
* Handler for File &rarr; Quit. Note that this is *only* for the
1718+
* File menu. On macOS, it will not call System.exit() because the
1719+
* application will handle that. If calling this from elsewhere,
1720+
* you'll need a System.exit() call on macOS.
17281721
* @return false if canceled, true otherwise.
17291722
*/
17301723
public boolean handleQuit() {
@@ -1777,6 +1770,46 @@ protected boolean handleQuitEach() {
17771770
}
17781771

17791772

1773+
public void handleRestart() {
1774+
File app = Platform.getProcessingApp();
1775+
System.out.println(app);
1776+
if (app.exists()) {
1777+
if (handleQuitEach()) { // only if everything saved
1778+
SingleInstance.clearRunning();
1779+
1780+
// Launch on quit
1781+
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
1782+
try {
1783+
//Runtime.getRuntime().exec(app.getAbsolutePath());
1784+
System.out.println("launching");
1785+
Process p;
1786+
if (Platform.isMacOS()) {
1787+
p = Runtime.getRuntime().exec(new String[]{
1788+
"open", "-n", "-a", app.getAbsolutePath()
1789+
});
1790+
} else {
1791+
p = PApplet.launch(app.getAbsolutePath());
1792+
}
1793+
System.out.println("launched with result " + p.waitFor());
1794+
System.out.flush();
1795+
} catch (Exception e) {
1796+
e.printStackTrace();
1797+
}
1798+
}));
1799+
handleQuit();
1800+
// handleQuit() does not call System.exit() on macOS
1801+
if (Platform.isMacOS()) {
1802+
System.exit(0);
1803+
}
1804+
}
1805+
} else {
1806+
Messages.showWarning("Cannot Restart",
1807+
"Cannot automatically restart because the Processing\n" +
1808+
"application has been renamed. Please quit and then restart manually.");
1809+
}
1810+
}
1811+
1812+
17801813
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17811814

17821815

app/src/processing/app/Platform.java

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/*
44
Part of the Processing project - http://processing.org
55
6-
Copyright (c) 2012-20 The Processing Foundation
6+
Copyright (c) 2012-23 The Processing Foundation
77
Copyright (c) 2008-12 Ben Fry and Casey Reas
88
99
This program is free software; you can redistribute it and/or modify
@@ -25,9 +25,12 @@
2525

2626
import java.io.File;
2727
import java.io.IOException;
28+
import java.lang.management.ManagementFactory;
2829
import java.net.URISyntaxException;
2930
import java.net.URL;
31+
import java.util.ArrayList;
3032
import java.util.HashMap;
33+
import java.util.List;
3134
import java.util.Map;
3235

3336
import com.sun.jna.platform.FileUtils;
@@ -404,6 +407,114 @@ static public String getJavaPath() {
404407
}
405408

406409

410+
static protected File getProcessingApp() {
411+
File appFile;
412+
if (Platform.isMacOS()) {
413+
// walks up from Processing.app/Contents/Java to Processing.app
414+
// (or whatever the user has renamed it to)
415+
appFile = getContentFile("../..");
416+
} else if (Platform.isWindows()) {
417+
appFile = getContentFile("processing.exe");
418+
} else {
419+
appFile = getContentFile("processing");
420+
}
421+
try {
422+
return appFile.getCanonicalFile();
423+
424+
} catch (Exception e) {
425+
e.printStackTrace();
426+
}
427+
return null;
428+
}
429+
430+
431+
// Not great, shows the crusty Duke icon in the dock.
432+
// Better to just re-launch the .exe instead.
433+
// Hacked up from <a href="https://lewisleo.blogspot.com/2012/08/programmatically-restart-java.html">this code</a>.
434+
static private void restartJavaApplication() {
435+
// System.out.println("java path: " + javaPath);
436+
// String java = System.getProperty("java.home") + "/bin/java";
437+
// Tested and working with JDK 17 [fry 230122]
438+
// System.out.println("sun java command: " + System.getProperty("sun.java.command"));
439+
// System.out.println("class path: " + System.getProperty("java.class.path"));
440+
List<String> cmd = new ArrayList<>();
441+
442+
// Add the path to the current java binary
443+
cmd.add(getJavaPath());
444+
445+
// Get all the VM arguments that are currently in use
446+
List<String> vmArguments =
447+
ManagementFactory.getRuntimeMXBean().getInputArguments();
448+
449+
// Add all the arguments we're using now, except for -agentlib
450+
for (String arg : vmArguments) {
451+
if (!arg.contains("-agentlib")) {
452+
cmd.add(arg);
453+
}
454+
}
455+
456+
// Does not work for .jar files, should this be used in a more general way
457+
cmd.add("-cp");
458+
cmd.add(System.getProperty("java.class.path"));
459+
460+
// Finally, add the class that was used to launch the app
461+
// (in our case, this is the Processing splash screen)
462+
String javaCommand = System.getProperty("sun.java.command");
463+
String[] splitCommand = PApplet.split(javaCommand, ' ');
464+
// if (splitCommand.length > 1) {
465+
// try {
466+
// Util.saveFile(javaCommand, PApplet.desktopFile("arrrrrghs.txt"));
467+
// } catch (IOException e) {
468+
// throw new RuntimeException(e);
469+
// }
470+
// }
471+
cmd.add(splitCommand[0]); // should be the main class name
472+
473+
ProcessBuilder builder = new ProcessBuilder(cmd);
474+
475+
/*
476+
StringBuffer vmArgsOneLine = new StringBuffer();
477+
for (String arg : vmArguments) {
478+
// if it's the agent argument : we ignore it otherwise the
479+
// address of the old application and the new one will be in conflict
480+
if (!arg.contains("-agentlib")) {
481+
vmArgsOneLine.append(arg);
482+
vmArgsOneLine.append(" ");
483+
}
484+
}
485+
// init the command to execute, add the vm args
486+
final StringBuffer cmd = new StringBuffer("\"" + java + "\" " + vmArgsOneLine);
487+
// program main and program arguments (be careful a sun property. might not be supported by all JVM)
488+
String[] mainCommand = System.getProperty("sun.java.command").split(" ");
489+
// program main is a jar
490+
if (mainCommand[0].endsWith(".jar")) {
491+
// if it's a jar, add -jar mainJar
492+
cmd.append("-jar " + new File(mainCommand[0]).getPath());
493+
} else {
494+
// else it's a .class, add the classpath and mainClass
495+
cmd.append("-cp \"" + System.getProperty("java.class.path") + "\" " + mainCommand[0]);
496+
}
497+
// finally add program arguments
498+
for (int i = 1; i < mainCommand.length; i++) {
499+
cmd.append(" ");
500+
cmd.append(mainCommand[i]);
501+
}
502+
*/
503+
// execute the command in a shutdown hook, to be sure that all the
504+
// resources have been disposed before restarting the application
505+
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
506+
try {
507+
// System.out.println(new StringList(cmd).join(" "));
508+
// Runtime.getRuntime().exec(cmd.toArray(new String[0]));
509+
builder.start();
510+
} catch (IOException e) {
511+
e.printStackTrace();
512+
}
513+
}));
514+
System.exit(0);
515+
}
516+
517+
407518
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
408519

409520

app/src/processing/app/SingleInstance.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ static boolean alreadyRunning(String[] args) {
5454
}
5555

5656

57+
/**
58+
* Disable briefly for Processing to restart itself.
59+
*/
60+
static public void clearRunning() {
61+
Preferences.unset(SERVER_PORT);
62+
Preferences.save();
63+
}
64+
65+
5766
static void startServer(final Base base) {
5867
try {
5968
Messages.log("Opening SingleInstance socket");

todo.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ _ update console.scrollbar.thumb.rollover.color and console.scrollbar.thumb.pres
2929
_ currently just using .enabled.color because they weren't in ColorSet
3030

3131

32+
_ remove temporary 'restart' menu before release
33+
34+
_ implement automatic updates?
35+
_ especially with fixes to updates on startup...
36+
3237
_ export to IntelliJ? how tricky?
3338
_ just copy jars to /lib?
3439
_ point to binaries in /Applications/Processing.app? (no)

0 commit comments

Comments
 (0)