package org.greenstone.gatherer.util;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import org.greenstone.gatherer.DebugStream;


/**
 * This class provides a convenient method of running external programs and viewing/analysing
 * their output. The external programs may be run with or without arguments. 
 */
public class ExternalProgram
{
    private Process programProcess = null;

    private BufferedReader programOut = null;
    private BufferedReader programErr = null;


    /**
     * Prepares to run a specified external program with the specified arguments.
     *
     * @param programName The name (and path, if necessary) of the program to run.
     * @param programArgs The arguments to provide to the program when run.
     */
    public ExternalProgram(String programName, String programArgs)
	throws IOException
    {
	// Run the program
	programProcess = Runtime.getRuntime().exec(programName + " " + programArgs);

	// Grab the program output
	programOut = new BufferedReader(new InputStreamReader(programProcess.getInputStream()));
	programErr = new BufferedReader(new InputStreamReader(programProcess.getErrorStream()));

    }



    /**
     */
    public int exitProgram()
	throws IOException
    {
	// Finished, thank you
	//programIn.close();

	// Wait for the process to finish
	try {
	    programProcess.waitFor();
	}
	catch (InterruptedException ex) {
	    throw new Error("Internal Error: Process interrupted.\n" + ex);
	}

	// Return the program exit value
	return programProcess.exitValue();
    }


    /**
     * Returns a single line of output sent by the program to standard output.
     *
     * @return a single line of output sent by the program to standard output.
     */
    public String getLineOfProgramOutput()
    {
	// Read in a line from the program output
	try {
	    if (programOut.ready())
		return programOut.readLine();
	    else
		return null;
	}
	catch (IOException ex) {
	    DebugStream.println("Error: Exception occurred while reading program output.");
	    DebugStream.println("Exception: " + ex);
	    return null;
	}
    }


    /**
     * Returns a single line of output sent by the program to standard error.
     *
     * @return a single line of output sent by the program to standard error.
     */
    public String getLineOfProgramError()
    {
	// Read in a line from the program error
	try {
	    if (programErr.ready())
		return programErr.readLine();
	    else
		return null;
	}
	catch (IOException ex) {
	    DebugStream.println("Error: Exception occurred while reading program error.");
	    DebugStream.println("Exception: " + ex);
	    return null;
	}
    }
}
