/*******************************************************************************
 *  Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 * 
 *  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;
import org.osgi.framework.Version;

/**
 * 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<>();

	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<>(classNames.size());
		}
		buildListeners.addAll(classNames);
	}

	protected void addBuildListener(String clazz) {
		if (buildListeners == null) {
			buildListeners = new ArrayList<>();
		}
		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<>(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<>();
			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<>();
				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[] { "'", //$NON-NLS-1$
						defaultTarget, "'" })); //$NON-NLS-1$
			}
			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<>();
			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<>(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<>(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<>(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() }), ioe);
			}
			catch (NullPointerException npe) {
				throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Could_not_load_the_version_information, new Object[] {
						npe.getMessage() }), npe);
			}
		}
		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();
		Version osgiVersion = new Version(version);
		Version osgiComparison = new Version(comparison);
		return osgiVersion.compareTo(osgiComparison) >= 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<>(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<>(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<>(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<>();
		}
		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<>();
		}
		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;
	}
}
