/*******************************************************************************
 * 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<String> types = new ArrayList<String>();
		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> set = new HashSet<String>();
		for (Iterator<LaunchShortcutExtension> iter = exts.listIterator(); iter.hasNext();) {
			LaunchShortcutExtension ext = iter.next();
			try {
				if(ext.evalEnablementExpression(context, ext.getContextualLaunchEnablementExpression())) {
					set.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();
			}
		}
		LaunchManager lm = (LaunchManager) DebugPlugin.getDefault().getLaunchManager();
		ILaunchConfigurationType type = null;
		for (String id : set) {
			type = lm.getLaunchConfigurationType(id);
			if(type != null) { 
				if(!types.contains(type) && type.isPublic() && !"org.eclipse.ui.externaltools.builder".equals(type.getCategory())) { //$NON-NLS-1$
					types.add(type.getIdentifier());
				}
			}
		}
		return types.toArray(new String[types.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);
			}
		}
	}	

}
