/*******************************************************************************
 * 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 - initial API and implementation
 *     Juan A. Hernandez - bug 89926
 *     dakshinamurthy.karra@gmail.com - bug 165371
 *     Ericsson AB, Hamdan Msheik - Bug 389564
 *******************************************************************************/
package org.eclipse.ant.internal.launching.launchConfigurations;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.tools.ant.ProjectHelper;
import org.eclipse.ant.core.AntCorePlugin;
import org.eclipse.ant.core.AntCorePreferences;
import org.eclipse.ant.core.AntRunner;
import org.eclipse.ant.core.Property;
import org.eclipse.ant.core.Task;
import org.eclipse.ant.core.Type;
import org.eclipse.ant.internal.core.AbstractEclipseBuildLogger;
import org.eclipse.ant.internal.launching.AntLaunch;
import org.eclipse.ant.internal.launching.AntLaunching;
import org.eclipse.ant.internal.launching.AntLaunchingUtil;
import org.eclipse.ant.internal.launching.debug.IAntDebugConstants;
import org.eclipse.ant.internal.launching.debug.model.RemoteAntDebugBuildListener;
import org.eclipse.ant.launching.IAntLaunchConstants;
import org.eclipse.core.externaltools.internal.IExternalToolConstants;
import org.eclipse.core.externaltools.internal.launchConfigurations.BackgroundResourceRefresher;
import org.eclipse.core.externaltools.internal.launchConfigurations.ExternalToolsCoreUtil;
import org.eclipse.core.resources.IProject;
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.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.RefreshUtil;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.AbstractVMInstall;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.SocketUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;

import com.ibm.icu.text.MessageFormat;

/**
 * Launch delegate for Ant builds
 */
public class AntLaunchDelegate extends LaunchConfigurationDelegate {

	private static final String ANT_LOGGER_CLASS = "org.eclipse.ant.internal.launching.runtime.logger.AntProcessBuildLogger"; //$NON-NLS-1$
	private static final String ANT_DEBUG_LOGGER_CLASS = "org.eclipse.ant.internal.launching.runtime.logger.AntProcessDebugBuildLogger"; //$NON-NLS-1$
	private static final String NULL_LOGGER_CLASS = "org.eclipse.ant.internal.launching.runtime.logger.NullBuildLogger"; //$NON-NLS-1$
	private static final String REMOTE_ANT_LOGGER_CLASS = "org.eclipse.ant.internal.launching.remote.logger.RemoteAntBuildLogger"; //$NON-NLS-1$
	private static final String REMOTE_ANT_DEBUG_LOGGER_CLASS = "org.eclipse.ant.internal.launching.remote.logger.RemoteAntDebugBuildLogger"; //$NON-NLS-1$
	private static final String BASE_DIR_PREFIX = "-Dbasedir="; //$NON-NLS-1$
	private static final String INPUT_HANDLER_CLASS = "org.eclipse.ant.internal.ui.antsupport.inputhandler.AntInputHandler"; //$NON-NLS-1$
	private static final String REMOTE_INPUT_HANDLER_CLASS = "org.eclipse.ant.internal.ui.antsupport.inputhandler.ProxyInputHandler"; //$NON-NLS-1$

	/**
	 * String attribute identifying the build scope for a launch configuration. <code>null</code> indicates the default workspace build.
	 * 
	 * Note: this attribute was used with the old 'AntBuildTab' which has been replaced by the 'ExternalToolsBuildTab'. The 'ExternalToolsBuildTab'
	 * uses a different attribute key, so use the external tools attribute when present: IExternalToolConstants.ATTR_BUILD_SCOPE
	 */
	private static final String ATTR_BUILD_SCOPE = AntLaunching.getUniqueIdentifier() + ".ATTR_BUILD_SCOPE"; //$NON-NLS-1$

