/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * 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.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
	 */
	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<ILaunchHistoryChangedListener>(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
		ILaunch[] launches = launchManager.getLaunches();
		for (int i = 0; i < launches.length; i++) {
			launchAdded(launches[i]);
		}
	}

	/**
	 * 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<ILaunchConfiguration>();
		ILaunchConfigurationType type = null;
		LaunchConfigurationTypeContribution contribution = null;
		ILaunchConfiguration configuration = null;
		for (int i = 0; i < configurations.length; i++) {
			configuration = configurations[i];
			try {
				type = configuration.getType();
				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<ILaunchDelegate>();
		for(int i = 0; i < delegates.length; i++) {
			//filter by capabilities
			if(!WorkbenchActivityHelper.filterItem(new LaunchDelegateContribution(delegates[i]))) {
				set.add(delegates[i]);
			}
		}
		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();
	        Object[] launches= lManager.getLaunches();
	        for (int i= 0; i < launches.length; i++) {
	            ILaunch launch= (ILaunch)launches[i];
	            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 (int i = 0; i < configurations.length; i++) {
			ILaunchConfiguration configuration = configurations[i];
			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("UTF8")); //$NON-NLS-1$
			}
		}
	}

	/**
	 * 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)) {
					ILaunchConfiguration[] configs = getLaunchConfigurations(element);
					for (int j = 0; j < configs.length; j++) {
						history.addHistory(configs[j], 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
					ILaunchConfiguration[] configurations = getLaunchManager().getLaunchConfigurations();
					for (int j = 0; j < configurations.length; j++) {
						history.checkFavorites(configurations[j]);
					}
				}
			}
		}
	}

	/**
	 * 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<ILaunchConfiguration>();
		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()) {
				LaunchHistory history = null;
				for (int i = 0; i < histories.length; i++) {
					history = histories[i];
					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<LaunchShortcutExtension>(infos.length);
			for (int i = 0; i < infos.length; i++) {
				fLaunchShortcuts.add(new LaunchShortcutExtension(infos[i]));
			}
			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<String, LaunchGroupExtension>(infos.length);
			LaunchGroupExtension ext = null;
			for (int i = 0; i < infos.length; i++) {
				ext = new LaunchGroupExtension(infos[i]);
				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<LaunchShortcutExtension>();
		List<LaunchShortcutExtension> sc = getLaunchShortcuts();
		List<IResource> ctxt = new ArrayList<IResource>();
		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<IResource>();
		list.add(resource);
		IEvaluationContext context = DebugUIPlugin.createEvaluationContext(list);
		context.setAllowPluginActivation(true);
		context.addVariable("selection", list); //$NON-NLS-1$
		HashSet<String> contributedTypeIds = new HashSet<String>();
		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<String>();
		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<ILaunchConfiguration>();
		try {
			if(resource != null) {
				String[] ctypes = types;
				if(ctypes == null) {
					ctypes = getApplicableConfigurationTypes(resource);
				}
				//copy into collection for hashcode matching
				HashSet<String> typeset = new HashSet<String>(ctypes.length);
				for(int i = 0; i < ctypes.length; i++) {
					typeset.add(ctypes[i]);
				}
				ILaunchConfiguration[] configurations = filterConfigs(getLaunchManager().getLaunchConfigurations());
				ILaunchConfiguration configuration = null;
				IResource[] resrcs = null;
				for(int i = 0; i < configurations.length; i++) {
					configuration = configurations[i];
					if(typeset.contains(configuration.getType().getIdentifier()) && acceptConfiguration(configuration)) {
						resrcs = configuration.getMappedResources();
						if (resrcs != null) {
							for (int j = 0; j < resrcs.length; j++) {
								if (resource.equals(resrcs[j]) || resource.getFullPath().isPrefixOf(resrcs[j].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<LaunchShortcutExtension>(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<String, List<LaunchShortcutExtension>>(10);
		}
		for (LaunchShortcutExtension ext : getLaunchShortcuts()) {
			for (String id : ext.getPerspectives()) {
				List<LaunchShortcutExtension> list = fLaunchShortcutsByPerspective.get(id);
				if (list == null) {
					list = new ArrayList<LaunchShortcutExtension>(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<ILaunchConfiguration>();
			LaunchHistory history = getLaunchHistory(group.getIdentifier());
			if(history != null) {
				ILaunchConfiguration[] configs = history.getCompleteLaunchHistory();
				for(int i = 0; i < configs.length; i++) {
					if(configurations.contains(configs[i])) {
						if(resource instanceof IContainer) {
							return configs[i];
						}
						else {
							candidates.add(configs[i]);
						}
					}
				}
				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(int i = 0; i < res.length; i++) {
									if(res[i].equals(resource)) {
										return config;
									}
								}
							}
						}
						catch(CoreException ce) {}
					}
				}
				for(int i = 0; i < configs.length; i++) {
					if(candidates.contains(configs[i])) {
						return configs[i];
					}
				}
			}
		}
		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<String, LaunchHistory>(groups.length);
			ILaunchGroup extension = null;
			for (int i = 0; i < groups.length; i++) {
				extension = groups[i];
				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[] groups = getLaunchGroups();
		ILaunchGroup extension = null;
		for (int i = 0; i < groups.length; i++) {
			extension = groups[i];
			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) {
		StringBuffer buff = new StringBuffer();
		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;
		ILaunchConfiguration[] configurations = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(type);
		ILaunchConfiguration configuration = null;
		for (int i = 0; i < configurations.length; i++) {
			configuration = configurations[i];
			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);
			}
		}
	}

}
