package fr.adrienbrault.idea.symfony2plugin.installer; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.*; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.util.Arrays; /** * @author Daniel Espendiller <daniel@espendiller.net> */ abstract public class SymfonyInstallerCommandExecutor { private static final long CHECKING_TIMEOUT_IN_MILLISECONDS = 1000L; private final Project myProject; private final VirtualFile baseDir; private final String[] command; public SymfonyInstallerCommandExecutor(@NotNull Project project, @NotNull VirtualFile baseDir, @NotNull String[] command) { this.myProject = project; this.baseDir = baseDir; this.command = command; } public void execute() { Task task = new Task.Modal(this.myProject, getProgressTitle(), true) { public void run(@NotNull final ProgressIndicator indicator) { indicator.setIndeterminate(true); String[] myCommand = SymfonyInstallerCommandExecutor.this.command; StringBuilder sb = new StringBuilder(); sb.append("Running: "); for (String aCommandToRun : Arrays.copyOfRange(myCommand, 1, myCommand.length)) { if (aCommandToRun.length() > 35) { aCommandToRun = "..." + aCommandToRun.substring(aCommandToRun.length() - 35); } sb.append(" ").append(aCommandToRun); } indicator.setText(sb.toString()); boolean cancelledByUser = false; final StringBuilder outputBuilder = new StringBuilder(); try { OSProcessHandler processHandler = ScriptRunnerUtil.execute(myCommand[0], SymfonyInstallerCommandExecutor.this.baseDir.getPath(), null, Arrays.copyOfRange(myCommand, 1, myCommand.length)); processHandler.addProcessListener(new ProcessAdapter() { @Override public void onTextAvailable(ProcessEvent event, com.intellij.openapi.util.Key outputType) { String text = event.getText(); outputBuilder.append(text); text = SymfonyInstallerUtil.formatConsoleTextIndicatorOutput(text); if(StringUtils.isNotBlank(text)) { indicator.setText2(text); } } }); processHandler.startNotify(); for (;;){ boolean finished = processHandler.waitFor(CHECKING_TIMEOUT_IN_MILLISECONDS); if (finished) { break; } if (indicator.isCanceled()) { cancelledByUser = true; OSProcessManager.getInstance().killProcessTree(processHandler.getProcess()); break; } } } catch (ExecutionException e) { SymfonyInstallerCommandExecutor.this.onError(e.getMessage()); return; } if(cancelledByUser) { SymfonyInstallerCommandExecutor.this.onError("Checkout canceled"); return; } String output = outputBuilder.toString(); if (StringUtils.isBlank(output) || !SymfonyInstallerUtil.isSuccessfullyInstalled(output)) { String message = SymfonyInstallerUtil.formatExceptionMessage(output); if(message == null) { message = "The unexpected happens..."; } SymfonyInstallerCommandExecutor.this.onError(message); return; } indicator.setText2("Preparing Project Structure..."); try { File fromDir = new File(baseDir.getPath() + "/" + SymfonyInstallerUtil.PROJECT_SUB_FOLDER); FileUtil.copyDirContent(fromDir, new File(baseDir.getPath())); FileUtil.delete(fromDir); } catch (IOException e) { SymfonyInstallerCommandExecutor.this.onError(e.getMessage()); return; } SymfonyInstallerCommandExecutor.this.onFinish(SymfonyInstallerUtil.extractSuccessMessage(output)); } }; ProgressManager.getInstance().run(task); } abstract protected void onFinish(@Nullable String successMessage); abstract protected void onError(@NotNull String message); protected abstract String getProgressTitle(); }