package externalExecutor;

import java.io.*;
import java.util.List;


/**
 * Esta clase permite la ejecución de comandos en terminal de Linux,
 *  así como la captura de la salida (stdout y stderr) de la ejecución de éstos
 * 
 * @author Enrique M.L
 *
 */
public class ExternalExecutor {
	private List<String> command;
	private ThreadedStreamHandler inputStreamHandler;
	private ThreadedStreamHandler errorStreamHandler;
	private String run_path;
	private int exitValue;
	
    public ExternalExecutor(final List<String> commandInformation, String path){
    	if (commandInformation==null) throw new NullPointerException("Wrong command syntax.");
	    this.command = commandInformation;
	    this.run_path = path;
	}
    
    private void setExitValue(int pexitValue){
    	exitValue = pexitValue;
    }
    
    public int getExitValue(){
    	return exitValue;
    }

	@SuppressWarnings("finally")
	public int executeCommand() {
		
		int exitValue = -99;
		
	    try
	    {
	      ProcessBuilder pb = new ProcessBuilder(command);
	      
	      pb.directory(new File(run_path));
	      
	      Process process = pb.start();
	      //Get stdin, stdout and stderr
	      OutputStream stdOutput = process.getOutputStream();
	      InputStream inputStream = process.getInputStream();
	      InputStream errorStream = process.getErrorStream();
	      
	      
	      if (inputStream == null || errorStream == null)
	    	  System.out.println("ERRORACO");

	      //Create handlers
	      String adminPassword = "nothing";
	      inputStreamHandler = new ThreadedStreamHandler(inputStream, stdOutput, adminPassword);
	      //StringBuilder a = inputStreamHandler.getOutputBuffer();
	      
	      errorStreamHandler = new ThreadedStreamHandler(errorStream);

	      inputStreamHandler.start();
	      errorStreamHandler.start();

	      //Wait for the process to give a return vaule
	      exitValue = process.waitFor();
	 
	      setExitValue(exitValue);
	      
	      //Stop and join the threads
	      inputStreamHandler.interrupt();
	      errorStreamHandler.interrupt();
	      inputStreamHandler.join();
	      errorStreamHandler.join();
	    }
	    catch (IOException e)
	    {
	    	e.printStackTrace();
	    }
	    catch (InterruptedException e)
	    {
	    	e.printStackTrace();
	    }
	    finally
	    {
	      return exitValue;
	    }
	  }

    /**
     * Retorna la salida estándar
     * 
     * @return
     */
	public StringBuilder getStandardOutputFromCommand(){
		StringBuilder a= inputStreamHandler.getOutputBuffer();
	    return a;
	}

	/**
	 * Retorna el error estándar
	 * 
	 * @return
	 */
    public StringBuilder getStandardErrorFromCommand(){
    	return errorStreamHandler.getOutputBuffer();
	  }
}
