IDEA-58913 [hg] use OSProcessHandler and pooled thread.
authorKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Fri, 8 Apr 2011 11:52:50 +0000 (15:52 +0400)
committerKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Fri, 8 Apr 2011 11:54:21 +0000 (15:54 +0400)
plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java
plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/execution/SocketServer.java

index 0c608f735cc6a2a08f96926767305f75288a7a6b..385e390e8b77e008789b724d111a698eaf0f8ca7 100644 (file)
@@ -134,6 +134,9 @@ public final class HgCommandExecutor {
     } catch (IOException e) {
       showError(e);
       LOG.info("IOException during preparing command", e);
+      promptServer.stop();
+      warningServer.stop();
+      passServer.stop();
       return null;
     }
     cmdLine.addAll(myOptions);
index 592b2b270247ee675af0ff6f3adef87800f80f21..f89df8c1804326799d968bf31d31d78f4c4a3431 100644 (file)
@@ -12,6 +12,8 @@
 // limitations under the License.
 package org.zmlx.hg4idea.execution;
 
+import com.intellij.execution.process.CapturingProcessHandler;
+import com.intellij.execution.process.ProcessOutput;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.text.StringUtil;
 
@@ -56,48 +58,19 @@ public final class ShellCommand {
         processBuilder = processBuilder.directory(new File(dir));
       }
       Process process = processBuilder.start();
-      Thread outReaderThread = startReader(
-        new InputStreamReader(process.getInputStream(), charset), out
-      );
-      Thread errReaderThread = startReader(
-        new InputStreamReader(process.getErrorStream()), err
-      );
-      process.waitFor();
-      int exitValue = process.exitValue();
-      outReaderThread.join();
-      errReaderThread.join();
+
+      CapturingProcessHandler processHandler = new CapturingProcessHandler(process);
+      final ProcessOutput processOutput = processHandler.runProcess();
+
+      int exitValue = processOutput.getExitCode();
+      out.write(processOutput.getStdout());
+      err.write(processOutput.getStderr());
       return new HgCommandResult(out, err, exitValue );
     } catch (IOException e) {
       throw new ShellCommandException(e);
     }
   }
 
-  private Thread startReader(final InputStreamReader in, final Writer writer) {
-    Thread readingThread = new Thread(new Runnable() {
-      public void run() {
-        char[] buffer = new char[BUFFER_SIZE];
-        int count;
-        try {
-          while ((count = in.read(buffer)) > 0) {
-            writer.write(buffer, 0, count);
-          }
-          writer.flush();
-        } catch (IOException e) {
-          LOG.info(e.getMessage());
-        } finally {
-          try {
-            in.close();
-          }
-          catch (IOException e) {
-            // ignore
-          }
-        }
-      }
-    });
-    readingThread.start();
-    return readingThread;
-  }
-
   /**
    * Escapes charactes in the command which will be executed via 'bash -c' - these are standard chars like \n, and some bash specials.
    * @param source Original string.
index 9bc32a79315ba39a940ba17b83c19fe35adaf690..2e2df465ec7cb9bcaadb0c74374d80c7541327dd 100644 (file)
 // limitations under the License.
 package org.zmlx.hg4idea.execution;
 
+import com.intellij.openapi.application.ApplicationManager;
+
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketException;
+import java.util.concurrent.Future;
 
 /**
  * Common server class that contains the boiler-plate code to set up a server socket.
  * The actual logic is delegated to the Protocol instance.
  */
 public class SocketServer {
-  protected Thread serverThread;
-  protected ServerSocket serverSocket;
-  private final Protocol protocol;
+  protected ServerSocket myServerSocket;
+  private final Protocol myProtocol;
+  private Future<?> myExecutingFuture;
 
   public SocketServer(Protocol protocol) {
-    this.protocol = protocol;
+    myProtocol = protocol;
   }
 
   public int start() throws IOException {
-    serverSocket = new ServerSocket(0);
-    int port = serverSocket.getLocalPort();
+    myServerSocket = new ServerSocket(0);
+    int port = myServerSocket.getLocalPort();
 
-    serverThread = new Thread("hg4idea prompt server") {
+    myExecutingFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
       @Override
       public void run() {
         try {
           boolean _continue = true;
           while (_continue) {
-            Socket socket = serverSocket.accept();
+            Socket socket = myServerSocket.accept();
             try {
-              _continue = protocol.handleConnection(socket);
+              _continue = myProtocol.handleConnection(socket);
             }
             finally {
               socket.close();
             }
           }
-        } catch (SocketException e) {
+        }
+        catch (SocketException e) {
           //socket was closed, that's OK
-        } catch (IOException e) {
+        }
+        catch (IOException e) {
           throw new RuntimeException(e); //TODO implement catch clause
         }
       }
-    };
-    serverThread.start();
+    });
 
     return port;
   }
 
   public void stop() {
-    serverThread.interrupt();
+    myExecutingFuture.cancel(true);
     try {
-      serverSocket.close();
+      myServerSocket.close();
     } catch (IOException e) {
       throw new RuntimeException(e); //TODO implement catch clause
     }
-
   }
 
   public static abstract class Protocol {