/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *******************************************************************************/
package org.eclipse.debug.internal.ui.launchConfigurations;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
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.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchDelegate;
import org.eclipse.debug.core.ILaunchListener;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.internal.core.IConfigurationElementConstants;
import org.eclipse.debug.internal.core.LaunchManager;
import org.eclipse.debug.internal.ui.DebugPluginImages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.ILaunchHistoryChangedListener;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.debug.ui.ILaunchGroup;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.activities.IWorkbenchActivitySupport;
import org.eclipse.ui.activities.WorkbenchActivityHelper;
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 UI related launch configuration artifacts
 *
 * Since 3.3 the Launch Configuration Manager is an <code>ISaveParticipant</code>, allowing it to participate in
 * workspace persistence life-cycles.
 *
 * @see ISaveParticipant
 * @see org.eclipse.debug.ui.ILaunchShortcut
 * @see ILaunchGroup
 * @see ILaunchListener
 * @see ILaunchHistoryChangedListener
 * @see DebugUIPlugin
 * @see LaunchHistory
 */
public class LaunchConfigurationManager implements ILaunchListener, ISaveParticipant {
	/**
	 * A comparator for the ordering of launch shortcut extensions
	 * @since 3.3
	 */
	static class ShortcutComparator implements Comparator<LaunchShortcutExtension> {
		/**
		 * @see Comparator#compare(Object, Object)
		 */
		@Override
		public int compare(LaunchShortcutExtension a, LaunchShortcutExtension b) {
			LaunchShortcutExtension shorcutA = a;
			String labelA = shorcutA.getLabel();
			String pathA = shorcutA.getMenuPath();
			LaunchShortcutExtension shortcutB = b;
			String labelB = shortcutB.getLabel();
			String pathB = shortcutB.getMenuPath();

			// group by path, then sort by label
			// a null path sorts last (i.e. highest)
			if (nullOrEqual(pathA, pathB)) {
				// null labels sort last (i.e. highest)
				if (labelA == labelB) {
					return 0;
				}
				if (labelA == null) {
					return 1;
				}
				if (labelB == null) {
					return -1;
				}
				return labelA.compareToIgnoreCase(labelB);
			}
			// compare paths
			if (pathA == null) {
				return 1;
			}
			if (pathB == null) {
				return -1;
			}
			return pathA.compareToIgnoreCase(pathB);
		}

		private boolean nullOrEqual(String a, String b) {
			if (a == null) {
				return b == null;
			}
			return a.equals(b);
		}

	}

	/**
	 * Launch group extensions, keyed by launch group identifier.
	 */
	protected Map<String, LaunchGroupExtension> fLaunchGroups;

	/**
	 * Launch histories keyed by launch group identifier
	 */
	protected Map<String, LaunchHistory> fLaunchHistories;

	/**
	 * The list of registered implementors of <code>ILaunchHistoryChangedListener</code>
	 */
	protected List<ILaunchHistoryChangedListener> fLaunchHistoryChangedListeners = new ArrayList<>(3);

	/**
	 * Launch shortcuts
	 */
	private List<LaunchShortcutExtension> fLaunchShortcuts = null;

	/**
	 * Launch shortcuts, cached by perspective ids
	 */
	private Map<String, List<LaunchShortcutExtension>> fLaunchShortcutsByPerspective = null;

	/**
	 * Cache of launch configuration tab images with error overlays
	 */
	protected ImageRegistry fErrorImages = null;

	/**
	 * true when restoring launch history
	 */
	protected boolean fRestoring = false;

	/**
	 * The name of the file used to persist the launch history.
	 */
	private static final String LAUNCH_CONFIGURATION_HISTORY_FILENAME = "launchConfigurationHistory.xml"; //$NON-NLS-1$

	/**
	 * performs initialization of the manager when it is started
	 */
	public void startup() {
		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
		launchManager.addLaunchListener(this);
		DebugUIPlugin.getDefault().addSaveParticipant(this);
		//update histories for launches already registered
		for (ILaunch launch : launchManager.getLaunches()) {
			launchAdded(launch);
		}
	}

	/**
	 * Returns whether any launch config supports the given mode.
	 *
	 * @param mode launch mode
	 * @return whether any launch config supports the given mode
	 */
	public boolean launchModeAvailable(String mode) {
		return ((LaunchManager)DebugPlugin.getDefault().getLaunchManager()).launchModeAvailable(mode);
	}

	/**
	 * Returns whether the given launch configuration should be visible in the
	 * debug UI. If the config is marked as private, or belongs to a different
	 * category (i.e. non-null), then this configuration should not be displayed
	 * in the debug UI.
	 *
	 * @param launchConfiguration the configuration to check for the {@link IDebugUIConstants#ATTR_PRIVATE} attribute
	 * @return boolean
	 */
	public static boolean isVisible(ILaunchConfiguration launchConfiguration) {
		try {
			return !(launchConfiguration.getAttribute(IDebugUIConstants.ATTR_PRIVATE, false));
		} catch (CoreException e) {
		}
		return false;
	}

