/*******************************************************************************
 *  Copyright (c) 2000, 2015 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 - derived implementation
 *     Blake Meike (blakem@world.std.com)- patch for bug 31691 and bug 34488
 *     Rob Stryker - Bug 459188 - InternalAntRunner tries to set null user property
 *******************************************************************************/

package org.eclipse.ant.internal.core.ant;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Vector;

import org.apache.tools.ant.AntTypeDefinition;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.DemuxOutputStream;
import org.apache.tools.ant.Diagnostics;
import org.apache.tools.ant.Main;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.TaskAdapter;
import org.apache.tools.ant.XmlLogger;
import org.eclipse.ant.core.AntCorePlugin;
import org.eclipse.ant.core.AntCorePreferences;
import org.eclipse.ant.core.AntSecurityException;
import org.eclipse.ant.core.ProjectInfo;
import org.eclipse.ant.core.Property;
import org.eclipse.ant.core.TargetInfo;
import org.eclipse.ant.core.Task;
import org.eclipse.ant.core.Type;
import org.eclipse.ant.internal.core.AbstractEclipseBuildLogger;
import org.eclipse.ant.internal.core.AntCoreUtil;
import org.eclipse.ant.internal.core.AntSecurityManager;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;
import org.osgi.framework.Bundle;

/**
 * Eclipse application entry point into Ant. Derived from the original Ant Main class to ensure that the functionality is equivalent when running in
 * the platform.
 */
public class InternalAntRunner {

	private IProgressMonitor monitor;
	private ArrayList<String> buildListeners;
	private String buildFileLocation;

	/**
	 * Targets we want to run.
	 */
	private Vector<String> targets;

	private Map<String, String> userProperties;
	private boolean noExplicitUserProperties = true;

	private Project currentProject;

	private String defaultTarget;

	private BuildLogger buildLogger = null;

	/**
	 * Cache of the Ant version number when it has been loaded
	 */
	private String antVersionNumber = null;

	/** Current message output status. Follows Project.MSG_XXX */
	private int messageOutputLevel = Project.MSG_INFO;

	/** Indicates whether output to the log is to be unadorned. */
	private boolean emacsMode = false;

	/** Indicates we should only parse and display the project help information */
	private boolean projectHelp = false;

	/** Stream that we are using for logging */
	private PrintStream out = System.out;

	/** Stream that we are using for logging error messages */
	private PrintStream err = System.err;

	/**
	 * The Ant logger class. There may be only one logger. It will have the right to use the 'out' PrintStream. The class must implement the
	 * BuildLogger interface. An empty String indicates that no logger is to be used. A <code>null</code> name indicates that the
	 * <code>org.apache.tools.ant.DefaultLogger</code> will be used.
	 */
	private String loggerClassname = null;

	/** Extra arguments to be parsed as command line arguments. */
	private String[] extraArguments = null;

	private boolean executed = false;

	private ArrayList<String> propertyFiles = new ArrayList<String>();

	private URL[] customClasspath = null;

	/**
	 * The Ant InputHandler class. There may be only one input handler.
	 */
	private String inputHandlerClassname = null;

	private String buildAntHome = null;

	/**
	 * Indicates whether to execute all targets that do not depend on failed targets
	 * 
	 * @since Ant 1.6.0
	 */
	private boolean keepGoing = false;

	/**
	 * Indicates whether this build is to support interactive input
	 * 
	 * @since Ant 1.6.0
	 */
	private boolean allowInput = true;

	private String fEarlyErrorMessage = null;

	private boolean unknownTargetsFound = false;

	/**
	 * Adds a build listener.
	 * 
	 * @param classNames
	 *            the fully qualified names of the build listeners to be added
	 */
	public void addBuildListeners(List<String> classNames) {
		if (buildListeners == null) {
			buildListeners = new ArrayList<String>(classNames.size());
		}
		buildListeners.addAll(classNames);
	}

	protected void addBuildListener(String clazz) {
		if (buildListeners == null) {
			buildListeners = new ArrayList<String>();
		}
		buildListeners.add(clazz);
	}

	/**
	 * Adds a build logger. There can be only one build logger.
	 * 
	 * @param className
	 *            The fully qualified name of the build logger to add
	 */
	public void addBuildLogger(String className) {
		loggerClassname = className;
	}

	/**
	 * Adds user properties to the current collection of user properties.
	 * 
	 * @param properties
	 *            The user properties to be added
	 */
	public void addUserProperties(Map<String, String> properties) {
		if (userProperties == null) {
			userProperties = new HashMap<String, String>(properties);
		} else {
			userProperties.putAll(properties);
		}
		noExplicitUserProperties = false;
	}

	/**
	 * Adds user property files.
	 * 
	 * @param additionalPropertyFiles
	 *            The property files to add
	 * @since 2.1
	 */
	public void addPropertyFiles(String[] additionalPropertyFiles) {
		propertyFiles.addAll(Arrays.asList(additionalPropertyFiles));
	}

