1a3a2472ab0926fd2d92b610797b0beca1191e86
[idea/community.git] / platform / platform-impl / src / com / intellij / ide / actions / CreateLauncherScriptAction.java
1 /*
2  * Copyright 2000-2010 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.ide.actions;
17
18 import com.intellij.execution.ExecutionException;
19 import com.intellij.execution.configurations.GeneralCommandLine;
20 import com.intellij.openapi.actionSystem.AnAction;
21 import com.intellij.openapi.actionSystem.AnActionEvent;
22 import com.intellij.openapi.actionSystem.PlatformDataKeys;
23 import com.intellij.openapi.application.ApplicationNamesInfo;
24 import com.intellij.openapi.application.PathManager;
25 import com.intellij.openapi.diagnostic.Logger;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.ui.DialogWrapper;
28 import com.intellij.openapi.ui.Messages;
29 import com.intellij.openapi.util.SystemInfo;
30 import com.intellij.openapi.util.io.FileUtil;
31 import com.intellij.openapi.vfs.CharsetToolkit;
32
33 import javax.script.ScriptEngine;
34 import javax.script.ScriptEngineManager;
35 import javax.script.ScriptException;
36 import javax.swing.*;
37 import java.io.File;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.InputStreamReader;
41
42 /**
43  * @author yole
44  */
45 public class CreateLauncherScriptAction extends AnAction {
46   private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateLauncherScriptAction");
47
48   @Override
49   public void actionPerformed(AnActionEvent e) {
50     Project project = e.getData(PlatformDataKeys.PROJECT);
51     showDialog(project);
52   }
53
54   public static void showDialog(Project project) {
55     CreateLauncherScriptDialog dialog = new CreateLauncherScriptDialog(project);
56     dialog.show();
57     if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
58       return;
59     }
60     createLauncherScript(project, new File(dialog.myPathField.getText(), dialog.myNameField.getText()).getPath());
61   }
62
63   public static void createLauncherScript(Project project, String pathname) {
64     try {
65       final File scriptFile = createLauncherScriptFile();
66       File scriptTarget = new File(pathname);
67       if (scriptTarget.exists()) {
68         int rc = Messages.showOkCancelDialog(project, "The file " + scriptTarget + " already exists. Would you like to overwrite it?",
69                                              "Create Launcher Script", Messages.getQuestionIcon());
70         if (rc != 0) {
71           return;
72         }
73       }
74       if (!scriptFile.renameTo(scriptTarget)) {
75         final String mvCommand = "mv -f " + scriptFile + " " + pathname;
76         sudo(mvCommand, "In order to create a launcher script in " + scriptTarget.getParent() + ", please enter your administrator password:");
77       }
78     }
79     catch (Exception e) {
80       LOG.info(e);
81       Messages.showErrorDialog(project, "Failed to create launcher script: " + e.getMessage(), "Create Launcher Script");
82     }
83   }
84
85   private static boolean sudo(String mvCommand, final String prompt) throws IOException, ScriptException, ExecutionException {
86     if (SystemInfo.isMac) {
87       final ScriptEngine engine = new ScriptEngineManager(null).getEngineByName("AppleScript");
88       if (engine == null) {
89         throw new IOException("Could not find AppleScript engine");
90       }
91       engine.eval("do shell script \"" + mvCommand + "\" with administrator privileges");
92     }
93     else if (SystemInfo.isUnix) {
94       GeneralCommandLine cmdLine = new GeneralCommandLine();
95       if (SystemInfo.isGnome) {
96         cmdLine.setExePath("gksudo");
97         cmdLine.addParameters("--message", prompt);
98       }
99       else if (SystemInfo.isKDE) {
100         cmdLine.setExePath("kdesudo");
101       }
102       else {
103         Messages.showMessageDialog("Unsupported graphical environment. Please execute the following command from the shell:\n" + mvCommand,
104                                    "Create Launcher Script",
105                                    Messages.getInformationIcon());
106         return true;
107       }
108       cmdLine.addParameter(mvCommand);
109       cmdLine.createProcess();
110     }
111     return false;
112   }
113
114   private static File createLauncherScriptFile() throws IOException {
115     final File tempFile = FileUtil.createTempFile("launcher", "");
116
117     final InputStream stream = CreateLauncherScriptAction.class.getClassLoader().getResourceAsStream("launcher.py");
118     String launcherContents = FileUtil.loadTextAndClose(new InputStreamReader(stream));
119     launcherContents = launcherContents.replace("$CONFIG_PATH$", PathManager.getConfigPath());
120
121     String homePath = PathManager.getHomePath();
122     String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase();
123     if (SystemInfo.isMac) {
124       launcherContents = launcherContents.replace("$RUN_PATH$", homePath + "/Contents/MacOS/" + productName);
125     }
126     else {
127       launcherContents = launcherContents.replace("$RUN_PATH$", homePath + "/bin/" + productName + ".sh");
128     }
129     FileUtil.writeToFile(tempFile, launcherContents.getBytes(CharsetToolkit.UTF8_CHARSET));
130     if (!tempFile.setExecutable(true)) {
131       throw new IOException("Failed to mark the launcher script as executable");
132     }
133     return tempFile;
134   }
135
136   public static String defaultScriptName() {
137     String productName = ApplicationNamesInfo.getInstance().getProductName();
138     if (productName.equalsIgnoreCase("RubyMine")) {
139       return "mine";
140     }
141     else if (productName.equalsIgnoreCase("PyCharm")) {
142       return "charm";
143     }
144     return "idea";
145   }
146
147   @Override
148   public void update(AnActionEvent e) {
149     boolean canCreateScript = SystemInfo.isUnix || SystemInfo.isMac;
150     e.getPresentation().setVisible(canCreateScript);
151   }
152
153   public static class CreateLauncherScriptDialog extends DialogWrapper {
154     private JPanel myMainPanel;
155     private JTextField myNameField;
156     private JTextField myPathField;
157     private JLabel myTitle;
158
159     protected CreateLauncherScriptDialog(Project project) {
160       super(project);
161       init();
162       setTitle("Create Launcher Script");
163       final String productName = ApplicationNamesInfo.getInstance().getProductName();
164       myTitle.setText(myTitle.getText().replace("$APPNAME", productName));
165       myNameField.setText(defaultScriptName());
166     }
167
168     @Override
169     protected JComponent createCenterPanel() {
170       return myMainPanel;
171     }
172   }
173 }