package org.rubypeople.rdt.internal.launching; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; /* There is a different behaviour, when a ruby application ist started from commandlined compared to a ruby application started with RDT. E.g. there must be additional STDOUT.flush commands for RDT started applications in order to achieve same bahvior. */ public class EvaluateRubyProcessOutput implements Runnable { // Allocate 1K buffers for Input and Error Streams.. private byte[] inBuffer = new byte[1024]; private byte[] errBuffer = new byte[1024]; // Declare internal variables we will need.. private Process process; private InputStream pErrorStream; private InputStream pInputStream; private OutputStream pOutputStream; private PrintWriter outputWriter; private Thread inReadThread; private Thread errReadThread; public EvaluateRubyProcessOutput(Process p) { // Save variables.. process = p; // Get the streams.. pErrorStream = process.getErrorStream(); pInputStream = process.getInputStream(); pOutputStream = process.getOutputStream(); // Create a PrintWriter on top of the output stream.. // Create the threads and start them.. inReadThread = new Thread(this); errReadThread = new Thread(this); outputWriter = new PrintWriter(pOutputStream, true); new Thread() { public void run() { try { // This Thread just waits for the process to // end and notifies the handler.. process.waitFor() ; System.out.println("Process endend.") ; } catch (InterruptedException ex) { ex.printStackTrace(); } } }.start(); inReadThread.start(); errReadThread.start(); } private void processNewInput(String input) { // Handle process new input.. //handler.processNewInput(input); System.out.println(input) ; } private void processNewError(String error) { // Handle process new error.. //handler.processNewError(error); } // Run the command and return the ExecHelper wrapper object.. // Send the output string through the print writer.. public void sendOutput(String output) { outputWriter.println(output); } public void run() { // Are we on the InputRead Thread? if (inReadThread == Thread.currentThread()) { try { // Read the InputStream in a loop until we find no // more bytes to read.. for (int i = 0; i > -1; i = pInputStream.read(inBuffer)) { // We have a new segment of input, so process // it as a String.. processNewInput(new String(inBuffer, 0, i)); } } catch (IOException ex) { ex.printStackTrace(); } // Are we on the ErrorRead Thread? } else if (errReadThread == Thread.currentThread()) { try { // Read the ErrorStream in a loop until we find no // more bytes to read.. for (int i = 0; i > -1; i = pErrorStream.read(errBuffer)) { // We have a new segment of error, so process // it as a String.. processNewError(new String(errBuffer, 0, i)); } } catch (IOException ex) { ex.printStackTrace(); } } } public static void main(String[] args) throws Exception { /* file D:\\Temp\\test.rb: class Hello attr_reader :msg def initialize @msg = "Hello, World\n" end end h = Hello.new puts h.msg print "Press RETURN" STDOUT.flush input = $stdin.gets puts "You entered #{input}" */ Process p = Runtime.getRuntime().exec("D:\\ruby-1.8.0\\ruby\\bin\\ruby.exe D:\\Temp\\test.rb"); EvaluateRubyProcessOutput erpo = new EvaluateRubyProcessOutput(p) ; String in = new BufferedReader(new InputStreamReader(System.in)).readLine() ; erpo.sendOutput(in) ; } }