	/**
	 * Tries to add the build listeners to the backing {@link Project}
	 * 
	 * @param project
	 *            the project to add the listeners to
	 * @param log
	 *            if we should be logging {@link ClassCastException}s here or not.
	 */
	protected void addBuildListeners(Project project, boolean log) {
		String className = null;
		try {
			BuildLogger logger = createLogger();
			if (logger != null) {
				project.addBuildListener(logger);
			}
			if (buildListeners != null) {
				for (Iterator<String> iterator = buildListeners.iterator(); iterator.hasNext();) {
					className = iterator.next();
					Class<?> listener = Class.forName(className);
					project.addBuildListener((BuildListener) listener.newInstance());
				}
			}
		}
		catch (ClassCastException e) {
			String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_not_an_instance_of_apache_ant_BuildListener, new Object[] { className });
			if (log) {
				logMessage(null, message, Project.MSG_ERR);
			}
			throw new BuildException(message, e);
		}
		catch (BuildException e) {
			throw e;
		}
		catch (Exception e) {
			throw new BuildException(e);
		}
	}

	private void setProperties(Project project, boolean substituteVariables) {
		setBuiltInProperties(project);
		if (userProperties != null) {
			for (Iterator<Map.Entry<String, String>> iterator = userProperties.entrySet().iterator(); iterator.hasNext();) {
				Entry<String, String> entry = iterator.next();
				String value = entry.getValue();
				if (substituteVariables && value != null) {
					try {
						value = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(value);
					}
					catch (CoreException e) {
						// do nothing
					}
				}
				if (value != null)
					project.setUserProperty(entry.getKey(), value);
			}
			// may have properties set (always have the Ant process ID)
			// using the Arguments and not the Properties page
			// if set using the arguments, still include the global properties
			if (noExplicitUserProperties) {
				setGlobalProperties(project, substituteVariables);
			}
		} else {
			setGlobalProperties(project, substituteVariables);
		}
	}

	/**
	 * Sets the default <code>ant.file</code> and <code>ant.version</code> properties in the given {@link Project}
	 * 
	 * @param project
	 */
	protected void setBuiltInProperties(Project project) {
		// note also see processAntHome for system properties that are set
		project.setUserProperty("ant.file", getBuildFileLocation()); //$NON-NLS-1$
		project.setUserProperty("ant.version", Main.getAntVersion()); //$NON-NLS-1$
	}

	private void setGlobalProperties(Project project, boolean substituteVariables) {
		AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences();
		List<Property> properties = prefs.getProperties();
		if (properties != null) {
			for (Property property : properties) {
				String value = property.getValue(substituteVariables);
				if (value != null) {
					project.setUserProperty(property.getName(), value);
				}
			}
		}
	}

	private void setTasks(Project project) {
		List<Task> tasks = AntCorePlugin.getPlugin().getPreferences().getTasks();
		for (Task task : tasks) {
			if (isVersionCompatible("1.6")) { //$NON-NLS-1$
				AntTypeDefinition def = new AntTypeDefinition();
				String name = ProjectHelper.genComponentName(task.getURI(), task.getTaskName());
				def.setName(name);
				def.setClassName(task.getClassName());
				def.setClassLoader(this.getClass().getClassLoader());
				def.setAdaptToClass(org.apache.tools.ant.Task.class);
				def.setAdapterClass(TaskAdapter.class);
				ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def);
			} else {
				try {
					Class<?> taskClass = Class.forName(task.getClassName());
					if (isVersionCompatible("1.5")) { //$NON-NLS-1$
						try {
							project.checkTaskClass(taskClass);
						}
						catch (BuildException e) {
							IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, MessageFormat.format(InternalAntMessages.InternalAntRunner_Error_setting_Ant_task, new Object[] { task.getTaskName() }), e);
							AntCorePlugin.getPlugin().getLog().log(status);
							continue;
						}
					}
					project.addTaskDefinition(task.getTaskName(), taskClass);
				}
				catch (ClassNotFoundException e) {
					IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, MessageFormat.format(InternalAntMessages.InternalAntRunner_Class_not_found_for_task, new Object[] {
							task.getClassName(), task.getTaskName() }), e);
					AntCorePlugin.getPlugin().getLog().log(status);
				}
			}
		}
	}

	private void setTypes(Project project) {
		List<Type> types = AntCorePlugin.getPlugin().getPreferences().getTypes();
		for (Iterator<Type> iterator = types.iterator(); iterator.hasNext();) {
			Type type = iterator.next();
			if (isVersionCompatible("1.6")) { //$NON-NLS-1$
				AntTypeDefinition def = new AntTypeDefinition();
				String name = ProjectHelper.genComponentName(type.getURI(), type.getTypeName());
				def.setName(name);
				def.setClassName(type.getClassName());
				def.setClassLoader(this.getClass().getClassLoader());
				ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def);
			} else {
				try {
					Class<?> typeClass = Class.forName(type.getClassName());
					project.addDataTypeDefinition(type.getTypeName(), typeClass);
				}
				catch (ClassNotFoundException e) {
					IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, MessageFormat.format(InternalAntMessages.InternalAntRunner_Class_not_found_for_type, new Object[] {
							type.getClassName(), type.getTypeName() }), e);
					AntCorePlugin.getPlugin().getLog().log(status);
				}
			}
		}
	}

	/**
	 * Parses the build file and adds necessary information into the given project.
	 * 
	 * @param project
	 *            The project to configure
	 */
	protected void parseBuildFile(Project project) {
		File buildFile = new File(getBuildFileLocation());
		if (!buildFile.exists()) {
			throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Buildfile_does_not_exist, new Object[] { buildFile.getAbsolutePath() }));
		}
		if (!buildFile.isFile()) {
			throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Buildfile_is_not_a_file, new Object[] { buildFile.getAbsolutePath() }));
		}

		if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
			parseBuildFile(project, buildFile);
		} else {
			ProjectHelper helper = ProjectHelper.getProjectHelper();
			project.addReference("ant.projectHelper", helper); //$NON-NLS-1$
			helper.parse(project, buildFile);
		}
	}

	/**
	 * @deprecated support for Ant older than 1.5
	 */
	@Deprecated
	private void parseBuildFile(Project project, File buildFile) {
		ProjectHelper.configureProject(project, buildFile);
	}

	/**
	 * Gets all the target information from the build script. Returns a list of lists. Each item in the enclosing list represents a target, where the
	 * first element is the name, the second element is the description, the third element is the project name, and the last elements is an array of
	 * dependencies.
	 * 
	 * @return a list of {@link TargetInfo} objects
	 */
	public List<TargetInfo> getTargets() {
		try {
			setJavaClassPath();
			Project antProject = getProject();
			processAntHome(false);
			antProject.init();
			setTypes(antProject);
			boolean exceptionState = processProperties(AntCoreUtil.getArrayList(extraArguments));
			if (fEarlyErrorMessage != null) {
				if (exceptionState) {
					throw new BuildException(fEarlyErrorMessage);
				}
			}

			setProperties(antProject, false);
			if (isVersionCompatible("1.5")) { //$NON-NLS-1$
				new InputHandlerSetter().setInputHandler(antProject, "org.eclipse.ant.internal.core.ant.NullInputHandler"); //$NON-NLS-1$
			}
			parseBuildFile(antProject);
			defaultTarget = antProject.getDefaultTarget();
			Hashtable<String, Target> projectTargets = antProject.getTargets();
			ArrayList<TargetInfo> infos = new ArrayList<TargetInfo>();
			ProjectInfo pinfo = new ProjectInfo(antProject.getName(), antProject.getDescription());
			boolean defaultFound = false;
			for (Target target : projectTargets.values()) {
				String name = target.getName();
				if (name.length() == 0) {
					// "no name" implicit target of Ant 1.6
					continue;
				}
				if (target.getName().equals(defaultTarget)) {
					defaultFound = true;
				}
				ArrayList<String> dependencies = new ArrayList<String>();
				Enumeration<String> enumeration = target.getDependencies();
				while (enumeration.hasMoreElements()) {
					dependencies.add(enumeration.nextElement());
				}
				String[] dependencyArray = new String[dependencies.size()];
				dependencies.toArray(dependencyArray);
				TargetInfo info = new TargetInfo(pinfo, name, target.getDescription(), dependencyArray, defaultFound);
				infos.add(info);
			}
			if (!defaultFound) {
				// default target must exist
				throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Default_target_does_not_exist, new Object[] {
						"'", defaultTarget, "'" })); //$NON-NLS-1$ //$NON-NLS-2$
			}
			return infos;
		}
		finally {
			processAntHome(true);
		}
	}

	/**
	 * Returns a list of target names in the build script.
	 * 
	 * @return a list of target names
	 */
	private List<String> getTargetNames() {
		try {
			setJavaClassPath();
			Project antProject;

			antProject = getProject();
			processAntHome(false);
			antProject.init();
			setTypes(antProject);
			processProperties(AntCoreUtil.getArrayList(extraArguments));

			setProperties(antProject, false);
			if (isVersionCompatible("1.5")) { //$NON-NLS-1$
				new InputHandlerSetter().setInputHandler(antProject, "org.eclipse.ant.internal.core.ant.NullInputHandler"); //$NON-NLS-1$
			}
			parseBuildFile(antProject);
			Hashtable<String, Target> projectTargets = antProject.getTargets();
			ArrayList<String> names = new ArrayList<String>();
			for (Target target : projectTargets.values()) {
				String name = target.getName();
				if (name.length() == 0) {
					// "no name" implicit target of Ant 1.6
					continue;
				}
				names.add(name);
			}
			return names;
		}
		finally {
			processAntHome(true);
		}
	}

	private Project getProject() {
		Project antProject;
		if (isVersionCompatible("1.6")) { //$NON-NLS-1$
			// in Ant version 1.6 or greater all tasks can exist outside the scope of a target
			if (isVersionCompatible("1.6.3")) { //$NON-NLS-1$
				antProject = new InternalProject2();
			} else {
				antProject = new Project();
			}
		} else {
			antProject = new InternalProject();
		}
		return antProject;
	}

	/**
	 * Returns the default target name that was last computed or <code>null</code> if no default target has been computed.
	 * 
	 * @return the default target name
	 */
	public String getDefaultTarget() {
		return defaultTarget;
	}

	/**
	 * Runs the build script.
	 */
	public void run() {
		run(AntCoreUtil.getArrayList(extraArguments));
	}

	private void printArguments(Project project) {
		if ((messageOutputLevel != Project.MSG_DEBUG) && (messageOutputLevel != Project.MSG_VERBOSE)) {
			return;
		}
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < extraArguments.length; i++) {
			sb.append(extraArguments[i]);
			sb.append(' ');
		}
		project.log(MessageFormat.format(InternalAntMessages.InternalAntRunner_Arguments, new Object[] { sb.toString().trim() }));
	}

	private void createMonitorBuildListener(Project project) {
		if (monitor == null) {
			return;
		}
		Vector<String> chosenTargets = targets;
		if (chosenTargets == null || chosenTargets.isEmpty()) {
			chosenTargets = new Vector<String>(1);
			String defltTarget = project.getDefaultTarget();
			if (defltTarget != null) {
				chosenTargets.add(defltTarget);
			}
		}
		project.addBuildListener(new ProgressBuildListener(project, chosenTargets, monitor));
	}

	/**
	 * Invokes the building of a project object and executes a build using either a given target or the default target. This method is called if
	 * running in headless mode.
	 * 
	 * @see org.eclipse.ant.core.AntRunner#run(Object)
	 * @param argArray
	 *            the command line arguments
	 * @exception Exception
	 *                execution exceptions
	 */
	public void run(Object argArray) throws Exception {
		run(AntCoreUtil.getArrayList((String[]) argArray));
	}

	/**
	 * Attempts to run the given list of command line arguments. Note that the list passed to this method must support {@link List#remove(Object)}. <br>
	 * <br>
	 * This method directly processes the following arguments:
	 * <ul>
	 * <li><b>-projecthelp</b>, <b>-p</b> - print project help information</li>
	 * </ul>
	 * 
	 * @param argList
	 *            the raw list of command line arguments
	 */
	private void run(List<String> argList) {
		setCurrentProject(new Project());
		if (isVersionCompatible("1.6.3")) { //$NON-NLS-1$
			new ExecutorSetter().setExecutor(currentProject);
		}
		Throwable error = null;
		PrintStream originalErr = System.err;
		PrintStream originalOut = System.out;
		InputStream originalIn = System.in;

		SecurityManager originalSM = System.getSecurityManager();
		setJavaClassPath();
		executed = true;
		processAntHome(false);
		try {
			if (argList != null && (argList.remove("-projecthelp") || argList.remove("-p"))) { //$NON-NLS-1$ //$NON-NLS-2$
				projectHelp = true;
			}
			getCurrentProject().init();
			if (argList != null) {
				executed = preprocessCommandLine(argList);
				if (!executed) {
					return;
				}
			}

			boolean exceptionState = processProperties(argList);

			addBuildListeners(getCurrentProject(), true);

			addInputHandler(getCurrentProject());

			remapSystemIn();
			System.setOut(new PrintStream(new DemuxOutputStream(getCurrentProject(), false)));
			System.setErr(new PrintStream(new DemuxOutputStream(getCurrentProject(), true)));

			if (!projectHelp) {
				fireBuildStarted(getCurrentProject());
			}

			if (fEarlyErrorMessage != null) {
				// an error occurred processing the properties
				// build started has fired and we have
				// listeners/loggers to report the error
				logMessage(getCurrentProject(), fEarlyErrorMessage, Project.MSG_ERR);
				if (exceptionState) {
					throw new BuildException(fEarlyErrorMessage);
				}
			}

			// properties can only be set after buildStarted as some listeners/loggers
			// depend on this (e.g. XMLLogger)
			setProperties(getCurrentProject(), true);

			if (argList != null && !argList.isEmpty()) {
				try {
					executed = processCommandLine(argList);
				}
				catch (BuildException e) {
					executed = false;
					throw e;
				}
			}
			if (!executed) {
				return;
			}

			// needs to occur after processCommandLine(List)
			if (allowInput && (inputHandlerClassname != null && inputHandlerClassname.length() > 0)) {
				if (isVersionCompatible("1.6")) { //$NON-NLS-1$
					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=182577
					// getCurrentProject().setDefaultInputStream(originalIn);
					System.getProperties().remove("eclipse.ant.noInput"); //$NON-NLS-1$
				}
			} else {
				// set the system property that any input handler
				// can check to see if handling input is allowed
				System.setProperty("eclipse.ant.noInput", "true"); //$NON-NLS-1$//$NON-NLS-2$
				if (isVersionCompatible("1.5") && (inputHandlerClassname == null || inputHandlerClassname.length() == 0)) { //$NON-NLS-1$
					InputHandlerSetter setter = new InputHandlerSetter();
					setter.setInputHandler(getCurrentProject(), "org.eclipse.ant.internal.core.ant.FailInputHandler"); //$NON-NLS-1$
				}
			}

			if (!projectHelp) {
				logMessage(currentProject, MessageFormat.format(InternalAntMessages.InternalAntRunner_Build_file, new Object[] { getBuildFileLocation() }), Project.MSG_INFO);

				setTasks(getCurrentProject());
				setTypes(getCurrentProject());

				if (isVersionCompatible("1.6")) { //$NON-NLS-1$
					getCurrentProject().setKeepGoingMode(keepGoing);
				}
				parseBuildFile(getCurrentProject());
			}

			createMonitorBuildListener(getCurrentProject());

			if (projectHelp) {
				if (isVersionCompatible("1.7")) { //$NON-NLS-1$
					new EclipseMainHelper().runProjectHelp(getBuildFileLocation(), getCurrentProject());
					return;
				}
				logMessage(currentProject, InternalAntMessages.InternalAntRunner_ant_1_7_needed_for_help_info, Project.MSG_ERR);
				executed = false;
				return;
			}

			if (extraArguments != null) {
				printArguments(getCurrentProject());
			}
			System.setSecurityManager(new AntSecurityManager(originalSM, Thread.currentThread()));

			if (targets == null) {
				targets = new Vector<String>(1);
			}
			String dtarget = currentProject.getDefaultTarget();
			if (targets.isEmpty() && dtarget != null) {
				targets.add(dtarget);
			}
			if (!isVersionCompatible("1.6.3")) { //$NON-NLS-1$
				getCurrentProject().addReference(IAntCoreConstants.TARGET_VECTOR_NAME, targets);
			}
			getCurrentProject().executeTargets(targets);
		}
		catch (OperationCanceledException e) {
			executed = false;
			logMessage(currentProject, e.getMessage(), Project.MSG_INFO);
			throw e;
		}
		catch (AntSecurityException e) {
			// expected
		}
		catch (RuntimeException e) {
			error = e;
			throw e;
		}
		catch (Error e) {
			error = e;
			throw e;
		}
		finally {
			System.setErr(originalErr);
			System.setOut(originalOut);
			System.setIn(originalIn);
			if (System.getSecurityManager() instanceof AntSecurityManager) {
				System.setSecurityManager(originalSM);
			}

			if (!projectHelp) {
				if (AntCorePlugin.getPlugin().getBundle().getState() != Bundle.ACTIVE) {
					return;
				}
				fireBuildFinished(getCurrentProject(), error);
			}

			// close any user specified build log
			if (err != originalErr) {
				err.close();
			}
			if (out != originalOut) {
				out.close();
			}

			processAntHome(true);
			if (!allowInput) {
				System.getProperties().remove("eclipse.ant.noInput"); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Re-maps {@link System.in} to the Ant input stream setter
	 */
	protected void remapSystemIn() {
		if (!isVersionCompatible("1.6")) { //$NON-NLS-1$
			return;
		}
		DemuxInputStreamSetter setter = new DemuxInputStreamSetter();
		setter.remapSystemIn(currentProject);
	}

	private void processAntHome(boolean finished) {
		AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences();
		String antHome = prefs.getAntHome();
		if (buildAntHome != null && !finished) {
			antHome = buildAntHome;
		}
		if (antHome == null || antHome.length() == 0) {
			System.getProperties().remove("ant.home"); //$NON-NLS-1$
			System.getProperties().remove("ant.library.dir"); //$NON-NLS-1$
		} else {
			System.setProperty("ant.home", antHome); //$NON-NLS-1$
			File antLibDir = new File(antHome, "lib"); //$NON-NLS-1$
			System.setProperty("ant.library.dir", antLibDir.getAbsolutePath()); //$NON-NLS-1$
		}
	}

	public void setAntHome(String antHome) {
		this.buildAntHome = antHome;
	}

	/**
	 * Creates and returns the default build logger for logging build events to the ant log.
	 * 
	 * @return the default build logger for logging build events to the ant log can return <code>null</code> if no logging is to occur
	 */
	protected BuildLogger createLogger() {
		if (loggerClassname == null) {
			buildLogger = new DefaultLogger();
		} else if (!IAntCoreConstants.EMPTY_STRING.equals(loggerClassname)) {
			try {
				buildLogger = (BuildLogger) (Class.forName(loggerClassname).newInstance());
			}
			catch (ClassCastException e) {
				String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_not_an_instance_of_apache_ant_BuildLogger, new Object[] { loggerClassname });
				logMessage(null, message, Project.MSG_ERR);
				throw new BuildException(message, e);
			}
			catch (Exception e) {
				String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_Unable_to_instantiate_logger, new Object[] { loggerClassname });
				logMessage(null, message, Project.MSG_ERR);
				throw new BuildException(message, e);
			}
		}

		if (buildLogger != null) {
			buildLogger.setMessageOutputLevel(messageOutputLevel);
			buildLogger.setOutputPrintStream(out);
			buildLogger.setErrorPrintStream(err);
			buildLogger.setEmacsMode(emacsMode);
			if (buildLogger instanceof AbstractEclipseBuildLogger) {
				((AbstractEclipseBuildLogger) buildLogger).configure(userProperties);
			}
		}

		return buildLogger;
	}

	/**
	 * Project.fireBuildStarted is protected in Ant earlier than 1.5.*. Provides backwards compatibility with old Ant installs.
	 */
	protected void fireBuildStarted(Project project) {
		if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
			BuildEvent event = new BuildEvent(project);
			for (BuildListener listener : project.getBuildListeners()) {
				listener.buildStarted(event);
			}
		} else {
			project.fireBuildStarted();
		}
	}

	/**
	 * Sends the the event to the backing project that the build has completed
	 * 
	 * @param project
	 * @param error
	 */
	protected void fireBuildFinished(Project project, Throwable error) {
		if (usingXmlLogger()) {
			// generate the log file in the correct location
			String fileName = project.getProperty("XmlLogger.file"); //$NON-NLS-1$
			if (fileName == null) {
				fileName = "log.xml"; //$NON-NLS-1$
			}
			String realPath = new Path(getBuildFileLocation()).toFile().getAbsolutePath();
			IPath path = new Path(realPath);
			path = path.removeLastSegments(1);
			path = path.addTrailingSeparator();
			path = path.append(fileName);

			project.setProperty("XmlLogger.file", path.toOSString()); //$NON-NLS-1$
		}
		if (error == null && executed) {
			logMessage(project, InternalAntMessages.InternalAntRunner_BUILD_SUCCESSFUL_1, messageOutputLevel);
		}
		if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
			BuildEvent event = new BuildEvent(project);
			event.setException(error);
			for (BuildListener listener : project.getBuildListeners()) {
				listener.buildFinished(event);
			}
		} else {
			project.fireBuildFinished(error);
		}
	}

	private boolean usingXmlLogger() {
		if (buildLogger instanceof XmlLogger) {
			return true;
		}
		if (buildListeners != null) {
			for (BuildListener listener : currentProject.getBuildListeners()) {
				if (listener instanceof XmlLogger) {
					return true;
				}
			}
		}
		return false;
	}

	protected void logMessage(Project project, String message, int priority) {
		if (project != null) {
			project.log(message, priority);
		} else {
			if (buildListeners != null) {
				Project p = new Project();
				addBuildListeners(p, false);
				p.log(message, priority);
			} else {
				IStatus s = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.INTERNAL_ERROR, message, null);
				AntCorePlugin.getPlugin().getLog().log(s);
			}
		}
	}

	/**
	 * Sets the buildFileLocation.
	 * 
	 * @param buildFileLocation
	 *            the file system location of the build file
	 */
	public void setBuildFileLocation(String buildFileLocation) {
		this.buildFileLocation = buildFileLocation;
		if (currentProject != null) {
			currentProject.setUserProperty("ant.file", buildFileLocation); //$NON-NLS-1$
		}
	}

	/**
	 * Sets the input handler class name.
	 * 
	 * @param inputHandlerClassname
	 *            the name of the class to use for the input handler
	 */
	public void setInputHandler(String inputHandlerClassname) {
		this.inputHandlerClassname = inputHandlerClassname;
	}

	/**
	 * Returns the class name of the input handler to use
	 * 
	 * @return the input handler class name
	 */
	protected String getInputHandler() {
		return this.inputHandlerClassname;
	}

	protected String getBuildLogger() {
		return this.loggerClassname;
	}

	/**
	 * Returns the location of the buildfile. If one has not been supplied the default location of <code>build.xml</code> will be returned
	 * 
	 * @return the absolute location of the build file
	 */
	protected String getBuildFileLocation() {
		if (buildFileLocation == null) {
			buildFileLocation = new File("build.xml").getAbsolutePath(); //$NON-NLS-1$
		}
		return buildFileLocation;
	}

	/**
	 * Sets the message output level. Use -1 for none.
	 * 
	 * @param level
	 *            The message output level
	 */
	public void setMessageOutputLevel(int level) {
		messageOutputLevel = level;
		if (buildLogger != null) {
			buildLogger.setMessageOutputLevel(level);
		}
	}

	/**
	 * Sets the extra user arguments
	 * 
	 * @param args
	 *            The extra user arguments
	 */
	public void setArguments(String[] args) {
		extraArguments = args;
	}

	/**
	 * Sets the execution targets.
	 * 
	 * @param executionTargets
	 *            The targets to execute for the build
	 */
	public void setExecutionTargets(String[] executionTargets) {
		targets = new Vector<String>(executionTargets.length);
		for (int i = 0; i < executionTargets.length; i++) {
			targets.add(executionTargets[i]);
		}
	}

	/*
	 * Returns a String representation of the Ant version number as specified in the version.txt file.
	 */
	protected String getAntVersionNumber() throws BuildException {
		if (antVersionNumber == null) {
			try (InputStream in = Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt")) { //$NON-NLS-1$
				Properties props = new Properties();
				props.load(in);
				String versionNumber = props.getProperty("VERSION"); //$NON-NLS-1$
				antVersionNumber = versionNumber;
			}
			catch (IOException ioe) {
				throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Could_not_load_the_version_information, new Object[] { ioe.getMessage() }));
			}
			catch (NullPointerException npe) {
				throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Could_not_load_the_version_information, new Object[] { npe.getMessage() }));
			}
		}
		return antVersionNumber;
	}

	/*
	 * Returns whether the given version is compatible with the current Ant version. A version is compatible if it is less than or equal to the
	 * current version.
	 */
	protected boolean isVersionCompatible(String comparison) {
		String version = getAntVersionNumber();
		return version.compareTo(comparison) >= 0;
	}

	/**
	 * Pre-processes the raw command line to set up input handling and logging. <br>
	 * <br>
	 * This method checks for the following command line arguments:
	 * <ul>
	 * <li><b>-inputhandler</b> <em>&lt;class&gt;</em> - the class which will handle input requests</li>
	 * <li><b>-logger</b> <em>&lt;classname&gt;</em> - the class which is to perform logging</li>
	 * <li><b>-listener</b> <em>&lt;classname&gt;</em> - add an instance of class as a project listener</li>
	 * </ul>
	 * 
	 * @param commands
	 *            the raw command line arguments passed in from the application
	 * @return <code>true</code> if it is OK to run with the given list of arguments <code>false</code> otherwise
	 */
	protected boolean preprocessCommandLine(List<String> commands) {
		String arg = AntCoreUtil.getArgument(commands, "-listener"); //$NON-NLS-1$
		while (arg != null) {
			if (arg.length() == 0) {
				throw new BuildException(InternalAntMessages.InternalAntRunner_specify_a_classname_using_the_listener_argument);
			}
			if (buildListeners == null) {
				buildListeners = new ArrayList<String>(1);
			}
			buildListeners.add(arg);
			arg = AntCoreUtil.getArgument(commands, "-listener"); //$NON-NLS-1$
		}

		arg = AntCoreUtil.getArgument(commands, "-logger"); //$NON-NLS-1$
		if (arg != null) {
			if (arg.length() == 0) {
				throw new BuildException(InternalAntMessages.InternalAntRunner_specify_a_classname_using_the_logger_argument);
			}
			loggerClassname = arg;
		}
		arg = AntCoreUtil.getArgument(commands, "-logger"); //$NON-NLS-1$
		if (arg != null) {
			throw new BuildException(InternalAntMessages.InternalAntRunner_Only_one_logger_class_may_be_specified);
		}

		arg = AntCoreUtil.getArgument(commands, "-inputhandler"); //$NON-NLS-1$
		if (arg != null) {
			if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
				throw new BuildException(InternalAntMessages.InternalAntRunner_Specifying_an_InputHandler_is_an_Ant_1_5_feature);
			}
			if (arg.length() == 0) {
				throw new BuildException(InternalAntMessages.InternalAntRunner_specify_a_classname_the_inputhandler_argument);
			}
			inputHandlerClassname = arg;
		}
		arg = AntCoreUtil.getArgument(commands, "-inputhandler"); //$NON-NLS-1$
		if (arg != null) {
			throw new BuildException(InternalAntMessages.InternalAntRunner_Only_one_input_handler_class_may_be_specified);
		}
		return true;
	}

	/**
	 * Process the command line arguments. <br>
	 * <br>
	 * The listing of supported Ant command line arguments is:
	 * <ul>
	 * <li><b>-buildfile</b>, <b>-file</b>, <b>-f</b> <em>&lt;file&gt;</em> - use given buildfile</li>
	 * <li><b>-debug</b>, <b>-d</b> - print debugging information</li>
	 * <li><b>-diagnostics</b> - print information that might be helpful diagnose or report problems</li>
	 * <li><b>-emacs</b>, <b>-e</b> - produce logging information without adornments</li>
	 * <li><b>-find</b>, <b>-s</b> <em>&lt;file&gt;</em> - search for buildfile towards the root of the filesystem and use it</li>
	 * <li><b>-help</b>, <b>-h</b> - print this message</li>
	 * <li><b>-keep-going</b>, <b>-k</b> - execute all targets that do not depend on failed target(s)</li>
	 * <li><b>-lib</b> <em>&lt;path&gt;</em> - specifies a path to search for jars and classes</li>
	 * <li><b>-logfile</b>, <b>-l</b> <em>&lt;file&gt;</em> - use given file for logging</li>
	 * <li><b>-noinput</b> - do not allow interactive input</li>
	 * <li><b>-quiet</b>, <b>-q</b> - be extra quiet</li>
	 * <li><b>-verbose</b>, <b>-v</b> - be extra verbose</li>
	 * <li><b>-version</b> - print the version information and exit</li>
	 * </ul>
	 * The list of other Ant command line arguments that we currently do not support:
	 * <ul>
	 * <li><b>-nice</b> <em>&lt;number&gt;</em> - A niceness value for the main thread - 1 (lowest) to 10 (highest); 5 is the default</li>
	 * <li><b>-nouserlib</b> - Run ant without using the jar files from ${user.home}/.ant/lib</li>
	 * <li><b>-noclasspath</b> - Run ant without using CLASSPATH</li>
	 * <li><b>-autoproxy</b> - Java 1.5+ : use the OS proxies</li>
	 * <li><b>-main</b> <em>&lt;class&gt;</em> - override Ant's normal entry point</li>
	 * </ul>
	 * 
	 * @param list
	 *            the raw command line arguments passed in from the application
	 * @return <code>true</code> if it is OK to run with the given list of arguments <code>false</code> otherwise
	 */
	private boolean processCommandLine(List<String> commands) {
		if (commands.remove("-help") || commands.remove("-h")) { //$NON-NLS-1$ //$NON-NLS-2$
			if (isVersionCompatible("1.7")) { //$NON-NLS-1$
				new EclipseMainHelper().runUsage(getBuildFileLocation(), currentProject);
			} else {
				logMessage(currentProject, InternalAntMessages.InternalAntRunner_ant_1_7_needed_for_help_message, Project.MSG_WARN);
			}
			return false;
		}

		if (commands.remove("-version")) { //$NON-NLS-1$
			printVersion();
			return false;
		}

		if (commands.remove("-verbose") || commands.remove("-v")) { //$NON-NLS-1$ //$NON-NLS-2$
			printVersion();
			setMessageOutputLevel(Project.MSG_VERBOSE);
		}

		if (commands.remove("-debug") || commands.remove("-d")) { //$NON-NLS-1$ //$NON-NLS-2$
			printVersion();
			setMessageOutputLevel(Project.MSG_DEBUG);
		}

		if (commands.remove("-quiet") || commands.remove("-q")) { //$NON-NLS-1$ //$NON-NLS-2$
			setMessageOutputLevel(Project.MSG_WARN);
		}

		if (commands.remove("-emacs") || commands.remove("-e")) { //$NON-NLS-1$ //$NON-NLS-2$
			emacsMode = true;
			if (buildLogger != null) {
				buildLogger.setEmacsMode(true);
			}
		}

		if (commands.remove("-diagnostics")) { //$NON-NLS-1$
			if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
				throw new BuildException(InternalAntMessages.InternalAntRunner_The_diagnositics_options_is_an_Ant_1_5_feature);
			}
			try {
				Diagnostics.doReport(System.out);
			}
			catch (NullPointerException e) {
				logMessage(currentProject, InternalAntMessages.InternalAntRunner_anthome_must_be_set_to_use_ant_diagnostics, Project.MSG_ERR);
			}
			return false;
		}

		String arg = AntCoreUtil.getArgument(commands, "-logfile"); //$NON-NLS-1$
		if (arg == null) {
			arg = AntCoreUtil.getArgument(commands, "-l"); //$NON-NLS-1$
		}
		if (arg != null) {
			if (arg.length() == 0) {
				String message = InternalAntMessages.InternalAntRunner_specify_a_log_file_using_the_log_argument;
				logMessage(currentProject, message, Project.MSG_ERR);
				throw new BuildException(message);
			}
			try {
				createLogFile(arg);
			}
			catch (IOException e) {
				// just log message and ignore exception
				logMessage(currentProject, MessageFormat.format(InternalAntMessages.InternalAntRunner_Could_not_write_to_log_file, new Object[] { arg }), Project.MSG_ERR);
				return false;
			}

		}
		arg = AntCoreUtil.getArgument(commands, "-buildfile"); //$NON-NLS-1$
		if (arg == null) {
			arg = AntCoreUtil.getArgument(commands, "-file"); //$NON-NLS-1$
			if (arg == null) {
				arg = AntCoreUtil.getArgument(commands, "-f"); //$NON-NLS-1$
			}
		}
		if (arg != null) {
			if (arg.length() == 0) {
				String message = InternalAntMessages.InternalAntRunner_specify_a_buildfile_using_the_buildfile_argument;
				logMessage(currentProject, message, Project.MSG_ERR);
				throw new BuildException(message);
			}
			setBuildFileLocation(arg);
		}
		if (isVersionCompatible("1.6")) { //$NON-NLS-1$
			if (commands.remove("-k") || commands.remove("-keep-going")) { //$NON-NLS-1$ //$NON-NLS-2$
				keepGoing = true;
			}
			if (commands.remove("-noinput")) { //$NON-NLS-1$
				allowInput = false;
			}
			arg = AntCoreUtil.getArgument(commands, "-lib"); //$NON-NLS-1$
			if (arg != null) {
				logMessage(currentProject, InternalAntMessages.InternalAntRunner_157, Project.MSG_ERR);
				return false;
			}
		}

		arg = AntCoreUtil.getArgument(commands, "-find"); //$NON-NLS-1$
		if (arg == null) {
			arg = AntCoreUtil.getArgument(commands, "-s"); //$NON-NLS-1$
		}
		if (arg != null) {
			logMessage(currentProject, InternalAntMessages.InternalAntRunner_find_not_supported, Project.MSG_ERR);
			return false;
		}

		if (!commands.isEmpty()) {
			processUnrecognizedCommands(commands);
		}

		if (!commands.isEmpty()) {
			processUnrecognizedTargets(commands);
		}

		if (!commands.isEmpty()) {
			processTargets(commands);
		}

		if (unknownTargetsFound && (targets == null || targets.isEmpty())) {
			// Some targets are specified but none of them are good. Hence quit
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=352536
			logMessage(currentProject, InternalAntMessages.InternalAntRunner_no_known_target, Project.MSG_ERR);
			return false;
		}
		return true;
	}

	/**
	 * Checks for unrecognized targets on the command line and removes them.
	 * 
	 * @since 3.6
	 */
	private void processUnrecognizedTargets(List<String> commands) {
		List<String> names = getTargetNames();
		ListIterator<String> iterator = commands.listIterator();
		while (iterator.hasNext()) {
			String target = iterator.next();
			if (!names.contains(target)) {
				iterator.remove();
				String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_unknown_target, new Object[] { target });
				logMessage(currentProject, message, Project.MSG_WARN);
				unknownTargetsFound = true;
			}
		}
	}

	/**
	 * Checks for unrecognized arguments on the command line. Since there is no syntactic way to distinguish between ant -foo target1 target2 ant -foo
	 * fooarg target we remove everything up to the last argument that begins with a '-'. In the latter case, above, that means that there will be an
	 * extra target, 'fooarg', left lying around.
	 */
	protected void processUnrecognizedCommands(List<String> commands) {
		int p = -1;

		// find the last arg that begins with '-'
		for (int i = commands.size() - 1; i >= 0; i--) {
			if (commands.get(i).startsWith("-")) { //$NON-NLS-1$
				p = i;
				break;
			}
		}
		if (p < 0) {
			return;
		}

		// remove everything preceding that last '-arg'
		String s = IAntCoreConstants.EMPTY_STRING;
		for (int i = 0; i <= p; i++) {
			s += " " + (commands.get(0)); //$NON-NLS-1$
			commands.remove(0);
		}

		// warn of ignored commands
		String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_Unknown_argument, new Object[] { s.substring(1) });
		logMessage(currentProject, message, Project.MSG_WARN);
	}

	/**
	 * Checks for targets specified at the command line.
	 */
	protected void processTargets(List<String> commands) {
		if (targets == null) {
			targets = new Vector<String>(commands.size());
		}
		for (Iterator<String> iter = commands.iterator(); iter.hasNext();) {
			targets.add(iter.next());
		}
	}

	/**
	 * Creates the log file with the name specified by the user. If the fileName is not absolute, the file will be created in the working directory if
	 * specified or in the same directory as the location of the build file.
	 */
	protected void createLogFile(String fileName) throws FileNotFoundException, IOException {
		File logFile = AntCoreUtil.getFileRelativeToBaseDir(fileName, currentProject.getUserProperty("basedir"), getBuildFileLocation()); //$NON-NLS-1$
		// this stream is closed in the finally block of run(list)
		out = new PrintStream(new FileOutputStream(logFile));
		err = out;
		logMessage(currentProject, MessageFormat.format(InternalAntMessages.InternalAntRunner_Using_file_as_build_log, new Object[] { logFile.getCanonicalPath() }), Project.MSG_INFO);
		if (buildLogger != null) {
			buildLogger.setErrorPrintStream(err);
			buildLogger.setOutputPrintStream(out);
		}
	}

	/**
	 * Processes the command line properties and adds the user properties. <br>
	 * <br>
	 * Any user properties that have been explicitly set are set as well. Ensures that -D properties take precedence. <br>
	 * <br>
	 * This command lie arguments used are:
	 * <ul>
	 * <li><b>-D</b> <em>&lt;property&gt;=&lt;value&gt;</em> - use value for given property</li>
	 * <li><b>-propertyfile</b> <em>&lt;name&gt;</em> - load all properties from file with -D properties taking precedence</li>
	 * </ul>
	 */
	private boolean processProperties(List<String> commands) {
		boolean exceptionToBeThrown = false;
		// MULTIPLE property files are allowed
		String arg = AntCoreUtil.getArgument(commands, "-propertyfile"); //$NON-NLS-1$
		while (arg != null) {
			if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
				fEarlyErrorMessage = InternalAntMessages.InternalAntRunner_Specifying_property_files_is_a_Ant_1_5_feature;
				break;
			}
			if (arg.length() == 0) {
				fEarlyErrorMessage = InternalAntMessages.InternalAntRunner_specify_a_property_filename_when_using_propertyfile_argument;
				exceptionToBeThrown = true;
				break;
			}

			propertyFiles.add(arg);
			arg = AntCoreUtil.getArgument(commands, "-propertyfile"); //$NON-NLS-1$
		}

		String[] globalPropertyFiles = AntCorePlugin.getPlugin().getPreferences().getCustomPropertyFiles();
		if (globalPropertyFiles.length > 0) {
			if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
				fEarlyErrorMessage = InternalAntMessages.InternalAntRunner_Specifying_property_files_is_a_Ant_1_5_feature;
			} else {
				if (propertyFiles == null) {
					propertyFiles = new ArrayList<String>(globalPropertyFiles.length);
				}
				propertyFiles.addAll(Arrays.asList(globalPropertyFiles));
			}
		}

		if (propertyFiles != null && !propertyFiles.isEmpty()) {
			loadPropertyFiles();
		}

		if (commands != null) {
			processMinusDProperties(commands);
		}
		return exceptionToBeThrown;
	}

	/**
	 * Process properties specified using <code>-D</code>
	 * 
	 * @param commands
	 */
	protected void processMinusDProperties(List<String> commands) {
		if (!commands.isEmpty() && userProperties == null) {
			userProperties = new HashMap<String, String>();
		}
		AntCoreUtil.processMinusDProperties(commands, userProperties);
	}

	/**
	 * Logs a message with the client indicating the version of <b>Ant</b> that this class fronts.
	 */
	protected void printVersion() {
		logMessage(currentProject, Main.getAntVersion(), Project.MSG_INFO);
	}

	/**
	 * Sets the build progress monitor.
	 * 
	 * @param monitor
	 *            The progress monitor to use
	 */
	public void setProgressMonitor(IProgressMonitor monitor) {
		this.monitor = monitor;
	}

	/**
	 * Returns the current {@link Project} context
	 * 
	 * @return the current {@link Project}
	 */
	protected Project getCurrentProject() {
		return currentProject;
	}

	/**
	 * Sets the current {@link Project} context
	 * 
	 * @param currentProject
	 *            the new {@link Project}
	 */
	protected void setCurrentProject(Project currentProject) {
		this.currentProject = currentProject;
	}

	public String getBuildExceptionErrorMessage(Throwable t) {
		if (t instanceof BuildException) {
			return t.toString();
		}
		return null;
	}

	/**
	 * Load all properties from the files specified by -propertyfile.
	 */
	protected void loadPropertyFiles() {
		if (userProperties == null) {
			userProperties = new HashMap<String, String>();
		}
		try {
			List<Properties> allProperties = AntCoreUtil.loadPropertyFiles(propertyFiles, currentProject.getUserProperty("basedir"), getBuildFileLocation()); //$NON-NLS-1$
			Iterator<Properties> iter = allProperties.iterator();
			while (iter.hasNext()) {
				Properties props = iter.next();
				Enumeration<?> propertyNames = props.propertyNames();
				while (propertyNames.hasMoreElements()) {
					String name = (String) propertyNames.nextElement();
					// most specific to global
					// do not overwrite specific with a global property
					if (userProperties.get(name) == null) {
						userProperties.put(name, props.getProperty(name));
					}
				}
			}
		}
		catch (IOException e) {
			fEarlyErrorMessage = MessageFormat.format(InternalAntMessages.InternalAntRunner_could_not_load_property_file, new Object[] { e.getMessage() });
		}
	}

	/**
	 * Creates the InputHandler and adds it to the project.
	 * 
	 * @exception BuildException
	 *                if a specified InputHandler implementation could not be loaded.
	 */
	protected void addInputHandler(Project project) {
		if (!isVersionCompatible("1.5") || (inputHandlerClassname != null && inputHandlerClassname.length() == 0)) { //$NON-NLS-1$
			return;
		}
		InputHandlerSetter setter = new InputHandlerSetter();
		setter.setInputHandler(project, inputHandlerClassname);
	}

	/*
	 * Sets the Java class path in org.apache.tools.ant.types.Path
	 */
	private void setJavaClassPath() {
		URL[] antClasspath = null;
		AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences();
		if (customClasspath == null) {
			antClasspath = prefs.getURLs();
		} else {
			URL[] extraClasspath = prefs.getExtraClasspathURLs();
			antClasspath = new URL[customClasspath.length + extraClasspath.length];
			System.arraycopy(customClasspath, 0, antClasspath, 0, customClasspath.length);
			System.arraycopy(extraClasspath, 0, antClasspath, customClasspath.length, extraClasspath.length);
		}
		StringBuffer buff = new StringBuffer();
		File file = null;
		for (int i = 0; i < antClasspath.length; i++) {
			try {
				file = new File(FileLocator.toFileURL(antClasspath[i]).getPath());
			}
			catch (IOException e) {
				continue;
			}
			buff.append(file.getAbsolutePath());
			buff.append("; "); //$NON-NLS-1$
		}

		org.apache.tools.ant.types.Path systemClasspath = new org.apache.tools.ant.types.Path(null, buff.substring(0, buff.length() - 2));
		org.apache.tools.ant.types.Path.systemClasspath = systemClasspath;
	}

	/**
	 * Sets the custom classpath to be included when setting the Java classpath for this build.
	 * 
	 * @param classpath
	 *            The custom classpath for this build.
	 */
	public void setCustomClasspath(URL[] classpath) {
		customClasspath = classpath;
	}
}