	/**
	 * Attribute identifier specifying whether referenced projects should be considered when computing the projects to build. Default value is
	 * <code>true</code>.
	 * 
	 * Note: this attribute was used with the old 'AntBuildTab' which has been replaced by the 'ExternalToolsBuildTab'. The 'ExternalToolsBuildTab'
	 * uses a different attribute key, so use the external tools attribute when present: IExternalToolConstants.ATTR_INCLUDE_REFERENCED_PROJECTS
	 */
	private static final String ATTR_INCLUDE_REFERENCED_PROJECTS = AntLaunching.getUniqueIdentifier() + ".ATTR_INCLUDE_REFERENCED_PROJECTS"; //$NON-NLS-1$

	private static String fgSWTLibraryLocation;

	private String fMode;
	ILaunchManager launchManager;

	private boolean fUserSpecifiedLogger = false;

	@Override
	public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
		String path = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, new String("")); //$NON-NLS-1$
		if (!path.isEmpty()) {
			IPath jrePath = Path.fromPortableString(path);
			IVMInstall vm = JavaRuntime.getVMInstall(jrePath);
			if (vm instanceof AbstractVMInstall) {
				AbstractVMInstall install = (AbstractVMInstall) vm;
				String vmver = install.getJavaVersion();
				// versionToJdkLevel only handles 3 char versions = 1.5, 1.6, 1.9, etc
				if (vmver.length() > 3) {
					vmver = vmver.substring(0, 3);
				}
				// int ver = (int) (CompilerOptions.versionToJdkLevel(vmver) >>> 16);
				if (JavaCore.compareJavaVersions(vmver, JavaCore.VERSION_1_8) < 0) {
					boolean useDefault = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, true);
					if (useDefault) { // Java 1.7 and above is required if Default Ant Home is used
						IStatus status = new Status(IStatus.ERROR, AntLaunching.PLUGIN_ID, 1, AntLaunchConfigurationMessages.AntLaunchDelegate_Launching__0__2, null);
						throw new CoreException(status);
					}
				}
			}
		}
		if (monitor.isCanceled()) {
			return;
		}
		fUserSpecifiedLogger = false;
		fMode = mode;
		launchManager = DebugPlugin.getDefault().getLaunchManager();

		// migrate the config to the new classpath format if required
		AntLaunchingUtil.migrateToNewClasspathFormat(configuration);

		boolean isSeparateJRE = AntLaunchingUtil.isSeparateJREAntBuild(configuration);

		if (AntLaunchingUtil.isLaunchInBackground(configuration)) {
			monitor.beginTask(MessageFormat.format(AntLaunchConfigurationMessages.AntLaunchDelegate_Launching__0__1, new Object[] {
					configuration.getName() }), 10);
		} else {
			monitor.beginTask(MessageFormat.format(AntLaunchConfigurationMessages.AntLaunchDelegate_Running__0__2, new Object[] {
					configuration.getName() }), 100);
		}

		// resolve location
		IPath location = ExternalToolsCoreUtil.getLocation(configuration);
		monitor.worked(1);

		if (monitor.isCanceled()) {
			return;
		}

		if (!isSeparateJRE && AntRunner.isBuildRunning()) {
			IStatus status = new Status(IStatus.ERROR, AntLaunching.PLUGIN_ID, 1, MessageFormat.format(AntLaunchConfigurationMessages.AntLaunchDelegate_Build_In_Progress, new Object[] {
					location.toOSString() }), null);
			throw new CoreException(status);
		}

		// resolve working directory
		IPath workingDirectory = ExternalToolsCoreUtil.getWorkingDirectory(configuration);
		String basedir = null;
		if (workingDirectory != null) {
			basedir = workingDirectory.toOSString();
		}
		monitor.worked(1);

		if (monitor.isCanceled()) {
			return;
		}

		// link the process to its build logger via a timestamp
		long timeStamp = System.currentTimeMillis();
		String idStamp = Long.toString(timeStamp);
		StringBuffer idProperty = new StringBuffer("-D"); //$NON-NLS-1$
		idProperty.append(AbstractEclipseBuildLogger.ANT_PROCESS_ID);
		idProperty.append('=');
		idProperty.append(idStamp);

		// resolve arguments
		String[] arguments = ExternalToolsCoreUtil.getArguments(configuration);

		Map<String, String> userProperties = AntLaunchingUtil.getProperties(configuration);
		if (userProperties != null) {// create a copy so as to not affect the
			// configuration with transient
			// properties
			userProperties = new HashMap<>(userProperties);
		}
		String[] propertyFiles = AntLaunchingUtil.getPropertyFiles(configuration);
		String[] targets = AntLaunchingUtil.getTargetNames(configuration);
		URL[] customClasspath = AntLaunchingUtil.getCustomClasspath(configuration);
		String antHome = AntLaunchingUtil.getAntHome(configuration);

		boolean setInputHandler = true;
		try {
			// check if set specify inputhandler
			setInputHandler = configuration.getAttribute(AntLaunching.SET_INPUTHANDLER, true);
		}
		catch (CoreException ce) {
			AntLaunching.log(ce);
		}

		AntRunner runner = null;
		if (!isSeparateJRE) {
			runner = configureAntRunner(configuration, location, basedir, idProperty, arguments, userProperties, propertyFiles, targets, customClasspath, antHome, setInputHandler);
		}

		monitor.worked(1);

		if (monitor.isCanceled()) {
			return;
		}
		boolean captureOutput = ExternalToolsCoreUtil.getCaptureOutput(configuration);
		int port = -1;
		int requestPort = -1;
		if (isSeparateJRE && captureOutput) {
			if (userProperties == null) {
				userProperties = new HashMap<>();
			}
			port = SocketUtil.findFreePort();
			userProperties.put(AbstractEclipseBuildLogger.ANT_PROCESS_ID, idStamp);
			userProperties.put("eclipse.connect.port", Integer.toString(port)); //$NON-NLS-1$
			if (fMode.equals(ILaunchManager.DEBUG_MODE)) {
				requestPort = SocketUtil.findFreePort();
				userProperties.put("eclipse.connect.request_port", Integer.toString(requestPort)); //$NON-NLS-1$
			}
		}

		StringBuffer commandLine = generateCommandLine(location, arguments, userProperties, propertyFiles, targets, antHome, basedir, isSeparateJRE, captureOutput, setInputHandler);

		if (isSeparateJRE) {
			monitor.beginTask(MessageFormat.format(AntLaunchConfigurationMessages.AntLaunchDelegate_Launching__0__1, new Object[] {
					configuration.getName() }), 10);
			runInSeparateVM(configuration, launch, monitor, idStamp, antHome, port, requestPort, commandLine, captureOutput, setInputHandler);
		} else {
			runInSameVM(configuration, launch, monitor, location, idStamp, runner, commandLine);
		}

		monitor.done();
	}

	private void runInSameVM(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor, IPath location, String idStamp, AntRunner runner, StringBuffer commandLine) throws CoreException {
		Map<String, String> attributes = new HashMap<>(2);
		attributes.put(IProcess.ATTR_PROCESS_TYPE, IAntLaunchConstants.ID_ANT_PROCESS_TYPE);
		attributes.put(AbstractEclipseBuildLogger.ANT_PROCESS_ID, idStamp);

		final AntProcess process = new AntProcess(location.toOSString(), launch, attributes);
		setProcessAttributes(process, idStamp, commandLine);
		boolean debug = fMode.equals(ILaunchManager.DEBUG_MODE);
		if (debug || AntLaunchingUtil.isLaunchInBackground(configuration)) {
			final AntRunner finalRunner = runner;
			Runnable r = () -> {
				try {
					finalRunner.run(process);
				}
				catch (CoreException e) {
					handleException(e, AntLaunchConfigurationMessages.AntLaunchDelegate_Failure);
				}
				process.terminated();
			};
			Thread background = new Thread(r);
			background.setDaemon(true);
			background.start();
			monitor.worked(1);
			// refresh resources after process finishes
			if (configuration.getAttribute(RefreshUtil.ATTR_REFRESH_SCOPE, (String) null) != null) {
				BackgroundResourceRefresher refresher = new BackgroundResourceRefresher(configuration, process);
				refresher.startBackgroundRefresh();
			}
		} else {
			// execute the build
			try {
				process.setProgressMonitor(monitor);
				runner.run(monitor);
			}
			catch (CoreException e) {
				process.terminated();
				monitor.done();
				handleException(e, AntLaunchConfigurationMessages.AntLaunchDelegate_23);
				return;
			}
			process.terminated();

			// refresh resources
			RefreshUtil.refreshResources(configuration, monitor);
		}
	}

	private AntRunner configureAntRunner(ILaunchConfiguration configuration, IPath location, String baseDir, StringBuffer idProperty, String[] arguments, Map<String, String> userProperties, String[] propertyFiles, String[] targets, URL[] customClasspath, String antHome, boolean setInputHandler) throws CoreException {
		int argLength = 1; // at least one user property - timestamp
		if (arguments != null) {
			argLength += arguments.length;
		}
		if (baseDir != null && baseDir.length() > 0) {
			argLength++;
		}
		String[] runnerArgs = new String[argLength];
		if (arguments != null) {
			System.arraycopy(arguments, 0, runnerArgs, 0, arguments.length);
		}
		if (baseDir != null && baseDir.length() > 0) {
			runnerArgs[runnerArgs.length - 2] = BASE_DIR_PREFIX + baseDir;
		}
		runnerArgs[runnerArgs.length - 1] = idProperty.toString();

		AntRunner runner = new AntRunner();
		runner.setBuildFileLocation(location.toOSString());
		boolean captureOutput = ExternalToolsCoreUtil.getCaptureOutput(configuration);
		if (captureOutput) {
			if (fMode.equals(ILaunchManager.DEBUG_MODE)) {
				runner.addBuildLogger(ANT_DEBUG_LOGGER_CLASS);
			} else {
				runner.addBuildLogger(ANT_LOGGER_CLASS);
			}
		} else {
			runner.addBuildLogger(NULL_LOGGER_CLASS);
		}
		if (setInputHandler) {
			runner.setInputHandler(INPUT_HANDLER_CLASS);
		} else {
			runner.setInputHandler(""); //$NON-NLS-1$
		}
		runner.setArguments(runnerArgs);
		if (userProperties != null) {
			runner.addUserProperties(userProperties);
		}

		if (propertyFiles != null) {
			runner.setPropertyFiles(propertyFiles);
		}

		if (targets != null) {
			runner.setExecutionTargets(targets);
		}

		if (customClasspath != null) {
			runner.setCustomClasspath(customClasspath);
		}

		if (antHome != null) {
			runner.setAntHome(antHome);
		}
		return runner;
	}

	private void handleException(final CoreException e, final String title) {
		AntLaunching.log(title, e);
	}

	private void setProcessAttributes(IProcess process, String idStamp, StringBuffer commandLine) {
		// link the process to the Eclipse build logger via a timestamp
		if (!fUserSpecifiedLogger) {
			process.setAttribute(AbstractEclipseBuildLogger.ANT_PROCESS_ID, idStamp);
		}

		// create "fake" command line for the process
		if (commandLine != null) {
			process.setAttribute(IProcess.ATTR_CMDLINE, commandLine.toString());
		}
	}

	private StringBuffer generateCommandLine(IPath location, String[] arguments, Map<String, String> userProperties, String[] propertyFiles, String[] targets, String antHome, String basedir, boolean separateVM, boolean captureOutput, boolean setInputHandler) {
		StringBuffer commandLine = new StringBuffer();

		if (!separateVM) {
			commandLine.append("ant"); //$NON-NLS-1$
		}

		if (arguments != null) {
			commandLine.append(' ');
			commandLine.append(DebugPlugin.renderArguments(arguments, null));
		}

		AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences();
		if (propertyFiles == null) { // global
			String[] files = prefs.getCustomPropertyFiles();
			for (int i = 0; i < files.length; i++) {
				String path = files[i];
				commandLine.append(" -propertyfile \""); //$NON-NLS-1$
				commandLine.append(path);
				commandLine.append('\"');
			}
		} else {// "local" configuration
			for (int i = 0; i < propertyFiles.length; i++) {
				String path = propertyFiles[i];
				commandLine.append(" -propertyfile \""); //$NON-NLS-1$
				commandLine.append(path);
				commandLine.append('\"');
			}
		}
		// "local" configuration
		if (userProperties != null) {
			Iterator<String> keys = userProperties.keySet().iterator();
			String key;
			while (keys.hasNext()) {
				key = keys.next();
				appendProperty(commandLine, key, userProperties.get(key));
			}
		}

		// global
		List<Property> properties = null;
		if (!separateVM) {
			properties = prefs.getProperties();
		} else {
			properties = prefs.getRemoteAntProperties();
		}

		// if we have user properties this means that the user has chosen to
		// override the global properties
		// if in a separate VM and have only two (or three if debug) user
		// properties these are really only Eclipse generated properties
		// and the user is still using the global properties
		int numberOfEclipseProperties = 2;
		if (userProperties != null && userProperties.get("eclipse.connect.request_port") != null) { //$NON-NLS-1$
			numberOfEclipseProperties = 3; // debug mode
		}
		boolean useGlobalProperties = userProperties == null || (separateVM && userProperties.size() == numberOfEclipseProperties);
		if (useGlobalProperties) {
			for (Iterator<Property> iter = properties.iterator(); iter.hasNext();) {
				Property property = iter.next();
				String key = property.getName();
				String value = property.getValue(false);
				if (value != null) {
					appendProperty(commandLine, key, value);
				}
			}
		}

		if (basedir != null && basedir.length() > 0) {
			appendProperty(commandLine, "basedir", basedir); //$NON-NLS-1$
		}

		if (antHome != null) {
			commandLine.append(" \"-Dant.home="); //$NON-NLS-1$
			commandLine.append(antHome);
			commandLine.append('\"');
		}

		if (separateVM) {
			if (commandLine.indexOf("-logger") == -1) { //$NON-NLS-1$
				if (captureOutput) {
					commandLine.append(" -logger "); //$NON-NLS-1$
					if (fMode.equals(ILaunchManager.DEBUG_MODE)) {
						commandLine.append(REMOTE_ANT_DEBUG_LOGGER_CLASS);
					} else {
						commandLine.append(REMOTE_ANT_LOGGER_CLASS);
					}
				}
			} else {
				fUserSpecifiedLogger = true;
			}
			if (commandLine.indexOf("-inputhandler") == -1 && setInputHandler) { //$NON-NLS-1$
				commandLine.append(" -inputhandler "); //$NON-NLS-1$
				commandLine.append(REMOTE_INPUT_HANDLER_CLASS);
			}
		} else {
			if (commandLine.indexOf("-inputhandler") == -1 && setInputHandler) { //$NON-NLS-1$
				commandLine.append(" -inputhandler "); //$NON-NLS-1$
				commandLine.append(INPUT_HANDLER_CLASS);
			}
			if (commandLine.indexOf("-logger") == -1) { //$NON-NLS-1$
				commandLine.append(" -logger "); //$NON-NLS-1$
				if (fMode.equals(ILaunchManager.DEBUG_MODE)) {
					commandLine.append(ANT_DEBUG_LOGGER_CLASS);
				} else if (captureOutput) {
					commandLine.append(ANT_LOGGER_CLASS);
				} else {
					commandLine.append(NULL_LOGGER_CLASS);
				}
			}
		}

		if (separateVM) {
			appendTaskAndTypes(prefs, commandLine);
		}
		commandLine.append(" -buildfile \""); //$NON-NLS-1$
		commandLine.append(location.toOSString());
		commandLine.append('\"');

		if (targets != null) {
			for (int i = 0; i < targets.length; i++) {
				commandLine.append(" \""); //$NON-NLS-1$
				commandLine.append(targets[i]);
				commandLine.append('\"');
			}
		}
		return commandLine;
	}

	private void appendTaskAndTypes(AntCorePreferences prefs, StringBuffer commandLine) {
		List<Task> tasks = prefs.getRemoteTasks();
		for (Task task : tasks) {
			commandLine.append(" -eclipseTask "); //$NON-NLS-1$
			String name = ProjectHelper.genComponentName(task.getURI(), task.getTaskName());
			commandLine.append(name);
			commandLine.append(',');
			commandLine.append(task.getClassName());
		}

		List<Type> types = prefs.getRemoteTypes();
		for (Type type : types) {
			commandLine.append(" -eclipseType "); //$NON-NLS-1$
			String name = ProjectHelper.genComponentName(type.getURI(), type.getTypeName());
			commandLine.append(name);
			commandLine.append(',');
			commandLine.append(type.getClassName());
		}
	}

	private void appendProperty(StringBuffer commandLine, String name, String value) {
		commandLine.append(" \"-D"); //$NON-NLS-1$
		commandLine.append(name);
		commandLine.append('=');
		commandLine.append(value);
		if (value.length() > 0 && value.charAt(value.length() - 1) == File.separatorChar) {
			commandLine.append(File.separatorChar);
		}
		commandLine.append("\""); //$NON-NLS-1$
	}

	private void runInSeparateVM(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor, String idStamp, String antHome, int port, int requestPort, StringBuffer commandLine, boolean captureOutput, boolean setInputHandler) throws CoreException {
		boolean debug = fMode.equals(ILaunchManager.DEBUG_MODE);
		if (captureOutput) {
			String encoding = DebugPlugin.getDefault().getLaunchManager().getEncoding(configuration);
			if (debug) {
				RemoteAntDebugBuildListener listener = new RemoteAntDebugBuildListener(launch, encoding);
				if (requestPort != -1) {
					listener.startListening(port, requestPort);
				}
			} else if (!fUserSpecifiedLogger) {
				RemoteAntBuildListener client = new RemoteAntBuildListener(launch, encoding);
				if (port != -1) {
					client.startListening(port);
				}
			}
		}

		ILaunchConfigurationWorkingCopy copy = configuration.getWorkingCopy();
		setDefaultWorkingDirectory(copy);
		copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, commandLine.toString());
		copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, IAntLaunchConstants.MAIN_TYPE_NAME);
		StringBuffer vmArgs = generateVMArguments(copy, setInputHandler, antHome);
		copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, vmArgs.toString());
		copy.setAttribute(ILaunchManager.ATTR_PRIVATE, true);
		if (copy.getAttribute(IAntLaunchConstants.ATTR_DEFAULT_VM_INSTALL, false)) {
			setDefaultVM(configuration, copy);
		}

		copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_USE_START_ON_FIRST_THREAD, false);

		if (debug) { // do not allow launch in foreground bug 83254
			copy.setAttribute(IExternalToolConstants.ATTR_LAUNCH_IN_BACKGROUND, true);
		}

		// set the ANT_HOME environment variable
		if (antHome != null) {
			Map<String, String> vars = copy.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, new HashMap<String, String>(1));
			vars.put("ANT_HOME", antHome); //$NON-NLS-1$
			copy.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, vars);
		}
		// copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
		// "-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000");
		IProgressMonitor subMonitor = SubMonitor.convert(monitor, 10);
		AntJavaLaunchDelegate delegate = new AntJavaLaunchDelegate();
		delegate.preLaunchCheck(copy, ILaunchManager.RUN_MODE, subMonitor);
		delegate.launch(copy, ILaunchManager.RUN_MODE, launch, subMonitor);
		final IProcess[] processes = launch.getProcesses();
		for (int i = 0; i < processes.length; i++) {
			setProcessAttributes(processes[i], idStamp, null);
		}

		if (AntLaunchingUtil.isLaunchInBackground(copy)) {
			// refresh resources after process finishes
			if (configuration.getAttribute(RefreshUtil.ATTR_REFRESH_SCOPE, (String) null) != null) {
				BackgroundResourceRefresher refresher = new BackgroundResourceRefresher(configuration, processes[0]);
				refresher.startBackgroundRefresh();
			}
		} else {
			final boolean[] terminated = new boolean[1];
			terminated[0] = launch.isTerminated();
			IDebugEventSetListener listener = new IDebugEventSetListener() {
				@Override
				public void handleDebugEvents(DebugEvent[] events) {
					for (int i = 0; i < events.length; i++) {
						DebugEvent event = events[i];
						for (int j = 0, numProcesses = processes.length; j < numProcesses; j++) {
							if (event.getSource() == processes[j] && event.getKind() == DebugEvent.TERMINATE) {
								terminated[0] = true;
								break;
							}
						}
					}
				}
			};
			DebugPlugin.getDefault().addDebugEventListener(listener);
			monitor.subTask(AntLaunchConfigurationMessages.AntLaunchDelegate_28);
			while (!monitor.isCanceled() && !terminated[0]) {
				try {
					Thread.sleep(50);
				}
				catch (InterruptedException e) {
					// do nothing
				}
			}
			DebugPlugin.getDefault().removeDebugEventListener(listener);
			if (!monitor.isCanceled()) {
				// refresh resources
				RefreshUtil.refreshResources(configuration, monitor);
			}
		}
	}

	@SuppressWarnings("deprecation")
	private void setDefaultVM(ILaunchConfiguration configuration, ILaunchConfigurationWorkingCopy copy) {
		try {
			JavaRuntime.getJavaProject(configuration);
			// remove the vm name, install type and jre container path for the
			// Java launching concept of default VM
			copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, (String) null);
			copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, (String) null);
			copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, (String) null);
		}
		catch (CoreException ce) {
			// not in a Java project
			IVMInstall defaultVMInstall = JavaRuntime.getDefaultVMInstall();
			copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, defaultVMInstall.getName());
			copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, defaultVMInstall.getVMInstallType().getId());
		}
	}

	private StringBuffer generateVMArguments(ILaunchConfiguration config, boolean setInputHandler, String antHome) {
		StringBuffer vmArgs = new StringBuffer();
		try {
			String configArgs = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, (String) null);
			if (configArgs != null) {
				vmArgs.append(configArgs);
				vmArgs.append(' ');
			}
		}
		catch (CoreException e) {
			// do nothing
		}

		if (antHome != null) {
			vmArgs.append("-Dant.home=\""); //$NON-NLS-1$
			vmArgs.append(antHome);
			vmArgs.append("\" "); //$NON-NLS-1$

			File antLibDir = new File(antHome, "lib"); //$NON-NLS-1$
			vmArgs.append("-Dant.library.dir=\""); //$NON-NLS-1$
			vmArgs.append(antLibDir.getAbsolutePath());
			vmArgs.append('\"');
		}
		if (setInputHandler) {
			String swtLocation = getSWTLibraryLocation();
			if (swtLocation != null) {
				vmArgs.append(" -Djava.library.path=\""); //$NON-NLS-1$
				String javaLibPath = System.getProperty("java.library.path"); //$NON-NLS-1$
				javaLibPath = stripUnescapedQuotes(javaLibPath);
				if (javaLibPath != null) {
					vmArgs.append(javaLibPath);
					if (vmArgs.charAt(vmArgs.length() - 1) != File.pathSeparatorChar) {
						vmArgs.append(File.pathSeparatorChar);
					}
				}
				vmArgs.append(swtLocation);
				vmArgs.append('"');
			}
		}
		return vmArgs;
	}

	private String stripUnescapedQuotes(String javaLibPath) {
		StringBuffer buf = new StringBuffer(javaLibPath.length());
		for (int i = 0; i < javaLibPath.length(); i++) {
			char c = javaLibPath.charAt(i);
			switch (c) {
				case '"':
					if (i != 0 && javaLibPath.charAt(i - 1) == '\\') {
						buf.append(c);
					}
					break;
				default:
					buf.append(c);
					break;
			}
		}
		return buf.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#getBuildOrder (org.eclipse.debug.core.ILaunchConfiguration, java.lang.String)
	 */
	@Override
	protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException {
		String scopeKey = ATTR_BUILD_SCOPE;
		String refKey = ATTR_INCLUDE_REFERENCED_PROJECTS;
		if (configuration.hasAttribute(IExternalToolConstants.ATTR_BUILD_SCOPE)
				|| configuration.hasAttribute(IExternalToolConstants.ATTR_INCLUDE_REFERENCED_PROJECTS)) {
			// use new attributes when present - see bug 282581
			scopeKey = IExternalToolConstants.ATTR_BUILD_SCOPE;
			refKey = IExternalToolConstants.ATTR_INCLUDE_REFERENCED_PROJECTS;
		}
		IProject[] projects = ExternalToolsCoreUtil.getBuildProjects(configuration, scopeKey);
		if (projects == null) {
			return null;
		}
		boolean isRef = ExternalToolsCoreUtil.isIncludeReferencedProjects(configuration, refKey);
		if (isRef) {
			return computeReferencedBuildOrder(projects);
		}
		return computeBuildOrder(projects);
	}

	private String getSWTLibraryLocation() {
		if (fgSWTLibraryLocation == null) {
			Bundle bundle = Platform.getBundle("org.eclipse.swt"); //$NON-NLS-1$
			BundleWiring wiring = bundle.adapt(BundleWiring.class);
			List<BundleWire> fragmentWires = wiring == null ? Collections.<BundleWire> emptyList()
					: wiring.getProvidedWires(HostNamespace.HOST_NAMESPACE);
			if (fragmentWires.isEmpty()) {
				return null;
			}
			Bundle fragBundle = fragmentWires.get(0).getRequirer().getBundle();
			try {
				URL url = FileLocator.toFileURL(fragBundle.getEntry("/")); //$NON-NLS-1$
				try {
					IPath path = new Path(URIUtil.toURL(URIUtil.toURI(url)).getPath());
					path = path.removeTrailingSeparator();
					fgSWTLibraryLocation = path.toOSString();
				}
				catch (URISyntaxException e) {
					AntLaunching.log(e);
				}
			}
			catch (IOException e) {
				// do nothing
			}
		}
		return fgSWTLibraryLocation;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#getBreakpoints (org.eclipse.debug.core.ILaunchConfiguration)
	 */
	@Override
	protected IBreakpoint[] getBreakpoints(ILaunchConfiguration configuration) {
		IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
		if (!breakpointManager.isEnabled()) {
			// no need to check breakpoints individually.
			return null;
		}
		return breakpointManager.getBreakpoints(IAntDebugConstants.ID_ANT_DEBUG_MODEL);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#saveBeforeLaunch (org.eclipse.debug.core.ILaunchConfiguration, java.lang.String,
	 * org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	protected boolean saveBeforeLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
		if (IExternalToolConstants.ID_EXTERNAL_TOOLS_BUILDER_LAUNCH_CATEGORY.equals(configuration.getType().getCategory())) {
			// don't prompt for builders
			return true;
		}
		return super.saveBeforeLaunch(configuration, mode, monitor);
	}

	/**
	 * Sets the default working directory to be the parent folder of the buildfile if the user has not explicitly set the working directory.
	 */
	private void setDefaultWorkingDirectory(ILaunchConfigurationWorkingCopy copy) {
		try {
			String wd = copy.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String) null);
			if (wd == null) {
				wd = ExternalToolsCoreUtil.getLocation(copy).removeLastSegments(1).toOSString();
				copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, wd);
			}
		}
		catch (CoreException e) {
			AntLaunching.log(e.getStatus());
		}
	}

	@Override
	public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
		return new AntLaunch(configuration, mode, null);
	}
}
