title: Java Process with concurrent Input/Output Streams
body: <p>I am trying to create a sort of console/terminal that allows the user to input a string, which then gets made into a process and the results are printed out. Just like a normal console. But I am having trouble managing the input/output streams. I have looked into <a href="https://stackoverflow.com/questions/3643939/java-process-with-input-output-stream">this thread</a>, but that solution sadly doesn't apply to my problem.</p>
  
  <p>Along with the standard commands like "ipconfig" and "cmd.exe", I need to be able to run a script and use the same inputstream to pass some arguments, if the script is asking for input.</p>
  
  <p>For example, after running a script "python pyScript.py", I should be able pass further input to the script if it is asking for it(example: raw_input), while also printing the output from the script. The basic behavior you would expect from a terminal.</p>
  
  <p>What I've got so far:</p>
  
  <pre><code>import java.awt.BorderLayout;
  import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.event.KeyEvent;
  import java.awt.event.KeyListener;
  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 javax.swing.JFrame;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
  import javax.swing.JTextPane;
  import javax.swing.text.BadLocationException;
  import javax.swing.text.Document;
  
  public class Console extends JFrame{
  
      JTextPane inPane, outPane;
      InputStream inStream, inErrStream;
      OutputStream outStream;
  
      public Console(){
          super("Console");
          setPreferredSize(new Dimension(500, 600));
          setLocationByPlatform(true);
          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
          // GUI
          outPane = new JTextPane();
          outPane.setEditable(false);
          outPane.setBackground(new Color(20, 20, 20));
          outPane.setForeground(Color.white);
          inPane = new JTextPane();
          inPane.setBackground(new Color(40, 40, 40));
          inPane.setForeground(Color.white);
          inPane.setCaretColor(Color.white);
  
          JPanel panel = new JPanel(new BorderLayout());
          panel.add(outPane, BorderLayout.CENTER);
          panel.add(inPane, BorderLayout.SOUTH);
  
          JScrollPane scrollPanel = new JScrollPane(panel);
  
          getContentPane().add(scrollPanel);
  
          // LISTENER
          inPane.addKeyListener(new KeyListener(){
              @Override
              public void keyPressed(KeyEvent e){
                if(e.getKeyCode() == KeyEvent.VK_ENTER){
                      e.consume();
                      read(inPane.getText());
                  }
              }
              @Override
              public void keyTyped(KeyEvent e) {}
  
              @Override
              public void keyReleased(KeyEvent e) {}
          });
  
  
          pack();
          setVisible(true);
      }
  
      private void read(String command){
          println(command);
  
          // Write to Process
          if (outStream != null) {
              System.out.println("Outstream again");
              BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outStream));
              try {
                  writer.write(command);
                  //writer.flush();
                  //writer.close();
              } catch (IOException e1) {
                  e1.printStackTrace();
              }
          }
  
          // Execute Command
          try {
              exec(command);
          } catch (IOException e) {}
  
          inPane.setText("");
      }
  
      private void exec(String command) throws IOException{
          Process pro = Runtime.getRuntime().exec(command, null);
  
          inStream = pro.getInputStream();
          inErrStream = pro.getErrorStream();
          outStream = pro.getOutputStream();
  
          Thread t1 = new Thread(new Runnable() {
              public void run() {
                  try {
                      String line = null;
                      while(true){
                          BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
                          while ((line = in.readLine()) != null) {
                              println(line);
                          }
                          BufferedReader inErr = new BufferedReader(new InputStreamReader(inErrStream));
                          while ((line = inErr.readLine()) != null) {
                              println(line);
                          }
                          Thread.sleep(1000);
                      }
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          });
          t1.start();
      }
  
      public void println(String line) {
          Document doc = outPane.getDocument();
          try {
              doc.insertString(doc.getLength(), line + "\n", null);
          } catch (BadLocationException e) {}
      }
  
      public static void main(String[] args){
          new Console();
      }
  }
  </code></pre>
  
  <p>I don't use the mentioned <code>ProcessBuilder</code>, since I do like to differentiate between error and normal stream.  </p>
  
  <p><strong>UPDATE 29.08.2016</strong></p>
  
  <p>With the help of @ArcticLord we have achieved what was asked in the original question.
  Now it is just a matter of ironing out any strange behavior like the non terminating process. The Console has a "stop" button that simply calls pro.destroy(). But for some reason this does not work for infinitely running processes, that are spamming outputs.</p>
  
  <p>Console: <a href="http://pastebin.com/vyxfPEXC" rel="nofollow noreferrer">http://pastebin.com/vyxfPEXC</a></p>
  
  <p>InputStreamLineBuffer: <a href="http://pastebin.com/TzFamwZ1" rel="nofollow noreferrer">http://pastebin.com/TzFamwZ1</a></p>
  
  <p>Example code that does <strong>not</strong> stop:</p>
  
  <pre><code>public class Infinity{
      public static void main(String[] args){ 
          while(true){
              System.out.println(".");
          }
      }
  }
  </code></pre>
  
  <p>Example code that does stop:</p>
  
  <pre><code>import java.util.concurrent.TimeUnit;
  
  public class InfinitySlow{
      public static void main(String[] args){ 
          while(true){
              try {
                  TimeUnit.SECONDS.sleep(1);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              System.out.println(".");
          }
      }
  }
  </code></pre>