/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ant.core;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.ant.internal.core.AntClassLoader;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.core.InternalCoreAntMessages;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPlatformRunnable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;

/**
 * Entry point for running Ant builds inside Eclipse.
 * Clients may instantiate this class; it is not intended to be subclassed.
 */
public class AntRunner implements IPlatformRunnable {

	private static boolean buildRunning= false;
	protected String buildFileLocation = IAntCoreConstants.DEFAULT_BUILD_FILENAME;
	protected List buildListeners;
	protected String[] targets;
	protected Map userProperties;
	protected int messageOutputLevel = 2; // Project.MSG_INFO
	protected String buildLoggerClassName;
	protected String inputHandlerClassName;
	protected String[] arguments;
	protected String[] propertyFiles;
	protected URL[] customClasspath;
	protected String antHome;

	/**
	 * Sets the build file location on the file system.
	 * 
	 * @param buildFileLocation the file system location of the build file
	 */
	public void setBuildFileLocation(String buildFileLocation) {
		if (buildFileLocation == null) {
			this.buildFileLocation = IAntCoreConstants.DEFAULT_BUILD_FILENAME;
		} else {
			this.buildFileLocation = buildFileLocation;
		}
	}

	/**
	 * Set the message output level.
	 * <p>
	 * Valid values are:
	 * <ul>
	 * <li><code>org.apache.tools.ant.Project.ERR</code>, 
	 * <li><code>org.apache.tools.ant.Project.WARN</code>,
	 * <li><code>org.apache.tools.ant.Project.INFO</code>,
	 * <li><code>org.apache.tools.ant.Project.VERBOSE</code> or
	 * <li><code>org.apache.tools.ant.Project.DEBUG</code>
	 * </ul>
	 * 
	 * @param level the message output level
	 */
	public void setMessageOutputLevel(int level) {
		messageOutputLevel = level;
	}

	/**
	 * Sets the arguments to be passed to the build (e.g. -Dos=win32 -Dws=win32
	 * - verbose).
	 * 
	 * @param arguments the arguments to be passed to the build
	 */
	public void setArguments(String arguments) {
		this.arguments = getArray(arguments);
	}

	/*
	 * Helper method to ensure an array is converted into an ArrayList.
	 */
	private String[] getArray(String args) {
		StringBuffer sb = new StringBuffer();
		boolean waitingForQuote = false;
		ArrayList result = new ArrayList();
		for (StringTokenizer tokens = new StringTokenizer(args, ", \"", true); tokens.hasMoreTokens();) { //$NON-NLS-1$
			String token = tokens.nextToken();
			if (waitingForQuote) {
				if (token.equals("\"")) { //$NON-NLS-1$
					result.add(sb.toString());
					sb.setLength(0);
					waitingForQuote = false;
				} else {
					sb.append(token);
				}
			} else {
				if (token.equals("\"")) { //$NON-NLS-1$
					// test if we have something like -Dproperty="value"
					if (result.size() > 0) {
						int index = result.size() - 1;
						String last = (String) result.get(index);
						if (last.charAt(last.length() - 1) == '=') {
							result.remove(index);
							sb.append(last);
						}
					}
					waitingForQuote = true;
				} else {
					if (!(token.equals(",") || token.equals(" "))) //$NON-NLS-1$ //$NON-NLS-2$
						result.add(token);
				}
			}
		}
		return (String[]) result.toArray(new String[result.size()]);
	}

	/**
	 * Sets the arguments to be passed to the build (e.g. -Dos=win32 -Dws=win32 -verbose).
	 * 
	 * @param arguments the arguments to be passed to the build
	 * @since 2.1
	 */
	public void setArguments(String[] arguments) {
		this.arguments = arguments;
	}

	/**
	 * Sets the targets and execution order.
	 * 
	 * @param executionTargets which targets should be run and in which order
	 */
	public void setExecutionTargets(String[] executionTargets) {
		this.targets = executionTargets;
	}

