/*
 *  PHEX - The pure-java Gnutella-servent.
 *  Copyright (C) 2001 - 2004 Gregor Koukkoullis ( phex <at> kouk <dot> de )
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package phex.utils;

import java.util.*;
import java.util.regex.*;

import java.io.*;

public class Runner
{
 
    public int result;

    // Suck all the output from the given process and return when it's complete
    public Runner ( String commandLine )
    {
        go ( parseCommandLine (commandLine) );
    }

    public Runner ( String[] commandLine )
    {
        go ( commandLine );
    }

    public void go ( String[] commands )
    {
        Process proc = null;
        try
        {
            proc = java.lang.Runtime.getRuntime().exec( commands );
        }
        catch ( IOException ex )
        {
            ex.printStackTrace();
        }
        //prepare buffers for process output and error streams
        StringBuffer err=new StringBuffer();
        StringBuffer out=new StringBuffer();    
        try
            {
            //create thread for reading inputStream (process' stdout)
            StreamReaderThread outThread=new StreamReaderThread(proc.getInputStream(),out);
            //create thread for reading errorStream (process' stderr)
            StreamReaderThread errThread=new StreamReaderThread(proc.getErrorStream(),err);
            //start both threads
            outThread.start();
            errThread.start();
            //wait for process to end
            result=proc.waitFor();
            //finish reading whatever's left in the buffers
            outThread.join();
            errThread.join();

            if (result!=0) 
            {
                System.out.println("Process " +  " returned non-zero value:" + result);
                System.out.println("Process output:\n" + out.toString());
                System.out.println("Process error:\n" + err.toString());
            } else {
                System.out.println("Process " +  " executed successfully");
                System.out.println("Process output:\n" + out.toString());
                System.out.println("Process error:\n" + err.toString());
            }
        }
        catch (Exception e)
        {
            System.out.println("Error executing. ");
            e.printStackTrace();
            //throw e;
        }
    }

    /*
     * Splits the given string at whitespace, respecting
     * quoted strings
     */
    public static String[] parseCommandLine ( String commandLine )
    {
        // Define a pattern which will split on spaces but respect quotes
        Pattern p = Pattern.compile("(\".*?\"|\\S+)", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(commandLine);
        List tokens = new LinkedList();
        String[] result;
        int counter = 0;
        while ( m.find() )
        {
            tokens.add( m.group(1) );
            counter++;
        }
        result = new String[counter];
        Iterator it = tokens.iterator();
        String quoteString = "\"";
        for (int i = 0; i < counter ; i++)
        {
            String field = (String) it.next();
            if ( field.startsWith("\"") || true ) // ie: unix
            {
                result[i] = field;
            } else
            {
                result[i] = new String (quoteString + field + quoteString);
            }
        }
        return result;
    }

    private String[] parseCommandLineOld ( String commandLine )
    {
        Reader r = new StringReader ( commandLine );
        StreamTokenizer t = new StreamTokenizer( r );
        t.wordChars(0x0000, 0x00FF); 
        t.quoteChar('"');
        t.whitespaceChars(' ', ' ');

        List tokens = new LinkedList();
        String[] result;
        int counter = 0;
        try
        {
            while ( t.nextToken() != StreamTokenizer.TT_EOF )
            {
                tokens.add( t.sval );
                counter++;
            }
        }
        catch ( IOException ex )
        {
            ex.printStackTrace();
        }

        result = new String[counter];
        Iterator it = tokens.iterator();
        String quoteString = "\"";
        for (int i = 0; i < counter ; i++)
        {
            result[i] = new String (quoteString + (String) it.next() + quoteString);
        }
        return result;
    }

    public class StreamReaderThread extends Thread
    {
        StringBuffer mOut;
        InputStreamReader mIn;
        
        public StreamReaderThread(InputStream in, StringBuffer out)
        {
            mOut=out;
            mIn=new InputStreamReader(in);
        }
            
        public void run()
        {
            int ch;
            try
            {
                while(-1 != (ch=mIn.read()))
                    mOut.append((char)ch);
            }
            catch (Exception e)
            {
                mOut.append("\nRead error:" + e.getMessage());
            }
        }
    }
}

