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);
}
});
}
}