/*******************************************************************************
 * Copyright (c) 2000, 2021 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
 *     Sebastian Davids - bug 50567 Eclipse native environment support on Win98
 *     Pawel Piech - Bug 82001: When shutting down the IDE, the debugger should first
 *     attempt to disconnect debug targets before terminating them
 *     Alena Laskavaia - Bug 259281
 *     Marc Khouzam - Bug 313143: Preferred Launch Delegate not recovered from preferences
 *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
 *******************************************************************************/
package org.eclipse.debug.internal.core;


import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationListener;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchDelegate;
import org.eclipse.debug.core.ILaunchListener;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.ILaunchMode;
import org.eclipse.debug.core.ILaunchesListener;
import org.eclipse.debug.core.ILaunchesListener2;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IDisconnect;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
import org.eclipse.debug.core.sourcelookup.ISourcePathComputer;
import org.eclipse.debug.internal.core.sourcelookup.SourceContainerType;
import org.eclipse.debug.internal.core.sourcelookup.SourcePathComputer;
import org.eclipse.osgi.service.environment.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Manages launch configurations, launch configuration types, and registered launches.
 *
 * @see ILaunchManager
 */
public class LaunchManager extends PlatformObject implements ILaunchManager, IResourceChangeListener {

	/**
	 * Preferred launch delegate preference name.
	 * <p>
	 * Prior to 3.5 this preferred launch delegates for all launch
	 * configuration types were serialized into a single XML string
	 * and stored in this preference.
	 * </p>
	 * <p>
	 * Since 3.5, the preferred launch delegates are stored in a separate
	 * preference for each launch configuration type.  The name of this
	 * preference is composed of the prefix, followed by a slash, followed by
	 * the launch configuration type id.  The values contain a set of launch
	 * delegates, delimited by a semicolon, and each delegate entry contains
	 * the delegate ID, followed by a comma, followed by comma-delimited
	 * launch modes.
	 *
	 * @since 3.3
	 */
	protected static final String PREF_PREFERRED_DELEGATES = DebugPlugin.getUniqueIdentifier() + ".PREFERRED_DELEGATES"; //$NON-NLS-1$

	/**
	 * Constant to define debug.ui for the status codes
	 *
	 * @since 3.2
	 */
	private static final String DEBUG_UI = "org.eclipse.debug.ui"; //$NON-NLS-1$