	/**
	 * Adds a build listener. The parameter <code>className</code>
	 * is the class name of a <code>org.apache.tools.ant.BuildListener</code>
	 * implementation. The class will be instantiated at runtime and the
	 * listener will be called on build events
	 * (<code>org.apache.tools.ant.BuildEvent</code>).
	 *
	 * @param className a build listener class name
	 */
	public void addBuildListener(String className) {
		if (className == null) {
			return;
		}
		if (buildListeners == null) {
			buildListeners = new ArrayList(5);
		}
		buildListeners.add(className);
	}

	/**
	 * Sets the build logger. The parameter <code>className</code>
	 * is the class name of a <code>org.apache.tools.ant.BuildLogger</code>
	 * implementation. The class will be instantiated at runtime and the
	 * logger will be called on build events
	 * (<code>org.apache.tools.ant.BuildEvent</code>).  
	 * Only one build logger is permitted for any build.
	 * 
	 *
	 * @param className a build logger class name
	 */
	public void addBuildLogger(String className) {
		buildLoggerClassName = className;
	}

	/**
	 * Adds user-defined properties. Keys and values must be String objects.
	 * 
	 * @param properties a Map of user-defined properties
	 */
	public void addUserProperties(Map properties) {
		if (userProperties == null) {
			userProperties= new HashMap(properties);
		} else {
			userProperties.putAll(properties);
		}
	}

