package com.github.aureliano.achmed.command;

import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.Callable;

import com.github.aureliano.achmed.helper.StringHelper;

public class CommandRunner implements Callable<CommandResponse> {

	private List<String> command;
	private File workingDir;
	private boolean verbose;
	
	public CommandRunner(String command, String dir, boolean verbose) {
		this.command = Arrays.asList(command.split("\\s+"));
		this.workingDir = new File(dir);
		this.verbose = verbose;
	}
	
	public CommandResponse call() throws Exception {
		return this.execute();
	}
	
	public CommandResponse execute() {
		ProcessBuilder builder = new ProcessBuilder(this.command);
		builder.directory(this.workingDir);
		
		int exitStatus = Integer.parseInt("1" + this.command.size());
		Process process = null;
		CommandResponse response = new CommandResponse(StringHelper.join(this.command, " "));
		
		try {
			process = builder.start();
			response.withOutput(this.scanCommand(process));
			exitStatus = process.waitFor();
		} catch (Exception ex) {
			response.withError(this.readError(process));
		}
		
		return response.withExitStatusCode(exitStatus);
	}
	
	private String scanCommand(Process process) {
		return this.consumeStream(process.getInputStream(), this.verbose);
	}
	
	private String readError(Process process) {
		return this.consumeStream(process.getErrorStream(), true);
	}
	
	private String consumeStream(InputStream stream, boolean verbose) {
		Scanner scanner = new Scanner(stream);
		StringBuilder builder = new StringBuilder();
		
		while (scanner.hasNextLine()) {
			String line = scanner.nextLine();
			builder.append(line).append("\n");
			
			if (verbose) {
				System.out.println(line);
			}
		}
		
		if (builder.length() > 0) {
			builder.deleteCharAt(builder.length() - 1);
		}
		scanner.close();
		
		return builder.toString();
	}
}
@@ -39,16 +39,47 @@
 mmand;%0A%0A
+import java.io.BufferedReader;%0A
 import j
@@ -119,16 +119,50 @@
 Stream;%0A
+import java.io.InputStreamReader;%0A
 import j
@@ -205,34 +205,8 @@
 st;%0A
-import java.util.Scanner;%0A
 impo
@@ -240,16 +240,78 @@
 lable;%0A%0A
+import com.github.aureliano.achmed.exception.AchmedException;%0A
 import c
@@ -1189,16 +1189,20 @@
 cess));%0A
+%09%09%09%0A
 %09%09%09exitS
@@ -1672,35 +1672,83 @@
 %7B%0A%09%09
-Scanner scanner = new Scann
+try (BufferedReader bufferedReader = new BufferedReader(new InputStreamRead
 er(s
@@ -1753,18 +1753,22 @@
 (stream)
-;%0A
+)) %7B%0A%09
 %09%09String
@@ -1812,83 +1812,93 @@
 ;%0A%09%09
+%09
 %0A%09%09
-while (scanner.hasNextLine()) %7B%0A%09%09%09String line = scanner.nextLine();
+%09String line = null;%0A%09%09%09while ((line = bufferedReader.readLine()) != null) %7B
 %0A%09%09%09
+%09
 buil
@@ -1931,17 +1931,19 @@
 n%22);%0A%09%09%09
-%0A
+%09%0A%09
 %09%09%09if (v
@@ -1948,24 +1948,25 @@
 (verbose) %7B%0A
+%09
 %09%09%09%09System.o
@@ -1990,17 +1990,21 @@
 %0A%09%09%09
+%09
 %7D%0A
+%09
 %09%09%7D%0A%09%09
-%0A
+%09%0A%09
 %09%09if
@@ -2032,16 +2032,17 @@
 0) %7B%0A%09%09%09
+%09
 builder.
@@ -2083,32 +2083,16 @@
 ;%0A%09%09
+%09
 %7D%0A%09%09
-scanner.close();%0A%09
 %09%0A
+%09
 %09%09re
@@ -2116,12 +2116,77 @@
 ring();%0A
+%09%09%7D catch (Exception ex) %7B%0A%09%09%09throw new AchmedException(ex);%0A%09%09%7D%0A
 %09%7D%0A%7D

Use buffered reader instead of scanner to read process stream.