package dropdash.sh;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.google.common.base.Function;

public class ShellCommand implements Command {

	private String[] command;
	protected Function<String, String> filter;
	private String output;
	private String error;
	private int result;

	public ShellCommand(String shell, String command, Function<String, String> filter) {
		this.filter = filter;
		this.command = new String[] { shell, "-c", command };
	}

	public ShellCommand(String command, Function<String, String> filter) {
		this("bash", command, filter);
	}

	public ShellCommand(String shell, String command) {
		this(shell, command, null);
	}

	public ShellCommand(String command) {
		this("bash", command, null);
	}

	@Override
	public String execute() {
		result = -1;
		try {
			ProcessRunner pr = new ProcessRunner(command);
			result = pr.waitFor();
			output = pr.getOutput();
			error = pr.getError();
			if (filter != null) {
				output = filter.apply(output);
			}
			return output;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	@Override
	public String getOutput() {
		return output;
	}

	@Override
	public String getError() {
		return error;
	}

	@Override
	public int getResult() {
		return result;
	}

	class ProcessRunner {

		private Process process;
		private StreamReader outReader;
		private StreamReader errReader;

		public ProcessRunner(String[] command) throws IOException {
			process = new ProcessBuilder(command).start();
			outReader = new StreamReader(process.getInputStream());
			errReader = new StreamReader(process.getInputStream());
			outReader.start();
			errReader.start();
		}

		public String getError() {
			return errReader.getOutput();
		}

		public String getOutput() {
			return outReader.getOutput();
		}

		public int waitFor() throws InterruptedException {
			return process.waitFor();
		}

	}

	class StreamReader extends Thread {

		private InputStream in;
		private StringBuffer sb;

		public StreamReader(InputStream inputStream) {
			this.in = inputStream;
			this.sb = new StringBuffer();
		}

		@Override
		public void run() {
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			String line = "";
			try {
				while ((line = reader.readLine()) != null) {
					sb.append(line + "\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public String getOutput() {
			return sb.toString();
		}

	}
}

@@ -137,16 +137,74 @@
 eader;%0A%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0A
 import c
@@ -284,16 +284,97 @@
 mand %7B%0A%0A
+%09private static final Logger log = LoggerFactory.getLogger(ShellCommand.class);%0A%0A
 %09private
@@ -1536,30 +1536,28 @@
 ate 
+Input
 Stream
-Reader outReader
+ inStream
 ;%0A%09%09
@@ -1568,30 +1568,72 @@
 ate 
+Input
 Stream
-Reader errReader
+ erStream;%0A%09%09private String err;%0A%09%09private String out
 ;%0A%0A%09
@@ -1750,37 +1750,19 @@
 %0A%09%09%09
-outReader = new StreamReader(
+inStream = 
 proc
@@ -1785,110 +1785,46 @@
 am()
-)
 ;%0A%09%09%09er
-rReader = new StreamReader(process.getInputStream());%0A%09%09%09outReader.start();%0A%09%09%09errReader.start
+Stream = process.getErrorStream
 ();%0A
@@ -1870,34 +1870,16 @@
 turn err
-Reader.getOutput()
 ;%0A%09%09%7D%0A%0A%09
@@ -1924,26 +1924,8 @@
  out
-Reader.getOutput()
 ;%0A%09%09
@@ -1983,22 +1983,25 @@
 on %7B%0A%09%09%09
-return
+int res =
  process
@@ -2016,255 +2016,160 @@
 ();%0A
-%09%09%7D%0A%0A%09%7D%0A%0A%09class StreamR
+%0A%09%09%09out = read(inStream);%0A%09%09%09err = r
 ead
+(
 er
- extends Thread %7B
+Stream);
 %0A%0A%09%09
+%09
-private InputStream in;%0A%09%09private StringBuffer sb;%0A%0A%09%09public StreamReader(InputStream inputStream) %7B%0A%09%09%09this.in = inputStream;%0A%09%09%09this.sb = new StringBuffer();%0A%09%09%7D%0A%0A%09%09@Override%0A%09%09public void run() %7B
+return res;%0A%09%09%7D%0A%0A%09%09private String read(InputStream in) %7B%0A%09%09%09StringBuffer sb = new StringBuffer();
 %0A%09%09%09
@@ -2390,68 +2390,53 @@
 %09%09%09%09
-e.printStackTrace();%0A%09%09%09%7D%0A%09%09%7D%0A%0A%09%09public String getOutput() %7B
+log.error(%22cannot read InputStream%22, e);%0A%09%09%09%7D
 %0A%09%09%09

Fix Threading problem.