	/**
	 * Listing of unsupported launch configuration names for the Win 32 platform
	 * @since 3.5
	 */
	static final String[] UNSUPPORTED_WIN32_CONFIG_NAMES = new String[] {"aux", "clock$", "com1", "com2", "com3", "com4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
		"com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
		"lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$

	/**
	 * Disallowed characters for launch configuration names
	 * '@' and '&' are disallowed because they corrupt menu items.
	 *
	 * @since 3.5
	 */
	static final char[] DISALLOWED_CONFIG_NAME_CHARS = new char[] { '@', '&','\\', '/', ':', '*', '?', '"', '<', '>', '|', '\0' };

	/**
	 * Status code for which a UI prompter is registered.
	 *
	 * @since 3.2
	 */
	protected static final IStatus promptStatus = new Status(IStatus.INFO, DEBUG_UI, 200, IInternalDebugCoreConstants.EMPTY_STRING, null);

	/**
	 * Step filter manager
	 */
	private StepFilterManager fStepFilterManager = null;

	/**
	 * Notifies a launch config listener in a safe runnable to handle
	 * exceptions.
	 */
	class ConfigurationNotifier implements ISafeRunnable {

		private ILaunchConfigurationListener fListener;
		private int fType;
		private ILaunchConfiguration fConfiguration;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during launch configuration change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		/**
		 * Notifies the given listener of the add/change/remove
		 *
		 * @param configuration the configuration that has changed
		 * @param update the type of change
		 */
		public void notify(ILaunchConfiguration configuration, int update) {
			fConfiguration = configuration;
			fType = update;
			for (ILaunchConfigurationListener iLaunchConfigurationListener : fLaunchConfigurationListeners) {
				fListener = iLaunchConfigurationListener;
				SafeRunner.run(this);
			}
			fConfiguration = null;
			fListener = null;
		}

		@Override
		public void run() throws Exception {
			switch (fType) {
				case ADDED:
					fListener.launchConfigurationAdded(fConfiguration);
					break;
				case REMOVED:
					fListener.launchConfigurationRemoved(fConfiguration);
					break;
				case CHANGED:
					fListener.launchConfigurationChanged(fConfiguration);
					break;
				default:
					break;
			}
		}
	}

	/**
	 * Notifies a launch listener (multiple launches) in a safe runnable to
	 * handle exceptions.
	 */
	class LaunchesNotifier implements ISafeRunnable {

		private ILaunchesListener fListener;
		private int fType;
		private ILaunch[] fNotifierLaunches;
		private ILaunch[] fRegistered;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during launch change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		/**
		 * Notifies the given listener of the adds/changes/removes
		 *
		 * @param launches the launches that changed
		 * @param update the type of change
		 */
		public void notify(ILaunch[] launches, int update) {
			fNotifierLaunches = launches;
			fType = update;
			fRegistered = null;
			for (ILaunchesListener iLaunchesListener : fLaunchesListeners) {
				fListener = iLaunchesListener;
				SafeRunner.run(this);
			}
			fNotifierLaunches = null;
			fRegistered = null;
			fListener = null;
		}

		@Override
		public void run() throws Exception {
			switch (fType) {
				case ADDED:
					fListener.launchesAdded(fNotifierLaunches);
					break;
				case REMOVED:
					fListener.launchesRemoved(fNotifierLaunches);
					break;
				case CHANGED:
				case TERMINATE:
					if (fRegistered == null) {
						List<ILaunch> registered = null;
						for (int j = 0; j < fNotifierLaunches.length; j++) {
							if (isRegistered(fNotifierLaunches[j])) {
								if (registered != null) {
									registered.add(fNotifierLaunches[j]);
								}
							} else if (registered == null) {
								registered = new ArrayList<>(fNotifierLaunches.length);
								for (int k = 0; k < j; k++) {
									registered.add(fNotifierLaunches[k]);
								}
							}
						}
						if (registered == null) {
							fRegistered = fNotifierLaunches;
						} else {
							fRegistered = registered.toArray(new ILaunch[registered.size()]);
						}
					}
					if (fRegistered.length > 0) {
						if (fType == CHANGED) {
							fListener.launchesChanged(fRegistered);
						}
						if (fType == TERMINATE && fListener instanceof ILaunchesListener2) {
							((ILaunchesListener2)fListener).launchesTerminated(fRegistered);
						}
					}
					break;
				default:
					break;
			}
		}
	}

	/**
	 * Visitor for handling a resource begin deleted, and the need to check mapped configurations
	 * for auto-deletion
	 * @since 3.4
	 */
	class MappedResourceVisitor implements IResourceDeltaVisitor {

		@Override
		public boolean visit(IResourceDelta delta) throws CoreException {
			if (0 != (delta.getFlags() & IResourceDelta.OPEN)) {
				return false;
			}
			if(delta.getKind() == IResourceDelta.REMOVED && delta.getFlags() != IResourceDelta.MOVED_TO) {
				ArrayList<ILaunchConfiguration> configs = collectAssociatedLaunches(delta.getResource());
				for (ILaunchConfiguration config : configs) {
					try {
						config.delete();
					} catch (CoreException e) {
						DebugPlugin.log(e.getStatus());
					}
				}
				return false;
			}
			return true;
		}
	}

	/**
	 * Visitor for handling resource deltas.
	 */
	class LaunchManagerVisitor implements IResourceDeltaVisitor {

		@Override
		public boolean visit(IResourceDelta delta) {
			if (delta == null) {
				return false;
			}
			if (0 != (delta.getFlags() & IResourceDelta.OPEN)) {
				if (delta.getResource() instanceof IProject) {
					IProject project = (IProject)delta.getResource();
					if (project.isOpen()) {
						LaunchManager.this.projectOpened(project);
					} else {
						LaunchManager.this.projectClosed(project);
					}
				}
				return false;
			}
			IResource resource = delta.getResource();
			if (resource instanceof IFile) {
				IFile file = (IFile)resource;
				if (ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION.equals(file.getFileExtension()) || ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION.equals(file.getFileExtension())) {
					ILaunchConfiguration handle = new LaunchConfiguration(file);
					switch (delta.getKind()) {
						case IResourceDelta.ADDED :
							LaunchManager.this.launchConfigurationAdded(handle);
							break;
						case IResourceDelta.REMOVED :
							LaunchManager.this.launchConfigurationDeleted(handle);
							break;
						case IResourceDelta.CHANGED :
							LaunchManager.this.launchConfigurationChanged(handle);
							break;
						default:
							break;
					}
				}
				return false;
			}
			return true;
		}
	}

	/**
	 * Notifies a launch listener (single launch) in a safe runnable to handle
	 * exceptions.
	 */
	class LaunchNotifier implements ISafeRunnable {

		private ILaunchListener fListener;
		private int fType;
		private ILaunch fLaunch;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during launch change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		/**
		 * Notifies listeners of the add/change/remove
		 *
		 * @param launch the launch that has changed
		 * @param update the type of change
		 */
		public void notify(ILaunch launch, int update) {
			fLaunch = launch;
			fType = update;
			for (ILaunchListener iLaunchListener : fListeners) {
				fListener = iLaunchListener;
				SafeRunner.run(this);
			}
			fLaunch = null;
			fListener = null;
		}

		@Override
		public void run() throws Exception {
			switch (fType) {
				case ADDED:
					fListener.launchAdded(fLaunch);
					break;
				case REMOVED:
					fListener.launchRemoved(fLaunch);
					break;
				case CHANGED:
					if (isRegistered(fLaunch)) {
						fListener.launchChanged(fLaunch);
					}
					break;
				default:
					break;
			}
		}
	}

	/**
	 * Collects files whose extension matches the launch configuration file
	 * extension.
	 */
	static class ResourceProxyVisitor implements IResourceProxyVisitor {

		private List<IResource> fList;

		protected ResourceProxyVisitor(List<IResource> list) {
			fList= list;
		}

		@Override
		public boolean visit(IResourceProxy proxy) {
			if (proxy.getType() == IResource.FILE) {
				if (ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION.equalsIgnoreCase(proxy.requestFullPath().getFileExtension()) || ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION.equalsIgnoreCase(proxy.requestFullPath().getFileExtension())) {
					fList.add(proxy.requestResource());
				}
				return false;
			}
			return true;
		}
	}

	/**
	 * Internal class used to hold information about a preferred delegate
	 *
	 * @since 3.3
	 */
	static class PreferredDelegate {
		private ILaunchDelegate fDelegate = null;
		private String fTypeid = null;
		private Set<String> fModes = null;

		public PreferredDelegate(ILaunchDelegate delegate, String typeid, Set<String> modes) {
			fDelegate = delegate;
			fTypeid = typeid;
			fModes = modes;
		}

		public String getTypeId() {
			return fTypeid;
		}

		public Set<String> getModes() {
			return fModes;
		}

		public ILaunchDelegate getDelegate() {
			return fDelegate;
		}
	}

	/**
	 * Types of notifications
	 */
	public static final int ADDED = 0;
	public static final int REMOVED= 1;
	public static final int CHANGED= 2;
	public static final int TERMINATE= 3;

	/**
	 * The collection of native environment variables on the user's system. Cached
	 * after being computed once as the environment cannot change.
	 */
	private static HashMap<String, String> fgNativeEnv = null;
	private static HashMap<String, String> fgNativeEnvCasePreserved = null;

	/**
	 * Path to the local directory where local launch configurations
	 * are stored with the workspace.
	 */
	public static final IPath LOCAL_LAUNCH_CONFIGURATION_CONTAINER_PATH =
		DebugPlugin.getDefault().getStateLocation().append(".launches"); //$NON-NLS-1$
	/**
	 * Returns a Document that can be used to build a DOM tree
	 * @return the Document
	 * @throws ParserConfigurationException if an exception occurs creating the document builder
	 * @since 3.0
	 */
	public static Document getDocument() throws ParserConfigurationException {
		DocumentBuilderFactory dfactory= DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder= dfactory.newDocumentBuilder();
		Document doc= docBuilder.newDocument();
		return doc;
	}

	/**
	 * Serializes a XML document into a string - encoded in UTF8 format, with
	 * platform line separators.
	 *
	 * @param doc document to serialize
	 * @return the document as a string
	 * @throws TransformerException if an unrecoverable error occurs during the
	 *             serialization
	 * @throws IOException if I/O error occurs
	 */
	public static String serializeDocument(Document doc) throws TransformerException, IOException {
		ByteArrayOutputStream s = new ByteArrayOutputStream();
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer transformer = factory.newTransformer();
		transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
		transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
		DOMSource source = new DOMSource(doc);
		StreamResult outputTarget = new StreamResult(s);
		transformer.transform(source, outputTarget);
		return s.toString(StandardCharsets.UTF_8);
	}

	/**
	 * Collection of defined launch configuration type
	 * extensions.
	 */
	private List<ILaunchConfigurationType> fLaunchConfigurationTypes = null;

	/**
	 * Launch configuration cache. Keys are <code>LaunchConfiguration</code>,
	 * values are <code>LaunchConfigurationInfo</code>.
	 */
	private Map<ILaunchConfiguration, LaunchConfigurationInfo> fLaunchConfigurations = new HashMap<>(10);

	/**
	 * A cache of launch configuration names currently in the workspace.
	 */
	private volatile String[] fSortedConfigNames = null;

	/**
	 * Collection of all launch configurations in the workspace.
	 * <code>List</code> of <code>ILaunchConfiguration</code>.
	 */
	private List<ILaunchConfiguration> fLaunchConfigurationIndex = null;

	/**
	 * Launch configuration comparator extensions,
	 * keyed by attribute name.
	 */
	private Map<String, LaunchConfigurationComparator> fComparators = null;

	/**
	 * Registered launch modes, or <code>null</code> if not initialized.
	 * Keys are mode identifiers, values are <code>ILaunchMode</code>s.
	 */
	private Map<String, ILaunchMode> fLaunchModes = null;

	/**
	 * A map of LaunchDelegate objects stored by id of delegate, or launch config type
	 */
	private HashMap<String, LaunchDelegate> fLaunchDelegates = null;

	/**
	 * Initial startup cache of preferred delegate so that the debug preferences are only parsed once
	 *
	 * @since 3.3
	 */
	private Set<PreferredDelegate> fPreferredDelegates = null;

	/**
	 * Collection of launches
	 */
	private List<ILaunch> fLaunches = new ArrayList<>(10);
	/**
	 * Set of launches for efficient 'isRegistered()' check TODO remove this -
	 * Launches don't implement hashCode() or equals() - so its no more
	 * efficient than walking the other collection
	 */
	private Set<ILaunch> fLaunchSet = new HashSet<>(10);

	/**
	 * Collection of listeners
	 */
	private ListenerList<ILaunchListener> fListeners = new ListenerList<>();

	/**
	 * Collection of "plural" listeners.
	 * @since 2.1
	 */
	private ListenerList<ILaunchesListener> fLaunchesListeners = new ListenerList<>();

	/**
	 * Visitor used to process resource deltas,
	 * to update launch configuration index.
	 */
	private LaunchManagerVisitor fgVisitor;

	/**
	 * Visitor used to process a deleted resource,
	 * to remove mapped launch configurations in the event
	 * auto-removal of launch configurations is enabled
	 *
	 * @since 3.4
	 */
	private MappedResourceVisitor fgMRVisitor;

	/**
	 * Whether this manager is listening for resource change events
	 */
	private boolean fListening = false;

	/**
	 * Launch configuration listeners
	 */
	private ListenerList<ILaunchConfigurationListener> fLaunchConfigurationListeners = new ListenerList<>();

	/**
	 * Table of source locator extensions. Keys
	 * are identifiers, and values are associated
	 * configuration elements.
	 */
	private Map<String, IConfigurationElement> fSourceLocators = null;

	/**
	 * The handles of launch configurations being moved, or <code>null</code>
	 */
	private ILaunchConfiguration fFrom;

	private ILaunchConfiguration fTo;

	/**
	 * Map of source container type extensions. Keys are extension ids
	 * and values are associated configuration elements.
	 */
	private Map<String, ISourceContainerType> sourceContainerTypes;

	/**
	 * Map of source path computer extensions. Keys are extension ids
	 * and values are associated configuration elements.
	 */
	private Map<String, ISourcePathComputer> sourcePathComputers;

	/**
	 * TODO, we can probably remove this too
	 */
	private Set<String> fActiveModes;

	@Override
	public void addLaunch(ILaunch launch) {
		if (internalAddLaunch(launch)) {
			fireUpdate(launch, ADDED);
			fireUpdate(new ILaunch[] {launch}, ADDED);
		}
	}

	@Override
	public void addLaunchConfigurationListener(ILaunchConfigurationListener listener) {
		fLaunchConfigurationListeners.add(listener);
	}

	@Override
	public void addLaunches(ILaunch[] launches) {
		List<ILaunch> added = new ArrayList<>(launches.length);
		for (ILaunch launch : launches) {
			if (internalAddLaunch(launch)) {
				added.add(launch);
			}
		}
		if (!added.isEmpty()) {
			ILaunch[] addedLaunches = added.toArray(new ILaunch[added.size()]);
			fireUpdate(addedLaunches, ADDED);
			for (int i = 0; i < addedLaunches.length; i++) {
				fireUpdate(launches[i], ADDED);
			}
		}
	}

	@Override
	public void addLaunchListener(ILaunchesListener listener) {
		fLaunchesListeners.add(listener);
	}

	@Override
	public void addLaunchListener(ILaunchListener listener) {
		fListeners.add(listener);
	}

	/**
	 * Computes and caches the native system environment variables as a map of
	 * variable names and values (Strings) in the given map.
	 * <p>
	 * Note that WIN32 system environment preserves
	 * the case of variable names but is otherwise case insensitive.
	 * Depending on what you intend to do with the environment, the
	 * lack of normalization may or may not be create problems. This
	 * method preserves mixed-case keys using the variable names
	 * recorded by the OS.
	 * </p>
	 * @param cache the map
	 * @since 3.1
	 */
	private void cacheNativeEnvironment(Map<String, String> cache) {
		try {
			String nativeCommand= null;
			boolean isWin9xME= false; //see bug 50567
			String fileName= null;
			if (Platform.getOS().equals(Constants.OS_WIN32)) {
				String osName= System.getProperty("os.name"); //$NON-NLS-1$
				isWin9xME= osName != null && (osName.startsWith("Windows 9") || osName.startsWith("Windows ME")); //$NON-NLS-1$ //$NON-NLS-2$
				if (isWin9xME) {
					// Win 95, 98, and ME
					// SET might not return therefore we pipe into a file
					IPath stateLocation= DebugPlugin.getDefault().getStateLocation();
					fileName= stateLocation.toOSString() + File.separator  + "env.txt"; //$NON-NLS-1$
					nativeCommand= "command.com /C set > " + fileName; //$NON-NLS-1$
				} else {
					// Win NT, 2K, XP
					nativeCommand= "cmd.exe /C set"; //$NON-NLS-1$
				}
			} else if (!Platform.getOS().equals(Constants.OS_UNKNOWN)){
				nativeCommand= "env";		 //$NON-NLS-1$
			}
			if (nativeCommand == null) {
				return;
			}
			Process process= Runtime.getRuntime().exec(nativeCommand);
			if (isWin9xME) {
				//read piped data on Win 95, 98, and ME
				Properties p= new Properties();
				File file= new File(fileName);
				try(InputStream stream = new BufferedInputStream(new FileInputStream(file))){
					p.load(stream);
					if (!file.delete()) {
						file.deleteOnExit(); // if delete() fails try again on VM close
					}
					for (Entry<Object, Object> entry : p.entrySet()) {
						// Win32's environment variables are case insensitive. Put everything
						// to uppercase so that (for example) the "PATH" variable will match
						// "pAtH" correctly on Windows.
						String key = (String) entry.getKey();
						//no need to cast value
						cache.put(key, (String) p.get(key));
					}
				}
			} else {
				//read process directly on other platforms
				//we need to parse out matching '{' and '}' for function declarations in .bash environments
				// pattern is [func name]=() { and we must find the '}' on its own line with no trailing ';'
				try (InputStream stream = process.getInputStream();
				InputStreamReader isreader = new InputStreamReader(stream);
				BufferedReader reader = new BufferedReader(isreader)) {
					String line = reader.readLine();
					String key = null;
					String value = null;
					String newLine = System.lineSeparator();
					while (line != null) {
						int func = line.indexOf("=()"); //$NON-NLS-1$
						if (func > 0) {
							key = line.substring(0, func);
							// scan until we find the closing '}' with no
							// following chars
							value = line.substring(func + 1);
							while (line != null && !line.equals("}")) { //$NON-NLS-1$
								line = reader.readLine();
								if (line != null) {
									value += newLine + line;
								}
							}
							line = reader.readLine();
						}
						else {
							int separator = line.indexOf('=');
							if (separator > 0) {
								key = line.substring(0, separator);
								value = line.substring(separator + 1);
								line = reader.readLine();
								if (line != null) {
									// this line has a '=' read ahead to check
									// next line for '=', might be broken on
									// more than one line
									// also if line starts with non-identifier -
									// it is remainder of previous variable
									while (line.indexOf('=') < 0 || (line.length() > 0 && !Character.isJavaIdentifierStart(line.charAt(0)))) {
										value += newLine + line;
										line = reader.readLine();
										if (line == null) {
											// if next line read is the end of
											// the file quit the loop
											break;
										}
									}
								}
							}
						}
						if (key != null) {
							cache.put(key, value);
							key = null;
							value = null;
						} else {
							line = reader.readLine();
						}
					}
				}
			}
		} catch (IOException e) {
			// Native environment-fetching code failed.
			// This can easily happen and is not useful to log.
		}
	}

	/**
	 * Clears all launch configurations (if any have been accessed)
	 */
	private void clearAllLaunchConfigurations() {
		if (fLaunchConfigurationTypes != null) {
			fLaunchConfigurationTypes.clear();
		}
		if (fLaunchConfigurationIndex != null) {
			fLaunchConfigurationIndex.clear();
		}
	}

	@Override
	public String getEncoding(ILaunchConfiguration configuration) throws CoreException {
		String encoding = configuration.getAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING, (String)null);
		if(encoding == null) {
			IResource[] resources = configuration.getMappedResources();
			if(resources != null && resources.length > 0) {
				IResource res = resources[0];
				if(res instanceof IFile) {
					return ((IFile)res).getCharset();
				}
				else if(res instanceof IContainer) {
					return ((IContainer)res).getDefaultCharset();
				}
			}
			else {
				return ResourcesPlugin.getEncoding();
			}
		}
		return encoding;
	}

