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

Last change on this file since 6125 was 6125, checked in by bastiK, 6 years ago

see #7275 - allow script to handle restart

When JOSM was started with parameter -Djosm.restart=true, a
user request for restart will simply terminate the application
with exit code 9.
The start script is then responsible for the restart.

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