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