	/**
	 * Returns the buildfile target information.
	 * 
	 * @return an array containing the target information
	 * 
	 * @see TargetInfo
	 * @since 2.1
	 * @throws CoreException Thrown if problem is encountered determining the targets
	 */
	public synchronized TargetInfo[] getAvailableTargets() throws CoreException {
		Class classInternalAntRunner= null;
		Object runner= null;
		ClassLoader originalClassLoader= Thread.currentThread().getContextClassLoader();
		try {
			classInternalAntRunner = getInternalAntRunner();
			runner = classInternalAntRunner.newInstance();
			
			basicConfigure(classInternalAntRunner, runner);
					
			// get the info for each targets
			Method getTargets = classInternalAntRunner.getMethod("getTargets", null); //$NON-NLS-1$
			Object results = getTargets.invoke(runner, null);
			// get the default target
			Method getDefault= classInternalAntRunner.getMethod("getDefaultTarget", null); //$NON-NLS-1$
			String defaultName= (String)getDefault.invoke(runner, null);
			// collect the info into target objects
			List infos = (List) results;
			
			ProjectInfo project= new ProjectInfo((String)infos.remove(0), (String)infos.remove(0));
			int i= 0;
			Iterator iter= infos.iterator();
			TargetInfo[] targetInfo= new TargetInfo[infos.size()];
			List info;
			while (iter.hasNext()) {
				info= (List)iter.next();
				targetInfo[i++] = new TargetInfo(project, (String)info.get(0), (String)info.get(1), (String[])info.get(2), info.get(0).equals(defaultName));
			}
			return targetInfo;
		} catch (NoClassDefFoundError e) {
			problemLoadingClass(e);
			//not possible to reach this line
			return new TargetInfo[0];
		} catch (ClassNotFoundException e) {
			problemLoadingClass(e);
			//not possible to reach this line
			return new TargetInfo[0];
		} catch (InvocationTargetException e) {
			handleInvocationTargetException(runner, classInternalAntRunner, e);
			//not possible to reach this line
			return new TargetInfo[0];
		} catch (Exception e) {
			String message = (e.getMessage() == null) ? InternalCoreAntMessages.AntRunner_Build_Failed__3 : e.getMessage(); //$NON-NLS-1$
			throw new CoreException(new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, message, e));
		} finally {
			Thread.currentThread().setContextClassLoader(originalClassLoader);
		}
	}

	private void basicConfigure(Class classInternalAntRunner, Object runner) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		Method setBuildFileLocation = classInternalAntRunner.getMethod("setBuildFileLocation", new Class[] { String.class }); //$NON-NLS-1$
		setBuildFileLocation.invoke(runner, new Object[] { buildFileLocation });
		
		if (antHome != null) {	
			Method setAntHome = classInternalAntRunner.getMethod("setAntHome", new Class[] { String.class }); //$NON-NLS-1$
			setAntHome.invoke(runner, new Object[] { antHome });
		}
		
		setProperties(runner, classInternalAntRunner);
		
		if (arguments != null && arguments.length > 0) {
			Method setArguments = classInternalAntRunner.getMethod("setArguments", new Class[] { String[].class }); //$NON-NLS-1$
			setArguments.invoke(runner, new Object[] { arguments });
		}
	}

	/**
	 * Runs the build file. If a progress monitor is specified it will be
	 * available during the script execution as a reference in the Ant Project
	 * (<code>org.apache.tools.ant.Project.getReferences()</code>). A long-
	 * running task could, for example, get the monitor during its execution and
	 * check for cancellation. The key value to retrieve the progress monitor
	 * instance is <code>AntCorePlugin.ECLIPSE_PROGRESS_MONITOR</code>.
	 * 
	 * Only one build can occur at any given time.
	 * 
	 * Sets the current threads context class loader to the AntClassLoader
	 * for the duration of the build.
	 * 
	 * @param monitor a progress monitor, or <code>null</code> if progress
	 *    reporting and cancellation are not desired
	 * @throws CoreException Thrown if a build is already occuring or if an exception occurs during the build
	 */
	public void run(IProgressMonitor monitor) throws CoreException {
		if (buildRunning) {
			IStatus status= new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, MessageFormat.format(InternalCoreAntMessages.AntRunner_Already_in_progess, new String[]{buildFileLocation}), null); //$NON-NLS-1$
			throw new CoreException(status);
		}
		buildRunning= true;
		Object runner= null;
		Class classInternalAntRunner= null;
		ClassLoader originalClassLoader= Thread.currentThread().getContextClassLoader();
		try {
			classInternalAntRunner = getInternalAntRunner();
			runner = classInternalAntRunner.newInstance();
			// set build file
			Method setBuildFileLocation = classInternalAntRunner.getMethod("setBuildFileLocation", new Class[] { String.class }); //$NON-NLS-1$
			setBuildFileLocation.invoke(runner, new Object[] { buildFileLocation });
			
			//set the custom classpath
			if (customClasspath != null) {
				Method setCustomClasspath = classInternalAntRunner.getMethod("setCustomClasspath", new Class[] { URL[].class }); //$NON-NLS-1$
				setCustomClasspath.invoke(runner, new Object[] { customClasspath });
			}
			
			// add listeners
			if (buildListeners != null) {
				Method addBuildListeners = classInternalAntRunner.getMethod("addBuildListeners", new Class[] { List.class }); //$NON-NLS-1$
				addBuildListeners.invoke(runner, new Object[] { buildListeners });
			}
			
			if (buildLoggerClassName == null) {
				//indicate that the default logger is not to be used
				buildLoggerClassName= ""; //$NON-NLS-1$
			}
			// add build logger
			Method addBuildLogger = classInternalAntRunner.getMethod("addBuildLogger", new Class[] { String.class }); //$NON-NLS-1$
			addBuildLogger.invoke(runner, new Object[] { buildLoggerClassName });
			
			if (inputHandlerClassName != null) {	
				// add the input handler
				Method setInputHandler = classInternalAntRunner.getMethod("setInputHandler", new Class[] { String.class }); //$NON-NLS-1$
				setInputHandler.invoke(runner, new Object[] { inputHandlerClassName });
			}
			
			basicConfigure(classInternalAntRunner, runner);
			
			// add progress monitor
			if (monitor != null) {
				Method setProgressMonitor = classInternalAntRunner.getMethod("setProgressMonitor", new Class[] { IProgressMonitor.class }); //$NON-NLS-1$
				setProgressMonitor.invoke(runner, new Object[] { monitor });
			}
			
			// set message output level
			if (messageOutputLevel != 2) { //changed from the default Project.MSG_INFO
				Method setMessageOutputLevel = classInternalAntRunner.getMethod("setMessageOutputLevel", new Class[] { int.class }); //$NON-NLS-1$
				setMessageOutputLevel.invoke(runner, new Object[] { new Integer(messageOutputLevel)});
			}
			
			// set execution targets
			if (targets != null) {
				Method setExecutionTargets = classInternalAntRunner.getMethod("setExecutionTargets", new Class[] { String[].class }); //$NON-NLS-1$
				setExecutionTargets.invoke(runner, new Object[] { targets });
			} 

			// run
			Method run = classInternalAntRunner.getMethod("run", null); //$NON-NLS-1$
			run.invoke(runner, null);
		} catch (NoClassDefFoundError e) {
			problemLoadingClass(e);
		} catch (ClassNotFoundException e) {
			problemLoadingClass(e);
		} catch (InvocationTargetException e) {
			handleInvocationTargetException(runner, classInternalAntRunner, e);
		} catch (Exception e) {
			String message = (e.getMessage() == null) ? InternalCoreAntMessages.AntRunner_Build_Failed__3 : e.getMessage(); //$NON-NLS-1$
			IStatus status= new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, message, e);
			throw new CoreException(status);
		} finally {
			buildRunning= false;
			Thread.currentThread().setContextClassLoader(originalClassLoader);
		}
	}

	private Class getInternalAntRunner() throws ClassNotFoundException {
		ClassLoader loader = getClassLoader();
		Thread.currentThread().setContextClassLoader(loader);
		return loader.loadClass("org.eclipse.ant.internal.core.ant.InternalAntRunner"); //$NON-NLS-1$
	}

	private void setProperties(Object runner, Class classInternalAntRunner)
		throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		// add properties
		if (userProperties != null) {
			Method addUserProperties = classInternalAntRunner.getMethod("addUserProperties", new Class[] { Map.class }); //$NON-NLS-1$
			addUserProperties.invoke(runner, new Object[] { userProperties });
		}
		
		// add property files
		if (propertyFiles != null) {
			Method addPropertyFiles = classInternalAntRunner.getMethod("addPropertyFiles", new Class[] { String[].class }); //$NON-NLS-1$
			addPropertyFiles.invoke(runner, new Object[] { propertyFiles });
		}
	}

	/*
	 * Handles exceptions that are loaded by the Ant Class Loader by
	 * asking the Internal Ant Runner class for the correct error message.
	 * 
	 * Handles OperationCanceledExceptions, nested NoClassDefFoundError and
	 * nested ClassNotFoundException
	 */
	protected void handleInvocationTargetException(Object runner, Class classInternalAntRunner, InvocationTargetException e) throws CoreException {
		Throwable realException = e.getTargetException();
		if (realException instanceof OperationCanceledException) {
			return;
		}
		String message= null;
		if (runner != null) {
			try {
				Method getBuildErrorMessage = classInternalAntRunner.getMethod("getBuildExceptionErrorMessage", new Class[] { Throwable.class }); //$NON-NLS-1$
				message= (String)getBuildErrorMessage.invoke(runner, new Object[] { realException });
			} catch (Exception ex) {
				//do nothing as already in error state
			}
		}
		// J9 throws NoClassDefFoundError nested in a InvocationTargetException
		if (message == null && ((realException instanceof NoClassDefFoundError) || (realException instanceof ClassNotFoundException))) {
			problemLoadingClass(realException);
			return;
		}
		boolean internalError= false;
		if (message == null) {
			//error did not result from a BuildException
			internalError= true;
			message = (realException.getMessage() == null) ? InternalCoreAntMessages.AntRunner_Build_Failed__3 : realException.getMessage(); //$NON-NLS-1$
		}
		IStatus status= new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, message, realException);
		if (internalError) {
			AntCorePlugin.getPlugin().getLog().log(status);
		}
		throw new CoreException(status);
	}

	protected void problemLoadingClass(Throwable e) throws CoreException {
		String missingClassName= e.getMessage();
		String message;
		if (missingClassName != null) {
			missingClassName= missingClassName.replace('/', '.');
			message= InternalCoreAntMessages.AntRunner_Could_not_find_one_or_more_classes__Please_check_the_Ant_classpath__2; //$NON-NLS-1$
			message= MessageFormat.format(message, new String[]{missingClassName});
		} else {
			message= InternalCoreAntMessages.AntRunner_Could_not_find_one_or_more_classes__Please_check_the_Ant_classpath__1; //$NON-NLS-1$
		}
		IStatus status= new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, message, e);
		AntCorePlugin.getPlugin().getLog().log(status);
		throw new CoreException(status);
	}

	/**
	 * Runs the build file.
	 * @throws CoreException Thrown if a build is already occuring or if an exception occurs during the build
	 */
	public void run() throws CoreException {
		run(/*IProgressMonitor*/null);
	}

	/**
	 * Invokes the building of a project object and executes a build using either a given
	 * target or the default target. This method is called when running Eclipse headless
	 * and specifying <code>org.eclipse.ant.core.antRunner</code> as the application.
	 * 
	 * Sets the current threads context class loader to the AntClassLoader
	 * for the duration of the build.
	 *
	 * @param argArray the command line arguments
	 * @exception Exception if a problem occurred during the buildfile execution
	 * @return an exit object (<code>EXIT_OK</code>) indicating normal termination if no exception occurs
	 * @see org.eclipse.core.boot.IPlatformRunnable#run(java.lang.Object)
	 */
	public Object run(Object argArray) throws Exception {
		ClassLoader originalClassLoader= Thread.currentThread().getContextClassLoader();
		try {
			//set the preferences for headless mode
			AntCorePlugin.getPlugin().setRunningHeadless(true);
			
			// Add debug information if necessary - fix for bug 5672.
			// Since the platform parses the -debug command line arg
			// and removes it from the args passed to the applications,
			// we have to check if Eclipse is in debug mode in order to
			// forward the -debug argument to Ant.
			if (Platform.inDebugMode()) {
				String[] args = (String[]) argArray;
				String[] newArgs = new String[args.length + 1];
				for (int i = 0; i < args.length; i++) {
					newArgs[i] = args[i];
				}
				newArgs[args.length] = "-debug"; //$NON-NLS-1$
				argArray = newArgs;
			}
			ClassLoader loader = getClassLoader();
			Thread.currentThread().setContextClassLoader(loader);
			Class classInternalAntRunner = loader.loadClass("org.eclipse.ant.internal.core.ant.InternalAntRunner"); //$NON-NLS-1$
			Object runner = classInternalAntRunner.newInstance();
			Method run = classInternalAntRunner.getMethod("run", new Class[] { Object.class }); //$NON-NLS-1$
			run.invoke(runner, new Object[] { argArray });
		} finally {
			Thread.currentThread().setContextClassLoader(originalClassLoader);
		}

		return EXIT_OK;
	}
	
	private ClassLoader getClassLoader() {
		if (customClasspath == null) {
			return AntCorePlugin.getPlugin().getNewClassLoader();
		} 
		AntCorePreferences preferences = AntCorePlugin.getPlugin().getPreferences();
		List fullClasspath= new ArrayList();
		fullClasspath.addAll(Arrays.asList(customClasspath));
		fullClasspath.addAll(Arrays.asList(preferences.getExtraClasspathURLs()));
		return new AntClassLoader((URL[])fullClasspath.toArray(new URL[fullClasspath.size()]), preferences.getPluginClassLoaders());
	}
	
	/**
	 * Sets the input handler. The parameter <code>className</code>
	 * is the class name of a <code>org.apache.tools.ant.input.InputHandler</code>
	 * implementation. The class will be instantiated at runtime and the
	 * input handler will be used to respond to &lt;input&gt; requests
	 * Only one input handler is permitted for any build.
	 * 
	 * @param className an input handler class name
	 * @since 2.1
	 */
	public void setInputHandler(String className) {
		inputHandlerClassName= className;
	}
	
	/**
	 * Sets the user specified property files.
	 * @param propertyFiles array of property file paths
	 * @since 2.1
	 */
	public void setPropertyFiles(String[] propertyFiles) {
		this.propertyFiles= propertyFiles;
	}

	/**
	 * Sets the custom classpath to use for this build
	 * @param customClasspath array of URLs that define the custom classpath
	 */
	public void setCustomClasspath(URL[] customClasspath) {
		this.customClasspath = customClasspath;
	}
	
	/**
	 * Sets the Ant home to use for this build
	 * @param antHome String specifying the Ant home to use
	 * @since 2.1
	 */
 	public void setAntHome(String antHome) {
 		this.antHome= antHome;
 	}
	/**
	 * Returns whether an Ant build is already in progress
	 * 
	 * Only one Ant build can occur at any given time.
	 * 
	 * @since 2.1
	 * @return boolean
	 */
	public static boolean isBuildRunning() {
		return buildRunning;
	}
}
