diff options
author | Markus Duft | 2016-05-11 13:52:28 +0000 |
---|---|---|
committer | Markus Duft | 2016-11-30 09:42:25 +0000 |
commit | 97be8772a897b47a48b2d4b6ef33b46811408b7f (patch) | |
tree | ef2793a75f11741be425b7d236695df5f0f252d2 /org.eclipse.debug.core | |
parent | 66da2950cc347953d38ae225f82b5f23f5e960e7 (diff) | |
download | eclipse.platform.debug-97be8772a897b47a48b2d4b6ef33b46811408b7f.tar.gz eclipse.platform.debug-97be8772a897b47a48b2d4b6ef33b46811408b7f.tar.xz eclipse.platform.debug-97be8772a897b47a48b2d4b6ef33b46811408b7f.zip |
Initial contribution of Launch Groups
The initial contribution is a slightly modified/polished version of the
launch group code in org.eclipse.cdt.launch.
A follow up commit will contain additional modifications to merge
features from another (external) implementation of launch groups.
Bug: 492788
Change-Id: Ie0a902b857a5c2cc02f5c36d8591001493bd6e19
Signed-off-by: Markus Duft <markus.duft@ssi-schaefer.com>
Diffstat (limited to 'org.eclipse.debug.core')
8 files changed, 709 insertions, 0 deletions
diff --git a/org.eclipse.debug.core/META-INF/MANIFEST.MF b/org.eclipse.debug.core/META-INF/MANIFEST.MF index 0effc659e..e306ac17c 100644 --- a/org.eclipse.debug.core/META-INF/MANIFEST.MF +++ b/org.eclipse.debug.core/META-INF/MANIFEST.MF @@ -14,6 +14,7 @@ Export-Package: org.eclipse.debug.core, org.eclipse.debug.core.sourcelookup.containers, org.eclipse.debug.internal.core;x-friends:="org.eclipse.debug.ui,org.eclipse.debug.tests,org.eclipse.debug.examples.mixedmode", org.eclipse.debug.internal.core.commands;x-friends:="org.eclipse.debug.ui", + org.eclipse.debug.internal.core.groups, org.eclipse.debug.internal.core.sourcelookup;x-friends:="org.eclipse.debug.ui", org.eclipse.debug.internal.core.sourcelookup.containers;x-friends:="org.eclipse.debug.ui", org.eclipse.debug.internal.core.variables;x-friends:="org.eclipse.debug.ui,org.eclipse.jdt.debug.ui" diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.java index 5e4d8ad30..48bec126b 100644 --- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.java +++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.java @@ -32,6 +32,20 @@ public class DebugCoreMessages extends NLS { public static String DebugPlugin_8; public static String DebugPlugin_Eclipse_runtime_does_not_support_working_directory_2; public static String EnvironmentVariableResolver_0; + public static String GroupLaunchConfigurationDelegate_Delay; + public static String GroupLaunchConfigurationDelegate_Delaying; + public static String GroupLaunchConfigurationDelegate_Launching; + public static String GroupLaunchConfigurationDelegate_mode_debug; + + public static String GroupLaunchConfigurationDelegate_mode_inherit; + + public static String GroupLaunchConfigurationDelegate_mode_profile; + + public static String GroupLaunchConfigurationDelegate_mode_run; + + public static String GroupLaunchConfigurationDelegate_None; + public static String GroupLaunchConfigurationDelegate_Wait_until_terminated; + public static String GroupLaunchConfigurationDelegate_Waiting_for_termination; public static String LaunchConfiguration_0; public static String LaunchConfiguration_11; public static String LaunchConfiguration_13; diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.properties b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.properties index cf51e242e..0e20ad951 100644 --- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.properties +++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.properties @@ -26,6 +26,16 @@ DebugPlugin_6=An exception occurred in asynchronous runnable. DebugPlugin_7=An exception occurred while filtering debug events. DebugPlugin_8=An exception occurred while dispatching debug events. EnvironmentVariableResolver_0=Environment variable not specified +GroupLaunchConfigurationDelegate_Delay=Delay +GroupLaunchConfigurationDelegate_Delaying=Delaying next launch by {0} seconds +GroupLaunchConfigurationDelegate_Launching=Launching ''{0}'' +GroupLaunchConfigurationDelegate_mode_debug=debug +GroupLaunchConfigurationDelegate_mode_inherit=inherit +GroupLaunchConfigurationDelegate_mode_profile=profile +GroupLaunchConfigurationDelegate_mode_run=run +GroupLaunchConfigurationDelegate_None=None +GroupLaunchConfigurationDelegate_Wait_until_terminated=Wait until terminated +GroupLaunchConfigurationDelegate_Waiting_for_termination=Waiting for termination of ''{0}'' SystemPropertyResolver_0=System property not specified InputStreamMonitor_label=Input Stream Monitor Launch_terminate_failed=Terminate failed diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunch.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunch.java new file mode 100644 index 000000000..df314a18a --- /dev/null +++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunch.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2009, 2016 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + * Freescale Semiconductor + * SSI Schaefer + *******************************************************************************/ +package org.eclipse.debug.internal.core.groups; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchesListener2; +import org.eclipse.debug.core.Launch; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.internal.core.DebugCoreMessages; + +/** + * A specialization of launch to track sub-launches life-cycle, also terminates + * itself when all sub-launches are terminated + * + * @since 3.11 + */ +public class GroupLaunch extends Launch implements ILaunchesListener2 { + + /** + * Whether this process has been terminated + */ + private boolean fTerminated; + + /** + * Keeps track of whether launching has been finished + */ + private boolean fLaunched = false; + + /** + * A map of all our sub-launches and the current processes that belong + * to each one. + */ + private Map<ILaunch, IProcess[]> subLaunches = new HashMap<ILaunch, IProcess[]>(); + + public GroupLaunch(ILaunchConfiguration launchConfiguration, String mode) { + super(launchConfiguration, mode, null); + getLaunchManager().addLaunchListener((ILaunchesListener2) this); + } + + public void markLaunched() { + fLaunched = true; + } + + /** + * Associate the launch + * + * @param subLaunch + */ + public void addSubLaunch(ILaunch subLaunch) { + subLaunches.put(subLaunch, new IProcess[] {}); + } + + private boolean isChild(ILaunch launch) { + for (ILaunch subLaunch : subLaunches.keySet()) { + if (subLaunch == launch) { + return true; + } + } + return false; + } + + /** + * Override default behavior by querying all sub-launches to see if they + * are terminated + * + * @see org.eclipse.debug.core.Launch#isTerminated() + */ + @Override + public boolean isTerminated() { + if (fTerminated) { + return true; + } + + if (subLaunches.size() == 0) { + return false; + } + + for (ILaunch launch : subLaunches.keySet()) { + if (!launch.isTerminated()) { + return false; + } + } + return true; + } + + /** + * Override default behavior by querying all sub-launches if they can be + * terminated + * + * @see org.eclipse.debug.core.Launch#canTerminate() + */ + @Override + public boolean canTerminate() { + if (subLaunches.size() == 0) { + return false; + } + + for (ILaunch launch : subLaunches.keySet()) { + if (launch.canTerminate()) { + return true; + } + } + return false; + } + + /** + * Override default behavior by terminating all sub-launches + * + * @see org.eclipse.debug.core.Launch#terminate() + */ + @Override + public void terminate() throws DebugException { + MultiStatus status = new MultiStatus(DebugPlugin.getUniqueIdentifier(), DebugException.REQUEST_FAILED, DebugCoreMessages.Launch_terminate_failed, null); + + // somebody want's to explicitly kill the whole group, which should + // immediately terminate and stop launching. So allow termination of the + // group when children disappear even if launching has not finished yet. + markLaunched(); + + for (ILaunch launch : subLaunches.keySet()) { + if (launch.canTerminate()) { + try { + launch.terminate(); + } catch (DebugException e) { + status.merge(e.getStatus()); + } + } + } + + if (status.isOK()) { + return; + } + + IStatus[] children = status.getChildren(); + if (children.length == 1) { + throw new DebugException(children[0]); + } + + throw new DebugException(status); + } + + /** + * Handle terminated sub-launch + * + * @param launch + */ + private void launchTerminated(ILaunch launch) { + if (this == launch) { + return; + } + + // Remove sub launch, keeping the processes of the terminated launch + // to show the association and to keep the console content accessible + if (subLaunches.remove(launch) != null) { + // terminate ourselves if this is the last sub launch + if (subLaunches.size() == 0 && fLaunched) { + fTerminated = true; + fireTerminate(); + } + } + } + + @Override + public void launchChanged(ILaunch launch) { + if (this == launch) { + return; + } + + // add/remove processes + if (isChild(launch)) { + // Remove old processes + IProcess[] oldProcesses = subLaunches.get(launch); + IProcess[] newProcesses = launch.getProcesses(); + + // avoid notifications when processes have not changed. + if (!Arrays.equals(oldProcesses, newProcesses)) { + for (IProcess oldProcess : oldProcesses) { + removeProcess(oldProcess); + } + + // Add new processes + for (IProcess newProcess : newProcesses) { + addProcess(newProcess); + } + + // Replace the processes of the changed launch + subLaunches.put(launch, newProcesses); + } + } + } + + @Override + public void launchRemoved(ILaunch launch) { + if (this == launch) { + super.launchRemoved(launch); + // Remove the processes we got from the sub-launches from this + // launch + IProcess[] processes = getProcesses(); + for (IProcess process : processes) { + removeProcess(process); + } + + getLaunchManager().removeLaunchListener((ILaunchesListener2) this); + } + } + + @Override + public void launchesTerminated(ILaunch[] launches) { + for (ILaunch launch : launches) { + launchTerminated(launch); + } + } + + @Override + public void launchesAdded(ILaunch[] launches) { + for (ILaunch launch : launches) { + launchAdded(launch); + } + } + + @Override + public void launchesChanged(ILaunch[] launches) { + for (ILaunch launch : launches) { + launchChanged(launch); + } + } + + @Override + public void launchesRemoved(ILaunch[] launches) { + for (ILaunch launch : launches) { + launchRemoved(launch); + } + } +}
\ No newline at end of file diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchConfigurationDelegate.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchConfigurationDelegate.java new file mode 100644 index 000000000..8d9f5a7d5 --- /dev/null +++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchConfigurationDelegate.java @@ -0,0 +1,343 @@ +/******************************************************************************* + * Copyright (c) 2009, 2016 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + * Freescale Semiconductor + * SSI Schaefer + *******************************************************************************/ +package org.eclipse.debug.internal.core.groups; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.IStatusHandler; +import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2; +import org.eclipse.debug.core.model.LaunchConfigurationDelegate; +import org.eclipse.debug.internal.core.DebugCoreMessages; +import org.eclipse.debug.internal.core.IInternalDebugCoreConstants; +import org.eclipse.debug.internal.core.groups.GroupLaunchElement.GroupElementPostLaunchAction; +import org.eclipse.osgi.util.NLS; + +/** + * Group Launch delegate. Launches each configuration in the user selected mode + * + * @since 3.11 + */ +public class GroupLaunchConfigurationDelegate extends LaunchConfigurationDelegate implements ILaunchConfigurationDelegate2 { + public static final int CODE_GROUP_LAUNCH_START = 233; + public static final int CODE_GROUP_LAUNCH_DONE = 234; + + private static final String NAME_PROP = "name"; //$NON-NLS-1$ + private static final String ENABLED_PROP = "enabled"; //$NON-NLS-1$ + private static final String MODE_PROP = "mode"; //$NON-NLS-1$ + private static final String ACTION_PROP = "action"; //$NON-NLS-1$ + private static final String ACTION_PARAM_PROP = "actionParam"; //$NON-NLS-1$ + private static final String MULTI_LAUNCH_CONSTANTS_PREFIX = "org.eclipse.debug.core.launchGroup"; //$NON-NLS-1$ + + private static final String DEBUG_CORE = "org.eclipse.debug.core"; //$NON-NLS-1$ + + private static final Status UNSUPPORTED_MODE = new Status(IStatus.ERROR, DEBUG_CORE, 230, IInternalDebugCoreConstants.EMPTY_STRING, null); + private static final Status GROUP_ELEMENT_STARTED = new Status(IStatus.OK, DEBUG_CORE, 231, IInternalDebugCoreConstants.EMPTY_STRING, null); + private static final Status GROUP_CYCLE = new Status(IStatus.ERROR, DEBUG_CORE, 232, IInternalDebugCoreConstants.EMPTY_STRING, null); + + private static final Status GROUP_LAUNCH_START = new Status(IStatus.INFO, DEBUG_CORE, CODE_GROUP_LAUNCH_START, IInternalDebugCoreConstants.EMPTY_STRING, null); + private static final Status GROUP_LAUNCH_DONE = new Status(IStatus.INFO, DEBUG_CORE, CODE_GROUP_LAUNCH_DONE, IInternalDebugCoreConstants.EMPTY_STRING, null); + + public GroupLaunchConfigurationDelegate() { + // nothing + } + + @Override + public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException { + return new GroupLaunch(configuration, mode); + } + + @Override + public void launch(ILaunchConfiguration groupConfig, String mode, final ILaunch groupLaunch, IProgressMonitor monitor) throws CoreException { + final GroupLaunch group = (GroupLaunch) groupLaunch; + + IStatusHandler groupStateHandler = DebugPlugin.getDefault().getStatusHandler(GROUP_LAUNCH_START); + groupStateHandler.handleStatus(GROUP_LAUNCH_START, group); + + try { + SubMonitor progress = SubMonitor.convert(monitor, NLS.bind(DebugCoreMessages.GroupLaunchConfigurationDelegate_Launching, groupConfig.getName()), 1000); + + List<GroupLaunchElement> launches = createLaunchElements(groupConfig); + for (int i = 0; i < launches.size(); ++i) { + GroupLaunchElement le = launches.get(i); + + if (!le.enabled) { + continue; + } + + // find launch; if not found, skip (error?) + final ILaunchConfiguration conf = findLaunch(le.name); + if (conf == null) { + continue; + } + + // determine mode for each launch + final String localMode; + if (!le.mode.equals(GroupLaunchElement.MODE_INHERIT)) { + localMode = le.mode; + } else { + localMode = mode; + } + if (!conf.supportsMode(localMode)) { + IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(UNSUPPORTED_MODE); + handler.handleStatus(UNSUPPORTED_MODE, new String[] { + conf.getName(), localMode }); + continue; + } + + if (groupConfig.getName().equals(conf.getName())) { + // loop detected. report as appropriate and die. + IStatusHandler cycleHandler = DebugPlugin.getDefault().getStatusHandler(GROUP_CYCLE); + cycleHandler.handleStatus(GROUP_CYCLE, conf.getName()); + } else { + launchChild(progress.newChild(1000 / launches.size()), group, le, conf, localMode, (i == launches.size() - 1)); + } + + // in case the group has been terminated while waiting in the + // post launch action. + if (group.isTerminated()) { + break; + } + } + + + if (!group.hasChildren()) { + DebugPlugin.getDefault().getLaunchManager().removeLaunch(group); + } + } finally { + // safety net - launching is finished also in case of a problem. + group.markLaunched(); + groupStateHandler.handleStatus(GROUP_LAUNCH_DONE, group); + monitor.done(); + } + } + + private void launchChild(SubMonitor monitor, final GroupLaunch group, GroupLaunchElement le, final ILaunchConfiguration child, final String localMode, boolean lastConfig) throws CoreException { + ILaunch subLaunch = child.launch(localMode, monitor); + group.addSubLaunch(subLaunch); + + // Now that we added the launch in our list, we have already + // received the real launchChanged event, and did not know + // it was part of our list + // So, fake another event now. + group.launchChanged(subLaunch); + + // give handler a chance to perform additional actions after + // launching each of the members. + IStatusHandler postLaunchHandler = DebugPlugin.getDefault().getStatusHandler(GROUP_ELEMENT_STARTED); + postLaunchHandler.handleStatus(GROUP_ELEMENT_STARTED, new ILaunch[] { + group, subLaunch }); + + // if this is the last child, mark the group as "launching finished", so + // that from now on the last terminating child will also terminate the + // group. + if (lastConfig) { + group.markLaunched(); + } + + postLaunchAction(subLaunch, le, monitor); + } + + private void postLaunchAction(ILaunch subLaunch, GroupLaunchElement le, IProgressMonitor monitor) { + switch (le.action) { + case NONE: + return; + case WAIT_FOR_TERMINATION: + monitor.subTask(NLS.bind(DebugCoreMessages.GroupLaunchConfigurationDelegate_Waiting_for_termination, subLaunch.getLaunchConfiguration().getName())); + while (!subLaunch.isTerminated() && !monitor.isCanceled()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + } + monitor.subTask(""); //$NON-NLS-1$ + break; + case DELAY: + Integer waitSecs = (Integer) le.actionParam; + if (waitSecs != null) { + monitor.subTask(NLS.bind(DebugCoreMessages.GroupLaunchConfigurationDelegate_Delaying, waitSecs.toString())); + try { + Thread.sleep(waitSecs * 1000); // param is milliseconds + } catch (InterruptedException e) { + // ok + } + } + break; + + default: + assert false : "new post launch action type is missing logic"; //$NON-NLS-1$ + } + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.debug.core.model.LaunchConfigurationDelegate#buildProjects( + * org.eclipse.core.resources.IProject[], + * org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected void buildProjects(IProject[] projects, IProgressMonitor monitor) throws CoreException { + // do nothing, project can be rebuild for each launch individually + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.debug.core.model.LaunchConfigurationDelegate#buildForLaunch( + * org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, + * org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException { + // not build for this one + return false; + } + + protected static ILaunchConfiguration findLaunch(String name) throws CoreException { + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfiguration[] launchConfigurations = launchManager.getLaunchConfigurations(); + for (int i = 0; i < launchConfigurations.length; i++) { + ILaunchConfiguration lConf = launchConfigurations[i]; + if (lConf.getName().equals(name)) { + return lConf; + } + } + return null; + } + + /** + * (Re-)reads all {@link GroupLaunchElement}s from a + * {@link ILaunchConfiguration}s attributes. + * + * @param configuration the launch configuration; this must be of the type + * handled by this delegate + * @return all {@link GroupLaunchElement}s found in the given + * {@link ILaunchConfiguration}s attributes. Never + * <code>null</code>. + */ + public static List<GroupLaunchElement> createLaunchElements(ILaunchConfiguration configuration) { + List<GroupLaunchElement> result = new ArrayList<>(); + try { + Map<?, ?> attrs = configuration.getAttributes(); + for (Iterator<?> iterator = attrs.keySet().iterator(); iterator.hasNext();) { + String attr = (String) iterator.next(); + try { + if (attr.startsWith(GroupLaunchConfigurationDelegate.MULTI_LAUNCH_CONSTANTS_PREFIX)) { + String prop = attr.substring(GroupLaunchConfigurationDelegate.MULTI_LAUNCH_CONSTANTS_PREFIX.length() + 1); + int k = prop.indexOf('.'); + String num = prop.substring(0, k); + int index = Integer.parseInt(num); + String name = prop.substring(k + 1); + if (name.equals(NAME_PROP)) { + GroupLaunchElement el = new GroupLaunchElement(); + el.index = index; + el.name = (String) attrs.get(attr); + + Object actionParam = null; + String actionStr = (String) attrs.get(getProp(index, ACTION_PROP)); + + GroupElementPostLaunchAction action; + try { + action = GroupElementPostLaunchAction.valueOf(actionStr); + } catch (Exception e) { + action = GroupElementPostLaunchAction.NONE; + } + if (action == GroupElementPostLaunchAction.DELAY) { + try { + actionParam = Integer.parseInt((String) attrs.get(getProp(index, ACTION_PARAM_PROP))); + } catch (NumberFormatException exc) { + DebugPlugin.log(exc); + } + } + el.action = action; + el.actionParam = actionParam; + el.mode = (String) attrs.get(getProp(index, MODE_PROP)); + el.enabled = (Boolean) attrs.get(getProp(index, ENABLED_PROP)); + try { + el.data = findLaunch(el.name); + } catch (Exception e) { + el.data = null; + } + while (index >= result.size()) { + result.add(null); + } + result.set(index, el); + + } + } + } catch (Exception e) { + DebugPlugin.log(e); + } + } + } catch (CoreException e) { + DebugPlugin.log(e); + } + return result; + } + + public static void storeLaunchElements(ILaunchConfigurationWorkingCopy configuration, List<GroupLaunchElement> input) { + int i = 0; + removeLaunchElements(configuration); + for (GroupLaunchElement el : input) { + if (el == null) { + continue; + } + configuration.setAttribute(GroupLaunchConfigurationDelegate.getProp(i, NAME_PROP), el.name); + configuration.setAttribute(GroupLaunchConfigurationDelegate.getProp(i, ACTION_PROP), el.action.toString()); + // note: the saving of the action param will need to be enhanced if + // ever an action type is introduced that uses something that can't + // be reconstructed from its toString() + configuration.setAttribute(GroupLaunchConfigurationDelegate.getProp(i, ACTION_PARAM_PROP), el.actionParam != null ? el.actionParam.toString() : null); + configuration.setAttribute(GroupLaunchConfigurationDelegate.getProp(i, MODE_PROP), el.mode); + configuration.setAttribute(GroupLaunchConfigurationDelegate.getProp(i, ENABLED_PROP), el.enabled); + i++; + } + } + + public static void removeLaunchElements(ILaunchConfigurationWorkingCopy configuration) { + try { + Map<?, ?> attrs = configuration.getAttributes(); + for (Iterator<?> iterator = attrs.keySet().iterator(); iterator.hasNext();) { + String attr = (String) iterator.next(); + try { + if (attr.startsWith(GroupLaunchConfigurationDelegate.MULTI_LAUNCH_CONSTANTS_PREFIX)) { + configuration.removeAttribute(attr); + } + } catch (Exception e) { + DebugPlugin.log(e); + } + } + } catch (CoreException e) { + DebugPlugin.log(e); + } + } + + public static String getProp(int index, String string) { + return GroupLaunchConfigurationDelegate.MULTI_LAUNCH_CONSTANTS_PREFIX + "." + index + "." + string; //$NON-NLS-1$ //$NON-NLS-2$ + } +} diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchElement.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchElement.java new file mode 100644 index 000000000..310a8d368 --- /dev/null +++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchElement.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2009, 2016 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + * Freescale Semiconductor + * SSI Schaefer + *******************************************************************************/ +package org.eclipse.debug.internal.core.groups; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.internal.core.DebugCoreMessages; + +/** + * Represents a single child element of a launch group. + * + * @since 3.11 + */ +public class GroupLaunchElement { + public static final String MODE_INHERIT = "inherit"; //$NON-NLS-1$ + + /** + * Describes the possible post-launch actions for each + * {@link GroupLaunchElement}. + * <p> + * These actions get performed after the associated + * {@link GroupLaunchElement} has been launched, before the next one is + * launched (or launching is finished). + */ + public static enum GroupElementPostLaunchAction { + NONE(DebugCoreMessages.GroupLaunchConfigurationDelegate_None), // + WAIT_FOR_TERMINATION(DebugCoreMessages.GroupLaunchConfigurationDelegate_Wait_until_terminated), // + DELAY(DebugCoreMessages.GroupLaunchConfigurationDelegate_Delay); + + private final String description; + + private GroupElementPostLaunchAction(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + public static GroupLaunchElement.GroupElementPostLaunchAction valueOfDescription(String desc) { + for (GroupLaunchElement.GroupElementPostLaunchAction e : values()) { + if (e.description.equals(desc)) { + return e; + } + } + return NONE; + } + } + + public int index; + public boolean enabled = true; + public String mode = MODE_INHERIT; + public GroupLaunchElement.GroupElementPostLaunchAction action = GroupElementPostLaunchAction.NONE; + public Object actionParam; + public String name; + public ILaunchConfiguration data; +}
\ No newline at end of file diff --git a/org.eclipse.debug.core/plugin.properties b/org.eclipse.debug.core/plugin.properties index 18642a943..92558a352 100644 --- a/org.eclipse.debug.core/plugin.properties +++ b/org.eclipse.debug.core/plugin.properties @@ -69,3 +69,6 @@ current_date.description=Returns the current system time formatted as yyyyMMdd_H LineBreakpoint.name = Line Breakpoint Breakpoint.name = Breakpoint + +GroupLaunch.name=Launch Group +GroupLaunch.description=Launch several other configurations sequentially diff --git a/org.eclipse.debug.core/plugin.xml b/org.eclipse.debug.core/plugin.xml index 009a27b60..bd793e3f8 100644 --- a/org.eclipse.debug.core/plugin.xml +++ b/org.eclipse.debug.core/plugin.xml @@ -258,4 +258,23 @@ id="org.eclipse.debug.core.propertyTesters.launchable"> </propertyTester> </extension> + <extension + point="org.eclipse.debug.core.launchDelegates"> + <launchDelegate + delegate="org.eclipse.debug.internal.core.groups.GroupLaunchConfigurationDelegate" + delegateDescription="%GroupLaunch.description" + id="org.eclipse.debug.core.groups.GroupLaunchConfigurationDelegate" + modes="run,debug,profile" + name="%GroupLaunch.name" + type="org.eclipse.debug.core.groups.GroupLaunchConfigurationType"> + </launchDelegate> + </extension> + <extension + point="org.eclipse.debug.core.launchConfigurationTypes"> + <launchConfigurationType + id="org.eclipse.debug.core.groups.GroupLaunchConfigurationType" + name="%GroupLaunch.name" + public="true"> + </launchConfigurationType> + </extension> </plugin> |