import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
* @author yole
*/
public class CapturingProcessHandler extends OSProcessHandler {
- private static final Logger LOG = Logger.getInstance(CapturingProcessHandler.class);
-
- private final ProcessOutput myOutput = new ProcessOutput();
+ private final CapturingProcessRunner myProcessRunner;
public CapturingProcessHandler(@NotNull GeneralCommandLine commandLine) throws ExecutionException {
super(commandLine);
- addProcessListener(createProcessAdapter(myOutput));
+ myProcessRunner = new CapturingProcessRunner(this, processOutput -> createProcessAdapter(processOutput));
}
/** @deprecated Use {@link #CapturingProcessHandler(Process, Charset, String)} instead (to be removed in IDEA 17) */
*/
public CapturingProcessHandler(@NotNull Process process, @Nullable Charset charset, /*@NotNull*/ String commandLine) {
super(process, commandLine, charset);
- addProcessListener(createProcessAdapter(myOutput));
+ myProcessRunner = new CapturingProcessRunner(this, processOutput -> createProcessAdapter(processOutput));
}
protected CapturingProcessAdapter createProcessAdapter(ProcessOutput processOutput) {
return new CapturingProcessAdapter(processOutput);
}
- @NotNull
- public ProcessOutput runProcess() {
- startNotify();
- if (waitFor()) {
- setErrorCodeIfNotYetSet();
- }
- else {
- LOG.info("runProcess: exit value unavailable");
- }
- return myOutput;
+ @Override
+ public Charset getCharset() {
+ return myCharset != null ? myCharset : super.getCharset();
}
- private void setErrorCodeIfNotYetSet() {
- // if exit code was set on processTerminated, no need to rewrite it
- // WinPtyProcess returns -2 if pty is already closed
- if (!myOutput.isExitCodeSet()) {
- myOutput.setExitCode(getProcess().exitValue());
- }
+ @NotNull
+ public ProcessOutput runProcess() {
+ return myProcessRunner.runProcess();
}
/**
* @param timeoutInMilliseconds non-positive means infinity
*/
public ProcessOutput runProcess(int timeoutInMilliseconds) {
- return runProcess(timeoutInMilliseconds, true);
+ return myProcessRunner.runProcess(timeoutInMilliseconds);
}
/**
* @param destroyOnTimeout whether to kill the process after timeout passes
*/
public ProcessOutput runProcess(int timeoutInMilliseconds, boolean destroyOnTimeout) {
- // keep in sync with runProcessWithProgressIndicator
- if (timeoutInMilliseconds <= 0) {
- return runProcess();
- }
- else {
- startNotify();
- if (waitFor(timeoutInMilliseconds)) {
- setErrorCodeIfNotYetSet();
- }
- else {
- if (destroyOnTimeout) {
- destroyProcess();
- }
- myOutput.setTimeout();
- }
- return myOutput;
- }
- }
-
- @Override
- public Charset getCharset() {
- return myCharset != null ? myCharset : super.getCharset();
+ return myProcessRunner.runProcess(timeoutInMilliseconds, destroyOnTimeout);
}
@NotNull
public ProcessOutput runProcessWithProgressIndicator(@NotNull ProgressIndicator indicator) {
- return runProcessWithProgressIndicator(indicator, -1);
+ return myProcessRunner.runProcess(indicator);
}
@NotNull
public ProcessOutput runProcessWithProgressIndicator(@NotNull ProgressIndicator indicator, int timeoutInMilliseconds) {
- return runProcessWithProgressIndicator(indicator, timeoutInMilliseconds, true);
+ return myProcessRunner.runProcess(indicator, timeoutInMilliseconds);
}
@NotNull
public ProcessOutput runProcessWithProgressIndicator(@NotNull ProgressIndicator indicator, int timeoutInMilliseconds, boolean destroyOnTimeout) {
- // keep in sync with runProcess
- if (timeoutInMilliseconds <= 0) {
- timeoutInMilliseconds = Integer.MAX_VALUE;
- }
-
- final int WAIT_INTERVAL = 100;
- int waitingTime = 0;
- boolean setExitCode = true;
-
- startNotify();
- while (!waitFor(WAIT_INTERVAL)) {
- waitingTime += WAIT_INTERVAL;
-
- boolean timeout = waitingTime >= timeoutInMilliseconds;
- boolean canceled = indicator.isCanceled();
-
- if (canceled || timeout) {
- boolean destroying = canceled || destroyOnTimeout;
- setExitCode = destroying;
-
- if (destroying && !isProcessTerminating() && !isProcessTerminated()) {
- destroyProcess();
- }
-
- if (canceled) {
- myOutput.setCancelled();
- }
- else {
- myOutput.setTimeout();
- }
- break;
- }
- }
- if (setExitCode) {
- if (waitFor()) {
- setErrorCodeIfNotYetSet();
- }
- else {
- LOG.info("runProcess: exit value unavailable");
- }
- }
- return myOutput;
+ return myProcessRunner.runProcess(indicator, timeoutInMilliseconds, destroyOnTimeout);
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ */
+package com.intellij.execution.process;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.function.Function;
+
+public class CapturingProcessRunner {
+ @NotNull private ProcessOutput myOutput;
+ @NotNull private BaseProcessHandler myProcessHandler;
+ @NotNull private static final Logger LOG = Logger.getInstance(CapturingProcessRunner.class);
+
+ public CapturingProcessRunner(@NotNull BaseProcessHandler processHandler) {
+ this(processHandler, processOutput -> new CapturingProcessAdapter(processOutput));
+ }
+
+ public CapturingProcessRunner(@NotNull BaseProcessHandler processHandler,
+ @NotNull Function<ProcessOutput, ProcessAdapter> processAdapterProducer) {
+ myOutput = new ProcessOutput();
+ myProcessHandler = processHandler;
+ myProcessHandler.addProcessListener(processAdapterProducer.apply(myOutput));
+ }
+
+ @NotNull
+ public ProcessOutput runProcess() {
+ myProcessHandler.startNotify();
+ if (myProcessHandler.waitFor()) {
+ setErrorCodeIfNotYetSet();
+ }
+ else {
+ LOG.info("runProcess: exit value unavailable");
+ }
+ return myOutput;
+ }
+
+ @NotNull
+ public ProcessOutput runProcess(int timeoutInMilliseconds) {
+ return runProcess(timeoutInMilliseconds, true);
+ }
+
+ @NotNull
+ public ProcessOutput runProcess(int timeoutInMilliseconds, boolean destroyOnTimeout) {
+ // keep in sync with runProcessWithProgressIndicator
+ if (timeoutInMilliseconds <= 0) {
+ return runProcess();
+ }
+ else {
+ myProcessHandler.startNotify();
+ if (myProcessHandler.waitFor(timeoutInMilliseconds)) {
+ setErrorCodeIfNotYetSet();
+ }
+ else {
+ if (destroyOnTimeout) {
+ myProcessHandler.destroyProcess();
+ }
+ myOutput.setTimeout();
+ }
+ return myOutput;
+ }
+ }
+
+ @NotNull
+ public ProcessOutput runProcess(@NotNull ProgressIndicator indicator) {
+ return runProcess(indicator, -1);
+ }
+
+ @NotNull
+ public ProcessOutput runProcess(@NotNull ProgressIndicator indicator, int timeoutInMilliseconds) {
+ return runProcess(indicator, timeoutInMilliseconds, true);
+ }
+
+ @NotNull
+ public ProcessOutput runProcess(@NotNull ProgressIndicator indicator,
+ int timeoutInMilliseconds,
+ boolean destroyOnTimeout) {
+ // keep in sync with runProcess
+ if (timeoutInMilliseconds <= 0) {
+ timeoutInMilliseconds = Integer.MAX_VALUE;
+ }
+
+ final int WAIT_INTERVAL = 100;
+ int waitingTime = 0;
+ boolean setExitCode = true;
+
+ myProcessHandler.startNotify();
+ while (!myProcessHandler.waitFor(WAIT_INTERVAL)) {
+ waitingTime += WAIT_INTERVAL;
+
+ boolean timeout = waitingTime >= timeoutInMilliseconds;
+ boolean canceled = indicator.isCanceled();
+
+ if (canceled || timeout) {
+ boolean destroying = canceled || destroyOnTimeout;
+ setExitCode = destroying;
+
+ if (destroying && !myProcessHandler.isProcessTerminating() && !myProcessHandler.isProcessTerminated()) {
+ myProcessHandler.destroyProcess();
+ }
+
+ if (canceled) {
+ myOutput.setCancelled();
+ }
+ else {
+ myOutput.setTimeout();
+ }
+ break;
+ }
+ }
+ if (setExitCode) {
+ if (myProcessHandler.waitFor()) {
+ setErrorCodeIfNotYetSet();
+ }
+ else {
+ LOG.info("runProcess: exit value unavailable");
+ }
+ }
+ return myOutput;
+ }
+
+ private void setErrorCodeIfNotYetSet() {
+ // if exit code was set on processTerminated, no need to rewrite it
+ // WinPtyProcess returns -2 if pty is already closed
+ if (!myOutput.isExitCodeSet()) {
+ myOutput.setExitCode(myProcessHandler.getProcess().exitValue());
+ }
+ }
+}
+