package com.interpress_project.modernshare.serveradm;

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

import com.interpress_project.modernshare.ipcommon.SystemBase;
import com.interpress_project.modernshare.serveradm.exceptions.CommandExecutorException;

public class CommandExecutor {
	private final SystemBase sb = SystemBase.getInstance();
	private ProcessBuilder processBuilder;
	private Process process;
	private boolean bWaitFor = false;

	/**
	 * CommandExecutor
	 * @param bWaitFor
	 */
	public CommandExecutor(boolean bWaitFor) {
		this.bWaitFor = bWaitFor;
	}

	/**
	 * execute
	 * @param cmdlist
	 * @return
	 * @throws CommandExecutorException
	 */
	public int execute(ArrayList<String> cmdlist) throws CommandExecutorException {
		InputStream is = null, errs = null;
		int rcode = 0;

		try {
			processBuilder = new ProcessBuilder(cmdlist);
			processBuilder = processBuilder.redirectErrorStream(true);
			process = processBuilder.start();
			process.getOutputStream().close();

			is = process.getInputStream();
			errs = process.getErrorStream();
		}
		catch (Exception ex) {
			throw new CommandExecutorException("Command execute failed: " + ex.getMessage());
		}

		StreamGobbler sg = new StreamGobbler(is);
		sg.start();
		try {
			if (bWaitFor) {
				rcode = process.waitFor();
			}
		}
		catch (InterruptedException ex) {
			sb.getLogger().warn("InterupptedException waiting for command done: " + ex.getMessage());
		}
		finally {
			try {
				is.close();
				errs.close();
			}
			catch (IOException ex) {
				sb.getLogger().error("IOException closing command streams: " + ex.getMessage());
			}
		}
		return rcode;
	}

	/**
	 * destroy
	 */
	public void destroy() {
		if (process != null) {
			process.destroy();
		}
	}

	/**
	 * StreamGobbler
	 * @author ys
	 */
	private class StreamGobbler extends Thread {
		private InputStream is;

		/**
		 * StreamGobbler
		 * @param is
		 */
		public StreamGobbler(InputStream is) {
			this.setStream(is);
		}

		/**
		 * setStream
		 * @param is
		 */
		public void setStream(InputStream is) {
			this.is = is;
		}

		/**
		 * run
		 */
		public void run() {
			InputStreamReader isr = new InputStreamReader(is);
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			try {
				while ((line = br.readLine()) != null) {
					sb.getLogger().info(line);
				}
			}
			catch (Exception ex) {
			}
			finally {
				try {
					br.close();
				}
				catch (IOException e) {
				}
			}
		}
	}
}
