title: Java process cannot capture InputStream, OutputStream from gpg.exe
body: <p>I am trying to decrypt using <code>gpg.exe  --passphrase-file my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg</code> (without --batch and --yes option). I am also providing the encryption command if anyone cares to use it for testing <code>gpg.exe  --passphrase-file ..\BE\src\my.passphrase  --symmetric --output MTR241_20111124.htm.gpg MTR241_20111124.htm</code>.</p>
  
  <p>There are two cases.
  case 1: MTR241_20111124.htm file does not exist in the output dir. Both command prompt and captured output stream of exec gives same output.</p>
  
  <pre><code>C:\Eclipse\workspace2\sync_inbox&gt;gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
  Reading passphrase from file descriptor 3
  gpg: CAST5 encrypted data
  gpg: encrypted with 1 passphrase
  gpg: WARNING: message was not integrity protected
  </code></pre>
  
  <p>The same messags gets printed by java exec and command prompt.</p>
  
  <pre><code>C:\Eclipse\workspace2\sync_inbox&gt;gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
  inp&gt;gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
  gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
  gpg: CAST5 encrypted data
  gpg: encrypted with 1 passphrase
  gpg: WARNING: message was not integrity protected
  </code></pre>
  
  <p>So far good enough</p>
  
  <p>Case2: When the output file already exists as expected in command prompt it asked if I want to replace.</p>
  
  <pre><code>C:\Eclipse\workspace2\sync_inbox&gt;gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
  Reading passphrase from file descriptor 3
  gpg: CAST5 encrypted data
  gpg: encrypted with 1 passphrase
  File `MTR241_20111124.htm' exists. Overwrite? (y/N) y
  gpg: WARNING: message was not integrity protected
  </code></pre>
  
  <p>But this output is from java program which hangs after this first line. It does not print any line on console. If I enter 'y' in console, it does not accept the input and process. It simply hangs. I have to manually kill the process taskkill /F /IM gpg.exe only then the java console program accepts more commands and process.</p>
  
  <pre><code>C:\Eclipse\workspace2\sync_inbox&gt;gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
  inp&gt;gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
  gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
      --hangs here-- 
  </code></pre>
  
  <p>The normal interactive commands of course works, say for ex:</p>
  
  <pre><code>F:\eclipse\workspace\HTMLProcessor\BEQuery&gt;copy hello.txt world.txt
  inp&gt;copy hello.txt world.txt
  copy hello.txt world.txt
  Overwrite world.txt? (Yes/No/All): y
  inp&gt;y
  y
          1 file(s) copied.
  </code></pre>
  
  <p>So here is my question why does it fail to capture output stream of gpg only when it asks for the prompt whether to replace the existing output file.</p>
  
  <p>I already tried Runtime.exec(), ProcessBuilder, Plexus-Utils, ExpectJ, Ant to run this gpg.exe inside the java program all of them are showing the same result fails to capture output stream of the process in that special case. I even tried to write a <strong>.bat</strong> file to run the <code>gpg --decrypt</code> but even in that also it fails to capture output stream in above special case. </p>
  
  <p>I think it matters, the origin of gpg.exe. Well I got it in portable git distribution, in the bin folder gpg.exe is available.</p>
  
  <p>My question became really long and boring, but still for those who like to point out errors java code</p>
  
  <pre><code>package com.ycs.ezlink.scheduler.cmd;
  
  import java.io.BufferedReader;
  import java.io.BufferedWriter;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import org.apache.log4j.Logger;
  
  public class CmdRunner {
      private static Logger logger = Logger.getLogger(CmdRunner.class);
  
      static class StreamGobbler extends Thread
      {
          InputStream is;
          String type;
  
          StreamGobbler(InputStream is, String type)
          {
              this.is = is;
              this.type = type;
          }
  
          public void run() {
              try {
                  System.out.println("in run!");
                      System.out.println(type);
                      final byte[] buffer = new byte[1];
                      for (int length = 0; (length = is.read(buffer)) != -1;) {
                          System.out.write(buffer, 0, length);
                      }
                  } catch (IOException ioe) {
                      ioe.printStackTrace();
                  }
          }
      }
  
      public static int process(String cmd){
          int exitVal = 0; 
          try {
              Runtime rt = Runtime.getRuntime();
               Process proc = rt.exec(cmd);
               // any error message?
               StreamGobbler errorGobbler = new 
                   StreamGobbler(proc.getErrorStream(), "ERROR");            
  
               // any output?
               StreamGobbler outputGobbler = new 
                   StreamGobbler(proc.getInputStream(), "OUTPUT");
  
               // kick them off
               errorGobbler.start();
               outputGobbler.start();
  
               // any error???
               System.out.println("Waiting for cmd process to complete " );
              exitVal = proc.waitFor();
               System.out.println("ExitValue: " + exitVal);
          } catch (IOException e) {
              e.printStackTrace();
          } catch (InterruptedException e) {
              e.printStackTrace();
          }    
          return exitVal;
      }
  
      public static void main(String[] a) throws IOException, InterruptedException, TimeoutException, ExpectJException {
          String gzipCmd = "gpg.exe  --passphrase-file C:/Eclipse/workspace2/BE/src/my.passphrase --decrypt --output C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm.gpg";  
          //CmdRunner.process(gzipCmd); ///--fails
          //ProcessBuilder pb = new ProcessBuilder("gpg", "--passphrase-file", "C:/Eclipse/workspace2/BE/src/my.passphrase",
          "--decrypt","--output","C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm",
          "C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm.gpg"); ///--fails
          ProcessBuilder pb = new ProcessBuilder ("cmd");
          pb.redirectErrorStream(true);
          Process process = pb.start();
          OutputStream stdin = process.getOutputStream ();
          InputStream stderr = process.getErrorStream ();
          InputStream stdout = process.getInputStream ();
           StreamGobbler errorGobbler = new StreamGobbler(stderr, "ERROR");            
           errorGobbler.start();
           StreamGobbler stdoutGobbler = new StreamGobbler(stdout, "DEBUG");            
           stdoutGobbler.start();
  
           BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));
           String line;
           while ((line = scan.readLine())!= null) {
                  String input = line;
                  System.out.println("inp&gt;"+input);
                  if (input.trim().equals("exit")) {
                      stdin.write("exit\r\n".getBytes()); 
                      stdin.flush();
                      break;
                  } else {
                       stdin.write((input+"\r\n").getBytes());
                       stdin.flush();
                  }
              }
           System.out.println("exited..");
          int returnCode  = process.waitFor();
          System.out.println(returnCode);
      }
  }
  </code></pre>
  
  <p>One last word if I use the <code>gpg --batch</code> option, it no more prompts for the <code>y/N</code> input, so then it runs smoothly. But I am just curious to know, why would there be this problem. Although I have a feeling that gpg.exe was originally written for Unix/Linux like platform, so there might be some input output file redirection, but I would like to know more on the root cause of it, so that next time I know what to look for.</p>