package com.thedeanda.util.process;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//TODO: move this to a utils folder
public class RunExec {
	private static final Logger log = LoggerFactory.getLogger(RunExec.class);

	public static ProcessResult exec(String command, File directory)
			throws IOException {
		return exec(command, directory, 0);
	}

	public static ProcessResult exec(String command, File directory,
			int maxDuration) throws IOException {
		String[] parts = StringUtils.split(command);
		List<String> list = Arrays.asList(parts);
		return exec(list, directory, maxDuration);
	}

	public static ProcessResult exec(List<String> command, File directory)
			throws IOException {
		return exec(command, directory, 0);
	}

	/**
	 * 
	 * @param command
	 * @param directory
	 * @param maxDuration
	 *            - maximum amount of time in ms to let the command run before
	 *            aborting it
	 * @return
	 * @throws IOException
	 */
	public static ProcessResult exec(List<String> command, File directory,
			int maxDuration) throws IOException {

		File stdOutFile = File.createTempFile("runexec_", ".std");
		File errOutFile = File.createTempFile("runexec_", ".err");

		ProcessBuilder pb = new ProcessBuilder(command);
		pb.redirectError(errOutFile);
		pb.redirectOutput(stdOutFile);

		// pb.redirectErrorStream(true);
		if (directory != null)
			pb.directory(directory);

		final Process process = pb.start();

		// Wait to get exit value
		final IntegerHolder exitValue = new IntegerHolder();
		long duration = 0;
		Thread stdT = null;
		Thread errT = null;
		Thread waitT = null;
		String stdOut = null;
		String errOut = null;
		try {
			long start = System.currentTimeMillis();
			// make sure all threads start before timing for stop

			if (maxDuration <= 0) {
				exitValue.value = process.waitFor();
			} else {
				final CountDownLatch doneSignal = new CountDownLatch(1);
				waitT = new Thread(new Runnable() {
					@Override
					public void run() {
						try {
							exitValue.value = process.waitFor();
						} catch (InterruptedException e) {
							log.warn(e.getMessage(), e);
						}
						doneSignal.countDown();
					}
				});
				waitT.start();
				// wait for thread to finish...
				if (!doneSignal.await(maxDuration, TimeUnit.MILLISECONDS)) {
					// stop process
					log.warn("process took too long, aborting");
					process.destroy();
					waitT.interrupt();
					exitValue.value = -1;
				}
			}
			long end = System.currentTimeMillis();
			duration = end - start;

			stdOut = FileUtils.readFileToString(stdOutFile);
			errOut = FileUtils.readFileToString(errOutFile);

		} catch (InterruptedException e) {
			exitValue.value = -1;
			log.error(e.getMessage(), e);
		} finally {
			if (stdT != null)
				stdT.interrupt();
			if (errT != null)
				errT.interrupt();
			if (waitT != null)
				waitT.interrupt();
			stdOutFile.delete();
			errOutFile.delete();
		}

		return new ProcessResult(stdOut, errOut, exitValue.value, duration);
	}

}

@@ -1288,35 +1288,36 @@
 e directory,%0A%09%09%09
-int
+long
  maxDuration) th
@@ -1360,353 +1360,38 @@
 e = 
-File.createTempFile(%22runexec_%22, %22.std%22);%0A%09%09File errOutFile = File.createTempFile(%22runexec_%22, %22.err%22)
+null
 ;%0A
-%0A
 %09%09
-ProcessBuilder pb = new ProcessBuilder(command);%0A%09%09pb.redirectError(errOutFile);%0A%09%09pb.redirectOutput(stdOutFile);%0A%0A%09%09// pb.redirectErrorStream(true);%0A%09%09if (directory != null)%0A%09%09%09pb.directory(directory);%0A%0A%09%09final Process process = pb.start()
+File errOutFile = null
 ;%0A%0A%09
@@ -1497,52 +1497,8 @@
  0;%0A
-%09%09Thread stdT = null;%0A%09%09Thread errT = null;%0A
 %09%09Th
@@ -1572,16 +1572,382 @@
 %09%09try %7B%0A
+%09%09%09stdOutFile = File.createTempFile(%22runexec_%22, %22.std%22);%0A%09%09%09errOutFile = File.createTempFile(%22runexec_%22, %22.err%22);%0A%0A%09%09%09ProcessBuilder pb = new ProcessBuilder(command);%0A%09%09%09pb.redirectError(errOutFile);%0A%09%09%09pb.redirectOutput(stdOutFile);%0A%0A%09%09%09// pb.redirectErrorStream(true);%0A%09%09%09if (directory != null)%0A%09%09%09%09pb.directory(directory);%0A%0A%09%09%09final Process process = pb.start();%0A
 %09%09%09long 
@@ -3015,19 +3015,20 @@
 %0A%09%09%09if (
-std
+wait
 T != nul
@@ -3034,19 +3034,20 @@
 ll)%0A%09%09%09%09
-std
+wait
 T.interr
@@ -3060,20 +3060,26 @@
 %0A%09%09%09if (
-errT
+stdOutFile
  != null
@@ -3088,95 +3088,57 @@
 %09%09%09%09
-errT.interrupt();%0A%09%09%09if (waitT != null)%0A%09%09%09%09waitT.interrupt();%0A%09%09%09stdOutFile.delete();%0A
+stdOutFile.delete();%0A%09%09%09if (errOutFile != null)%0A%09
 %09%09%09e

fix try/catch/finally a bit