/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.actions;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.util.ExecUtil;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import static com.intellij.openapi.util.Pair.pair;
import static com.intellij.util.containers.ContainerUtil.newHashMap;
/**
* @author yole
*/
public class CreateLauncherScriptAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance(CreateLauncherScriptAction.class);
private static final String CONTENTS = "/Contents";
public static boolean isAvailable() {
return SystemInfo.isUnix;
}
@Override
public void update(@NotNull AnActionEvent e) {
boolean canCreateScript = isAvailable();
Presentation presentation = e.getPresentation();
presentation.setVisible(canCreateScript);
presentation.setEnabled(canCreateScript);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
if (!isAvailable()) return;
Project project = e.getProject();
CreateLauncherScriptDialog dialog = new CreateLauncherScriptDialog(project);
if (!dialog.showAndGet()) {
return;
}
String path = dialog.myPathField.getText();
assert path != null;
if (!path.startsWith("/")) {
String home = System.getenv("HOME");
if (home != null && new File(home).isDirectory()) {
if (path.startsWith("~")) {
path = home + path.substring(1);
}
else {
path = home + "/" + path;
}
}
}
String name = dialog.myNameField.getText();
assert name != null;
File target = new File(path, name);
if (target.exists()) {
String message = ApplicationBundle.message("launcher.script.overwrite", target);
String title = ApplicationBundle.message("launcher.script.title");
if (Messages.showOkCancelDialog(project, message, title, Messages.getQuestionIcon()) != Messages.OK) {
return;
}
}
createLauncherScript(project, target.getAbsolutePath());
}
public static void createLauncherScript(Project project, String pathName) {
if (!isAvailable()) return;
try {
File scriptFile = createLauncherScriptFile();
File scriptTarget = new File(pathName);
File scriptTargetDir = scriptTarget.getParentFile();
assert scriptTargetDir != null;
if (!(scriptTargetDir.exists() || scriptTargetDir.mkdirs()) || !scriptFile.renameTo(scriptTarget)) {
String scriptTargetDirPath = scriptTargetDir.getCanonicalPath();
// copy file and change ownership to root (UID 0 = root, GID 0 = root (wheel on Macs))
String installationScriptSrc =
"#!/bin/sh\n" +
"mkdir -p \"" + scriptTargetDirPath + "\"\n" +
"install -g 0 -o 0 \"" + scriptFile.getCanonicalPath() + "\" \"" + pathName + "\"";
File installationScript = ExecUtil.createTempExecutableScript("launcher_installer", ".sh", installationScriptSrc);
String prompt = ApplicationBundle.message("launcher.script.sudo.prompt", scriptTargetDirPath);
ExecUtil.sudoAndGetOutput(new GeneralCommandLine(installationScript.getPath()), prompt);
}
}
catch (Exception e) {
String message = e.getMessage();
if (!StringUtil.isEmptyOrSpaces(message)) {
LOG.warn(e);
Notifications.Bus.notify(
new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "Failed to create launcher script", message, NotificationType.ERROR),
project);
}
else {
LOG.error(e);
}
}
}
private static File createLauncherScriptFile() throws IOException, ExecutionException {
String runPath = PathManager.getHomePath();
String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase(Locale.US);
if (!SystemInfo.isMac) runPath += "/bin/" + productName + ".sh";
else if (runPath.endsWith(CONTENTS)) runPath = runPath.substring(0, runPath.length() - CONTENTS.length());
ClassLoader loader = CreateLauncherScriptAction.class.getClassLoader();
assert loader != null;
Map<String, String> variables = newHashMap(pair("$CONFIG_PATH$", PathManager.getConfigPath()), pair("$RUN_PATH$", runPath));
String launcherContents = StringUtil.convertLineSeparators(ExecUtil.loadTemplate(loader, "launcher.py", variables));
return ExecUtil.createTempExecutableScript("launcher", "", launcherContents);
}
public static String defaultScriptName() {
String scriptName = ApplicationNamesInfo.getInstance().getScriptName();
return StringUtil.isEmptyOrSpaces(scriptName) ? "idea" : scriptName;
}
public static class CreateLauncherScriptDialog extends DialogWrapper {
private JPanel myMainPanel;
private JTextField myNameField;
private JTextField myPathField;
private JLabel myTitle;
protected CreateLauncherScriptDialog(Project project) {
super(project);
init();
setTitle(ApplicationBundle.message("launcher.script.title"));
String productName = ApplicationNamesInfo.getInstance().getProductName();
myTitle.setText(myTitle.getText().replace("$APP_NAME$", productName));
myNameField.setText(defaultScriptName());
}
@Override
protected JComponent createCenterPanel() {
return myMainPanel;
}
}
}