Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Duft2016-05-11 09:52:28 -0400
committerMarkus Duft2016-11-30 04:42:25 -0500
commit97be8772a897b47a48b2d4b6ef33b46811408b7f (patch)
treeef2793a75f11741be425b7d236695df5f0f252d2 /org.eclipse.debug.core
parent66da2950cc347953d38ae225f82b5f23f5e960e7 (diff)
downloadeclipse.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')
-rw-r--r--org.eclipse.debug.core/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.java14
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/internal/core/DebugCoreMessages.properties10
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunch.java253
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchConfigurationDelegate.java343
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/internal/core/groups/GroupLaunchElement.java66
-rw-r--r--org.eclipse.debug.core/plugin.properties3
-rw-r--r--org.eclipse.debug.core/plugin.xml19
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>

Back to the top