	/**
	 * Returns a collection of launch configurations that does not contain
	 * configurations from disabled activities.
	 *
	 * @param configurations a collection of configurations
	 * @return the given collection minus any configurations from disabled activities
	 */
	public static ILaunchConfiguration[] filterConfigs(ILaunchConfiguration[] configurations) {
		IWorkbenchActivitySupport activitySupport = PlatformUI.getWorkbench().getActivitySupport();
		if (activitySupport == null) {
			return configurations;
		}
		List<ILaunchConfiguration> filteredConfigs = new ArrayList<>();
		for (ILaunchConfiguration configuration : configurations) {
			try {
				ILaunchConfigurationType type = configuration.getType();
				LaunchConfigurationTypeContribution contribution = new LaunchConfigurationTypeContribution(type);
				if (DebugUIPlugin.doLaunchConfigurationFiltering(configuration) & !WorkbenchActivityHelper.filterItem(contribution)) {
					filteredConfigs.add(configuration);
				}
			}
			catch (CoreException e) {DebugUIPlugin.log(e.getStatus());}
		}
		return filteredConfigs.toArray(new ILaunchConfiguration[filteredConfigs.size()]);
	}

	/**
	 * Returns a listing of <code>IlaunchDeleagtes</code> that does not contain any delegates from disabled activities
	 * @param type the type to get the delegates from
	 * @param modes the set of launch modes to get delegates for
	 * @return the filtered listing of <code>ILaunchDelegate</code>s or an empty array, never <code>null</code>.
	 * @throws CoreException if an exception occurs
	 * @since 3.3
	 */
	public static ILaunchDelegate[] filterLaunchDelegates(ILaunchConfigurationType type, Set<String> modes) throws CoreException {
		IWorkbenchActivitySupport as = PlatformUI.getWorkbench().getActivitySupport();
		ILaunchDelegate[] delegates = type.getDelegates(modes);
		if(as == null) {
			return delegates;
		}
		HashSet<ILaunchDelegate> set = new HashSet<>();
		for (ILaunchDelegate delegate : delegates) {
			//filter by capabilities
			if(!WorkbenchActivityHelper.filterItem(new LaunchDelegateContribution(delegate))) {
				set.add(delegate);
			}
		}
		return set.toArray(new ILaunchDelegate[set.size()]);
	}

	/**
	 * Performs cleanup operations when the manager is being disposed of.
	 */
	public void shutdown() {
		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
		launchManager.removeLaunchListener(this);
		if (fLaunchHistories != null) {
			for (LaunchHistory history : fLaunchHistories.values()) {
				history.dispose();
			}
		}
		DebugUIPlugin.getDefault().removeSaveParticipant(this);
	}

	/**
	 * @see ILaunchListener#launchRemoved(ILaunch)
	 */
	@Override
	public void launchRemoved(ILaunch launch) {}

	/**
	 * @see ILaunchListener#launchChanged(ILaunch)
	 */
	@Override
	public void launchChanged(ILaunch launch) {}

	/**
	 * Must not assume that will only be called from the UI thread.
	 *
	 * @see ILaunchListener#launchAdded(ILaunch)
	 */
	@Override
	public void launchAdded(final ILaunch launch) {
		removeTerminatedLaunches(launch);
	}

