/*******************************************************************************
 * 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.
	 */
	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
	 */
	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;
	}

}
