package jetbrains.mps.execution.api.commands; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import java.util.List; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import org.jetbrains.annotations.Nullable; import jetbrains.mps.internal.collections.runtime.Sequence; import java.io.File; import org.jetbrains.annotations.NotNull; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ExecutionException; import jetbrains.mps.internal.collections.runtime.ILeftCombinator; import java.io.IOException; import com.intellij.execution.process.ProcessNotCreatedException; import com.intellij.execution.configurations.GeneralCommandLine; import java.util.concurrent.CountDownLatch; import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import java.util.concurrent.TimeUnit; import com.intellij.openapi.application.ApplicationManager; public class ProcessHandlerBuilder { private static final Logger LOG = LogManager.getLogger(ProcessHandlerBuilder.class); private final List<String> myCommandLine = ListSequence.fromList(new ArrayList<String>()); public ProcessHandlerBuilder() { } public ProcessHandlerBuilder append(@Nullable String command) { if (!((command == null || command.length() == 0))) { ListSequence.fromList(myCommandLine).addSequence(Sequence.fromIterable(splitCommandInParts(command))); } return this; } public ProcessHandlerBuilder append(@Nullable File file) { if (file != null) { ListSequence.fromList(myCommandLine).addElement(file.getAbsolutePath()); } return this; } public ProcessHandlerBuilder append(String... command) { for (String commandPart : Sequence.fromArray(command)) { append(commandPart); } return this; } public ProcessHandlerBuilder append(@NotNull List<String> command) { for (String commandPart : command) { append(commandPart); } return this; } public ProcessHandlerBuilder append(@Nullable CommandPart commandPart) { if (commandPart != null) { ListSequence.fromList(myCommandLine).addSequence(ListSequence.fromList(commandPart.getCommandList())); } return this; } public ProcessHandler build() throws ExecutionException { return build(new File(System.getProperty("user.dir"))); } public ProcessHandler build(@NotNull File workingDirectory) throws ExecutionException { if (!(workingDirectory.exists())) { throw new ExecutionException("Working directory " + workingDirectory + " does not exist."); } ProcessBuilder builder = new ProcessBuilder(ListSequence.fromList(myCommandLine).toGenericArray(String.class)); builder.directory(workingDirectory); try { Process process = builder.start(); DefaultProcessHandler processHandler = new DefaultProcessHandler(process, ListSequence.fromList(myCommandLine).foldLeft("", new ILeftCombinator<String, String>() { public String combine(String s, String it) { return ((s == null || s.length() == 0) ? it : s + " " + it); } })); return processHandler; } catch (IOException e) { LOG.error("Start process failed", e); throw new ProcessNotCreatedException("Start process failed", e, getCommandLine(workingDirectory.getAbsolutePath())); } catch (NullPointerException e) { LOG.error("Start process failed: one of the command line arguments is null", e); throw new ProcessNotCreatedException("Start process failed: one of the command line arguments is null", e, getCommandLine(workingDirectory.getAbsolutePath())); } catch (Throwable t) { LOG.error("Start process failed", t); throw new ProcessNotCreatedException("Start process failed", t, getCommandLine(workingDirectory.getAbsolutePath())); } } private GeneralCommandLine getCommandLine(String workingDirectory) { GeneralCommandLine commandLine = new GeneralCommandLine(); commandLine.setExePath(ListSequence.fromList(myCommandLine).getElement(0)); commandLine.setWorkDirectory(workingDirectory); commandLine.addParameters(ListSequence.fromList(myCommandLine).tailListSequence(1)); return commandLine; } public static Iterable<String> splitCommandInParts(@NotNull String command) { List<String> result = ListSequence.fromList(new ArrayList<String>()); boolean insideQuotes = false; boolean escaped = false; StringBuilder sb = new StringBuilder(); for (int i = 0; i < command.length(); i++) { char currentChar = command.charAt(i); if (currentChar == '"' && !(escaped)) { insideQuotes = !(insideQuotes); continue; } if (currentChar == ' ' && !(insideQuotes)) { // word ended if (sb.length() > 0) { ListSequence.fromList(result).addElement(sb.toString()); sb = new StringBuilder(); } } else if (currentChar == '\\' && (i < command.length() - 1 && command.charAt(i + 1) == '"')) { escaped = true; continue; } else { // inside word sb.append(currentChar); } escaped = false; } if (sb.length() > 0) { ListSequence.fromList(result).addElement(sb.toString()); } return result; } private static CountDownLatch startCountDown(ProcessHandler process, final int[] exitCode) { final CountDownLatch countDown = new CountDownLatch(1); OutputRedirector.redirect(process, new ProcessAdapter() { @Override public void processTerminated(ProcessEvent event) { exitCode[0] = event.getExitCode(); countDown.countDown(); } }); process.startNotify(); return countDown; } public static int startAndWait(ProcessHandler process) { final int[] exitCode = new int[]{-1}; try { ProcessHandlerBuilder.startCountDown(process, exitCode).await(); } catch (InterruptedException e) { process.destroyProcess(); } return exitCode[0]; } public static int startAndWait(ProcessHandler process, long timeout) { final int[] exitCode = new int[]{-1}; try { ProcessHandlerBuilder.startCountDown(process, exitCode).await(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { process.destroyProcess(); } if (exitCode[0] < 0) { process.destroyProcess(); } return exitCode[0]; } public static void startLater(final ProcessHandler process, final long timeout, final int[] exitCode) { ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { @Override public void run() { exitCode[0] = ProcessHandlerBuilder.startAndWait(process, timeout); } }); } }