	/**
	 * Removes terminated launches from the launch view, leaving the specified launch in the view
	 * @param newLaunch the newly added launch to leave in the view
	 */
	protected void removeTerminatedLaunches(ILaunch newLaunch) {
		if (DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugUIConstants.PREF_AUTO_REMOVE_OLD_LAUNCHES)) {
			ILaunchManager lManager= DebugPlugin.getDefault().getLaunchManager();
			for (ILaunch launch : lManager.getLaunches()) {
				if (launch != newLaunch && launch.isTerminated()) {
					lManager.removeLaunch(launch);
				}
			}
		}
	}

	/**
	 * Returns the most recent launch for the given group, or <code>null</code>
	 * if none. This method does not include any filtering for the returned launch configuration.
	 *
	 * This method is exposed via DebugTools.getLastLaunch
	 * @param groupId the identifier of the {@link ILaunchGroup} to get the last launch from
	 *
	 * @return the last launch, or <code>null</code> if none
	 */
	public ILaunchConfiguration getLastLaunch(String groupId) {
		LaunchHistory history = getLaunchHistory(groupId);
		if (history != null) {
			return history.getRecentLaunch();
		}
		return null;
	}

	/**
	 * Returns the most recent launch for the given group taking launch configuration
	 * filters into account, or <code>null</code> if none.
	 *
	 * @param groupId launch group
	 * @return the most recent, un-filtered launch
	 */
	public ILaunchConfiguration getFilteredLastLaunch(String groupId) {
		LaunchHistory history = getLaunchHistory(groupId);
		if (history != null) {
			ILaunchConfiguration[] filterConfigs = history.getCompleteLaunchHistory();
			if (filterConfigs.length > 0) {
				return filterConfigs[0];
			}
		}
		return null;
	}

	/**
	 * Add the specified listener to the list of listeners that will be notified when the
	 * launch history changes.
	 * @param listener the listener to add - adding a duplicate listener has no effect
	 */
	public void addLaunchHistoryListener(ILaunchHistoryChangedListener listener) {
		if (!fLaunchHistoryChangedListeners.contains(listener)) {
			fLaunchHistoryChangedListeners.add(listener);
		}
	}

	/**
	 * Remove the specified listener from the list of listeners that will be notified when the
	 * launch history changes.
	 * @param listener the listener to remove
	 */
	public void removeLaunchHistoryListener(ILaunchHistoryChangedListener listener) {
		fLaunchHistoryChangedListeners.remove(listener);
	}

	/**
	 * Notify all launch history listeners that the launch history has changed in some way.
	 */
	protected void fireLaunchHistoryChanged() {
		for (ILaunchHistoryChangedListener listener : fLaunchHistoryChangedListeners) {
			listener.launchHistoryChanged();
		}
	}

	/**
	 * Returns the history listing as XML
	 * @return the history listing as XML
	 * @throws CoreException if an exception occurs
	 * @throws ParserConfigurationException if there is a problem creating the XML for the launch history
	 */
	protected String getHistoryAsXML() throws CoreException, ParserConfigurationException {
		Document doc = DebugUIPlugin.getDocument();
		Element historyRootElement = doc.createElement(IConfigurationElementConstants.LAUNCH_HISTORY);
		doc.appendChild(historyRootElement);
		for (LaunchHistory history : fLaunchHistories.values()) {
			Element groupElement = doc.createElement(IConfigurationElementConstants.LAUNCH_GROUP);
			groupElement.setAttribute(IConfigurationElementConstants.ID, history.getLaunchGroup().getIdentifier());
			historyRootElement.appendChild(groupElement);
			Element historyElement = doc.createElement(IConfigurationElementConstants.MRU_HISTORY);
			groupElement.appendChild(historyElement);
			createEntry(doc, historyElement, history.getCompleteLaunchHistory());
			Element favs = doc.createElement(IConfigurationElementConstants.FAVORITES);
			groupElement.appendChild(favs);
			createEntry(doc, favs, history.getFavorites());
			history.setSaved(true);
		}
		return DebugPlugin.serializeDocument(doc);
	}

	/**
	 * Creates a new launch history element and adds it to the specified <code>Document</code>
	 * @param doc the <code>Document</code> to add the new element to
	 * @param historyRootElement the root element
	 * @param configurations the configurations to create entries for
	 * @throws CoreException is an exception occurs
	 */
	protected void createEntry(Document doc, Element historyRootElement, ILaunchConfiguration[] configurations) throws CoreException {
		for (ILaunchConfiguration configuration : configurations) {
			if (configuration.exists()) {
				Element launch = doc.createElement(IConfigurationElementConstants.LAUNCH);
				launch.setAttribute(IConfigurationElementConstants.MEMENTO, configuration.getMemento());
				historyRootElement.appendChild(launch);
			}
		}
	}

	/**
	 * Returns the path to the local file for the launch history
	 * @return the file path for the launch history file
	 */
	protected IPath getHistoryFilePath() {
		return DebugUIPlugin.getDefault().getStateLocation().append(LAUNCH_CONFIGURATION_HISTORY_FILENAME);
	}

	/**
	 * Write out an XML file indicating the entries on the run & debug history lists and
	 * the most recent launch.
	 * @throws IOException if writing the history file fails
	 * @throws CoreException is an exception occurs
	 * @throws ParserConfigurationException if there is a problem reading the XML
	 */
	protected void persistLaunchHistory() throws IOException, CoreException, ParserConfigurationException {
		synchronized (this) {
			if (fLaunchHistories == null || fRestoring) {
				return;
			}
		}
		boolean shouldsave = false;
		for (LaunchHistory history : fLaunchHistories.values()) {
			shouldsave |= history.needsSaving();
		}
		if(shouldsave) {
			IPath historyPath = getHistoryFilePath();
			String osHistoryPath = historyPath.toOSString();
			String xml = getHistoryAsXML();
			File file = new File(osHistoryPath);
			file.createNewFile();

			try (FileOutputStream stream = new FileOutputStream(file)) {
				stream.write(xml.getBytes(StandardCharsets.UTF_8));
			}
		}
	}

	/**
	 * Find the XML history file and parse it.  Place the corresponding configurations
	 * in the appropriate history, and set the most recent launch.
	 */
	private void restoreLaunchHistory() {
		// Find the history file
		IPath historyPath = getHistoryFilePath();
		String osHistoryPath = historyPath.toOSString();
		File file = new File(osHistoryPath);
		// If no history file, nothing to do
		if (!file.exists()) {
			return;
		}

		Element rootHistoryElement= null;
		try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
			// Parse the history file
			try {
				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				parser.setErrorHandler(new DefaultHandler());
				rootHistoryElement = parser.parse(new InputSource(stream)).getDocumentElement();
			} catch (SAXException e) {
				DebugUIPlugin.log(e);
				return;
			} catch (ParserConfigurationException e) {
				DebugUIPlugin.log(e);
				return;
			}
		} catch (IOException exception) {
			DebugUIPlugin.log(exception);
			return;
		}
		// If root node isn't what we expect, return
		if (!rootHistoryElement.getNodeName().equalsIgnoreCase(IConfigurationElementConstants.LAUNCH_HISTORY)) {
			return;
		}
		// For each child of the root node, construct a launch config handle and add it to
		// the appropriate history, or set the most recent launch
		LaunchHistory[] histories = fLaunchHistories.values().toArray(new LaunchHistory[fLaunchHistories.size()]);
		NodeList list = rootHistoryElement.getChildNodes();
		int length = list.getLength();
		Node node = null;
		Element entry = 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().equalsIgnoreCase(IConfigurationElementConstants.LAUNCH)) {
					createHistoryElement(entry, histories, false);
				} else if (entry.getNodeName().equalsIgnoreCase(IConfigurationElementConstants.LAST_LAUNCH)) {
					createHistoryElement(entry, histories, true);
				} else if (entry.getNodeName().equals(IConfigurationElementConstants.LAUNCH_GROUP)) {
					String id = entry.getAttribute(IConfigurationElementConstants.ID);
					if (id != null) {
						LaunchHistory history = getLaunchHistory(id);
						if (history != null) {
							restoreHistory(entry, history);
						}
					}
				}
			}
		}
	}

	/**
	 * Restores the given launch history.
	 *
	 * @param groupElement launch group history
	 * @param history associated history cache
	 */
	private void restoreHistory(Element groupElement, LaunchHistory history) {
		NodeList nodes = groupElement.getChildNodes();
		int length = nodes.getLength();
		for (int i = 0; i < length; i++) {
			Node node = nodes.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element element = (Element)node;
				if (element.getNodeName().equals(IConfigurationElementConstants.MRU_HISTORY)) {
					for (ILaunchConfiguration config : getLaunchConfigurations(element)) {
						history.addHistory(config, false);
					}
				} else if (element.getNodeName().equals(IConfigurationElementConstants.FAVORITES)) {
					ILaunchConfiguration[] favs = getLaunchConfigurations(element);
					history.setFavorites(favs);
					// add any favorites that have been added to the workspace before this plug-in
					// was loaded - @see bug 231600
					for (ILaunchConfiguration configuration : getLaunchManager().getLaunchConfigurations()) {
						history.checkFavorites(configuration);
					}
				}
			}
		}
	}

	/**
	 * Restores a list of configurations.
	 * @param root element
	 * @return list of configurations under the element
	 */
	private ILaunchConfiguration[] getLaunchConfigurations(Element root) {
		List<ILaunchConfiguration> configs = new ArrayList<>();
		NodeList nodes = root.getChildNodes();
		int length = nodes.getLength();
		for (int i = 0; i < length; i++) {
			Node node = nodes.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element element = (Element) node;
				if (element.getNodeName().equals(IConfigurationElementConstants.LAUNCH)) {
					String memento = element.getAttribute(IConfigurationElementConstants.MEMENTO);
					if (memento != null) {
						try {
							ILaunchConfiguration configuration = DebugPlugin.getDefault().getLaunchManager().getLaunchConfiguration(memento);
							//touch the config to see if its type exists
							configuration.getType();
							if (configuration.exists()) {
								configs.add(configuration);
							}
						} catch (CoreException e) {
							//do nothing as we don't care about non-existent, or configs with no type
						}
					}
				}
			}
		}
		return configs.toArray(new ILaunchConfiguration[configs.size()]);
	}

	/**
	 * Construct a launch configuration corresponding to the specified XML
	 * element, and place it in the appropriate history.
	 * @param entry the XML entry to read from
	 * @param histories the array of histories to try and add the restored configurations to
	 * @param prepend if any restored items should be added to to top of the launch history
	 */
	private void createHistoryElement(Element entry, LaunchHistory[] histories, boolean prepend) {
		String memento = entry.getAttribute(IConfigurationElementConstants.MEMENTO);
		String mode = entry.getAttribute(IConfigurationElementConstants.MODE);
		try {
			ILaunchConfiguration launchConfig = DebugPlugin.getDefault().getLaunchManager().getLaunchConfiguration(memento);
			//touch the type to see if its type exists
			launchConfig.getType();
			if (launchConfig.exists()) {
				for (LaunchHistory history : histories) {
					if (history.accepts(launchConfig) && history.getLaunchGroup().getMode().equals(mode)) {
						history.addHistory(launchConfig, prepend);
					}
				}
			}
		} catch (CoreException e) {
			//do nothing, as we want to throw away invalid launch history entries silently
		}
	}

	/**
	 * Load all registered extensions of the 'launch shortcut' extension point.
	 */
	private synchronized void loadLaunchShortcuts() {
		if(fLaunchShortcuts == null) {
			// Get the configuration elements
			IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.EXTENSION_POINT_LAUNCH_SHORTCUTS);
			IConfigurationElement[] infos = extensionPoint.getConfigurationElements();

			// Load the configuration elements into a Map
			fLaunchShortcuts = new ArrayList<>(infos.length);
			for (IConfigurationElement info : infos) {
				fLaunchShortcuts.add(new LaunchShortcutExtension(info));
			}
			Collections.sort(fLaunchShortcuts, new ShortcutComparator());
		}
	}

	/**
	 * Load all registered extensions of the 'launch groups' extension point.
	 */
	private synchronized void loadLaunchGroups() {
		if (fLaunchGroups == null) {
			// Get the configuration elements
			IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.EXTENSION_POINT_LAUNCH_GROUPS);
			IConfigurationElement[] infos= extensionPoint.getConfigurationElements();

			// Load the configuration elements into a Map
			fLaunchGroups = new HashMap<>(infos.length);
			LaunchGroupExtension ext = null;
			for (IConfigurationElement info : infos) {
				ext = new LaunchGroupExtension(info);
				fLaunchGroups.put(ext.getIdentifier(), ext);
			}
		}
	}

	/**
	 * Returns all launch shortcuts
	 *
	 * @return all launch shortcuts
	 */
	public List<LaunchShortcutExtension> getLaunchShortcuts() {
		if (fLaunchShortcuts == null) {
			loadLaunchShortcuts();
		}
		return fLaunchShortcuts;
	}

	/**
	 * Creates a listing of the launch shortcut extensions that are applicable to the underlying resource
	 * @param resource the underlying resource
	 * @return a listing of applicable launch shortcuts or an empty list, never <code>null</code>
	 * @since 3.3
	 */
	public List<LaunchShortcutExtension> getLaunchShortcuts(IResource resource) {
		List<LaunchShortcutExtension> list = new ArrayList<>();
		List<LaunchShortcutExtension> sc = getLaunchShortcuts();
		List<IResource> ctxt = new ArrayList<>();
		if(resource != null) {
			ctxt.add(resource);
		}
		IEvaluationContext context = DebugUIPlugin.createEvaluationContext(ctxt);
		context.addVariable("selection", ctxt); //$NON-NLS-1$
		for (LaunchShortcutExtension ext : sc) {
			try {
				if(ext.evalEnablementExpression(context, ext.getContextualLaunchEnablementExpression()) && !WorkbenchActivityHelper.filterItem(ext)) {
					if(!list.contains(ext)) {
						list.add(ext);
					}
				}
			}
			catch(CoreException ce) {/*do nothing*/}
		}
		return list;
	}

	/**
	 * Returns an array of all of the ids of the <code>ILaunchConfigurationType</code>s that apply to the currently
	 * specified <code>IResource</code>.
	 *
	 * @param resource the resource context
	 * @return an array of applicable <code>ILaunchConfigurationType</code>  ids, or an empty array, never <code>null</code>
	 * @since 3.3
	 */
	public String[] getApplicableConfigurationTypes(IResource resource) {
		List<LaunchShortcutExtension> exts = getLaunchShortcuts();
		List<IResource> list = new ArrayList<>();
		list.add(resource);
		IEvaluationContext context = DebugUIPlugin.createEvaluationContext(list);
		context.setAllowPluginActivation(true);
		context.addVariable("selection", list); //$NON-NLS-1$
		HashSet<String> contributedTypeIds = new HashSet<>();
		for (Iterator<LaunchShortcutExtension> iter = exts.listIterator(); iter.hasNext();) {
			LaunchShortcutExtension ext = iter.next();
			try {
				if(ext.evalEnablementExpression(context, ext.getContextualLaunchEnablementExpression())) {
					contributedTypeIds.addAll(ext.getAssociatedConfigurationTypes());
				}
			}
			catch(CoreException ce) {
				IStatus status = new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), "Launch shortcut '" + ext.getId() + "' enablement expression caused exception. Shortcut was removed.", ce); //$NON-NLS-1$ //$NON-NLS-2$
				DebugUIPlugin.log(status);
				iter.remove();
			}
		}
		List<String> typeIds = new ArrayList<>();
		LaunchManager lm = (LaunchManager) DebugPlugin.getDefault().getLaunchManager();
		for (String id : contributedTypeIds) {
			ILaunchConfigurationType type = lm.getLaunchConfigurationType(id);
			if(type != null) {
				String identifier = type.getIdentifier();
				if (!typeIds.contains(identifier) && type.isPublic() && !"org.eclipse.ui.externaltools.builder".equals(type.getCategory())) { //$NON-NLS-1$
					typeIds.add(identifier);
				}
			}
		}
		return typeIds.toArray(new String[typeIds.size()]);
	}

	/**
	 * Returns an array of the <code>ILaunchConfiguration</code>s that apply to the specified <code>IResource</code>
	 * @param types the array of launch configuration type identifiers
	 * @param resource the resource
	 * @return an array of applicable <code>ILaunchConfiguration</code>s for the specified <code>IResource</code> or an empty
	 * array if none, never <code>null</code>
	 * @since 3.3
	 */
	public ILaunchConfiguration[] getApplicableLaunchConfigurations(String[] types, IResource resource) {
		ArrayList<ILaunchConfiguration> list = new ArrayList<>();
		try {
			if(resource != null) {
				String[] ctypes = types;
				if(ctypes == null) {
					ctypes = getApplicableConfigurationTypes(resource);
				}
				//copy into collection for hashcode matching
				HashSet<String> typeset = new HashSet<>(ctypes.length);
				Collections.addAll(typeset, ctypes);
				for (ILaunchConfiguration configuration : filterConfigs(getLaunchManager().getLaunchConfigurations())) {
					if(typeset.contains(configuration.getType().getIdentifier()) && acceptConfiguration(configuration)) {
						IResource[] resrcs = configuration.getMappedResources();
						if (resrcs != null) {
							for (IResource res : resrcs) {
								if (resource.equals(res) || resource.getFullPath().isPrefixOf(res.getFullPath())) {
									list.add(configuration);
									break;
								}
							}
						}
						else {
							//in the event the config has no mapping
							list.add(configuration);
						}
					}
				}
			}
		} catch (CoreException e) {
			list.clear();
			DebugPlugin.log(e);
		}
		return list.toArray(new ILaunchConfiguration[list.size()]);
	}

	/**
	 * Returns if the specified configuration should be considered as a potential candidate
	 * @param config to configuration
	 * @return if the specified configuration should be considered as a potential candidate
	 * @throws CoreException if an exception occurs
	 */
	private boolean acceptConfiguration(ILaunchConfiguration config) throws CoreException {
		if(config != null && !DebugUITools.isPrivate(config)) {
			if(!"org.eclipse.ui.externaltools".equals(config.getType().getCategory())) { //$NON-NLS-1$
				return true;
			}
			else {
				IResource[] res = config.getMappedResources();
				if(res != null) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Returns all launch shortcuts for the given category
	 * @param category the identifier of the category
	 *
	 * @return all launch shortcuts
	 */
	public List<LaunchShortcutExtension> getLaunchShortcuts(String category) {
		return filterShortcuts(getLaunchShortcuts(), category);
	}

	/**
	 * Return a list of filtered launch shortcuts, based on the given category.
	 *
	 * @param unfiltered the raw list of shortcuts to filter
	 * @param category the category to filter by
	 * @return List
	 */
	protected List<LaunchShortcutExtension> filterShortcuts(List<LaunchShortcutExtension> unfiltered, String category) {
		List<LaunchShortcutExtension> filtered = new ArrayList<>(unfiltered.size());
		for (LaunchShortcutExtension extension : unfiltered) {
			if (category == null) {
				if (extension.getCategory() == null) {
					filtered.add(extension);
				}
			} else if (category.equals(extension.getCategory())){
				filtered.add(extension);
			}
		}
		return filtered;
	}

	/**
	 * Returns all launch shortcuts defined for the given perspective,
	 * empty list if none.
	 *
	 * @param perpsective perspective identifier
	 * @param category the category for the shortcut
	 * @return all launch shortcuts defined for the given perspective,
	 * empty list if none.
	 * @deprecated the use of perspectives for launch shortcuts has been
	 * deprecated since 3.1, use a contextualLaunch element instead
	 */
	@Deprecated
	public List<LaunchShortcutExtension> getLaunchShortcuts(String perpsective, String category) {
		if (fLaunchShortcutsByPerspective == null) {
			fLaunchShortcutsByPerspective = new HashMap<>(10);
		}
		for (LaunchShortcutExtension ext : getLaunchShortcuts()) {
			for (String id : ext.getPerspectives()) {
				List<LaunchShortcutExtension> list = fLaunchShortcutsByPerspective.get(id);
				if (list == null) {
					list = new ArrayList<>(4);
					fLaunchShortcutsByPerspective.put(id, list);
				}
				list.add(ext);
			}
		}
		List<LaunchShortcutExtension> list = fLaunchShortcutsByPerspective.get(perpsective);
		if (list == null) {
			return Collections.EMPTY_LIST;
		}
		return filterShortcuts(list, category);
	}

	/**
	 * Returns the first occurrence of any one of the configurations in the provided list, if they are found in the launch history
	 * for the corresponding launch group
	 * @param configurations the raw list of configurations to examine
	 * @param group the launch group to get the launch history from
	 * @param resource the {@link IResource} context
	 * @return the associated launch configuration from the MRU listing or <code>null</code> if there isn't one
	 * @since 3.3
	 */
	public ILaunchConfiguration getMRUConfiguration(List<ILaunchConfiguration> configurations, ILaunchGroup group, IResource resource) {
		if(group != null) {
			ArrayList<ILaunchConfiguration> candidates = new ArrayList<>();
			LaunchHistory history = getLaunchHistory(group.getIdentifier());
			if(history != null) {
				ILaunchConfiguration[] configs = history.getCompleteLaunchHistory();
				for (ILaunchConfiguration config : configs) {
					if(configurations.contains(config)) {
						if(resource instanceof IContainer) {
							return config;
						}
						else {
							candidates.add(config);
						}
					}
				}
				if(resource != null) {
					//first try to find a config that exactly matches the resource mapping, and collect partial matches
					IResource[] res = null;
					for (ILaunchConfiguration config : candidates) {
						try {
							res = config.getMappedResources();
							if(res != null) {
								for (IResource re : res) {
									if(re.equals(resource)) {
										return config;
									}
								}
							}
						}
						catch(CoreException ce) {}
					}
				}
				for (ILaunchConfiguration config : configs) {
					if(candidates.contains(config)) {
						return config;
					}
				}
			}
		}
		return null;
	}

	/**
	 * Returns the shared config from the selected resource or <code>null</code> if the selected resources is not a shared config
	 * @param receiver the object to test if it is a shared launch configuration
	 * @return the shared config from the selected resource or <code>null</code> if the selected resources is not a shared config
	 * @since 3.3
	 */
	public ILaunchConfiguration isSharedConfig(Object receiver) {
		if(receiver instanceof IFile) {
			IFile file = (IFile) receiver;
			String ext = file.getFileExtension();
			if(ext == null) {
				return null;
			}
			if(ext.equals("launch")) { //$NON-NLS-1$
				ILaunchConfiguration config = DebugPlugin.getDefault().getLaunchManager().getLaunchConfiguration(file);
				if(config != null && config.exists()) {
					return config;
				}
			}
		}
		else if(receiver instanceof IFileEditorInput) {
			IFileEditorInput input = (IFileEditorInput) receiver;
			return isSharedConfig(input.getFile());
		}
		else if(receiver instanceof IEditorPart) {
			return isSharedConfig(((IEditorPart) receiver).getEditorInput());
		}
		else if (receiver instanceof IAdaptable) {
			IFile file = ((IAdaptable)receiver).getAdapter(IFile.class);
			if (file != null) {
				return isSharedConfig(file);
			}
		}
		return null;
	}

	/**
	 * Returns the image used to display an error in the given tab
	 * @param tab the tab to get the error image for
	 * @return the error image associated with the given tab
	 */
	public Image getErrorTabImage(ILaunchConfigurationTab tab) {
		if (fErrorImages == null) {
			fErrorImages = new ImageRegistry();
		}
		String key = tab.getClass().getName();
		Image image = fErrorImages.get(key);
		if (image == null) {
			// create image
			Image base = tab.getImage();
			if (base == null) {
				base = DebugPluginImages.getImage(IInternalDebugUIConstants.IMG_OVR_TRANSPARENT);
			}
			base = new Image(Display.getCurrent(), base, SWT.IMAGE_COPY);
			LaunchConfigurationTabImageDescriptor desc = new LaunchConfigurationTabImageDescriptor(base, LaunchConfigurationTabImageDescriptor.ERROR);
			image = desc.createImage();
			fErrorImages.put(key, image);
		}
		return image;
	}

	/**
	 * Return the launch group with the given id, or <code>null</code>
	 * @param id the identifier of the {@link LaunchGroupExtension}
	 *
	 * @return the launch group with the given id, or <code>null</code>
	 */
	public LaunchGroupExtension getLaunchGroup(String id) {
		if (fLaunchGroups == null) {
			loadLaunchGroups();
		}
		return fLaunchGroups.get(id);
	}

	/**
	 * Return all defined launch groups
	 *
	 * @return all defined launch groups
	 */
	public ILaunchGroup[] getLaunchGroups() {
		if (fLaunchGroups == null) {
			loadLaunchGroups();
		}
		return fLaunchGroups.values().toArray(new ILaunchGroup[fLaunchGroups.size()]);
	}

	/**
	 * Return the launch history with the given group id, or <code>null</code>
	 * @param id the identifier of the launch history
	 * @return the launch history with the given group id, or <code>null</code>
	 */
	public LaunchHistory getLaunchHistory(String id) {
		loadLaunchHistories();
		return fLaunchHistories.get(id);
	}

	/**
	 * Returns the singleton instance of the launch manager
	 * @return the singleton instance of the launch manager
	 * @since 3.3
	 */
	private LaunchManager getLaunchManager() {
		return (LaunchManager) DebugPlugin.getDefault().getLaunchManager();
	}

	/**
	 * Restore launch history
	 */
	private synchronized void loadLaunchHistories() {
		if (fLaunchHistories == null) {
			fRestoring = true;
			ILaunchGroup[] groups = getLaunchGroups();
			fLaunchHistories = new HashMap<>(groups.length);
			ILaunchGroup extension = null;
			for (ILaunchGroup group : groups) {
				extension = group;
				if (extension.isPublic()) {
					fLaunchHistories.put(extension.getIdentifier(), new LaunchHistory(extension));
				}
			}
			restoreLaunchHistory();
			fRestoring = false;
		}
	}

	/**
	 * Returns the default launch group for the given mode.
	 *
	 * @param mode the mode identifier
	 * @return launch group
	 */
	public LaunchGroupExtension getDefaultLaunchGroup(String mode) {
		if (mode.equals(ILaunchManager.DEBUG_MODE)) {
			return getLaunchGroup(IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP);
		}
		return getLaunchGroup(IDebugUIConstants.ID_RUN_LAUNCH_GROUP);
	}

	/**
	 * Returns the launch group the given launch configuration type belongs to, in
	 * the specified mode, or <code>null</code> if none.
	 *
	 * @param type the type
	 * @param mode the mode
	 * @return the launch group the given launch configuration belongs to, in
	 * the specified mode, or <code>null</code> if none
	 */
	public ILaunchGroup getLaunchGroup(ILaunchConfigurationType type, String mode) {
		if (!type.supportsMode(mode)) {
			return null;
		}
		String category = type.getCategory();
		ILaunchGroup extension = null;
		for (ILaunchGroup group : getLaunchGroups()) {
			extension = group;
			if (category == null) {
				if (extension.getCategory() == null && extension.getMode().equals(mode)) {
					return extension;
				}
			} else if (category.equals(extension.getCategory())) {
				if (extension.getMode().equals(mode)) {
					return extension;
				}
			}
		}
		return null;
	}

	/**
	 * Returns the {@link ILaunchGroup} for the given mode set and
	 * {@link ILaunchConfigurationType}.
	 * @param type the type
	 * @param modeset the set of modes, which are combined to one mode string
	 * @return the associated {@link ILaunchGroup} or <code>null</code>
	 *
	 * @since 3.4.0
	 */
	public ILaunchGroup getLaunchGroup(ILaunchConfigurationType type, Set<String> modeset) {
		StringBuilder buff = new StringBuilder();
		for (Iterator<String> iter = modeset.iterator(); iter.hasNext();) {
			buff.append(iter.next());
			if (iter.hasNext()) {
				buff.append(","); //$NON-NLS-1$
			}
		}
		return getLaunchGroup(type, buff.toString());
	}

	/**
	 * Returns the private launch configuration used as a place-holder to represent/store
	 * the information associated with a launch configuration type.
	 *
	 * @param type launch configuration type
	 * @return launch configuration
	 * @throws CoreException if an excpetion occurs
	 * @since 3.0
	 */
	public static ILaunchConfiguration getSharedTypeConfig(ILaunchConfigurationType type) throws CoreException {
		String id = type.getIdentifier();
		String name = id + ".SHARED_INFO"; //$NON-NLS-1$
		ILaunchConfiguration shared = null;
		for (ILaunchConfiguration configuration : DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(type)) {
			if (configuration.getName().equals(name)) {
				shared = configuration;
				break;
			}
		}

		if (shared == null) {
			// create a new shared config
			ILaunchConfigurationWorkingCopy workingCopy;
			workingCopy = type.newInstance(null, name);
			workingCopy.setAttribute(IDebugUIConstants.ATTR_PRIVATE, true);
			// null entries indicate default settings
			// save
			shared = workingCopy.doSave();
		}
		return shared;
	}


	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void doneSaving(ISaveContext context) {}

	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void prepareToSave(ISaveContext context) throws CoreException {}

	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#rollback(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void rollback(ISaveContext context) {}

	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#saving(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void saving(ISaveContext context) throws CoreException {
		try {
			persistLaunchHistory();
		}  catch (IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), "Internal error saving launch history", e)); //$NON-NLS-1$
		} catch (ParserConfigurationException e) {
			throw new CoreException(new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), "Internal error saving launch history", e)); //$NON-NLS-1$
		}
	}

	/**
	 * Sets the given launch to be the most recent launch in the launch
	 * history (for applicable histories).
	 * <p>
	 * @param launch the launch to prepend to its associated histories
	 * @since 3.3
	 */
	public void setRecentLaunch(ILaunch launch) {
		ILaunchGroup[] groups = DebugUITools.getLaunchGroups();
		int size = groups.length;
		for (int i = 0; i < size; i++) {
			String id = groups[i].getIdentifier();
			LaunchHistory history = getLaunchHistory(id);
			if (history != null) {
				history.launchAdded(launch);
			}
		}
	}

}
