/*******************************************************************************
 * 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();
			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);
			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();
			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();
		}
		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;
			message= MessageFormat.format(message, new String[]{missingClassName});
		} else {
			message= InternalCoreAntMessages.AntRunner_Could_not_find_one_or_more_classes__Please_check_the_Ant_classpath__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.runtime.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;
	}
}