	/**
	 * The launch config name cache is cleared when a config is added, deleted or changed.
	 */
	protected synchronized void clearConfigNameCache() {
		fSortedConfigNames = null;
	}

	/**
	 * Return an instance of DebugException containing the specified message and Throwable.
	 * @param message the message for the new {@link DebugException}
	 * @param throwable the underlying {@link Exception}
	 * @return the new {@link DebugException}
	 */
	protected DebugException createDebugException(String message, Throwable throwable) {
		return new DebugException(
					new Status(
					 IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
					 DebugException.REQUEST_FAILED, message, throwable
					)
				);
	}

	/**
	 * Return a LaunchConfigurationInfo object initialized from XML contained in
	 * the specified stream.  Simply pass out any exceptions encountered so that
	 * caller can deal with them.  This is important since caller may need access to the
	 * actual exception.
	 *
	 * @param stream the {@link InputStream} to read from
	 * @return the new {@link LaunchConfigurationInfo}
	 * @throws CoreException if a problem is encountered
	 * @throws ParserConfigurationException if the stream fails to parse
	 * @throws IOException if there is a problem handling the given stream or writing the new info file
	 * @throws SAXException if there is a SAX parse exception
	 */
	protected LaunchConfigurationInfo createInfoFromXML(InputStream stream) throws CoreException,
																			 ParserConfigurationException,
																			 IOException,
																			 SAXException {
		return createInfoFromXML(stream, false);
	}

	/**
	 * Return a LaunchConfigurationInfo object initialized from XML contained in
	 * the specified stream. Simply pass out any exceptions encountered so that
	 * caller can deal with them. This is important since caller may need access
	 * to the actual exception.
	 *
	 * @param stream the {@link InputStream} to read from
	 * @param isPrototype if the XML corresponds to a prototype
	 * @return the new {@link LaunchConfigurationInfo}
	 * @throws CoreException if a problem is encountered
	 * @throws ParserConfigurationException if the stream fails to parse
	 * @throws IOException if there is a problem handling the given stream or
	 *             writing the new info file
	 * @throws SAXException if there is a SAX parse exception
	 *
	 * @since 3.12
	 */
	protected LaunchConfigurationInfo createInfoFromXML(InputStream stream, boolean isPrototype) throws CoreException, ParserConfigurationException, IOException, SAXException {
		Element root = null;
		DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		parser.setErrorHandler(new DefaultHandler());
		root = parser.parse(new InputSource(stream)).getDocumentElement();
		LaunchConfigurationInfo info = new LaunchConfigurationInfo();
		info.initializeFromXML(root, isPrototype);
		return info;
	}

	/**
	 * Finds and returns all launch configurations in the given
	 * container (and sub-containers)
	 *
	 * @param container the container to search
	 * @return all launch configurations in the given container
	 */
	protected List<ILaunchConfiguration> findLaunchConfigurations(IContainer container) {
		if (container instanceof IProject && !((IProject)container).isOpen()) {
			return Collections.EMPTY_LIST;
		}
		List<IResource> list = new ArrayList<>(10);
		ResourceProxyVisitor visitor= new ResourceProxyVisitor(list);
		try {
			container.accept(visitor, IResource.NONE);
		} catch (CoreException ce) {
			//Closed project...should not be possible with previous check
		}
		List<ILaunchConfiguration> configs = new ArrayList<>(list.size());
		for (IResource resource : list) {
			ILaunchConfiguration config = getLaunchConfiguration((IFile) resource);
			if(config != null && config.exists()) {
				configs.add(config);
			}
		}
		return configs;
	}

	/**
	 * Searches for the {@link ILaunchConfiguration} with the given name
	 * @param name the name to search for
	 * @return the {@link ILaunchConfiguration} with the given name or <code>null</code>
	 * @since 3.8
	 */
	public ILaunchConfiguration findLaunchConfiguration(String name) {
		if(name != null) {
			for (ILaunchConfiguration config : getLaunchConfigurations()) {
				if(name.equals(config.getName())) {
					return config;
				}
			}
		}
		return null;
	}

