source: josm/trunk/src/org/openstreetmap/josm/actions/RestartAction.java@ 7420

Last change on this file since 7420 was 7335, checked in by Don-vip, 10 years ago

see #10230, see #10033 - big rework of HTTPS support for Remote Control:

  • HTTPS disabled by default, must be enabled in remote control preferences
  • Old certificate and private key removed from jar and Windows keystore if found, even if remote control disabled
  • New certificate generated at runtime with critical X509 extensions BasicConstraints (non-CA certificate), ExtendedKeyUsage (usage restriction for TLS server sessions)
  • New passwords generated at runtime (but stored in clear in user preferences)
  • Private key is no longer stored in Windows keystore (only certificate)
File size: 6.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.event.ActionEvent;
8import java.awt.event.KeyEvent;
9import java.io.File;
10import java.io.IOException;
11import java.lang.management.ManagementFactory;
12import java.util.ArrayList;
13import java.util.Arrays;
14import java.util.Collections;
15import java.util.List;
16
17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
19import org.openstreetmap.josm.tools.ImageProvider;
20import org.openstreetmap.josm.tools.Shortcut;
21
22/**
23 * Restarts JOSM as it was launched. Comes from "restart" plugin, originally written by Upliner.
24 * <br><br>
25 * Mechanisms have been improved based on #8561 discussions and <a href="http://lewisleo.blogspot.jp/2012/08/programmatically-restart-java.html">this article</a>.
26 * @since 5857
27 */
28public class RestartAction extends JosmAction {
29
30 /**
31 * Constructs a new {@code RestartAction}.
32 */
33 public RestartAction() {
34 super(tr("Restart"), "restart", tr("Restart the application."),
35 Shortcut.registerShortcut("file:restart", tr("File: {0}", tr("Restart")), KeyEvent.VK_J, Shortcut.ALT_CTRL_SHIFT), false);
36 putValue("help", ht("/Action/Restart"));
37 putValue("toolbar", "action/restart");
38 Main.toolbar.register(this);
39 setEnabled(isRestartSupported());
40 }
41
42 @Override
43 public void actionPerformed(ActionEvent e) {
44 // If JOSM has been started with property 'josm.restart=true' this means
45 // it is executed by a start script that can handle restart.
46 // Request for restart is indicated by exit code 9.
47 String scriptRestart = System.getProperty("josm.restart");
48 if ("true".equals(scriptRestart)) {
49 Main.exitJosm(true, 9);
50 }
51
52 try {
53 restartJOSM();
54 } catch (IOException ex) {
55 Main.error(ex);
56 }
57 }
58
59 /**
60 * Determines if restarting the application should be possible on this platform.
61 * @return {@code true} if the mandatory system property {@code sun.java.command} is defined, {@code false} otherwise.
62 * @since 5951
63 */
64 public static boolean isRestartSupported() {
65 return System.getProperty("sun.java.command") != null;
66 }
67
68 /**
69 * Restarts the current Java application
70 * @throws IOException
71 */
72 public static void restartJOSM() throws IOException {
73 if (isRestartSupported() && !Main.exitJosm(false, 0)) return;
74 try {
75 // java binary
76 final String java = System.getProperty("java.home") + File.separator + "bin" + File.separator +
77 (Main.isPlatformWindows() ? "java.exe" : "java");
78 if (!new File(java).isFile()) {
79 throw new IOException("Unable to find suitable java runtime at "+java);
80 }
81 final List<String> cmd = new ArrayList<>(Collections.singleton(java));
82 // vm arguments
83 for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
84 // if it's the agent argument : we ignore it otherwise the
85 // address of the old application and the new one will be in conflict
86 if (!arg.contains("-agentlib")) {
87 cmd.add(arg);
88 }
89 }
90 // program main and program arguments (be careful a sun property. might not be supported by all JVM)
91 String[] mainCommand = System.getProperty("sun.java.command").split(" ");
92 // look for a .jar in all chunks to support paths with spaces (fix #9077)
93 String jarPath = mainCommand[0];
94 for (int i = 1; i < mainCommand.length && !jarPath.endsWith(".jar"); i++) {
95 jarPath += " " + mainCommand[i];
96 }
97 // program main is a jar
98 if (jarPath.endsWith(".jar")) {
99 // if it's a jar, add -jar mainJar
100 cmd.add("-jar");
101 cmd.add(new File(jarPath).getPath());
102 } else {
103 // else it's a .class, add the classpath and mainClass
104 cmd.add("-cp");
105 cmd.add("\"" + System.getProperty("java.class.path") + "\"");
106 cmd.add(mainCommand[0]);
107 }
108 // if it's webstart add JNLP file
109 String jnlp = System.getProperty("jnlp.application.href");
110 if (jnlp != null) {
111 cmd.add(jnlp);
112 }
113 // finally add program arguments
114 cmd.addAll(Arrays.asList(Main.commandLineArgs));
115 Main.info("Restart "+cmd);
116 // execute the command in a shutdown hook, to be sure that all the
117 // resources have been disposed before restarting the application
118 Runtime.getRuntime().addShutdownHook(new Thread() {
119 @Override
120 public void run() {
121 try {
122 Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));
123 } catch (IOException e) {
124 Main.error(e);
125 }
126 }
127 });
128 // exit
129 System.exit(0);
130 } catch (Exception e) {
131 // something went wrong
132 throw new IOException("Error while trying to restart the application", e);
133 }
134 }
135
136 /**
137 * Returns a new {@code ButtonSpec} instance that performs this action.
138 * @return A new {@code ButtonSpec} instance that performs this action.
139 */
140 public static ButtonSpec getRestartButtonSpec() {
141 return new ButtonSpec(
142 tr("Restart"),
143 ImageProvider.get("restart"),
144 tr("Restart the application."),
145 ht("/Action/Restart"),
146 isRestartSupported()
147 );
148 }
149
150 /**
151 * Returns a new {@code ButtonSpec} instance that do not perform this action.
152 * @return A new {@code ButtonSpec} instance that do not perform this action.
153 */
154 public static ButtonSpec getCancelButtonSpec() {
155 return new ButtonSpec(
156 tr("Cancel"),
157 ImageProvider.get("cancel"),
158 tr("Click to restart later."),
159 null /* no specific help context */
160 );
161 }
162
163 /**
164 * Returns default {@code ButtonSpec} instances for this action (Restart/Cancel).
165 * @return Default {@code ButtonSpec} instances for this action.
166 * @see #getRestartButtonSpec
167 * @see #getCancelButtonSpec
168 */
169 public static ButtonSpec[] getButtonSpecs() {
170 return new ButtonSpec[] {
171 getRestartButtonSpec(),
172 getCancelButtonSpec()
173 };
174 }
175}
Note: See TracBrowser for help on using the repository browser.