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

	public LaunchManager() {
		getAllLaunchConfigurations();
	}

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

}
