/*******************************************************************************
 * Copyright (c) 2000, 2019 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 java.util.concurrent.atomic.AtomicBoolean;

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 AtomicBoolean terminated = new AtomicBoolean(false);
			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.set(true);
								break;
							}
						}
					}
				}
			};
			DebugPlugin.getDefault().addDebugEventListener(listener);
			terminated.compareAndSet(false, launch.isTerminated());
			monitor.subTask(AntLaunchConfigurationMessages.AntLaunchDelegate_28);
			while (!monitor.isCanceled() && !terminated.get()) {
				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);
	}
}