	/**
	 * Finds and returns all local launch configurations.
	 *
	 * @return all local launch configurations
	 */
	protected List<ILaunchConfiguration> findLocalLaunchConfigurations() {
		IPath containerPath = LOCAL_LAUNCH_CONFIGURATION_CONTAINER_PATH;
		final File directory = containerPath.toFile();
		if (directory.isDirectory()) {
			List<ILaunchConfiguration> configs = new ArrayList<>();
			FilenameFilter configFilter = (dir, name) -> dir.equals(directory) &&
					name.endsWith(ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION);
			File[] configFiles = directory.listFiles(configFilter);
			if (configFiles != null && configFiles.length > 0) {
				LaunchConfiguration config = null;
				for (File configFile : configFiles) {
					config = new LaunchConfiguration(LaunchConfiguration.getSimpleName(configFile.getName()), null, false);
					configs.add(config);
				}
			}
			FilenameFilter prototypeFilter = (dir, name) -> dir.equals(directory) && name.endsWith(ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION);
			File[] prototypeFiles = directory.listFiles(prototypeFilter);
			if (prototypeFiles != null && prototypeFiles.length > 0) {
				LaunchConfiguration config = null;
				for (File prototypeFile : prototypeFiles) {
					config = new LaunchConfiguration(LaunchConfiguration.getSimpleName(prototypeFile.getName()), null, true);
					configs.add(config);
				}
			}
			return configs;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * Fires notification to (single) listeners that a launch has been
	 * added/changed/removed.
	 *
	 * @param launch launch that has changed
	 * @param update type of change
	 */
	public void fireUpdate(ILaunch launch, int update) {
		new LaunchNotifier().notify(launch, update);
	}

	/**
	 * Fires notification to (plural) listeners that a launch has been
	 * added/changed/removed.
	 *
	 * @param launches launches that have changed
	 * @param update type of change
	 */
	public void fireUpdate(ILaunch[] launches, int update) {
		new LaunchesNotifier().notify(launches, update);
	}

	@Override
	public String generateUniqueLaunchConfigurationNameFrom(String baseName) {
		int index = 1;
		int length = baseName.length();
		int copyIndex = baseName.lastIndexOf(" ("); //$NON-NLS-1$
		String base = baseName;
		if (copyIndex > -1 && length > copyIndex + 2 && baseName.charAt(length - 1) == ')') {
			String trailer = baseName.substring(copyIndex + 2, length - 1);
			if (isNumber(trailer)) {
				try {
					index = Integer.parseInt(trailer);
					base = baseName.substring(0, copyIndex);
				}
				catch (NumberFormatException nfe) {}
			}
		}
		String newName = base;
		while (isExistingLaunchConfigurationName(newName)) {
			newName = MessageFormat.format(DebugCoreMessages.LaunchManager_31, new Object[] {
					base, Integer.toString(index) });
			index++;
		}
		return newName;
	}

	/**
	 * Return a String that can be used as the name of a launch configuration.  The name
	 * is guaranteed to be unique (no existing or temporary launch configurations will have this name).
	 * The name that is returned uses the <code>basename</code> as a starting point.  If
	 * there is no existing launch configuration with this name, then <code>basename</code>
	 * is returned.  Otherwise, the value returned consists of the specified base plus
	 * some suffix that guarantees uniqueness. Passing <code>null</code> as the set of reserved names will cause this
	 * method to return <code>generateUniqueLaunchConfigurationNameFrom(String baseName)</code>.
	 *
	 * By specifying a set of reserved names, you can further constrain the name that will be generated
	 * by this method. For example you can give a base name of 'test' and a reserved set of [test(1), test(2)],
	 * which will result in a name of 'test(3)' being returned iff a configuration with the name 'test' already exists.
	 *
	 * @return launch configuration name
	 * @param basename the String that the returned name must begin with
	 * @param reservednames a set of strings that is further used to constrain what names can be generated
	 * @since 3.3
	 */
	public String generateUniqueLaunchConfigurationNameFrom(String basename, Set<String> reservednames) {
		if(reservednames == null) {
			return generateUniqueLaunchConfigurationNameFrom(basename);
		}
		int index = 1;
		int length= basename.length();
		String base = basename;
		int copyIndex = base.lastIndexOf(" ("); //$NON-NLS-1$
		if (copyIndex > -1 && length > copyIndex + 2 && base.charAt(length - 1) == ')') {
			String trailer = base.substring(copyIndex + 2, length -1);
			if (isNumber(trailer)) {
				try {
					index = Integer.parseInt(trailer);
					base = base.substring(0, copyIndex);
				}
				catch (NumberFormatException nfe) {}
			}
		}
		String newname = base;
		StringBuilder buffer = null;
		while (isExistingLaunchConfigurationName(newname) || reservednames.contains(newname)) {
			buffer = new StringBuilder(base);
			buffer.append(" ("); //$NON-NLS-1$
			buffer.append(String.valueOf(index));
			index++;
			buffer.append(')');
			newname = buffer.toString();
		}
		return newname;
	}

	/**
	 * Returns a collection of all launch configuration handles in
	 * the workspace. This collection is initialized lazily.
	 *
	 * @return all launch configuration handles
	 */
	public synchronized List<ILaunchConfiguration> getAllLaunchConfigurations() {
		if (fLaunchConfigurationIndex == null) {
			try {
				fLaunchConfigurationIndex = new ArrayList<>(20);
				List<ILaunchConfiguration> configs = findLocalLaunchConfigurations();
				verifyConfigurations(configs, fLaunchConfigurationIndex);
				configs = findLaunchConfigurations(ResourcesPlugin.getWorkspace().getRoot());
				verifyConfigurations(configs, fLaunchConfigurationIndex);
			} finally {
				hookResourceChangeListener();
			}
		}
		return fLaunchConfigurationIndex;
	}

	/**
	 * Return a sorted array of the names of all <code>ILaunchConfiguration</code>s in
	 * the workspace.  These are cached, and cache is cleared when a new config is added,
	 * deleted or changed.
	 * @return the sorted array of {@link ILaunchConfiguration} names
	 */
	protected synchronized String[] getAllSortedConfigNames() {
		if (fSortedConfigNames == null) {
			List<ILaunchConfiguration> collection = getAllLaunchConfigurations();
			ILaunchConfiguration[] configs = collection.toArray(new ILaunchConfiguration[collection.size()]);
			fSortedConfigNames = new String[configs.length];
			for (int i = 0; i < configs.length; i++) {
				fSortedConfigNames[i] = configs[i].getName();
			}
			Arrays.sort(fSortedConfigNames);
		}
		return fSortedConfigNames;
	}

	/**
	 * Returns the comparator registered for the given attribute, or
	 * <code>null</code> if none.
	 *
	 * @param attributeName attribute for which a comparator is required
	 * @return comparator, or <code>null</code> if none
	 */
	protected Comparator<Object> getComparator(String attributeName) {
		Map<String, LaunchConfigurationComparator> map = getComparators();
		 return map.get(attributeName);
	}

	/**
	 * Returns comparators, loading if required
	 * @return the complete map of {@link ILaunchConfiguration} {@link Comparator}s
	 */
	protected Map<String, LaunchConfigurationComparator> getComparators() {
		initializeComparators();
		return fComparators;
	}

	/**
	 * Returns the launch configurations specified by the given
	 * XML document.
	 *
	 * @param root XML document
	 * @return list of launch configurations
	 * @throws CoreException if a problem is encountered
	 */
	protected List<ILaunchConfiguration> getConfigsFromXML(Element root) throws CoreException {
		DebugException invalidFormat =
			new DebugException(
				new Status(
				 IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
				 DebugException.REQUEST_FAILED, DebugCoreMessages.LaunchManager_Invalid_launch_configuration_index__18, null
				)
			);

		if (!root.getNodeName().equalsIgnoreCase("launchConfigurations")) { //$NON-NLS-1$
			throw invalidFormat;
		}

		// read each launch configuration
		List<ILaunchConfiguration> configs = new ArrayList<>(4);
		NodeList list = root.getChildNodes();
		int length = list.getLength();
		Node node = null;
		Element entry = null;
		String memento = null;
		for (int i = 0; i < length; ++i) {
			node = list.item(i);
			short type = node.getNodeType();
			if (type == Node.ELEMENT_NODE) {
				entry = (Element) node;
				if (!entry.getNodeName().equals("launchConfiguration")) { //$NON-NLS-1$
					throw invalidFormat;
				}
				memento = entry.getAttribute("memento"); //$NON-NLS-1$
				if (memento == null) {
					throw invalidFormat;
				}
				configs.add(getLaunchConfiguration(memento));
			}
		}
		return configs;
	}

	protected ConfigurationNotifier getConfigurationNotifier() {
		return new ConfigurationNotifier();
	}

	@Override
	public IDebugTarget[] getDebugTargets() {
		synchronized (fLaunches) {
			List<IDebugTarget> allTargets = new ArrayList<>(fLaunches.size());
			IDebugTarget[] targets = null;
			for (ILaunch launch : fLaunches) {
				targets = launch.getDebugTargets();
				Collections.addAll(allTargets, targets);
			}
			return allTargets.toArray(new IDebugTarget[allTargets.size()]);
		}
	}

	/**
	 * Returns the resource delta visitor for the launch manager.
	 *
	 * @return the resource delta visitor for the launch manager
	 */
	private LaunchManagerVisitor getDeltaVisitor() {
		if (fgVisitor == null) {
			fgVisitor= new LaunchManagerVisitor();
		}
		return fgVisitor;
	}

	/**
	 * Returns the resource delta visitor for auto-removal of mapped launch configurations
	 * @return the resource delta visitor for auto-removal of mapped launch configurations
	 *
	 * @since 3.4
	 */
	private MappedResourceVisitor getMappedResourceVisitor() {
		if(fgMRVisitor == null) {
			fgMRVisitor = new MappedResourceVisitor();
		}
		return fgMRVisitor;
	}

	@Override
	public String[] getEnvironment(ILaunchConfiguration configuration) throws CoreException {
		Map<String, String> configEnv = configuration.getAttribute(ATTR_ENVIRONMENT_VARIABLES, (Map<String, String>) null);
		if (configEnv == null) {
			return null;
		}
		Map<String, String> env = new HashMap<>();
		// build base environment
		boolean append = configuration.getAttribute(ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
		if (append) {
			env.putAll(getNativeEnvironmentCasePreserved());
		}

		// Add variables from config
		boolean win32= Platform.getOS().equals(Constants.OS_WIN32);
		String key = null;
		String value = null;
		Object nativeValue = null;
		String nativeKey = null;
		for (Entry<String, String> entry : configEnv.entrySet()) {
			key = entry.getKey();
			value = entry.getValue();
			// translate any string substitution variables
			if (value != null) {
				value = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(value);
			}
			boolean added= false;
			if (win32) {
				// First, check if the key is an exact match for an existing key.
				nativeValue = env.get(key);
				if (nativeValue != null) {
					// If an exact match is found, just replace the value
					env.put(key, value);
				} else {
					// Win32 variables are case-insensitive. If an exact match isn't found, iterate to
					// check for a case-insensitive match. We maintain the key's case (see bug 86725),
					// but do a case-insensitive comparison (for example, "pAtH" will still override "PATH").
					for (Entry<String, String> nativeEntry : env.entrySet()) {
						nativeKey = (nativeEntry).getKey();
						if (nativeKey.equalsIgnoreCase(key)) {
							nativeEntry.setValue(value);
							added = true;
							break;
						}
					}
				}
			}
			if (!added) {
				env.put(key, value);
			}
		}
		List<String> strings = new ArrayList<>(env.size());
		StringBuilder buffer = null;
		for (Entry<String, String> entry : env.entrySet()) {
			buffer = new StringBuilder(entry.getKey());
			buffer.append('=').append(entry.getValue());
			strings.add(buffer.toString());
		}
		return strings.toArray(new String[strings.size()]);
	}

	/**
	 * Returns the info object for the specified launch configuration.
	 * If the configuration exists, but is not yet in the cache,
	 * an info object is built and added to the cache.
	 * @param config the {@link ILaunchConfiguration} to get the info object from
	 * @return the {@link LaunchConfigurationInfo} object from the given {@link ILaunchConfiguration}
	 *
	 * @exception CoreException if an exception occurs building
	 *  the info object
	 * @exception DebugException if the config does not exist
	 * @since 3.5
	 */
	protected LaunchConfigurationInfo getInfo(LaunchConfiguration config) throws CoreException {
		LaunchConfigurationInfo info = fLaunchConfigurations.get(config);
		if (info == null) {
			IFileStore store = config.getFileStore();
			if (config.exists()) {
				BufferedInputStream stream = null;
				try {
					stream = new BufferedInputStream(store.openInputStream(EFS.NONE, null));
					info = createInfoFromXML(stream, isPrototype(store));
					synchronized (this) {
						fLaunchConfigurations.put(config, info);
					}
				} catch (FileNotFoundException e) {
					throwException(config, e);
				} catch (SAXException e) {
					throwException(config, e);
				} catch (ParserConfigurationException e) {
					throwException(config, e);
				} catch (IOException e) {
					throwException(config, e);
				} finally {
					if (stream != null) {
						try {
							stream.close();
						} catch (IOException e) {
							throwException(config, e);
						}
					}
				}

			} else if (store != null){
				throw createDebugException(MessageFormat.format(DebugCoreMessages.LaunchManager_does_not_exist, new Object[] {
						config.getName(), store.toURI().toString() }), null);
			} else {
				throw createDebugException(MessageFormat.format(DebugCoreMessages.LaunchManager_does_not_exist_no_store_found, new Object[] { config.getName() }), null);
			}
		}
		return info;
	}

	/**
	 * Check if the given {@link IFileStore} is a prototype.
	 *
	 * @param store the given {@link IFileStore}
	 * @return <code>true</code> if the given {@link IFileStore} is a prototype,
	 *         <code>false</code> otherwise.
	 *
	 * @since 3.12
	 */
	private boolean isPrototype(IFileStore store) {
		if (store.getName().endsWith("." + ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION)) { //$NON-NLS-1$
			return true;
		}
		return false;
	}

	/**
	 * Check if the given {@link File} is a prototype.
	 *
	 * @param file the given {@link File}
	 * @return <code>true</code> if the given {@link File} is a prototype,
	 *         <code>false</code> otherwise.
	 *
	 * @since 3.12
	 */
	private boolean isPrototype(File file) {
		if (file.getName().endsWith("." + ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION)) { //$NON-NLS-1$
			return true;
		}
		return false;
	}

	@Override
	public ILaunchConfiguration getLaunchConfiguration(IFile file) {
		hookResourceChangeListener();
		return new LaunchConfiguration(file);
	}

	@Override
	public ILaunchConfiguration getLaunchConfiguration(String memento) throws CoreException {
		hookResourceChangeListener();
		return new LaunchConfiguration(memento);
	}

	@Override
	public synchronized ILaunchConfiguration[] getLaunchConfigurations() {
		return getLaunchConfigurations(ILaunchConfiguration.CONFIGURATION);
	}

	@Override
	public ILaunchConfiguration[] getLaunchConfigurations(int kinds) {
		List<ILaunchConfiguration> allConfigs = getAllLaunchConfigurations();
		if (((kinds & ILaunchConfiguration.CONFIGURATION) > 0) && ((kinds & ILaunchConfiguration.PROTOTYPE) > 0)) {
			// all kinds
			return allConfigs.toArray(new ILaunchConfiguration[allConfigs.size()]);
		} else {
			List<ILaunchConfiguration> select = new ArrayList<>(allConfigs.size());
			Iterator<ILaunchConfiguration> iterator = allConfigs.iterator();
			while (iterator.hasNext()) {
				ILaunchConfiguration config = iterator.next();
				try {
					if ((config.getKind() & kinds) > 0) {
						select.add(config);
					}
				} catch (CoreException e) {
					DebugPlugin.log(e);
				}
			}
			return select.toArray(new ILaunchConfiguration[select.size()]);
		}
	}

	@Override
	public synchronized ILaunchConfiguration[] getLaunchConfigurations(ILaunchConfigurationType type) throws CoreException {
		return getLaunchConfigurations(type, ILaunchConfiguration.CONFIGURATION);
	}

	@Override
	public synchronized ILaunchConfiguration[] getLaunchConfigurations(ILaunchConfigurationType type, int kinds) throws CoreException {
		List<ILaunchConfiguration> configs = new ArrayList<>();
		for (ILaunchConfiguration config : getAllLaunchConfigurations()) {
			if (config.getType().equals(type) && ((config.getKind() & kinds) > 0)) {
				configs.add(config);
			}
		}
		return configs.toArray(new ILaunchConfiguration[configs.size()]);
	}

	/**
	 * Returns all launch configurations that are stored as resources
	 * in the given project.
	 *
	 * @param project a project
	 * @return collection of launch configurations that are stored as resources
	 *  in the given project
	 */
	protected synchronized List<ILaunchConfiguration> getLaunchConfigurations(IProject project) {
		List<ILaunchConfiguration> configs = new ArrayList<>();
		for (ILaunchConfiguration config : getAllLaunchConfigurations()) {
			IFile file = config.getFile();
			if (file != null && file.getProject().equals(project)) {
				configs.add(config);
			}
		}
		return configs;
	}

	@Override
	public ILaunchConfigurationType getLaunchConfigurationType(String id) {
		for (ILaunchConfigurationType type : getLaunchConfigurationTypes()) {
			if (type.getIdentifier().equals(id)) {
				return type;
			}
		}
		return null;
	}

	@Override
	public ILaunchConfigurationType[] getLaunchConfigurationTypes() {
		initializeLaunchConfigurationTypes();
		return fLaunchConfigurationTypes.toArray(new ILaunchConfigurationType[fLaunchConfigurationTypes.size()]);
	}

	@Override
	public ILaunch[] getLaunches() {
		synchronized (fLaunches) {
			return fLaunches.toArray(new ILaunch[fLaunches.size()]);
		}
	}

	@Override
	public ILaunchMode getLaunchMode(String mode) {
		initializeLaunchModes();
		return fLaunchModes.get(mode);
	}

	@Override
	public ILaunchMode[] getLaunchModes() {
		initializeLaunchModes();
		Collection<ILaunchMode> collection = fLaunchModes.values();
		return collection.toArray(new ILaunchMode[collection.size()]);
	}

	/**
	 * Returns all of the launch delegates. The returned listing of delegates cannot be directly used to launch,
	 * instead the method <code>IlaunchDelegate.getDelegate</code> must be used to acquire an executable form of
	 * the delegate, allowing us to maintain lazy loading of the delegates themselves.
	 * @return all of the launch delegates
	 *
	 * @since 3.3
	 */
	public ILaunchDelegate[] getLaunchDelegates() {
		initializeLaunchDelegates();
		Collection<LaunchDelegate> col = fLaunchDelegates.values();
		return col.toArray(new ILaunchDelegate[col.size()]);
	}

	/**
	 * Returns the listing of launch delegates that apply to the specified
	 * <code>ILaunchConfigurationType</code> id
	 * @param typeid the id of the launch configuration type to get delegates for
	 * @return An array of <code>LaunchDelegate</code>s that apply to the specified launch configuration
	 * type, or an empty array, never <code>null</code>
	 *
	 * @since 3.3
	 */
	public LaunchDelegate[] getLaunchDelegates(String typeid) {
		initializeLaunchDelegates();
		ArrayList<LaunchDelegate> list = new ArrayList<>();
		for (Entry<String, LaunchDelegate> entry : fLaunchDelegates.entrySet()) {
			LaunchDelegate ld = entry.getValue();
			if (ld.getLaunchConfigurationTypeId().equals(typeid)) {
				list.add(ld);
			}
		}
		return list.toArray(new LaunchDelegate[list.size()]);
	}

	/**
	 * This method returns the <code>ILaunchDelegate</code> instance corresponding to the id
	 * of the launch delegate specified
	 * @param id the id of the <code>ILaunchDelegate</code> to find
	 * @return the <code>ILaunchDelegate</code> or <code>null</code> if not found
	 *
	 * @since 3.3
	 */
	public ILaunchDelegate getLaunchDelegate(String id) {
		if(id != null) {
			for (ILaunchDelegate delegate : getLaunchDelegates()) {
				if(id.equals(delegate.getId())) {
					return delegate;
				}
			}
		}
		return null;
	}

	/**
	 * Initializes the listing of delegates available to the launching framework
	 *
	 * @since 3.3
	 */
	private synchronized void initializeLaunchDelegates() {
		if(fLaunchDelegates == null) {
			fLaunchDelegates = new HashMap<>();
			//get all launch delegate contributions
			IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_DELEGATES);
			LaunchDelegate delegate = null;
			for (IConfigurationElement info : extensionPoint.getConfigurationElements()) {
				delegate = new LaunchDelegate(info);
				fLaunchDelegates.put(delegate.getId(), delegate);
			}
			//get all delegates from launch configuration type contributions
			extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_CONFIGURATION_TYPES);
			for (IConfigurationElement info : extensionPoint.getConfigurationElements()) {
				//must check to see if delegate is provided in contribution
				if(info.getAttribute(IConfigurationElementConstants.DELEGATE) != null) {
					delegate = new LaunchDelegate(info);
					fLaunchDelegates.put(delegate.getId(), delegate);
				}
			}
		}
	}

	/**
	 * This method is used to initialize a simple listing of all preferred delegates, which is then used by each
	 * <code>ILaunchConfigurationType</code> to find if they have preferred delegates. Once an <code>ILaunchConfigurationType</code>
	 * has used this listing to initialize its preferred delegates it will maintain changes to its preferred delegate, which are
	 * then written back to the preference store only when the launch manager shuts down.
	 * <p>
	 * This cache is not synchronized with the runtime preferred delegates stored in launch configuration types.
	 * </p>
	 * @since 3.3
	 */
	private synchronized void initializePreferredDelegates() {
		if(fPreferredDelegates == null) {
			fPreferredDelegates = new HashSet<>();
			String preferred = Platform.getPreferencesService().getString(DebugPlugin.getUniqueIdentifier(), LaunchManager.PREF_PREFERRED_DELEGATES, IInternalDebugCoreConstants.EMPTY_STRING, null);
			if(!IInternalDebugCoreConstants.EMPTY_STRING.equals(preferred)) {
				try {
					Element root = DebugPlugin.parseDocument(preferred);
					NodeList nodes = root.getElementsByTagName(IConfigurationElementConstants.DELEGATE);
					Element element = null;
					String typeid = null;
					Set<String> modeset = null;
					for(int i = 0; i < nodes.getLength(); i++) {
						element = (Element) nodes.item(i);
						String delegateid = element.getAttribute(IConfigurationElementConstants.ID);
						typeid = element.getAttribute(IConfigurationElementConstants.TYPE_ID);
						String[] modes = element.getAttribute(IConfigurationElementConstants.MODES).split(","); //$NON-NLS-1$
						modeset = new HashSet<>(Arrays.asList(modes));
						LaunchDelegate delegate = getLaunchDelegateExtension(typeid, delegateid, modeset);
						if (delegate != null) {
							//take type id, modeset, delegate and create entry
							if(!IInternalDebugCoreConstants.EMPTY_STRING.equals(typeid) && modeset != null) {
								fPreferredDelegates.add(new PreferredDelegate(delegate, typeid, modeset));
							}
						}
					}
				}
				catch (CoreException e) {DebugPlugin.log(e);}
			}
		}
	}

	/**
	 * Allows internal access to reset preferred delegates when re-importing
	 * preferences.
	 *
	 * @since 3.6
	 */
	protected void resetPreferredDelegates() {
		fPreferredDelegates = null;
	}

	/**
	 * Allows internal access to a preferred delegate for a given type and mode set
	 * @param typeid the id of the <code>ILaunchConfigurationType</code> to find a delegate for
	 * @param modes the set of modes for the delegate
	 * @return the preferred delegate for the specified type id and mode set, or <code>null</code> if none
	 *
	 * @since 3.3
	 */
	protected ILaunchDelegate getPreferredDelegate(String typeid, Set<String> modes) {
		// Retrieve preferred delegates using legacy mechanism for backward
		// compatibility.
		initializePreferredDelegates();
		for (PreferredDelegate pd : fPreferredDelegates) {
			if (pd.getModes().equals(modes) && pd.getTypeId().equals(typeid)) {
				return pd.getDelegate();
			}
		}

		// @since 3.5
		// If the legacy mechanism didn't work, try the new preference name for
		// the given launch type.
		String preferred = Platform.getPreferencesService().getString(DebugPlugin.getUniqueIdentifier(), "//" + LaunchManager.PREF_PREFERRED_DELEGATES + '/' + typeid, IInternalDebugCoreConstants.EMPTY_STRING, null); //$NON-NLS-1$
		if (preferred != null && preferred.length() != 0) {
			StringTokenizer tokenizer = new StringTokenizer(preferred, ";"); //$NON-NLS-1$
			while(tokenizer.hasMoreTokens()) {
				StringTokenizer tokenizer2 = new StringTokenizer(tokenizer.nextToken(), ","); //$NON-NLS-1$
				String delegateId = tokenizer2.nextToken();
				HashSet<String> modeset = new HashSet<>();
				while(tokenizer2.hasMoreTokens()) {
					modeset.add(tokenizer2.nextToken());
				}
				LaunchDelegate delegate = getLaunchDelegateExtension(typeid, delegateId, modeset);
				if (delegate != null && modeset.equals(modes)) {
					return delegate;
				}
			}

		}
		return null;
	}

	/**
	 * Returns the launch delegate extension that matches the given type, delegate ID, and
	 * set of modes.
	 *
	 * @param typeId Launch configuration type.
	 * @param id Launch delegate ID.
	 * @param modeset Set of modes that the launch delegate applies to.
	 * @return The launch delegate matching the specified parameters, or
	 * <code>null</code> if not found.
	 *
	 * @since 3.5
	 */
	private LaunchDelegate getLaunchDelegateExtension(String typeId, String id, Set<String> modeset) {
		for (LaunchDelegate extension : getLaunchDelegates(typeId)) {
			if(id.equals(extension.getId())) {
				List<Set<String>> modesets = extension.getModes();
				if(modesets.contains(modeset)) {
					return extension;
				}
			}
		}
		return null;
	}

	/**
	 * Returns all launch configurations that are stored locally.
	 *
	 * @return collection of launch configurations stored locally
	 */
	protected synchronized List<ILaunchConfiguration> getLocalLaunchConfigurations() {
		List<ILaunchConfiguration> configs = new ArrayList<>();
		for (ILaunchConfiguration config : getAllLaunchConfigurations()) {
			if (config.isLocal()) {
				configs.add(config);
			}
		}
		return configs;
	}

	/**
	 * Returns the launch configurations mapping to the specified resource
	 * @param resource the resource to collect mapped launch configurations for
	 * @return a list of launch configurations if found or an empty list, never null
	 * @since 3.2
	 */
	public ILaunchConfiguration[] getMappedConfigurations(IResource resource) {
		List<ILaunchConfiguration> configurations = new ArrayList<>();
		for (ILaunchConfiguration config : getAllLaunchConfigurations()) {
			try {
				IResource[] resources = config.getMappedResources();
				if(resources != null) {
					for (IResource res : resources) {
						if(res.equals(resource)) {
							configurations.add(config);
							break;
						} else if (resource.getType() == IResource.PROJECT && res.getType() == IResource.FILE){
							if (res.getProject().equals(resource)) {
								configurations.add(config);
								break;
							}
						}
					}
				}
			} catch (CoreException ce) {
				DebugPlugin.log(ce);
			}
		}
		return configurations.toArray(new ILaunchConfiguration[configurations.size()]);
	}

	@Override
	public ILaunchConfiguration[] getMigrationCandidates() throws CoreException {
		List<ILaunchConfiguration> configs = new ArrayList<>();
		for (ILaunchConfiguration config : getAllLaunchConfigurations()) {
			if (!config.isReadOnly() && config.isMigrationCandidate()) {
				configs.add(config);
			}
		}
		return configs.toArray(new ILaunchConfiguration[configs.size()]);
	}

	@Override
	public ILaunchConfiguration getMovedFrom(ILaunchConfiguration addedConfiguration) {
		if (addedConfiguration.equals(fTo)) {
			return fFrom;
		}
		return null;
	}

	@Override
	public ILaunchConfiguration getMovedTo(ILaunchConfiguration removedConfiguration) {
		if (removedConfiguration.equals(fFrom)) {
			return fTo;
		}
		return null;
	}

	@Override
	public synchronized Map<String, String> getNativeEnvironment() {
		if (fgNativeEnv == null) {
			Map<String, String> casePreserved = getNativeEnvironmentCasePreserved();
			if (Platform.getOS().equals(Constants.OS_WIN32)) {
				fgNativeEnv = new HashMap<>();
				for (Entry<String, String> entry : casePreserved.entrySet()) {
					fgNativeEnv.put(entry.getKey().toUpperCase(), entry.getValue());
				}
			} else {
				fgNativeEnv = new HashMap<>(casePreserved);
			}
		}
		return new HashMap<>(fgNativeEnv);
	}

	@Override
	public synchronized Map<String, String> getNativeEnvironmentCasePreserved() {
		if (fgNativeEnvCasePreserved == null) {
			fgNativeEnvCasePreserved = new HashMap<>();
			cacheNativeEnvironment(fgNativeEnvCasePreserved);
		}
		return new HashMap<>(fgNativeEnvCasePreserved);
	}

	@Override
	public IProcess[] getProcesses() {
		synchronized (fLaunches) {
			List<IProcess> allProcesses = new ArrayList<>(fLaunches.size());
			IProcess[] processes = null;
			for (ILaunch launch : fLaunches) {
				processes = launch.getProcesses();
				Collections.addAll(allProcesses, processes);
			}
			return allProcesses.toArray(new IProcess[allProcesses.size()]);
		}
	}

	@Override
	public ISourceContainerType getSourceContainerType(String id) {
		initializeSourceContainerTypes();
		return sourceContainerTypes.get(id);
	}

	@Override
	public ISourceContainerType[] getSourceContainerTypes() {
		initializeSourceContainerTypes();
		Collection<ISourceContainerType> containers = sourceContainerTypes.values();
		return containers.toArray(new ISourceContainerType[containers.size()]);
	}

	@Override
	public ISourcePathComputer getSourcePathComputer(ILaunchConfiguration configuration) throws CoreException {
		String id = null;
		id = configuration.getAttribute(ISourcePathComputer.ATTR_SOURCE_PATH_COMPUTER_ID, (String)null);

		if (id == null) {
			//use default computer for configuration type, if any
			return configuration.getType().getSourcePathComputer();
		}
		return getSourcePathComputer(id);
	}

	@Override
	public ISourcePathComputer getSourcePathComputer(String id) {
		initializeSourceContainerTypes();
		return sourcePathComputers.get(id);
	}

	/**
	 * Starts listening for resource change events
	 */
	private synchronized void hookResourceChangeListener() {
		if (!fListening) {
			ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE);
			fListening = true;
		}
	}

