/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.org
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Initial developer(s): ____________________________________.
 * Contributor(s): ______________________________________.
 *
 * 01/05/30 Christophe Ney - Lutris Technologies
 *          Fix to handle arguments containing white spaces.
 * 00/13/03 Vincent Sheffer
 *          Exit properly on failure of the external command.
 * 00/02/05 Nozomi Matsumura
 *          GenIC i18n problem.
 *          GenIC invoke javac and javac's output has non asc-ii characters,
 *          javac's output did not show collectly.
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */


package org.objectweb.common;


/**
 * This class allows to run a command in sub-process.
 */

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.Process;
import java.lang.String;
import java.util.*;

public class Cmd {

    private Vector mCmd = new Vector();
    private String[] mEnv = null;

    /**
     * Construtor method of Cmd class.
     * @param cmd command
     */
    public Cmd(String cmd) {
	mCmd.addElement(cmd);
    }

    /**
     * Construtor method of Cmd class.
     * @param cmd command
     */
    public Cmd(String cmd, String[] env) {
	mCmd.addElement(cmd);
	mEnv = env;
    }

    /**
     * Add a new argument to the command.
     * @param arg argument added to the tail of the command argument list
     */
    public void addArgument(String arg) {
    mCmd.addElement(arg);
    }
    
    /**
     * Add a new argument to the command.
     * @param arg argument added to the tail of the command argument list
     */
    public void addArguments(Vector args) {
        Enumeration e = args.elements();
        while (e.hasMoreElements()) {
            mCmd.addElement((String)e.nextElement());
        }
    }
    
    /**
     * Execute the command.
     * (In case of the exit value of the command is not 0,
     * the output and error streams of the command is traced.)
     * @return false if the command cannot be executed, or if its exit value is not 0.
     */
    public boolean run() {
	RunnableStreamListener out, err;
	Process proc = null;
	boolean val = true;

	try {
        String[] cmd = new String[mCmd.size()];
        mCmd.copyInto(cmd);
        proc = Runtime.getRuntime().exec(cmd, mEnv);
	} catch (IOException e) {
	    TraceCore.error("Cmd:run IOException", e);
	    return(false);
	}
	out = new RunnableStreamListener(new BufferedReader(new InputStreamReader(proc.getInputStream())),
					 System.out);
	new Thread(out, "stdout listener for "+this.toString()).start();
	err = new RunnableStreamListener(new BufferedReader(new InputStreamReader(proc.getErrorStream())),
					 System.err);
	new Thread(err, "stderr listener for "+this.toString()).start();
	try {
	    val = proc.waitFor() == 0;
	} catch (InterruptedException e) {
	    TraceCore.error("Cmd:run InterruptedException", e);
	    val = false;
	}

	return(val);
    }
    
    /*
     * String representation of the object for UI purpose
     */
    public String toString() {
        StringBuffer buf = new StringBuffer();
        Enumeration e = mCmd.elements();
        while (e.hasMoreElements()) {
            String arg = (String)e.nextElement();
	    if (arg == null) {
		arg = "null";
	    }
            for (int i=0; i<arg.length();i++) {
                if (Character.isWhitespace(arg.charAt(i))) {
                    arg="\""+arg+"\"";
                    break;
                }
            }
            buf.append(arg);
            buf.append(' ');
        }
        return buf.toString().trim();
    }
    
}


//  this runs happily, swallowing the stdout from the process
class RunnableStreamListener implements Runnable {
    BufferedReader in_;
    PrintStream stream_;
    RunnableStreamListener(BufferedReader in, PrintStream stream ) {
        in_ = in;
        stream_ = stream;
    }
    public void run() {
        String line;
        try {
            while ((line = in_.readLine()) != null)
            stream_.println(line);
        } catch (IOException e ) {
            stream_.println(e.toString());
        }
    }
}

