Merge branch 'vromanik/ph' appcode/181.3203 clion/181.3209 dbe/181.3207 idea/181.3204 phpstorm/181.3205 pycharm/181.3202 pycharm/181.3206 rubymine/181.3208 webstorm/181.3211
authorVasily Romanikhin <vasily.romanikhin@jetbrains.com>
Sat, 27 Jan 2018 20:31:26 +0000 (23:31 +0300)
committerVasily Romanikhin <vasily.romanikhin@jetbrains.com>
Sat, 27 Jan 2018 20:31:26 +0000 (23:31 +0300)
platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java
platform/platform-api/src/com/intellij/execution/process/CapturingProcessRunner.java [new file with mode: 0644]

index dbc11b463a53d15b564ee5fdb9a9561bd9b0c238..f49f51f446750e86aff3a003e28681729f72f83f 100644 (file)
@@ -17,7 +17,6 @@ package com.intellij.execution.process;
 
 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;
@@ -30,13 +29,11 @@ import java.nio.charset.Charset;
  * @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) */
@@ -56,31 +53,21 @@ public class CapturingProcessHandler extends OSProcessHandler {
    */
   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();
   }
 
   /**
@@ -89,7 +76,7 @@ public class CapturingProcessHandler extends OSProcessHandler {
    * @param timeoutInMilliseconds non-positive means infinity
    */
   public ProcessOutput runProcess(int timeoutInMilliseconds) {
-    return runProcess(timeoutInMilliseconds, true);
+    return myProcessRunner.runProcess(timeoutInMilliseconds);
   }
 
   /**
@@ -99,83 +86,21 @@ public class CapturingProcessHandler extends OSProcessHandler {
    * @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
diff --git a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessRunner.java b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessRunner.java
new file mode 100644 (file)
index 0000000..ac14f6f
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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());
+    }
+  }
+}
+