	/**
	 * Load comparator extensions.
	 */
	private synchronized void initializeComparators() {
		if (fComparators == null) {
			IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_CONFIGURATION_COMPARATORS);
			IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
			fComparators = new HashMap<>(infos.length);
			IConfigurationElement configurationElement = null;
			String attr = null;
			for (IConfigurationElement info : infos) {
				configurationElement = info;
				attr = configurationElement.getAttribute("attribute"); //$NON-NLS-1$
				if (attr != null) {
					fComparators.put(attr, new LaunchConfigurationComparator(configurationElement));
				} else {
					// invalid status handler
					IStatus s = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.INTERNAL_ERROR,
							MessageFormat.format("Invalid launch configuration comparator extension defined by plug-in {0} - attribute not specified.", configurationElement.getContributor().getName()), null); //$NON-NLS-1$
					DebugPlugin.log(s);
				}
			}
		}
	}

	/**
	 * Initializes the listing of <code>LaunchConfigurationType</code>s.
	 */
	private synchronized void initializeLaunchConfigurationTypes() {
		if (fLaunchConfigurationTypes == null) {
			hookResourceChangeListener();
			IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_CONFIGURATION_TYPES);
			IConfigurationElement[] infos = extensionPoint.getConfigurationElements();
			fLaunchConfigurationTypes = new ArrayList<>(infos.length);
			for (IConfigurationElement info : infos) {
				fLaunchConfigurationTypes.add(new LaunchConfigurationType(info));
			}
		}
	}

	/**
	 * Load comparator extensions.
	 */
	private synchronized void initializeLaunchModes() {
		if (fLaunchModes == null) {
			try {
				IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_MODES);
				IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
				fLaunchModes = new HashMap<>();
				ILaunchMode mode = null;
				for (IConfigurationElement info : infos) {
					mode = new LaunchMode(info);
					fLaunchModes.put(mode.getIdentifier(), mode);
				}
			}
			catch (CoreException e) {DebugPlugin.log(e);}
		}
	}

	/**
	 * Initializes source container type and source path computer extensions.
	 */
	private synchronized void initializeSourceContainerTypes() {
		if (sourceContainerTypes == null) {
			IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_SOURCE_CONTAINER_TYPES);
			IConfigurationElement[] extensions = extensionPoint.getConfigurationElements();
			sourceContainerTypes = new HashMap<>();
			for (IConfigurationElement extension : extensions) {
				sourceContainerTypes.put(
						extension.getAttribute(IConfigurationElementConstants.ID),
						new SourceContainerType(extension));
			}
			extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_SOURCE_PATH_COMPUTERS);
			extensions = extensionPoint.getConfigurationElements();
			sourcePathComputers = new HashMap<>();
			for (IConfigurationElement extension : extensions) {
				sourcePathComputers.put(
						extension.getAttribute(IConfigurationElementConstants.ID),
						new SourcePathComputer(extension));
			}
		}
	}

	/**
	 * Register source locators.
	 */
	private synchronized void initializeSourceLocators() {
		if (fSourceLocators == null) {
			IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_SOURCE_LOCATORS);
			IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
			fSourceLocators = new HashMap<>(infos.length);
			IConfigurationElement configurationElement = null;
			String id = null;
			for (IConfigurationElement info : infos) {
				configurationElement = info;
				id = configurationElement.getAttribute(IConfigurationElementConstants.ID);
				if (id != null) {
					fSourceLocators.put(id,configurationElement);
				} else {
					// invalid status handler
					IStatus s = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.INTERNAL_ERROR,
							MessageFormat.format("Invalid source locator extension defined by plug-in \"{0}\": \"id\" not specified.", configurationElement.getContributor().getName()), null); //$NON-NLS-1$
					DebugPlugin.log(s);
				}
			}
		}
	}

	/**
	 * Adds the given launch object to the list of registered launches,
	 * and returns whether the launch was added.
	 *
	 * @param launch launch to register
	 * @return whether the launch was added
	 */
	protected boolean internalAddLaunch(ILaunch launch) {
		// ensure the step filter manager is created on the first launch
		getStepFilterManager();
		synchronized (fLaunches) {
			if (fLaunches.contains(launch)) {
				return false;
			}
			fLaunches.add(launch);
			fLaunchSet.add(launch);
			return true;
		}
	}

	/**
	 * Removes the given launch object from the collection of registered
	 * launches. Returns whether the launch was removed.
	 *
	 * @param launch the launch to remove
	 * @return whether the launch was removed
	 */
	protected boolean internalRemoveLaunch(ILaunch launch) {
		if (launch == null) {
			return false;
		}
		synchronized (fLaunches) {
			fLaunchSet.remove(launch);
			return fLaunches.remove(launch);
		}
	}

	@Override
	public boolean isExistingLaunchConfigurationName(String name) {
		String[] sortedConfigNames = getAllSortedConfigNames();
		int index = Arrays.binarySearch(sortedConfigNames, name);
		if (index < 0) {
			return false;
		}
		return true;
	}

	/**
	 * Returns whether the given String is composed solely of digits
	 * @param string the {@link String} to check
	 * @return <code>true</code> if the given {@link String} is a number <code>false</code> otherwise
	 */
	private boolean isNumber(String string) {
		int numChars= string.length();
		if (numChars == 0) {
			return false;
		}
		for (int i= 0; i < numChars; i++) {
			if (!Character.isDigit(string.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Returns whether the user has selected to delete associated configurations when a
	 * project is deleted.
	 *
	 * @return whether to auto-delete configurations
	 */
	private boolean isDeleteConfigurations() {
		return Platform.getPreferencesService().getBoolean(DebugPlugin.getUniqueIdentifier(), DebugPlugin.PREF_DELETE_CONFIGS_ON_PROJECT_DELETE, true, null);
	}

	@Override
	public boolean isRegistered(ILaunch launch) {
		synchronized (fLaunches) {
			return fLaunchSet.contains(launch);
		}
	}

	/**
	 * Returns whether the given launch configuration passes a basic
	 * integrity test by retrieving its type.
	 *
	 * @param config the configuration to verify
	 * @return whether the config meets basic integrity constraints
	 */
	protected boolean isValid(ILaunchConfiguration config) {
		try {
			config.getType();
		} catch (CoreException e) {
			if (e.getStatus().getCode() != DebugException.MISSING_LAUNCH_CONFIGURATION_TYPE) {
				// only log warnings due to something other than a missing
				// launch config type
				DebugPlugin.log(e);
			}
			return false;
		}
		return true;
	}

	/**
	 * Notifies the launch manager that a launch configuration
	 * has been added. The configuration is added to the index of
	 * configurations by project, and listeners are notified.
	 *
	 * @param config the launch configuration that was added
	 */
	protected void launchConfigurationAdded(ILaunchConfiguration config) {
		if (config.isWorkingCopy()) {
			return;
		}
		if (isValid(config)) {
			boolean added = false;
			synchronized (this) {
				List<ILaunchConfiguration> allConfigs = getAllLaunchConfigurations();
				if (!allConfigs.contains(config)) {
					allConfigs.add(config);
					added = true;
				}
			}
			if (added) {
				getConfigurationNotifier().notify(config, ADDED);
				clearConfigNameCache();
			}
		} else {
			launchConfigurationDeleted(config);
		}
	}

	/**
	 * Notifies the launch manager that a launch configuration
	 * has been changed. The configuration is removed from the
	 * cache of info objects such that the new attributes will
	 * be updated on the next access. Listeners are notified of
	 * the change.
	 *
	 * @param config the launch configuration that was changed
	 */
	protected void launchConfigurationChanged(ILaunchConfiguration config) {
		synchronized(this) {
			fLaunchConfigurations.remove(config);
		}
		clearConfigNameCache();
		if (isValid(config)) {
			// in case the config has been refreshed and it was removed from the
			// index due to 'out of synch with local file system' (see bug 36147),
			// add it back (will only add if required)
			launchConfigurationAdded(config);
			getConfigurationNotifier().notify(config, CHANGED);
		} else {
			launchConfigurationDeleted(config);
		}
	}

	/**
	 * Notifies the launch manager that a launch configuration
	 * has been deleted. The configuration is removed from the
	 * cache of info and from the index of configurations by
	 * project, and listeners are notified.
	 *
	 * @param config the launch configuration that was deleted
	 */
	protected void launchConfigurationDeleted(ILaunchConfiguration config) {
		boolean removed = false;
		synchronized (this) {
			Object key = fLaunchConfigurations.remove(config);
			removed = key != null;
			getAllLaunchConfigurations().remove(config);
		}
		if (removed) {
			getConfigurationNotifier().notify(config, REMOVED);
			clearConfigNameCache();
		}
	}

	@Override
	public IPersistableSourceLocator newSourceLocator(String identifier) throws CoreException {
		initializeSourceLocators();
		IConfigurationElement config = fSourceLocators.get(identifier);
		if (config == null) {
			throw new CoreException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.INTERNAL_ERROR,
 MessageFormat.format(DebugCoreMessages.LaunchManager_Source_locator_does_not_exist___0__13, new Object[] { identifier }), null));
		}
		IPersistableSourceLocator sourceLocator = (IPersistableSourceLocator)config.createExecutableExtension("class"); //$NON-NLS-1$
		if (sourceLocator instanceof AbstractSourceLookupDirector) {
			((AbstractSourceLookupDirector)sourceLocator).setId(identifier);
		}
		return sourceLocator;
	}

	/**
	 * The specified project has just closed - remove its
	 * launch configurations from the cached index.
	 *
	 * @param project the project that has been closed
	 */
	protected void projectClosed(IProject project) {
		// bug 12134
		terminateMappedConfigurations(project);
		for (ILaunchConfiguration config : getLaunchConfigurations(project)) {
			launchConfigurationDeleted(config);
		}

	}

	/**
	 * The specified project has just opened - add all launch
	 * configs in the project to the index of all configs.
	 *
	 * @param project the project that has been opened
	 */
	protected void projectOpened(IProject project) {
		for (ILaunchConfiguration config : findLaunchConfigurations(project)) {
			launchConfigurationAdded(config);
		}
	}

	@Override
	public void removeLaunch(final ILaunch launch) {
		if (internalRemoveLaunch(launch)) {
			fireUpdate(launch, REMOVED);
			fireUpdate(new ILaunch[] {launch}, REMOVED);
		}
	}

	@Override
	public void removeLaunchConfigurationListener(ILaunchConfigurationListener listener) {
		fLaunchConfigurationListeners.remove(listener);
	}

	@Override
	public void removeLaunches(ILaunch[] launches) {
		List<ILaunch> removed = new ArrayList<>(launches.length);
		for (ILaunch launch : launches) {
			if (internalRemoveLaunch(launch)) {
				removed.add(launch);
			}
		}
		if (!removed.isEmpty()) {
			ILaunch[] removedLaunches = removed.toArray(new ILaunch[removed.size()]);
			fireUpdate(removedLaunches, REMOVED);
			for (ILaunch launch : removedLaunches) {
				fireUpdate(launch, REMOVED);
			}
		}
	}

	@Override
	public void removeLaunchListener(ILaunchesListener listener) {
		fLaunchesListeners.remove(listener);
	}

	@Override
	public void removeLaunchListener(ILaunchListener listener) {
		fListeners.remove(listener);
	}

	/**
	 * Traverses the delta looking for added/removed/changed launch
	 * configuration files.
	 *
	 * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
	 */
	@Override
	public void resourceChanged(IResourceChangeEvent event) {
		IResourceDelta delta = event.getDelta();
		if (delta != null) {
			LaunchManagerVisitor visitor = getDeltaVisitor();
			MappedResourceVisitor v = null;
			if (isDeleteConfigurations()) {
				v = getMappedResourceVisitor();
			}
			try {
				delta.accept(visitor);
				if (v != null) {
					delta.accept(v);
				}
			} catch (CoreException e) {
				DebugPlugin.log(e.getStatus());
			}
		}
	}

	/**
	 * Gets the launch configuration associated with the specified <code>IResource</code>.
	 * This method relies on the resource mapping existing, if no such mapping
	 * exists the launch configuration is ignored.
	 *
	 * @param resource the resource to collect launch configurations for
	 * @return the list of associated launch configurations
	 */
	private ArrayList<ILaunchConfiguration> collectAssociatedLaunches(IResource resource) {
		ArrayList<ILaunchConfiguration> list = new ArrayList<>();
		try {
			ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
			IResource[] resources = null;
			for (ILaunchConfiguration config : configs) {
				if(config.isLocal()) {
					resources = config.getMappedResources();
					if(resources != null) {
						for (IResource res : resources) {
							if(resource.equals(res) ||
									resource.getFullPath().isPrefixOf(res.getFullPath())) {
								list.add(config);
								break;
							}
						}
					}
				}
			}
		} catch (CoreException e) {
			DebugPlugin.log(e);
		}
		return list;
	}

	/**
	 * Indicates the given launch configuration is being moved from the given
	 * location to the new location.
	 *
	 * @param from the location a launch configuration is being moved from, or
	 * <code>null</code>
	 * @param to the location a launch configuration is being moved to,
	 * or <code>null</code>
	 */
	protected void setMovedFromTo(ILaunchConfiguration from, ILaunchConfiguration to) {
		fFrom = from;
		fTo = to;
	}
	/**
	 * Terminates/Disconnects any active debug targets/processes.
	 * Clears launch configuration types.
	 */
	public void shutdown() {
		fListeners = new ListenerList<>();
		fLaunchesListeners = new ListenerList<>();
		fLaunchConfigurationListeners = new ListenerList<>();
		for (ILaunch launch : getLaunches()) {
			if(launch != null) {
				try {
					if (launch instanceof IDisconnect) {
						IDisconnect disconnect = (IDisconnect)launch;
						if (disconnect.canDisconnect()) {
							disconnect.disconnect();
						}
					}
					if (launch.canTerminate()) {
						launch.terminate();
					}
				} catch (DebugException e) {
					DebugPlugin.log(e);
				}
			}
		}

		persistPreferredLaunchDelegates();
		clearAllLaunchConfigurations();
		fStepFilterManager = null;
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
	}

	/**
	 * Saves the listings of preferred launch delegates from all of the launch configuration types
	 *
	 * @since 3.3
	 */
	public void persistPreferredLaunchDelegates() {
		ILaunchConfigurationType[] types = getLaunchConfigurationTypes();
		for (ILaunchConfigurationType type : types) {
			persistPreferredLaunchDelegate((LaunchConfigurationType)type);
		}
	}

	/**
	 * Persists the given launch configuration delegate.
	 * @param type Launch configuration type to persist
	 *
	 * @since 3.6
	 */
	public void persistPreferredLaunchDelegate(LaunchConfigurationType type) {
		String preferenceName = PREF_PREFERRED_DELEGATES + '/' + type.getIdentifier();
		Map<Set<String>, ILaunchDelegate> preferred = type.getPreferredDelegates();
		if(preferred != null && preferred.size() > 0) {
			StringBuilder str = new StringBuilder();
			for (Entry<Set<String>, ILaunchDelegate> entry : preferred.entrySet()) {
				Set<String> modes = entry.getKey();
				ILaunchDelegate delegate = entry.getValue();
				if (delegate != null) {
					str.append(delegate.getId());
					str.append(',');
					for (String mode : modes) {
						str.append(mode).append(',');
					}
					str.append(';');
				}
			}
			Preferences.setString(DebugPlugin.getUniqueIdentifier(), preferenceName, str.toString(), null);
		} else {
			Preferences.setToDefault(DebugPlugin.getUniqueIdentifier(), preferenceName);
		}

		// Reset the legacy preference string.
		Preferences.setToDefault(DebugPlugin.getUniqueIdentifier(), PREF_PREFERRED_DELEGATES);
	}

	/**
	 * finds and terminates any running launch configurations associated with the given resource
	 * @param resource the resource to search for launch configurations and hence launches for
	 * @since 3.2
	 */
	protected void terminateMappedConfigurations(IResource resource) {
		ILaunch[] launches = getLaunches();
		ILaunchConfiguration[] configs = getMappedConfigurations(resource);
		try {
			for (ILaunch launch : launches) {
				for (ILaunchConfiguration config : configs) {
					if (config.equals(launch.getLaunchConfiguration()) && launch.canTerminate()) {
						launch.terminate();
					}
				}
			}
		}
		catch(CoreException e) {DebugPlugin.log(e);}
	}

	/**
	 * Throws a debug exception with the given throwable that occurred
	 * while processing the given configuration.
	 * @param config the {@link ILaunchConfiguration} causing the exception
	 * @param e the {@link Exception} to throw
	 * @throws DebugException the new {@link DebugException} wrapping the given {@link Exception} and {@link ILaunchConfiguration}
	 * @since 3.5
	 */
	private void throwException(LaunchConfiguration config, Throwable e) throws DebugException {
		String uri = config.getName();
		try {
			IFileStore store = config.getFileStore();
			if (store != null) {
				uri = store.toString();
			}
		} catch (CoreException ce) {
		}
		throw createDebugException(MessageFormat.format(DebugCoreMessages.LaunchManager__0__occurred_while_reading_launch_configuration_file__1___1, new Object[] {
				e.toString(), uri }), e);
	}

	/**
	 * Verify basic integrity of launch configurations in the given list,
	 * adding valid configurations to the collection of all launch configurations.
	 * Exceptions are logged for invalid configurations.
	 *
	 * @param verify the list of configurations to verify
	 * @param valid the list to place valid configurations in
	 */
	protected void verifyConfigurations(List<ILaunchConfiguration> verify, List<ILaunchConfiguration> valid) {
		for (ILaunchConfiguration config : verify) {
			if (!valid.contains(config) && isValid(config)) {
				valid.add(config);
			}
		}
	}

	/**
	 * Returns the name of the given launch mode with accelerators removed,
	 * or <code>null</code> if none.
	 *
	 * @param id launch mode identifier
	 * @return launch mode name with accelerators removed or <code>null</code>
	 */
	public String getLaunchModeName(String id) {
		ILaunchMode launchMode = getLaunchMode(id);
		if (launchMode != null) {
			return removeAccelerators(launchMode.getLabel());
		}
		return null;
	}
	/**
	 * Returns the label with any accelerators removed.
	 *
	 * @param label label to process
	 * @return label without accelerators
	 */
	public static String removeAccelerators(String label) {
		String title = label;
		if (title != null) {
			// strip out any '&' (accelerators)
			int index = title.indexOf('&');
			if (index == 0) {
				title = title.substring(1);
			} else if (index > 0) {
				//DBCS languages use "(&X)" format
				if (title.charAt(index - 1) == '(' && title.length() >= index + 3 && title.charAt(index + 2) == ')') {
					String first = title.substring(0, index - 1);
					String last = title.substring(index + 3);
					title = first + last;
				} else if (index < (title.length() - 1)) {
					String first = title.substring(0, index);
					String last = title.substring(index + 1);
					title = first + last;
				}
			}
		}
		return title;
	}

	/**
	 * Returns the singleton step filter manager.
	 *
	 * @return the step filter manager
	 */
	public synchronized StepFilterManager getStepFilterManager() {
		if (fStepFilterManager == null) {
			fStepFilterManager = new StepFilterManager();
		}
		return fStepFilterManager;
	}

	/**
	 * Imports launch configurations represented by the given local files, overwriting
	 * any existing configurations. Sends launch configuration change notification
	 * as required (i.e. added or changed).
	 * <p>
	 * If a file is imported that has the same name as a configuration in the workspace
	 * (i.e. a shared configuration), the shared configuration is deleted (becomes local).
	 * </p>
	 * @param files files to import
	 * @param monitor progress monitor or <code>null</code>
	 * @throws CoreException if an exception occurs while importing configurations
	 * @since 3.4.0
	 */
	public void importConfigurations(File[] files, IProgressMonitor monitor) throws CoreException {
		Map<String, ILaunchConfiguration> sharedConfigs = new HashMap<>();
		for (ILaunchConfiguration config : getAllLaunchConfigurations()) {
			if (!config.isLocal()) {
				StringBuilder buf = new StringBuilder(config.getName());
				buf.append('.');
				if (config.isPrototype()) {
					buf.append(ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION);
				} else {
					buf.append(ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION);
				}
				sharedConfigs.put(buf.toString(), config);
			}
		}
		List<Status> stati = null;
		SubMonitor lmonitor = SubMonitor.convert(monitor, DebugCoreMessages.LaunchManager_29, files.length);
		for (File source : files) {
			if (lmonitor.isCanceled()) {
				break;
			}
			lmonitor.subTask(MessageFormat.format(DebugCoreMessages.LaunchManager_28, new Object[] { source.getName() }));
			IPath location = new Path(LOCAL_LAUNCH_CONFIGURATION_CONTAINER_PATH.toOSString()).append(source.getName());
			File target = location.toFile();
			IPath locationdir = location.removeLastSegments(1);
			if(!locationdir.toFile().exists()) {
				locationdir.toFile().mkdirs();
			}
			boolean added = !target.exists();
			try {
				copyFile(source, target);
				ILaunchConfiguration configuration = new LaunchConfiguration(LaunchConfiguration.getSimpleName(source.getName()), null, isPrototype(source));
				ILaunchConfiguration shared = sharedConfigs.get(target.getName());
				if (shared != null) {
					setMovedFromTo(shared, configuration);
					shared.delete();
					launchConfigurationChanged(configuration);
				} else if (added) {
					launchConfigurationAdded(configuration);
				} else {
					launchConfigurationChanged(configuration);
				}
			} catch (IOException e) {
				if (stati == null) {
					stati = new ArrayList<>();
				}
				stati.add(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR,
						MessageFormat.format(DebugCoreMessages.LaunchManager_27, source.getPath()), e));
			}
			lmonitor.worked(1);
		}
		if (!lmonitor.isCanceled()) {
			lmonitor.done();
		}
		if (stati != null) {
			if (stati.size() > 1) {
				MultiStatus multi = new MultiStatus(DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR, DebugCoreMessages.LaunchManager_26, null);
				for (Status status : stati) {
					multi.add(status);
				}
				throw new CoreException(multi);
			} else {
				throw new CoreException(stati.get(0));
			}
		}
	}

	/**
	 * Copies a file from one location to another, replacing any existing file.
	 *
	 * @param in the file to copy
	 * @param out the file to be copied out to
	 * @throws IOException if the file read fails
	 * @since 3.4.0
	 */
	private void copyFile(File in, File out) throws IOException {
		try (FileInputStream fis = new FileInputStream(in); FileOutputStream fos = new FileOutputStream(out)) {
			byte[] buf = new byte[1024];
			int i = 0;
			while ((i = fis.read(buf)) != -1) {
				fos.write(buf, 0, i);
			}
		}
	}

	/**
	 * Returns whether any launch config supports the given mode.
	 *
	 * @param mode launch mode
	 * @return whether any launch config supports the given mode
	 */
	public synchronized boolean launchModeAvailable(String mode) {
		if (fActiveModes == null) {
			fActiveModes = new HashSet<>(3);
			for (ILaunchConfigurationType type : getLaunchConfigurationTypes()) {
				for (ILaunchMode launchMode : getLaunchModes()) {
					if (type.supportsMode(launchMode.getIdentifier())) {
						fActiveModes.add(launchMode.getIdentifier());
					}
				}
			}
		}
		return fActiveModes.contains(mode);
	}

	@Override
	public String generateLaunchConfigurationName(String namePrefix) {
		String name = generateUniqueLaunchConfigurationNameFrom(namePrefix);
		try {
			isValidLaunchConfigurationName(name);
			return name;
		}
		catch(IllegalArgumentException iae) {
			//blanket change all reserved names
			if(Platform.OS_WIN32.equals(Platform.getOS())) {
				for (String element : UNSUPPORTED_WIN32_CONFIG_NAMES) {
					if(element.equals(name)) {
						name = "launch_configuration"; //$NON-NLS-1$
					}
				}
			}
			//blanket replace all invalid chars
			for (char element : DISALLOWED_CONFIG_NAME_CHARS) {
				name = name.replace(element, '_');
			}
		}
		//run it through the generator once more in case a replaced name has already been done
		return generateUniqueLaunchConfigurationNameFrom(name);
	}

	@Override
	public boolean isValidLaunchConfigurationName(String configname) throws IllegalArgumentException {
		if(Platform.OS_WIN32.equals(Platform.getOS())) {
			for (String element : UNSUPPORTED_WIN32_CONFIG_NAMES) {
				if(configname.equals(element)) {
					throw new IllegalArgumentException(MessageFormat.format(DebugCoreMessages.LaunchManager_invalid_config_name, new Object[] { configname }));
				}
			}
		}
		for (char element : DISALLOWED_CONFIG_NAME_CHARS) {
			if (configname.indexOf(element) > -1) {
				throw new IllegalArgumentException(MessageFormat.format(DebugCoreMessages.LaunchManager_invalid_config_name_char, new Object[] { String.valueOf(element) }));
			}
		}
		return true;
	}

}
