/*
 *  Copyright(c) 2003-2004 by the authors indicated in the @author tags.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.tigris.subversion.svnclientadapter.commandline;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;

/**
 * common methods for both SvnCommandLine and SvnAdminCommandLine 
 *  
 * @author Philip Schatz (schatz at tigris)
 * @author Cdric Chabanois (cchabanois at no-log.org)
 */
abstract class CommandLine {

	protected String CMD;
    protected CmdLineNotificationHandler notificationHandler;
    
	//Constructors
	CommandLine(String svnPath,CmdLineNotificationHandler notificationHandler) {
		CMD = svnPath;
        this.notificationHandler = notificationHandler;
	}

	//Methods
	String version() throws CmdLineException {
		ArrayList args = new ArrayList();
		args.add("--version");
		return execString(args,false);
	}


    /**
     * execute the given svn command and returns the corresponding process  
     */
	protected Process execProcess(ArrayList svnArguments) throws CmdLineException {
		Runtime rt = Runtime.getRuntime();

		String svnCommand = "";
		boolean nextIsPassword = false;
		for (Iterator it = svnArguments.iterator();it.hasNext();) {
			String arg = (String)it.next();
			
			if (nextIsPassword) {
				svnCommand += "*******";
				nextIsPassword = false;	
			} else {
				svnCommand += arg;
			}
			if (it.hasNext())
				svnCommand += " ";
			if (arg.equals("--password")) {
				// we don't want to show the password in the console ...
				nextIsPassword = true;
			}				
		}
        notificationHandler.logCommandLine(svnCommand);

		// we add "svn" or "svnadmin" to  the arguments and convert it to an array of strings
		ArrayList argsArrayList = new ArrayList(svnArguments);
		argsArrayList.add(0,CMD);
		String[] argsArray = new String[argsArrayList.size()];
		argsArrayList.toArray(argsArray);

		/* run the process */
		Process proc = null;
		try {
			proc = rt.exec(argsArray);
		} catch (IOException e) {
			throw new CmdLineException(e);
		}

		return proc;
	}

	/**
	 * runs the process and returns the results.
	 * @param cmd
	 * @return String
	 */
	protected String execString(ArrayList svnArguments, boolean coalesceLines) throws CmdLineException {
		Process proc = execProcess(svnArguments);

        CmdLineStreamPumper outPumper = new CmdLineStreamPumper(proc.getInputStream(),coalesceLines);
        CmdLineStreamPumper errPumper = new CmdLineStreamPumper(proc.getErrorStream());

        Thread threadOutPumper = new Thread(outPumper);
        Thread threadErrPumper = new Thread(errPumper);
        threadOutPumper.start();         
        threadErrPumper.start();
        try {
            outPumper.waitFor();
            errPumper.waitFor();
        } catch (InterruptedException e) {
        }
        
		try {
            String errMessage = errPumper.toString();
            if (errMessage.length() > 0) {
                throw new CmdLineException(errMessage);        
            }
            String outputString = outPumper.toString(); 

            notifyFromSvnOutput(outputString);
			return outputString;
		} catch (CmdLineException e) {
            notificationHandler.logException(e);
			throw e;
		}
	}

    /**
     * runs the command (returns nothing)
     * @param svnCommand
     * @throws CmdLineException
     */
	protected void execVoid(ArrayList svnArguments) throws CmdLineException {
		execString(svnArguments,false);
	}

	/**
	 * notify the listeners from the output. This is the default implementation
     *
	 * @param svnOutput
	 */
    protected void notifyFromSvnOutput(String svnOutput) {
		StringTokenizer st = new StringTokenizer(svnOutput, Helper.NEWLINE);
		int size = st.countTokens();
		//do everything but the last line
		for (int i = 1; i < size; i++) {
            notificationHandler.logMessage(st.nextToken());
		}

		//log the last line as the completed message.
		if (size > 0)
            notificationHandler.logCompleted(st.nextToken());
    }
    	
	
	
}


@@ -761,35 +761,8 @@
 st;%0A
-import java.util.Iterator;%0A
 impo
@@ -1698,21 +1698,22 @@
 or (
-Iterator
+int
  i
-t
  =
+ 0; i %3C
  svn
@@ -1726,70 +1726,186 @@
 nts.
-iterator();it.hasNext();) %7B%0A%09%09%09String arg = (String)it.next();
+size(); i++) %7B%0A%09%09%09if (i != 0)%0A%09%09%09%09svnCommand += %22 %22;%0A%09%09%09%0A%09%09%09String arg = (String)svnArguments.get(i);%0A%09%09%09%0A%09%09%09if (arg == %22%22) %7B%0A%09%09%09%09arg = %22%5C%22%5C%22%22;%0A%09%09%09%09svnArguments.set(i, arg);%0A%09%09%09%7D
 %0A%09%09%09
@@ -2032,51 +2032,11 @@
 %09%09%7D%0A
+
 %09%09%09
-if (it.hasNext())%0A%09%09%09%09svnCommand += %22 %22;
 %0A%09%09%09

Fix for issue 256 - Operations fail when no commit message given