Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/FullQualifiedId.java169
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperAttributeUtil.java283
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperManager.java73
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/activator/CoreBundleActivator.java72
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStep.java209
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepExecutor.java190
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepGroup.java71
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepper.java804
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroup.java814
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroupable.java207
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContext.java41
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextManipulator.java29
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStep.java66
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepExecutor.java33
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroup.java48
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupIterator.java59
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupable.java82
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedContextStep.java92
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IFullQualifiedId.java55
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepper.java120
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IVariantDelegate.java31
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/tracing/ITraceIds.java26
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepExtensionPointManager.java83
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionPointManager.java93
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionProxy.java69
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepperExtensionPointManager.java83
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.java61
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.properties36
28 files changed, 3999 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/FullQualifiedId.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/FullQualifiedId.java
new file mode 100644
index 000000000..fb7fb052c
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/FullQualifiedId.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
+
+/**
+ * Full qualified id implementation.
+ */
+public class FullQualifiedId implements IFullQualifiedId {
+ // The list of id's
+ private final List<IdData> ids = new ArrayList<IdData>();
+
+ // Inner class describing the data of an id.
+ private class IdData {
+ public String type = null;
+ public String id = null;
+ public String secondaryId = null;
+
+ /**
+ * Constructor.
+ *
+ * @param type The id type.
+ * @param id The id. Must not be <code>null</code>.
+ * @param secondaryId The secondary id.
+ */
+ public IdData(String type, String id, String secondaryId) {
+ Assert.isNotNull(id);
+
+ this.type = type;
+ this.id = id;
+ this.secondaryId = secondaryId;
+ }
+
+ /**
+ * Creates a string representation of the id and the given children.
+ */
+ public String toString(String children) {
+ String typeStr = type != null && type.trim().length() > 0 ? type.trim() : "ID"; //$NON-NLS-1$
+
+ StringBuilder toString = new StringBuilder();
+ toString.append('<');
+ toString.append(typeStr);
+ toString.append(" id=\""); //$NON-NLS-1$
+ toString.append(id.trim());
+ toString.append('"');
+ if (secondaryId != null && secondaryId.trim().length() > 0) {
+ toString.append(" secondaryId=\""); //$NON-NLS-1$
+ toString.append(secondaryId.trim());
+ toString.append('"');
+ }
+ if (children != null && children.trim().length() > 0) {
+ toString.append('>');
+ toString.append(children);
+ toString.append("</"); //$NON-NLS-1$
+ toString.append(type);
+ toString.append('>');
+ }
+ else {
+ toString.append("/>"); //$NON-NLS-1$
+ }
+ return toString.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return toString(null);
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ public FullQualifiedId(String type, String id, String secondaryId) {
+ ids.add(new IdData(type, id, secondaryId));
+ }
+
+ /*
+ * Private constructor for child and parent creation.
+ * To create the parent, id has to be null!
+ */
+ private FullQualifiedId(IdData[] parentData, String type, String id, String secondaryId) {
+ for (IdData parent : parentData) {
+ ids.add(new IdData(parent.type, parent.id, parent.secondaryId));
+ }
+ if (id != null) {
+ ids.add(new IdData(type, id, secondaryId));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId#createChildId(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public IFullQualifiedId createChildId(String type, String id, String secondaryId) {
+ return new FullQualifiedId(ids.toArray(new IdData[ids.size()]), type, id, secondaryId);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId#getType()
+ */
+ @Override
+ public String getType() {
+ return getIdData().type;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId#getId()
+ */
+ @Override
+ public String getId() {
+ return getIdData().id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId#getSecondaryId()
+ */
+ @Override
+ public String getSecondaryId() {
+ return getIdData().secondaryId;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId#getParentId()
+ */
+ @Override
+ public IFullQualifiedId getParentId() {
+ if (ids.size() > 1) {
+ return new FullQualifiedId(ids.subList(0, ids.size() - 1)
+ .toArray(new IdData[ids.size() - 1]), null, null, null);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ Assert.isTrue(!ids.isEmpty());
+
+ String toString = getIdData().toString();
+ if (ids.size() > 1) {
+ for (int i = ids.size() - 1; i > 0; i--) {
+ toString = ids.get(i - 1).toString(toString);
+ }
+ }
+ return toString;
+ }
+
+ private IdData getIdData() {
+ Assert.isTrue(!ids.isEmpty());
+ return ids.get(ids.size() - 1);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperAttributeUtil.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperAttributeUtil.java
new file mode 100644
index 000000000..85515ea93
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperAttributeUtil.java
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * A stepper attributes utility provides a set of static methods
+ * to access the attributes of a step.
+ */
+public class StepperAttributeUtil {
+ /**
+ * Get the full qualified key to get or set data in the data.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @return The full qualified key.
+ */
+ protected final static String getFullQualifiedKey(String key, IFullQualifiedId fullQualifiedId, Object data) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ return (fullQualifiedId != null ? fullQualifiedId.toString() : "") + key; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the properties container for the given data object.
+ *
+ * @param data The data object or <code>null</code>.
+ * @return The properties container or <code>null</code> if the container cannot be determined.
+ */
+ private static IPropertiesContainer getPropertiesContainer(Object data) {
+ if (data instanceof IPropertiesContainer) {
+ return (IPropertiesContainer) data;
+ }
+ if (data instanceof IAdaptable) {
+ return (IPropertiesContainer)((IAdaptable)data).getAdapter(IPropertiesContainer.class);
+ }
+ return null;
+ }
+
+ /**
+ * Get a property from the data. If the value is not stored within the full qualified id, the
+ * value stored within the parent id will be returned.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @return The property value or <code>null</code> if either the data has no property container
+ * or the property is not set.
+ */
+ public final static Object getProperty(String key, IFullQualifiedId fullQualifiedId, Object data) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return null;
+ }
+ if (fullQualifiedId == null || container
+ .getProperty(getFullQualifiedKey(key, fullQualifiedId, data)) != null) {
+ return container.getProperty(getFullQualifiedKey(key, fullQualifiedId, data));
+ }
+ return container.getProperty(getFullQualifiedKey(key, fullQualifiedId.getParentId(), data));
+ }
+
+ /**
+ * Get a string property from the data. If the value is not stored within the full qualified id,
+ * the value stored within the parent id will be returned.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @return The string property value or <code>null</code> if either the data has no property
+ * container or the property is not set.
+ */
+ public final static String getStringProperty(String key, IFullQualifiedId fullQualifiedId, Object data) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return null;
+ }
+ if (fullQualifiedId == null || container.getProperty(getFullQualifiedKey(key, fullQualifiedId, data)) != null) {
+ return container.getStringProperty(getFullQualifiedKey(key, fullQualifiedId, data));
+ }
+ return container.getStringProperty(getFullQualifiedKey(key, fullQualifiedId.getParentId(), data));
+ }
+
+ /**
+ * Get a boolean property from the data. If the value is not stored within the full qualified
+ * id, the value stored within the parent id will be returned.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @return The boolean property value or <code>false</code> if either the data has no property
+ * container or the property is not set.
+ */
+ public final static boolean getBooleanProperty(String key, IFullQualifiedId fullQualifiedId, Object data) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return false;
+ }
+ if (fullQualifiedId == null || container.getProperty(getFullQualifiedKey(key, fullQualifiedId, data)) != null) {
+ return container.getBooleanProperty(getFullQualifiedKey(key, fullQualifiedId, data));
+ }
+ return container.getBooleanProperty(getFullQualifiedKey(key, fullQualifiedId.getParentId(), data));
+ }
+
+ /**
+ * Get a int property from the data.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @return The int property value or <code>-1</code> if either the data has no property
+ * container or the property is not set.
+ */
+ public final static int getIntProperty(String key, IFullQualifiedId fullQualifiedId, Object data) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return -1;
+ }
+ if (fullQualifiedId == null || container.getProperty(getFullQualifiedKey(key, fullQualifiedId, data)) != null) {
+ return container.getIntProperty(getFullQualifiedKey(key, fullQualifiedId, data));
+ }
+ return container.getIntProperty(getFullQualifiedKey(key, fullQualifiedId.getParentId(), data));
+ }
+
+ /**
+ * Check if a property is set.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @return <code>true</code> if a property value is set.
+ */
+ public final static boolean isPropertySet(String key, IFullQualifiedId fullQualifiedId, Object data) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return false;
+ }
+ return container.getProperty(getFullQualifiedKey(key, fullQualifiedId, data)) != null;
+ }
+
+ /**
+ * Set a property value to the data.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @param value The new value.
+ * @return <code>true</code> if the value was set.
+ */
+ public final static boolean setProperty(String key, IFullQualifiedId fullQualifiedId, Object data, Object value) {
+ return setProperty(key, fullQualifiedId, data, value, false);
+ }
+
+ /**
+ * Set a property value to the data and optional share it through the parent full qualified id.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @param value The new value.
+ * @param share When <code>true</code>, the value is also stored within the parent full
+ * qualified id to share the value with other steps within the same parent (group).
+ * @return <code>true</code> if the value was set.
+ */
+ public final static boolean setProperty(String key, IFullQualifiedId fullQualifiedId, Object data, Object value, boolean share) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return false;
+ }
+ if (share && fullQualifiedId != null) {
+ container.setProperty(getFullQualifiedKey(key, fullQualifiedId.getParentId(), data), value);
+ }
+ return container.setProperty(getFullQualifiedKey(key, fullQualifiedId, data), value);
+ }
+
+ /**
+ * Set a boolean property value to the data.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @param value The new boolean value.
+ * @return <code>true</code> if the value was set.
+ */
+ public final static boolean setProperty(String key, IFullQualifiedId fullQualifiedId, Object data, boolean value) {
+ return setProperty(key, fullQualifiedId, data, value, false);
+ }
+
+ /**
+ * Set a boolean property value to the data and optional share it through the parent full
+ * qualified id.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @param value The new boolean value.
+ * @param share When <code>true</code>, the value is also stored within the parent full
+ * qualified id to share the value with other steps within the same parent (group).
+ * @return <code>true</code> if the value was set.
+ */
+ public final static boolean setProperty(String key, IFullQualifiedId fullQualifiedId, Object data, boolean value, boolean share) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return false;
+ }
+ if (share && fullQualifiedId != null) {
+ container.setProperty(getFullQualifiedKey(key, fullQualifiedId.getParentId(), data), value);
+ }
+ return container.setProperty(getFullQualifiedKey(key, fullQualifiedId, data), value);
+ }
+
+ /**
+ * Set a int property value to the data.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @param value The new int value.
+ * @return <code>true</code> if the value was set.
+ */
+ public final static boolean setProperty(String key, IFullQualifiedId fullQualifiedId, Object data, int value) {
+ return setProperty(key, fullQualifiedId, data, value, false);
+ }
+
+ /**
+ * Set an int property value to the data and optional share it through the parent full qualified
+ * id.
+ *
+ * @param key The key for the value.
+ * @param fullQualifiedId The full qualified id for this step.
+ * @param data The data.
+ * @param value The new int value.
+ * @param share When <code>true</code>, the value is also stored within the parent full
+ * qualified id to share the value with other steps within the same parent (group).
+ * @return <code>true</code> if the value was set.
+ */
+ public final static boolean setProperty(String key, IFullQualifiedId fullQualifiedId, Object data, int value, boolean share) {
+ Assert.isNotNull(key);
+ Assert.isNotNull(data);
+
+ IPropertiesContainer container = getPropertiesContainer(data);
+ if (container == null) {
+ return false;
+ }
+ if (share && fullQualifiedId != null) {
+ container.setProperty(getFullQualifiedKey(key, fullQualifiedId.getParentId(), data), value);
+ }
+ return container.setProperty(getFullQualifiedKey(key, fullQualifiedId, data), value);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperManager.java
new file mode 100644
index 000000000..c84d3da7a
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/StepperManager.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper;
+
+import org.eclipse.tcf.te.runtime.stepper.internal.extensions.StepExtensionPointManager;
+import org.eclipse.tcf.te.runtime.stepper.internal.extensions.StepGroupExtensionPointManager;
+import org.eclipse.tcf.te.runtime.stepper.internal.extensions.StepperExtensionPointManager;
+
+/**
+ * Central manager providing access to the stepper, steps and step groups
+ * contributed via extension points.
+ */
+public final class StepperManager {
+ // References to the extension point managers
+ private final StepExtensionPointManager stepExtManager = new StepExtensionPointManager();
+ private final StepperExtensionPointManager stepperExtManager = new StepperExtensionPointManager();
+ private final StepGroupExtensionPointManager stepGroupExtManager = new StepGroupExtensionPointManager();
+
+ /*
+ * Thread save singleton instance creation.
+ */
+ private static class LazyInstance {
+ public static StepperManager instance = new StepperManager();
+ }
+
+ /**
+ * Constructor.
+ */
+ StepperManager() {
+ super();
+ }
+
+ /**
+ * Returns the singleton instance of the manager.
+ */
+ public static StepperManager getInstance() {
+ return LazyInstance.instance;
+ }
+
+ /**
+ * Returns the step extension point manager instance.
+ *
+ * @return The step extension point manager instance.
+ */
+ public StepExtensionPointManager getStepExtManager() {
+ return stepExtManager;
+ }
+
+ /**
+ * Returns the stepper extension point manager instance.
+ *
+ * @return The stepper extension point manager instance.
+ */
+ public StepperExtensionPointManager getStepperExtManager() {
+ return stepperExtManager;
+ }
+
+ /**
+ * Returns the step group extension point manager instance.
+ *
+ * @return The step group extension point manager instance.
+ */
+ public StepGroupExtensionPointManager getStepGroupExtManager() {
+ return stepGroupExtManager;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/activator/CoreBundleActivator.java
new file mode 100644
index 000000000..6744469e0
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/activator/CoreBundleActivator.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.activator;
+
+import org.eclipse.tcf.te.runtime.tracing.TraceHandler;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class CoreBundleActivator implements BundleActivator {
+ // The bundle context
+ private static BundleContext context;
+ // The trace handler instance
+ private static TraceHandler traceHandler;
+
+ /**
+ * Returns the bundle context
+ *
+ * @return the bundle context
+ */
+ public static BundleContext getContext() {
+ return context;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getContext() != null && getContext().getBundle() != null) {
+ return getContext().getBundle().getSymbolicName();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the bundles trace handler.
+ *
+ * @return The bundles trace handler.
+ */
+ public static TraceHandler getTraceHandler() {
+ if (traceHandler == null) {
+ traceHandler = new TraceHandler(getUniqueIdentifier());
+ }
+ return traceHandler;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = bundleContext;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = null;
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStep.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStep.java
new file mode 100644
index 000000000..bee21a04e
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStep.java
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.extensions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tcf.te.runtime.stepper.StepperAttributeUtil;
+import org.eclipse.tcf.te.runtime.stepper.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContext;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
+import org.eclipse.tcf.te.runtime.stepper.nls.Messages;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtension;
+import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * An abstract step implementation.
+ */
+public abstract class AbstractContextStep extends ExecutableExtension implements IExtendedContextStep {
+ // List of string id's of the step dependencies.
+ private final List<String> dependencies = new ArrayList<String>();
+
+ /**
+ * The suffix to append to the full qualified step id to
+ * get the delayed status object.
+ */
+ public final static String SUFFIX_DELAYED_STATUS = "delayedStatus"; //$NON-NLS-1$
+
+ /**
+ * The suffix to append to the full qualified step id to
+ * get the step target event listener.
+ */
+ public final static String SUFFIX_EVENT_LISTENER = "eventListener"; //$NON-NLS-1$
+
+ /**
+ * The suffix to append to the full qualified step id to
+ * get the operational flag.
+ */
+ public final static String SUFFIX_OPERATIONAL = "operational"; //$NON-NLS-1$
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep#isSingleton()
+ */
+ @Override
+ public boolean isSingleton() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.ExecutableExtension#doSetInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void doSetInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ super.doSetInitializationData(config, propertyName, data);
+
+ // Read in the list of required step or step id's if specified.
+ dependencies.clear();
+ IConfigurationElement[] requires = config.getChildren("requires"); //$NON-NLS-1$
+ for (IConfigurationElement require : requires) {
+ String value = require.getAttribute("id"); //$NON-NLS-1$
+ if (value == null || value.trim().length() == 0) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ 0,
+ NLS.bind(Messages.AbstractContextStep_error_missingRequiredAttribute, "dependency id (requires)", getLabel()), //$NON-NLS-1$
+ null));
+ }
+ if (!dependencies.contains(value.trim())) {
+ dependencies.add(value.trim());
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep#initializeFrom(org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public void initializeFrom(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) {
+ Assert.isNotNull(context);
+ Assert.isNotNull(data);
+ Assert.isNotNull(fullQualifiedId);
+ Assert.isNotNull(monitor);
+
+ StepperAttributeUtil.setProperty(SUFFIX_DELAYED_STATUS, fullQualifiedId, data, false);
+ StepperAttributeUtil.setProperty(SUFFIX_OPERATIONAL, fullQualifiedId, data, true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep#cleanup(org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public void cleanup(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) {
+ StepperAttributeUtil.setProperty(SUFFIX_DELAYED_STATUS, fullQualifiedId, data, false);
+ StepperAttributeUtil.setProperty(SUFFIX_OPERATIONAL, fullQualifiedId, data, false);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep#rollback(org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.core.runtime.IStatus, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.core.runtime.IProgressMonitor, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
+ */
+ @Override
+ public void rollback(IContext context, IPropertiesContainer data, IStatus status, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor, ICallback callback) {
+ if (callback != null) callback.done(this, Status.OK_STATUS);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep#getTotalWork(org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer)
+ */
+ @Override
+ public int getTotalWork(IContext context, IPropertiesContainer data) {
+ return 10;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep#getDependencies()
+ */
+ @Override
+ public String[] getDependencies() {
+ return dependencies.toArray(new String[dependencies.size()]);
+ }
+
+ /**
+ * Invoke the specified callback and pass on the status and user defined data object.
+ *
+ * @param stepData
+ * @param fullQualifiedId
+ * @param callback
+ * @param status
+ * @param data
+ */
+ public final void callback(IPropertiesContainer stepData, IFullQualifiedId fullQualifiedId, ICallback callback, IStatus status, Object data) {
+ Assert.isNotNull(stepData);
+ Assert.isNotNull(fullQualifiedId);
+ Assert.isNotNull(callback);
+ Assert.isNotNull(status);
+
+ // Check if there have been states delayed
+ IStatus delayedStatus = (IStatus)StepperAttributeUtil.getProperty(SUFFIX_DELAYED_STATUS, fullQualifiedId, stepData);
+ if (status.getSeverity() != IStatus.ERROR && status.getSeverity() != IStatus.CANCEL && delayedStatus != null) {
+ if (status.getSeverity() == IStatus.OK) {
+ // replace the whole status with the delayed one
+ status = delayedStatus;
+ } else {
+ // Merge the passed in status and the delayed stati together
+ IStatus[] delayedStati = delayedStatus instanceof MultiStatus ? ((MultiStatus)delayedStatus).getChildren() : new IStatus[] { delayedStatus };
+ if (delayedStati.length > 0) {
+ if (!(status instanceof MultiStatus)) {
+ status = new MultiStatus(CoreBundleActivator.getUniqueIdentifier(), 0,
+ NLS.bind(Messages.AbstractContextStep_warning_stepFinishedWithWarnings, getLabel()),
+ null);
+
+ }
+ // At this point the status must be a MultiStatus
+ Assert.isTrue(status instanceof MultiStatus);
+ for (IStatus delayed : delayedStati) {
+ ((MultiStatus)status).merge(delayed);
+ }
+ }
+
+ }
+ }
+
+ // Finally invoke the callback
+ callback.setProperty(IContextStep.CALLBACK_PROPERTY_DATA, data);
+ callback.done(this, status);
+ }
+
+ /**
+ * Delay the reporting of the given status till the associated launch callback is invoked. If
+ * delayed states are available and the callback is invoked not with an error status, the
+ * delayed states will be reported instead.
+ *
+ * @param status The status to delay. Must be not <code>null</code> and either a warning or info status.
+ */
+ protected void delayStatus(IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IStatus status) {
+ Assert.isNotNull(status);
+ Assert.isTrue(status.getSeverity() == IStatus.WARNING || status.getSeverity() == IStatus.INFO);
+
+ IStatus delayedStatus = (IStatus)StepperAttributeUtil.getProperty(SUFFIX_DELAYED_STATUS, fullQualifiedId, data);
+ if (delayedStatus == null) {
+ StepperAttributeUtil.setProperty(SUFFIX_DELAYED_STATUS, fullQualifiedId, data, status);
+ } else if (delayedStatus instanceof MultiStatus) {
+ ((MultiStatus)delayedStatus).merge(status);
+ } else {
+ MultiStatus multiStatus = new MultiStatus(CoreBundleActivator.getUniqueIdentifier(), 0,
+ new IStatus[] { delayedStatus, status },
+ "", //$NON-NLS-1$
+ null);
+ StepperAttributeUtil.setProperty(SUFFIX_DELAYED_STATUS, fullQualifiedId, data, multiStatus);
+ }
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepExecutor.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepExecutor.java
new file mode 100644
index 000000000..1c02471dd
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepExecutor.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.extensions;
+
+import java.util.Date;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.tcf.te.runtime.stepper.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContext;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepExecutor;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.tracing.ITraceIds;
+import org.eclipse.tcf.te.runtime.callback.Callback;
+import org.eclipse.tcf.te.runtime.concurrent.util.ExecutorsUtil;
+import org.eclipse.tcf.te.runtime.interfaces.ISharedConstants;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+import org.eclipse.tcf.te.runtime.utils.ProgressHelper;
+import org.eclipse.tcf.te.runtime.utils.StatusHelper;
+
+/**
+ * Step executor implementation.
+ * <p>
+ * The step executor is responsible for initiating the execution of a single step. The executor
+ * creates and associated the step callback and blocks the execution till the executed step invoked
+ * the callback.
+ * <p>
+ * The step executor is passing any status thrown by the executed step to the parent stepper
+ * instance for handling.
+ * <p>
+ * If the step to execute is of type {@link IExtendedContextStep}, the step executor is calling
+ * {@link IExtendedContextStep#initializeFrom(org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, Object, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, IProgressMonitor)} and
+ * {@link IExtendedContextStep#validateExecute(org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, Object, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, IProgressMonitor)} before calling
+ * {@link IContextStep#execute(org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, Object, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, IProgressMonitor, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)}.
+ * <p>
+ * The methods will be called within the current step executor thread.
+ * <p>
+ * The stepper implementation can be traced and profiled by setting the debug options:
+ * <ul>
+ * <li><i>org.eclipse.tcf.te.runtime.stepper/trace/stepping</i></li>
+ * <li><i>org.eclipse.tcf.te.runtime.stepper/profile/stepping</i></li>
+ * </ul>
+ */
+public abstract class AbstractContextStepExecutor implements IContextStepExecutor {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepExecutor#execute(org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.tcf.te.runtime.stepper.interfaces.IContext, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public final void execute(IContextStep step, IFullQualifiedId id, final IContext context, final IPropertiesContainer data, IProgressMonitor progress) throws CoreException {
+ Assert.isNotNull(step);
+ Assert.isNotNull(id);
+ Assert.isNotNull(context);
+ Assert.isNotNull(data);
+ Assert.isNotNull(progress);
+
+ long startTime = System.currentTimeMillis();
+
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepExecutor#execute: *** START (" + step.getLabel() + ")", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ CoreBundleActivator.getTraceHandler().trace(" [" + ISharedConstants.TIME_FORMAT.format(new Date(startTime)) + "]" //$NON-NLS-1$ //$NON-NLS-2$
+ + " ***", //$NON-NLS-1$
+ 0, ITraceIds.PROFILE_STEPPING, IStatus.WARNING, this);
+
+ int ticksToUse = (step instanceof IExtendedContextStep) ? ((IExtendedContextStep)step).getTotalWork(context, data) : IProgressMonitor.UNKNOWN;
+ progress = ProgressHelper.getProgressMonitor(progress, ticksToUse);
+ ProgressHelper.beginTask(progress, step.getLabel(), ticksToUse);
+
+ // Create the handler (and the callback) for the current step
+ final Callback callback = new Callback();
+
+ // Catch any exception that might occur during execution.
+ // Errors are passed through by definition.
+ try {
+ // Execute the step. Spawn to the dispatch thread if necessary.
+ if (step instanceof IExtendedContextStep) {
+ IExtendedContextStep extendedStep = (IExtendedContextStep)step;
+
+ // IExtendedContextStep provides protocol for initialization and validation.
+ extendedStep.initializeFrom(context, data, id, progress);
+
+ // step is initialized -> now validate for execution.
+ // If the step if not valid for execution, validateExecute is throwing an exception.
+ extendedStep.validateExecute(context, data, id, progress);
+ }
+
+ step.execute(context, data, id, progress, callback);
+
+ // Wait till the step finished, an execution occurred or the
+ // user hit cancel on the progress monitor.
+ ExecutorsUtil.waitAndExecute(0, callback.getDoneConditionTester(null));
+
+ // Check the status of the step
+ normalizeStatus(step, id, context, data, callback.getStatus());
+ }
+ catch (Exception e) {
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepExecutor#execute: Exception catched: class ='" + e.getClass().getName() + "'" //$NON-NLS-1$ //$NON-NLS-2$
+ + ", message = '" + e.getLocalizedMessage() + "'" //$NON-NLS-1$ //$NON-NLS-2$
+ + ", cause = " //$NON-NLS-1$
+ + (e instanceof CoreException ? ((CoreException)e).getStatus().getException() : e.getCause()),
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+
+ // If the exception is a CoreException by itself, just re-throw
+ if (e instanceof CoreException) {
+ // Check if the message does need normalization
+ if (isExceptionMessageFormatted(e.getLocalizedMessage())) {
+ throw (CoreException)e;
+ }
+ // We have to normalize the status message first
+ normalizeStatus(step, id, context, data, ((CoreException)e).getStatus());
+ } else {
+ // all other exceptions are repackaged within a CoreException
+ normalizeStatus(step, id, context, data, StatusHelper.getStatus(e));
+ }
+ }
+ finally {
+ if (!progress.isCanceled()) {
+ progress.done();
+ }
+
+ // Give the step a chance for cleanup
+ if (step instanceof IExtendedContextStep) {
+ ((IExtendedContextStep)step).cleanup(context, data, id, progress);
+ }
+
+ long endTime = System.currentTimeMillis();
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepExecutor#execute: *** DONE (" + step.getLabel() + ")", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ CoreBundleActivator.getTraceHandler().trace(" [" + ISharedConstants.TIME_FORMAT.format(new Date(endTime)) //$NON-NLS-1$
+ + " , delay = " + (endTime - startTime) + " ms]" //$NON-NLS-1$ //$NON-NLS-2$
+ + " ***", //$NON-NLS-1$
+ 0, ITraceIds.PROFILE_STEPPING, IStatus.WARNING, this);
+ }
+ }
+
+ private void normalizeStatus(IContextStep step, IFullQualifiedId id, IContext context , IPropertiesContainer data, IStatus status) throws CoreException {
+ Assert.isNotNull(context);
+ Assert.isNotNull(data);
+ Assert.isNotNull(id);
+ Assert.isNotNull(step);
+
+ if (status == null || status.isOK()) {
+ return;
+ }
+
+ switch (status.getSeverity()) {
+ case IStatus.CANCEL:
+ throw new OperationCanceledException(status.getMessage());
+ default:
+ String message = formatMessage(status.getMessage(), status.getSeverity(), step, id, context, data);
+ status = new Status(status.getSeverity(), status.getPlugin(), status.getCode(), message != null ? message : status.getMessage(), status.getException());
+ throw new CoreException(status);
+ }
+ }
+
+ /**
+ * Checks if the given message is already formatted to get displayed to the user.
+ *
+ * @param message The message. Must not be <code>null</code>.
+ * @return <code>True</code> if the message is already formatted to get displayed to the user, <code>false</code> otherwise.
+ */
+ protected abstract boolean isExceptionMessageFormatted(String message);
+
+ /**
+ * Format the message depending on the severity.
+ *
+ * @param message The message to format.
+ * @param severity The message severity.
+ * @param step The step.
+ * @param id The full qualified step id.
+ * @param context The target context.
+ * @param data The step data.
+ * @return Formatted message.
+ */
+ protected abstract String formatMessage(String message, int severity, IContextStep step, IFullQualifiedId id, IContext context, IPropertiesContainer data);
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepGroup.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepGroup.java
new file mode 100644
index 000000000..04ca6c7be
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepGroup.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.extensions;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupIterator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtension;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
+
+/**
+ * Abstract context step group implementation.
+ */
+public abstract class AbstractContextStepGroup extends ExecutableExtension implements IContextStepGroup {
+
+ private ExecutableExtensionProxy<IContextStepGroupIterator> iteratorProxy = null;
+
+ /**
+ * Constant to be returned in case the step group contains no steps.
+ */
+ protected final static IContextStepGroupable[] NO_STEPS = new IContextStepGroupable[0];
+
+ /**
+ * Constructor.
+ */
+ public AbstractContextStepGroup() {
+ super();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup#isLocked()
+ */
+ @Override
+ public boolean isLocked() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.ExecutableExtension#doSetInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void doSetInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ super.doSetInitializationData(config, propertyName, data);
+
+ if (iteratorProxy == null) {
+ iteratorProxy = new ExecutableExtensionProxy<IContextStepGroupIterator>(config) {
+ @Override
+ protected String getExecutableExtensionAttributeName() {
+ return "iterator"; //$NON-NLS-1$
+ }
+ };
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup#getStepGroupIterator()
+ */
+ @Override
+ public IContextStepGroupIterator getStepGroupIterator() {
+ return iteratorProxy != null ? iteratorProxy.newInstance() : null;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepper.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepper.java
new file mode 100644
index 000000000..8f4d50906
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/AbstractContextStepper.java
@@ -0,0 +1,804 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.extensions;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tcf.te.runtime.stepper.StepperAttributeUtil;
+import org.eclipse.tcf.te.runtime.stepper.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContext;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextManipulator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepExecutor;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupIterator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IVariantDelegate;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.tracing.ITraceIds;
+import org.eclipse.tcf.te.runtime.stepper.nls.Messages;
+import org.eclipse.tcf.te.runtime.callback.Callback;
+import org.eclipse.tcf.te.runtime.concurrent.util.ExecutorsUtil;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtension;
+import org.eclipse.tcf.te.runtime.interfaces.ISharedConstants;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+import org.eclipse.tcf.te.runtime.utils.ProgressHelper;
+import org.eclipse.tcf.te.runtime.utils.StatusHelper;
+
+/**
+ * An abstract stepper implementation.
+ */
+public abstract class AbstractContextStepper extends ExecutableExtension implements IStepper, IContextManipulator {
+
+ private boolean initialized = false;
+ private boolean finished = false;
+ private IPropertiesContainer data = null;
+ private IFullQualifiedId fullQualifiedId = null;
+ private IProgressMonitor monitor = null;
+ private String activeContextId = null;
+ private IContext activeContext = null;
+ private boolean cancelable = true;
+
+ protected class ExecutedContextStep {
+ final IFullQualifiedId id;
+ final IContextStep step;
+
+ public ExecutedContextStep(IFullQualifiedId id, IContextStep step) {
+ this.id = id;
+ this.step = step;
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ public AbstractContextStepper() {
+ super();
+ }
+
+ /**
+ * Returns the name of what is executed by the stepper.
+ */
+ protected abstract String getName();
+
+ /**
+ * Returns the type if what is executed by the stepper.
+ */
+ protected abstract String getType();
+
+ /**
+ * Returns the sub type if what is executed by the stepper.
+ */
+ protected abstract String getSubType();
+
+ /**
+ * Returns the contexts the stepper is working with.
+ */
+ protected abstract IContext[] getContexts();
+
+ /**
+ * Returns the variant delegate to use or <code>null</code>.
+ */
+ protected abstract IVariantDelegate getVariantDelegate() throws CoreException;
+
+ /**
+ * Creates a new instance of the step executor to use for executing a step.
+ */
+ protected abstract IContextStepExecutor doCreateStepExecutor(IContextStep step, String secondaryId, IFullQualifiedId fullQualifiedStepId);
+
+ /**
+ * Returns the step group for the given arguments.
+ */
+ protected abstract IContextStepGroup getStepGroup(String type, String subType, String variant);
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#initialize(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public void initialize(IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) throws IllegalStateException {
+ Assert.isNotNull(data);
+ Assert.isNotNull(fullQualifiedId);
+ Assert.isNotNull(monitor);
+
+ // Assert stepper is not in use
+ if (isInitialized()) {
+ throw new IllegalStateException("Stepper instance already initialized!"); //$NON-NLS-1$
+ }
+
+ // set the initial stepper attributes
+ this.data = data;
+ this.monitor = monitor;
+ this.fullQualifiedId = fullQualifiedId;
+
+ // but not finished yet
+ this.finished = false;
+
+ // set the initial stepper attributes
+ this.activeContext = null;
+ this.activeContextId = null;
+
+ setInitialized();
+
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepper#initialize:" //$NON-NLS-1$
+ + " type='" + getType() + "'" //$NON-NLS-1$ //$NON-NLS-2$
+ + ", mode='" + getSubType() + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ }
+
+ /**
+ * Marks the stepper to be fully initialized.
+ */
+ protected final void setInitialized() {
+ initialized = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#isInitialized()
+ */
+ @Override
+ public final boolean isInitialized() {
+ return initialized;
+ }
+
+ /**
+ * Sets the cancelable state of the stepper.
+ *
+ * @param cancelable <code>True</code> if the stepper shall be cancelable, <code>false</code> if not.
+ */
+ protected final void setCancelable(boolean cancelable) {
+ this.cancelable = cancelable;
+ }
+
+ /**
+ * Returns the cancelable state of the stepper.
+ *
+ * @return <code>True</code> if the stepper is cancelable, <code>false</code> if not.
+ */
+ protected final boolean isCancelable() {
+ return cancelable;
+ }
+
+ /**
+ * Sets the active context.
+ *
+ * @param context The active context or <code>null</code>.
+ */
+ protected final void setActiveContext(IContext context) {
+ // do not use equals() here!!!
+ if (activeContext != context) {
+ if (activeContext instanceof IPropertiesContainer) {
+ ((IPropertiesContainer)activeContext).setProperty("stepperContext::" + getId(), null); //$NON-NLS-1$
+ }
+ activeContext = context;
+ if (activeContext instanceof IPropertiesContainer) {
+ ((IPropertiesContainer)activeContext).setProperty("stepperContext::" + getId(), true); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * Get the active context.
+ *
+ * @return The active context or <code>null</code>.
+ */
+ protected IContext getActiveContext() {
+ if (isInitialized() && activeContext == null) {
+ IContext newContext = (IContext)StepperAttributeUtil.getProperty(IContextManipulator.CONTEXT, getFullQualifiedId(), getData());
+ if (newContext != null) {
+ setActiveContext(newContext);
+ }
+ if (activeContext == null) {
+ IContext[] contexts = getContexts();
+ if (contexts != null && contexts.length > 0) {
+ for (IContext context : contexts) {
+ setActiveContext(context);
+ StepperAttributeUtil.setProperty(IContextManipulator.CONTEXT, getFullQualifiedId(), getData(), activeContext);
+ break;
+ }
+ }
+ }
+ }
+ return activeContext;
+ }
+
+ /**
+ * Sets the active context id.
+ *
+ * @param contextId The active context id or <code>null</code>.
+ */
+ protected final void setActiveContextId(String contextId) {
+ activeContextId = contextId;
+ }
+
+ /**
+ * Get the active context id.
+ *
+ * @return The active context id or <code>null</code>.
+ */
+ protected String getActiveContextId() {
+ if (isInitialized() && activeContextId == null) {
+ String newContextId = (String)StepperAttributeUtil.getProperty(IContextManipulator.CONTEXT_ID, getFullQualifiedId(), getData());
+ if (newContextId != null && newContextId.trim().length() > 0) {
+ activeContextId = newContextId.trim();
+ }
+ if (activeContextId == null) {
+ IContext context = getActiveContext();
+ if (context != null) {
+ activeContextId = context.getContextId();
+ StepperAttributeUtil.setProperty(IContextManipulator.CONTEXT_ID, getFullQualifiedId(), getData(), activeContextId);
+ }
+ }
+ }
+ return activeContextId;
+ }
+
+ /**
+ * Returns the currently associated data. The method returns
+ * <code>null</code> if the stepper is not in initialized state.
+ *
+ * @return The data or <code>null</code>
+ */
+ protected final IPropertiesContainer getData() {
+ return isInitialized() ? data : null;
+ }
+
+ /**
+ * Returns the full qualified id for this stepper.
+ *
+ * @return The full qualified stepper id.
+ */
+ protected final IFullQualifiedId getFullQualifiedId() {
+ return fullQualifiedId;
+ }
+
+ /**
+ * Returns the currently associated progress monitor. The method returns
+ * <code>null</code> if the stepper is not in initialized state.
+ *
+ * @return The progress monitor or <code>null</code>
+ */
+ protected final IProgressMonitor getMonitor() {
+ return isInitialized() ? monitor : null;
+ }
+
+ /**
+ * Marks the stepper to be finished.
+ */
+ protected final void setFinished() {
+ finished = true;
+ if (activeContext instanceof IPropertiesContainer) {
+ ((IPropertiesContainer)activeContext).setProperty("stepperContext::" + getId(), null); //$NON-NLS-1$
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#isFinished()
+ */
+ @Override
+ public final boolean isFinished() {
+ return finished;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#cleanup()
+ */
+ @Override
+ public void cleanup() {
+ // Set the progress monitor done here in any case
+ if (getMonitor() != null) getMonitor().done();
+
+ // Reset the initial stepper attributes
+ data = null;
+ monitor = null;
+ fullQualifiedId = null;
+ finished = false;
+ initialized = false;
+
+ // Reset the initial stepper attributes
+ setActiveContext(null);
+ setActiveContextId(null);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder buffer = new StringBuilder(getClass().getSimpleName());
+ buffer.append(" (" + getLabel() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append(": "); //$NON-NLS-1$
+ buffer.append("id = " + getId()); //$NON-NLS-1$
+ return buffer.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#execute()
+ */
+ @Override
+ public final void execute() throws CoreException {
+ long startTime = System.currentTimeMillis();
+
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepper#execute: *** ENTERED", //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ CoreBundleActivator.getTraceHandler().trace(" [" + ISharedConstants.TIME_FORMAT.format(new Date(startTime)) + "]" //$NON-NLS-1$ //$NON-NLS-2$
+ + " ***", //$NON-NLS-1$
+ 0, ITraceIds.PROFILE_STEPPING, IStatus.WARNING, this);
+
+ try {
+ // stepper must be initialized before executing
+ if (!isInitialized()) {
+ throw new CoreException(new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
+ Messages.AbstractContextStepper_error_initializeNotCalled));
+ }
+
+ // Create a container for collecting the non-severe status objects
+ // during the step execution. Non-severe status objects will
+ // be hold back till the execution completed or stopped with an error.
+ // Severe status objects are errors or cancellation.
+ List<IStatus> statusContainer = new ArrayList<IStatus>();
+
+ // start execution
+ internalExecute(statusContainer);
+
+ // If the warnings container is not empty, create a new status and
+ // throw a core exception
+ if (!statusContainer.isEmpty()) {
+ IStatus status = null;
+
+ // Check if we need a multi status
+ if (statusContainer.size() > 1) {
+ MultiStatus multiStatus =
+ new MultiStatus(CoreBundleActivator.getUniqueIdentifier(), 0,
+ NLS.bind(Messages.AbstractContextStepper_multiStatus_finishedWithWarnings, getName()), null);
+ for (IStatus subStatus : statusContainer) {
+ multiStatus.merge(subStatus);
+ }
+ status = multiStatus;
+ }
+ else {
+ status = statusContainer.get(0);
+ }
+
+ throw new CoreException(status);
+ }
+ }
+ finally {
+ // Mark the stepper finished
+ setFinished();
+
+ long endTime = System.currentTimeMillis();
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepper#execute: *** DONE", //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ CoreBundleActivator.getTraceHandler().trace(" [" + ISharedConstants.TIME_FORMAT.format(new Date(endTime)) //$NON-NLS-1$
+ + " , delay = " + (endTime - startTime) + " ms]" //$NON-NLS-1$ //$NON-NLS-2$
+ + " ***", //$NON-NLS-1$
+ 0, ITraceIds.PROFILE_STEPPING, IStatus.WARNING, this);
+ }
+ }
+
+ /**
+ * Executes a step or step group.
+ *
+ * @param statusContainer The status container. Must not be <code>null</code>.
+ * @throws CoreException If the execution fails.
+ */
+ protected void internalExecute(List<IStatus> statusContainer) throws CoreException {
+ Assert.isNotNull(statusContainer);
+
+ // Get the variant delegate
+ IVariantDelegate variantDelegate = getVariantDelegate();
+ String[] variants = null;
+ if (variantDelegate != null) {
+ // Determine the valid variants
+ variants = variantDelegate.getValidVariants(getActiveContext(), getData());
+ }
+
+ // Get the step group
+ IContextStepGroup stepGroup = null;
+ if (variants != null) {
+ for (String variant : variants) {
+ stepGroup = getStepGroup(getType(), getSubType(), variant);
+ if (stepGroup != null) {
+ break;
+ }
+ }
+ }
+ if (stepGroup == null) {
+ stepGroup = getStepGroup(getType(), getSubType(), null);
+ }
+
+ // If no step group could be found for any of the valid variants, throw an exception
+ if (stepGroup == null) {
+ throw new CoreException(new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
+ NLS.bind(Messages.AbstractContextStepper_error_missingStepGroup, getName())));
+ }
+
+ // Initialize the progress monitor
+ getMonitor().beginTask(stepGroup.getLabel(), calculateTotalWork(stepGroup));
+
+ IFullQualifiedId fullQualifiedId = getFullQualifiedId().createChildId(ID_TYPE_CONTEXT_ID, getActiveContextId(), null);
+ fullQualifiedId = fullQualifiedId.createChildId(ID_TYPE_STEP_GROUP_ID, stepGroup.getId(), null);
+ // Execute the step group
+ executeStepGroup(stepGroup, statusContainer, new ArrayList<ExecutedContextStep>(), fullQualifiedId);
+ }
+
+ /**
+ * Executes a step group.
+ *
+ * @param stepGroup The step group. Must be not <code>null</code>.
+ * @param statusContainer A list holding the warnings occurred during the execution. Must be not <code>null</code>.
+ * @param executedSteps A list holding the id's of the steps executed before. Must be not <code>null</code>.
+ * @param fullQualifiedGroupId The hierarchy of all parent step group id's separated by "::". Must be not <code>null</code>.
+ *
+ * @throws CoreException If the execution fails.
+ */
+ private void executeStepGroup(IContextStepGroup stepGroup, List<IStatus> statusContainer, List<ExecutedContextStep> executedSteps, IFullQualifiedId fullQualifiedGroupId) throws CoreException {
+ Assert.isNotNull(stepGroup);
+ Assert.isNotNull(statusContainer);
+ Assert.isNotNull(executedSteps);
+ Assert.isNotNull(fullQualifiedGroupId);
+
+ // Return immediately if the user canceled the monitor in the meanwhile
+ if (isCancelable() && getMonitor().isCanceled()) {
+ rollback(executedSteps, Status.CANCEL_STATUS, getMonitor());
+ throw new CoreException(StatusHelper.getStatus(new OperationCanceledException()));
+ }
+
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepper#execute: step group: '" + stepGroup.getLabel() + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+
+ IContextStepGroupIterator iterator = stepGroup.getStepGroupIterator();
+ IFullQualifiedId fullQualifiedIterationId = fullQualifiedGroupId;
+ int iteration = 0;
+
+ if (iterator != null) {
+ iterator.initialize(getActiveContext(), getData(), fullQualifiedGroupId, getMonitor());
+ }
+ boolean next = iterator == null || iterator.hasNext(getActiveContext(), getData(), fullQualifiedGroupId, getMonitor());
+
+ while (next) {
+ if (iterator != null) {
+ fullQualifiedIterationId = fullQualifiedGroupId.createChildId(ID_TYPE_STEP_GROUP_ITERATION_ID, iterator.getId(), ""+iteration); //$NON-NLS-1$
+ iterator.next(getActiveContext(), getData(), fullQualifiedIterationId, getMonitor());
+ // set the active context if the step has manipulated it
+ if (iterator instanceof IContextManipulator) {
+ IContext newContext =
+ (IContext)StepperAttributeUtil.getProperty(IContextManipulator.CONTEXT, fullQualifiedIterationId, getData());
+ String newContextId =
+ StepperAttributeUtil.getStringProperty(IContextManipulator.CONTEXT_ID, fullQualifiedIterationId, getData());
+ if (newContext != null) {
+ setActiveContext(newContext);
+ }
+ if (newContextId != null &&
+ newContextId.trim().length() > 0) {
+ setActiveContextId(newContextId.trim());
+ }
+ }
+ }
+ // Get the list of steps or step groups to execute.
+ IContextStepGroupable[] groupables = stepGroup.getSteps(getType(), getSubType());
+ for (IContextStepGroupable groupable : groupables) {
+ executeGroupable(groupable, statusContainer, executedSteps, fullQualifiedIterationId);
+ }
+ iteration++;
+ next = iterator != null && iterator.hasNext(getActiveContext(), getData(), fullQualifiedGroupId, getMonitor());
+ }
+ }
+
+ /**
+ * Executes a step groupable. The groupable might encapsulate a
+ * step or a step group.
+ *
+ * @param step The step groupable. Must be not <code>null</code>.
+ * @param statusContainer A list holding the warnings occurred during the execution. Must be not <code>null</code>.
+ * @param executedSteps A list holding the id's of the steps executed before. Must be not <code>null</code>.
+ * @param fullQualifiedParentId The hierarchy of all parent step group id's separated by "::". Must be not <code>null</code>.
+ *
+ * @throws CoreException If the execution failed.
+ */
+ private void executeGroupable(IContextStepGroupable groupable, List<IStatus> statusContainer, List<ExecutedContextStep> executedSteps, IFullQualifiedId fullQualifiedParentId) throws CoreException {
+ Assert.isNotNull(groupable);
+ Assert.isNotNull(statusContainer);
+ Assert.isNotNull(executedSteps);
+ Assert.isNotNull(fullQualifiedParentId);
+
+ // Return immediately if the user canceled the monitor in the meanwhile
+ if (isCancelable() && getMonitor() != null && getMonitor().isCanceled()) {
+ rollback(executedSteps, Status.CANCEL_STATUS, getMonitor());
+ throw new CoreException(StatusHelper.getStatus(new OperationCanceledException()));
+ }
+
+ // If the passed in groupable is disabled -> we are done immediately
+ if (groupable.isDisabled()) {
+ CoreBundleActivator.getTraceHandler().trace("AbstractContextStepper#executeGroupable: DROPPED DISABLED groupable: id = '" + groupable.getExtension().getId() + "'" //$NON-NLS-1$ //$NON-NLS-2$
+ + ", secondaryId = '" + groupable.getSecondaryId() + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ return;
+ }
+
+ // Check if all dependencies of the groupable have been executed before
+ checkForDependenciesExecuted(groupable, executedSteps);
+
+ if (groupable.getExtension() instanceof IContextStepGroup) {
+ IFullQualifiedId id = fullQualifiedParentId.createChildId(ID_TYPE_STEP_GROUP_ID, groupable.getExtension().getId(), groupable.getSecondaryId());
+ // If the passed in groupable is associated with a step group
+ // -> get the groupable from that group and execute them
+ executeStepGroup((IContextStepGroup)groupable.getExtension(), statusContainer, executedSteps, id);
+ }
+ else if (groupable.getExtension() instanceof IContextStep) {
+ // If the passed in groupable is associated with a step
+ // -> check if the required steps have been executed before,
+ // create a step executor and invoke the executor.
+ IContextStep step = (IContextStep)groupable.getExtension();
+
+ IFullQualifiedId id = fullQualifiedParentId.createChildId(ID_TYPE_STEP_ID, step.getId(), groupable.getSecondaryId());
+
+ // Create the step executor now
+ IContextStepExecutor executor = doCreateStepExecutor(step, groupable.getSecondaryId(), id);
+ Assert.isNotNull(executor);
+
+ try {
+ executedSteps.add(new ExecutedContextStep(id, step));
+ // Invoke the executor now
+ executor.execute(step, id, getActiveContext(), getData(), getMonitor());
+ // set the active context if the step has manipulated it
+ if (step instanceof IContextManipulator) {
+ IContext newContext = (IContext)StepperAttributeUtil.getProperty(IContextManipulator.CONTEXT, id, getData());
+ String newContextId = StepperAttributeUtil.getStringProperty(IContextManipulator.CONTEXT_ID, id, getData());
+ if (newContext != null) {
+ setActiveContext(newContext);
+ }
+ if (newContextId != null &&
+ newContextId.trim().length() > 0) {
+ setActiveContextId(newContextId.trim());
+ }
+ }
+ }
+ catch (Exception e) {
+ // Catch the CoreException first hand as we need to continue the
+ // stepping if the step returned with warnings or information only.
+ CoreException coreException = normalizeStatus(e, statusContainer);
+ // If the exception has been not eaten, rollback previously executed
+ // steps and re-throw the exception.
+ if (coreException != null) {
+ // Rollback everything, if the step(s) are supporting this and
+ // the cleanup hasn't been done already.
+ if (isInitialized()) {
+ rollback(executedSteps, coreException.getStatus(), getMonitor());
+ }
+
+ // Re-throw the exception
+ throw coreException;
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if all required dependencies have been executed before. If not, the method
+ * will throw an error status.
+ *
+ * @param groupable The groupable. Must be not <code>null</code>.
+ * @param executedSteps A list holding the id's of the steps executed before. Must be not <code>null</code>.
+ *
+ * @throws CoreException If a dependency has not been executed before.
+ */
+ protected void checkForDependenciesExecuted(IContextStepGroupable groupable, List<ExecutedContextStep> executedSteps) throws CoreException {
+ Assert.isNotNull(groupable);
+ Assert.isNotNull(executedSteps);
+
+ // Build up the complete list of dependencies.
+ List<String> dependencies = new ArrayList<String>(Arrays.asList(groupable.getDependencies()));
+ // If the groupable wraps a step, the step can have additional dependencies to check
+ if (groupable.getExtension() instanceof IContextStep) {
+ dependencies.addAll(Arrays.asList(((IContextStep)groupable.getExtension()).getDependencies()));
+ }
+
+ // Check each dependency now.
+ for (String dependency : dependencies) {
+ // The dependencies might be fully qualified. Split out the primary id.
+ String[] splitted = dependency.split("##", 2); //$NON-NLS-1$
+ String primaryId = splitted.length == 2 ? splitted[0] : dependency;
+
+ // Check if the id is in the list of executed steps. As the list contains
+ // the fully qualified id's, we cannot just check for contained
+ boolean requiredStepExecuted = false;
+ for (ExecutedContextStep step : executedSteps) {
+ if (step.step.getId().equals(primaryId)) {
+ requiredStepExecuted = true;
+ break;
+ }
+ }
+
+ if (!requiredStepExecuted) {
+ throw new CoreException(new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.AbstractContextStepper_error_requiredStepNotExecuted,
+ NLS.bind((groupable.getExtension() instanceof IContextStep
+ ? Messages.AbstractContextStepper_error_step
+ : Messages.AbstractContextStepper_error_requiredStepOrGroup), dependency),
+ NLS.bind(Messages.AbstractContextStepper_error_typeAndSubtype, getType(), getSubType()))));
+ }
+
+ // Recursive checking is not necessary here as the step or step group
+ // id's would have made it the executed steps list of they missed required
+ // steps or step groups.
+ }
+
+ }
+
+ /**
+ * Rollback the steps previously executed to the failed step. The rollback
+ * is executed in reverse order and the step must be of type {@link IWRExtendedTargetContextStep}
+ * to participate in the rollback.
+ *
+ * @param executedSteps
+ * @param progress
+ */
+ protected final void rollback(final List<ExecutedContextStep> executedSteps, final IStatus rollBackStatus, IProgressMonitor progress) {
+ Assert.isNotNull(executedSteps);
+
+ final IProgressMonitor rollbackProgress = ProgressHelper.getProgressMonitor(progress, 1);
+ ProgressHelper.beginTask(rollbackProgress, "Cancel", executedSteps.size()); //$NON-NLS-1$
+ final Callback finalCallback = new Callback();
+ final Callback rollbackCallback = new Callback() {
+ @Override
+ protected void internalDone(Object caller, IStatus status) {
+ if (!executedSteps.isEmpty()) {
+ setProperty(PROPERTY_IS_DONE, false);
+ ExecutedContextStep executedStep = executedSteps.remove(executedSteps.size()-1);
+ if (executedStep.step instanceof IExtendedContextStep) {
+ IExtendedContextStep step = (IExtendedContextStep)executedStep.step;
+ step.rollback(getActiveContext(), getData(), rollBackStatus, executedStep.id, rollbackProgress, this);
+ }
+ else {
+ this.done(this, status);
+ }
+ }
+ else {
+ finalCallback.done(this, Status.OK_STATUS);
+ }
+ }
+ };
+
+ rollbackCallback.done(this, rollBackStatus);
+ ExecutorsUtil.waitAndExecute(0, finalCallback.getDoneConditionTester(null));
+ }
+
+ /**
+ * Calculates the total work required for the step group. The total
+ * work is the sum of the total work of each sub step. If one of the
+ * steps returns {@link IProgressMonitor#UNKNOWN}, the total work will
+ * be unknown for the whole step group.
+ *
+ * @param stepGroup The step group. Must be not <code>null</code>.
+ * @return The total work required or {@link IProgressMonitor#UNKNOWN}.
+ *
+ * @throws CoreException If the total work of the step group cannot be determined.
+ */
+ protected int calculateTotalWork(IContextStepGroup stepGroup) throws CoreException {
+ Assert.isNotNull(stepGroup);
+
+ int totalWork = 0;
+
+ // Loop the group steps and summarize the returned total work
+ IContextStepGroupable[] groupables = stepGroup.getSteps(getType(), getSubType());
+ for (IContextStepGroupable groupable : groupables) {
+ int work = groupable.getExtension() instanceof IContextStep
+ ? ((IContextStep)groupable.getExtension()).getTotalWork(getActiveContext(), getData())
+ : groupable.getExtension() instanceof IContextStepGroup
+ ? calculateTotalWork((IContextStepGroup)groupable.getExtension())
+ : IProgressMonitor.UNKNOWN;
+
+ if (work == IProgressMonitor.UNKNOWN) {
+ totalWork = IProgressMonitor.UNKNOWN;
+ break;
+ }
+
+ totalWork += work;
+ }
+
+ return totalWork;
+ }
+
+ /**
+ * Normalize the associated status object of the given {@link CoreException}.
+ * <p>
+ * If the associated status contains only WARNING or INFORMATION status objects,
+ * the objects are added to the passed in status container. The passed in exception
+ * is dropped and the method will return <code>null</code>.
+ * <p>
+ * If the associated status contains only OK status objects, the passed in
+ * exception and the associated status are dropped and the method will return
+ * <code>null</code>.
+ * <p>
+ * If the associated status contain ERROR status objects, the passed in exception
+ * and the associated status objects are returned if the passed in status container
+ * is empty. If the status container is not empty, a new exception and multi status
+ * object is created and returned. The multi status object will contain all status
+ * objects from the status container and all objects of the originally associated
+ * status.
+ * <p>
+ * If the associated status contains a CANCEL status object, the passed in
+ * exception and the associated status objects are returned unmodified.
+ *
+ * @param e The core exception. Must be not <code>null</code>.
+ * @param statusContainer The list of non-severe status objects. Must be not <code>null</code>.
+ * @return The exception to re-throw or <code>null</code>.
+ */
+ private CoreException normalizeStatus(Exception e, List<IStatus> statusContainer) {
+ Assert.isNotNull(statusContainer);
+
+ CoreException coreException = null;
+
+ IStatus status = Status.OK_STATUS;
+ // Get the associated status from the exception
+ if (e instanceof CoreException) {
+ status = ((CoreException)e).getStatus();
+ coreException = (CoreException)e;
+ }
+ else if (e instanceof OperationCanceledException) {
+ status = new Status(IStatus.CANCEL, CoreBundleActivator.getUniqueIdentifier(), e.getLocalizedMessage(), e);
+ coreException = new CoreException(status);
+ }
+ else if (e != null) {
+ status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), e.getLocalizedMessage(), e);
+ coreException = new CoreException(status);
+ }
+
+ // Check the severity
+ // PS: MultiStatus.getSeverity() returns always the highest severity.
+ if (status.getSeverity() == IStatus.OK) {
+ // OK -> drop completely and return null
+ coreException = null;
+ }
+ else if (status.getSeverity() == IStatus.CANCEL) {
+ // CANCEL -> Check monitor to be canceled.
+ if (isCancelable()) {
+ if (getMonitor() != null && !getMonitor().isCanceled()) {
+ getMonitor().setCanceled(true);
+ }
+ }
+ }
+ else if (status.getSeverity() == IStatus.WARNING || status.getSeverity() == IStatus.INFO) {
+ // WARNING or INFORMATION -> add to the list and return null
+ statusContainer.add(status);
+ coreException = null;
+ }
+ else if (status.getSeverity() == IStatus.ERROR) {
+ // Error -> If the warnings container not empty, create
+ // a new MultiStatus.
+ if (!statusContainer.isEmpty()) {
+ MultiStatus multiStatus = new MultiStatus(status.getPlugin(), status.getCode(),
+ NLS.bind(Messages.AbstractContextStepper_multiStatus_finishedWithErrors, getName()), null);
+ for (IStatus stat : statusContainer) {
+ multiStatus.merge(stat);
+ }
+ // Re-throw via a new CoreException
+ coreException = new CoreException(multiStatus);
+ }
+ }
+
+ return coreException;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroup.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroup.java
new file mode 100644
index 000000000..869310605
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroup.java
@@ -0,0 +1,814 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.extensions;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tcf.te.runtime.stepper.StepperManager;
+import org.eclipse.tcf.te.runtime.stepper.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedContextStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.tracing.ITraceIds;
+import org.eclipse.tcf.te.runtime.stepper.nls.Messages;
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+
+/**
+ * A default step group implementation.
+ */
+public class ContextStepGroup extends AbstractContextStepGroup {
+
+ private boolean locked;
+ private String baseOn;
+
+ private final List<ReferenceSubElement> references = new ArrayList<ReferenceSubElement>();
+
+ /**
+ * Step group reference sub element.
+ */
+ protected final static class ReferenceSubElement implements org.eclipse.core.runtime.IExecutableExtension {
+ private String id;
+ private String secondaryId;
+ private String insertBefore;
+ private String insertAfter;
+ private String overwrite;
+ private boolean removable;
+ private boolean hidden;
+ private boolean disable;
+ private boolean singleton;
+ private final List<String> dependencies = new ArrayList<String>();
+
+ /**
+ * Returns the id of the referenced step or step group.
+ *
+ * @return The id of the referenced step or step group.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the secondary id of the referenced step or step group.
+ *
+ * @return The secondary id or <code>null</code>.
+ */
+ public String getSecondaryId() {
+ return secondaryId;
+ }
+
+ /**
+ * Sets the secondary id of the referenced step or step group.
+ *
+ * @return The secondary id or <code>null</code>.
+ */
+ public void setSecondardId(String secondaryId) {
+ this.secondaryId = secondaryId;
+ }
+
+ /**
+ * Returns the id of the step or step group the referenced
+ * step or group shall be inserted before.
+ *
+ * @return The id or <code>null</code>.
+ */
+ public String getInsertBefore() {
+ return insertBefore;
+ }
+
+ /**
+ * Returns the id of the step or step group the referenced
+ * step or group shall be inserted after.
+ *
+ * @return The id or <code>null</code>.
+ */
+ public String getInsertAfter() {
+ return insertAfter;
+ }
+
+ /**
+ * Returns the id of the step or step group the referenced
+ * step or group do overwrite.
+ *
+ * @return The id or <code>null</code>.
+ */
+ public String getOverwrite() {
+ return overwrite;
+ }
+
+ /**
+ * Returns if or if not the referenced step or step group
+ * can be removed by the user from the group.
+ *
+ * @return <code>True</code> if removable, <code>false</code> otherwise.
+ */
+ public boolean isRemovable() {
+ return removable;
+ }
+
+ /**
+ * Returns if or if not the referenced step or step group
+ * is hidden.
+ *
+ * @return <code>True</code> if hidden, <code>false</code> otherwise.
+ */
+ public boolean isHidden() {
+ return hidden;
+ }
+
+ /**
+ * Returns if or if not to disable the referenced step or step group.
+ *
+ * @return <code>True</code> if to disable, <code>false</code> otherwise.
+ */
+ public boolean isDisable() {
+ return disable;
+ }
+
+ /**
+ * Returns if or if not the referenced step or step group is a singleton.
+ *
+ * @return <code>True</code> if singleton, <code>false</code> otherwise.
+ */
+ public boolean isSingleton() {
+ return singleton;
+ }
+
+ /**
+ * Returns the list of dependencies.
+ * <p>
+ * The step or step group id might be fully qualified using the form
+ * <code>&quot;primaryId##secondaryId</code>. The <code>secondaryId</code> is optional.
+ *
+ * @return The list of dependencies or an empty list.
+ */
+ public String[] getDependencies() {
+ return dependencies.toArray(new String[dependencies.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ if (config == null) {
+ return;
+ }
+
+ String value = config.getAttribute("id"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.id = value.trim();
+ }
+
+ value = config.getAttribute("secondaryId"); //$NON-NLS-1$
+ setSecondardId(value != null && value.trim().length() > 0 ? value.trim() : null);
+
+ value = config.getAttribute("insertBefore"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.insertBefore = value.trim();
+ }
+
+ value = config.getAttribute("insertAfter"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.insertAfter = value.trim();
+ }
+
+ value = config.getAttribute("overwrite"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.overwrite = value.trim();
+ }
+
+ value = config.getAttribute("removable"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.removable = Boolean.parseBoolean(value.trim());
+ }
+
+ value = config.getAttribute("hidden"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.hidden = Boolean.parseBoolean(value.trim());
+ }
+
+ value = config.getAttribute("disable"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.disable = Boolean.parseBoolean(value.trim());
+ }
+
+ value = config.getAttribute("singleton"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.singleton = Boolean.parseBoolean(value.trim());
+ }
+
+ // Read in the list of dependencies if specified.
+ dependencies.clear();
+ IConfigurationElement[] requires = config.getChildren("requires"); //$NON-NLS-1$
+ for (IConfigurationElement require : requires) {
+ value = require.getAttribute("id"); //$NON-NLS-1$
+ if (value == null || value.trim().length() == 0) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ 0,
+ NLS.bind(Messages.AbstractContextStep_error_missingRequiredAttribute,
+ "dependency id (requires)", //$NON-NLS-1$
+ config.getName()),
+ null));
+ }
+ if (!dependencies.contains(value.trim())) {
+ dependencies.add(value.trim());
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (getId() != null && obj instanceof ReferenceSubElement) {
+ boolean secondaryIdEquals = false;
+ if (getSecondaryId() == null) {
+ secondaryIdEquals = ((ReferenceSubElement)obj).getSecondaryId() == null;
+ }
+ else {
+ secondaryIdEquals = getSecondaryId().equals(((ReferenceSubElement)obj).getSecondaryId());
+ }
+
+ return getId().equals(((ReferenceSubElement)obj).getId()) && secondaryIdEquals;
+ }
+ return super.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return getId() != null ? getId().hashCode() + (getSecondaryId() != null ? getSecondaryId().hashCode() : 0) : super.hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuffer buffer = new StringBuffer(getClass().getSimpleName());
+ buffer.append(": "); //$NON-NLS-1$
+ buffer.append("id = " + getId()); //$NON-NLS-1$
+ buffer.append(", secondaryId = " + getSecondaryId()); //$NON-NLS-1$
+ buffer.append(", insertBefore = " + getInsertBefore()); //$NON-NLS-1$
+ buffer.append(", insertAfter = " + getInsertAfter()); //$NON-NLS-1$
+ buffer.append(", overwrite = " + getOverwrite()); //$NON-NLS-1$
+ buffer.append(", removable = " + isRemovable()); //$NON-NLS-1$
+ buffer.append(", hidden = " + isHidden()); //$NON-NLS-1$
+ buffer.append(", disable = " + isDisable()); //$NON-NLS-1$
+ buffer.append(", singleton = " + isSingleton()); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ public ContextStepGroup() {
+ super();
+ locked = false;
+ baseOn = null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.AbstractContextStepGroup#isLocked()
+ */
+ @Override
+ public boolean isLocked() {
+ return locked;
+ }
+
+ /**
+ * Returns the id of the step group this step group is
+ * initially based on.
+ *
+ * @return The id or <code>null</code>.
+ */
+ protected String getBaseOn() {
+ return baseOn;
+ }
+
+ /**
+ * Returns the references.
+ */
+ protected List<ReferenceSubElement> getReferences() {
+ return references;
+ }
+
+ /**
+ * Check for duplicates of the referenced step or step group. The check
+ * will fail if multiple occurrence of a step or step group are found and
+ * the step or step group is supposed to be a singleton.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param reference The reference. Must not be <code>null</code>.
+ * @param type The type id. Must not be <code>null</code>.
+ * @param mode The sub type id. Must not be <code>null</code>.
+ *
+ * @throws CoreException If multiple occurrences of singleton references are found.
+ */
+ protected void checkForDuplicates(List<IContextStepGroupable> steps, ReferenceSubElement reference, String type, String mode) throws CoreException {
+ assert steps != null && reference != null;
+
+ // If the reference overwrites another reference, it is not a duplicate
+ String overwrite = reference.getOverwrite();
+ if (overwrite != null && overwrite.length() > 0) {
+ return;
+ }
+
+ boolean checkFailed = false;
+
+ for (IContextStepGroupable step : steps) {
+ if (step.getExtension().getId().equals(reference.getId())) {
+ // We've found an existing groupable with the reference id.
+ // If either the groupable, the reference or the extension is
+ // marked singleton, than this is an failure.
+ checkFailed = step.isSingleton() || reference.isSingleton()
+ || (step.getExtension() instanceof IExtendedContextStep
+ && ((IExtendedContextStep)step.getExtension()).isSingleton());
+ if (checkFailed) {
+ break;
+ }
+ }
+ }
+
+ if (checkFailed) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_multipleSingletonOccurrences,
+ NLS.bind(Messages.ContextStepGroup_error_stepGroup, getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_referencedStepOrGroup, reference.getId()),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+ }
+
+ /**
+ * Replace all references to a given step or step group with another one.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param oldId The id of the step or step group to replace. Must not be <code>null</code>.
+ * @param replacement The replacement. Must not be <code>null</code>.
+ * @param reference The reference sub element. Must not be <code>null</code>.
+ *
+ * @return The list of affected groupable's or an empty list.
+ */
+ protected List<IContextStepGroupable> onOverwrite(List<IContextStepGroupable> steps, String oldId, IExecutableExtension replacement, ReferenceSubElement reference) {
+ assert steps != null && oldId != null && replacement != null && reference != null;
+
+ List<IContextStepGroupable> affected = new ArrayList<IContextStepGroupable>();
+
+ // Isolate primary and secondary id
+ String primaryId = oldId;
+ String secondaryId = null;
+
+ String[] splitted = oldId.split("##", 2); //$NON-NLS-1$
+ if (splitted.length == 2) {
+ primaryId = splitted[0];
+ secondaryId = splitted[1];
+ }
+
+ for (IContextStepGroupable step : steps) {
+ // A step is clearly affected if the primary id and the secondary
+ // id (if any) matches the overwritten id
+ if (step.getExtension().getId().equals(primaryId)
+ && (secondaryId == null || secondaryId.equals(step.getSecondaryId()))) {
+ if (step instanceof ContextStepGroupable) {
+ ContextStepGroupable groupable = ((ContextStepGroupable)step);
+ // Update the grouped extension
+ groupable.setExtension(replacement);
+ // Update the groupable secondary id
+ groupable.setSecondaryId(reference.getSecondaryId());
+ // Add the groupable to the list of affected steps
+ affected.add(step);
+ }
+ }
+
+ // A step is affected as well if the step depends on the overwritten step
+ // In this case we have to update the dependencies.
+ List<String> dependencies = new ArrayList<String>(Arrays.asList(step.getDependencies()));
+ if (dependencies.contains(oldId)) {
+ String fullId = replacement.getId() + (reference.getSecondaryId() != null ? "##" + reference.getSecondaryId() : ""); //$NON-NLS-1$ //$NON-NLS-2$
+ // We have to replace the dependency at the exact position within the list
+ dependencies.set(dependencies.indexOf(oldId), fullId);
+ if (step instanceof ContextStepGroupable) {
+ ((ContextStepGroupable)step).setDependencies(dependencies.toArray(new String[dependencies.size()]));
+ }
+ }
+ }
+
+ return affected;
+ }
+
+ /**
+ * Insert the step before the specified step or step group. If no step or
+ * step group with the given id exist, the step is added to the end.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param id The id of the step or step group where to insert the new step before. Must not be <code>null</code>.
+ * @param newStep The step to add. Must not be <code>null</code>.
+ * @param reference The reference sub element. Must not be <code>null</code>.
+ *
+ * @return The list of affected groupable's or an empty list.
+ */
+ protected List<IContextStepGroupable> onInsertBefore(List<IContextStepGroupable> steps, String id, IExecutableExtension newStep, ReferenceSubElement reference) {
+ assert steps != null && id != null && newStep != null && reference != null;
+
+ List<IContextStepGroupable> affected = new ArrayList<IContextStepGroupable>();
+
+ // Isolate primary and secondary id
+ String primaryId = id;
+ String secondaryId = null;
+
+ String[] splitted = id.split("##", 2); //$NON-NLS-1$
+ if (splitted.length == 2) {
+ primaryId = splitted[0];
+ secondaryId = splitted[1];
+ }
+
+ // Always loop over all steps in case the anchor step is available
+ // multiple times. In such case, the new step is inserted at all
+ // occurrences.
+ for (int i = 0; i < steps.size(); i++) {
+ IContextStepGroupable step = steps.get(i);
+ if (!step.getExtension().getId().equals(primaryId)) {
+ continue;
+ }
+ if (secondaryId != null && !secondaryId.equals(step.getSecondaryId())) {
+ continue;
+ }
+
+ // Create a new groupable object for inserting
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ // Insert the new step at the current position
+ steps.add(i, groupable);
+ // And increase the counter --> Otherwise we would see the
+ // same step we want to insert before again!
+ i++;
+ // Add the new groupable to the list of affected steps
+ affected.add(groupable);
+ }
+
+ // If the step could not be added, add to the end of the list
+ if (affected.isEmpty()) {
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ steps.add(groupable);
+ }
+
+ return affected;
+ }
+
+ /**
+ * Insert the step after the specified step or step group. If no step or
+ * step group with the given id exist, the step is added to the end.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param id The id of the step or step group where to insert the new step after. Must not be <code>null</code>.
+ * @param newStep The step to add. Must not be <code>null</code>.
+ * @param reference The reference sub element. Must not be <code>null</code>.
+ *
+ * @return The list of affected groupable's or an empty list.
+ */
+ protected List<IContextStepGroupable> onInsertAfter(List<IContextStepGroupable> steps, String id, IExecutableExtension newStep, ReferenceSubElement reference) {
+ assert steps != null && id != null && newStep != null && reference != null;
+
+ List<IContextStepGroupable> affected = new ArrayList<IContextStepGroupable>();
+
+ // Isolate primary and secondary id
+ String primaryId = id;
+ String secondaryId = null;
+
+ String[] splitted = id.split("##", 2); //$NON-NLS-1$
+ if (splitted.length == 2) {
+ primaryId = splitted[0];
+ secondaryId = splitted[1];
+ }
+
+ // Always loop over all steps in case the anchor step is available
+ // multiple times. In such case, the new step is inserted at all
+ // occurrences.
+ for (int i = 0; i < steps.size(); i++) {
+ IContextStepGroupable step = steps.get(i);
+ if (!step.getExtension().getId().equals(primaryId)) {
+ continue;
+ }
+ if (secondaryId != null && !secondaryId.equals(step.getSecondaryId())) {
+ continue;
+ }
+
+ // Create a new groupable object for inserting
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ // Insert the new groupable after the current step or at the end (if i + 1 == steps.size())
+ steps.add(i + 1, groupable);
+ // Add the new groupable to the list of affected steps
+ affected.add(groupable);
+ }
+
+ // If the step could not be added, add to the end of the list
+ if (affected.isEmpty()) {
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ steps.add(groupable);
+ }
+
+ return affected;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup#getSteps(java.lang.String, java.lang.String)
+ */
+ @Override
+ public IContextStepGroupable[] getSteps(String type, String mode) throws CoreException {
+ assert type != null && mode != null;
+
+ // The list of resolved steps for the specified type and mode
+ List<IContextStepGroupable> steps = new ArrayList<IContextStepGroupable>();
+
+ // If this step group is based on another step group, we have to get the resolved
+ // steps from there first.
+ if (getBaseOn() != null) {
+ IContextStepGroup baseStepGroup = getStepGroup(getBaseOn());
+ // If the base step group cannot be found, that's an error. We cannot continue
+ // without the base group.
+ if (baseStepGroup == null) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_missingBaseStepGroup,
+ NLS.bind(Messages.ContextStepGroup_error_stepGroup, getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_referencedBaseGroup, getBaseOn()),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // Add all the steps from the base step group now to the list
+ steps.addAll(Arrays.asList(baseStepGroup.getSteps(type, mode)));
+ }
+
+ // Now process the references and modify the steps list accordingly
+ for (ReferenceSubElement reference : getReferences()) {
+ // Get the step or step group for the referenced id. Try the steps first.
+ IExecutableExtension candidate = getStep(reference.getId());
+ if (candidate == null) {
+ candidate = getStepGroup(reference.getId());
+ }
+
+ // If the candidate is null here, that's an error as a referenced step is missing.
+ if (candidate == null) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_missingReferencedStep,
+ NLS.bind(Messages.ContextStepGroup_error_stepGroup, getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_referencedStepOrGroup, reference.getId()),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // Check if the step is valid for the current launch configuration type and mode.
+ if (candidate instanceof IContextStep) {
+ boolean valid = isValidStep(candidate.getId(), type, mode);
+
+ if (!valid) {
+ CoreBundleActivator.getTraceHandler().trace(
+ "StepGroup#getSteps: SKIPPED step = '" + candidate.getLabel() + "'." //$NON-NLS-1$ //$NON-NLS-2$
+ + " Not valid for type id '" + type + "'" //$NON-NLS-1$ //$NON-NLS-2$
+ + " and mode '" + mode + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ continue;
+ }
+ }
+
+ // Check for duplicates of singleton references.
+ checkForDuplicates(steps, reference, type, mode);
+
+ // Check for the steps own dependencies to be valid for the current type id and mode
+ if (candidate instanceof IContextStep) {
+ checkForDependenciesValid((IContextStep) candidate, type, mode);
+ }
+
+ // Will contain the list of affected groupables from the whole list
+ List<IContextStepGroupable> affectedGroupables = new ArrayList<IContextStepGroupable>();
+
+ // Check first for overwriting groupables
+ String overwrite = reference.getOverwrite();
+ if (overwrite != null && overwrite.length() > 0) {
+ affectedGroupables.addAll(onOverwrite(steps, overwrite, candidate, reference));
+ } else {
+ // overwrite is not set -> process insertBefore or insertAfter
+ String insertBefore = reference.getInsertBefore();
+ String insertAfter = reference.getInsertAfter();
+
+ // If neither one is specified, the step or step group will be to the end of the list
+ if ((insertBefore == null || insertBefore.length() == 0)
+ && (insertAfter == null || insertAfter.length() == 0)) {
+ IContextStepGroupable groupable = new ContextStepGroupable(candidate, reference.getSecondaryId());
+ steps.add(groupable);
+ affectedGroupables.add(groupable);
+ } else {
+ // insertBefore comes first
+ if (insertBefore != null && insertBefore.length() > 0) {
+ affectedGroupables.addAll(onInsertBefore(steps, insertBefore, candidate, reference));
+ } else {
+ affectedGroupables.addAll(onInsertAfter(steps, insertAfter, candidate, reference));
+ }
+ }
+ }
+
+ // Process the groupable attributes on all affected groupables
+ for (IContextStepGroupable step : affectedGroupables) {
+ if (!(step instanceof ContextStepGroupable)) {
+ continue;
+ }
+
+ ContextStepGroupable groupable = (ContextStepGroupable)step;
+ groupable.setDependencies(reference.getDependencies());
+
+ if (!reference.isRemovable() && groupable.isRemovable()) {
+ groupable.setRemovable(reference.isRemovable());
+ }
+ if (reference.isHidden() && !groupable.isHidden()) {
+ groupable.setHidden(reference.isHidden());
+ }
+ if (reference.isDisable() && !groupable.isDisabled()) {
+ groupable.setDisabled(reference.isDisable());
+ }
+ if (reference.isSingleton() && !groupable.isSingleton()) {
+ groupable.setSingleton(reference.isSingleton());
+ }
+ }
+ }
+
+ return !steps.isEmpty() ? steps.toArray(new IContextStepGroupable[steps.size()]) : NO_STEPS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.ExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ references.clear();
+ super.setInitializationData(config, propertyName, data);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.extensions.AbstractContextStepGroup#doSetInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void doSetInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ super.doSetInitializationData(config, propertyName, data);
+
+ if (!locked) {
+ String lockedAttribute = config.getAttribute("locked"); //$NON-NLS-1$
+ if (lockedAttribute != null) {
+ this.locked = Boolean.parseBoolean(lockedAttribute);
+ }
+ }
+
+ if (baseOn == null || baseOn.trim().length() == 0) {
+ String baseOnAttribute = config.getAttribute("baseOn"); //$NON-NLS-1$
+ if (baseOnAttribute != null && baseOnAttribute.trim().length() > 0) {
+ this.baseOn = baseOnAttribute.trim();
+ }
+ }
+
+ Map<String, Integer> occurrences = new HashMap<String, Integer>();
+ IConfigurationElement[] childElements = config.getChildren("references"); //$NON-NLS-1$
+ for (IConfigurationElement childElement : childElements) {
+ IConfigurationElement[] references = childElement.getChildren("reference"); //$NON-NLS-1$
+ for (IConfigurationElement reference : references) {
+ ReferenceSubElement candidate = new ReferenceSubElement();
+ candidate.setInitializationData(reference, reference.getName(), null);
+ // If multiple references to the same step or step group exist, check
+ // for the secondaryId
+ if (occurrences.containsKey(candidate.getId())) {
+ // Occurrences are counted up always
+ int number = occurrences.get(candidate.getId()).intValue() + 1;
+ occurrences.put(candidate.getId(), Integer.valueOf(number));
+
+ if (candidate.getSecondaryId() == null) {
+ // secondaryId not explicitly set -> auto set
+ candidate.setSecondardId(Integer.toString(number));
+ }
+ } else {
+ // remember the occurrence of the reference
+ occurrences.put(candidate.getId(), Integer.valueOf(1));
+ }
+
+ // References are not sorted out here. That's the task of the resolver.
+ this.references.add(candidate);
+ }
+ }
+ }
+
+
+ /**
+ * Checks is all dependencies of the given step are available
+ * and valid for the given type id and mode.
+ *
+ * @param step The step. Must not be <code>null</code>.
+ * @param type The type id. Must not be <code>null</code>.
+ * @param mode The mode. Must not be <code>null</code>.
+ *
+ * @throws CoreException If a required step or step group is not available or not valid.
+ */
+ protected void checkForDependenciesValid(IContextStep step, String type, String mode) throws CoreException {
+ assert step != null && type != null && mode != null;
+
+ String[] dependencies = step.getDependencies();
+ for (String dependency : dependencies) {
+ // Get the step or step group. Try the steps first.
+ IExecutableExtension candidate = getStep(dependency);
+ if (candidate == null) {
+ candidate = getStepGroup(dependency);
+ }
+
+ // If the candidate is null here, that's an error as a required step or step group is missing.
+ if (candidate == null) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_missingRequiredStep,
+ NLS.bind(Messages.ContextStepGroup_error_step, step.getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_requiredStepOrGroup, dependency),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // If the candidate a step, validate the step
+ if (candidate instanceof IContextStep) {
+ IContextStep candidateStep = (IContextStep)candidate;
+ boolean valid = isValidStep(candidateStep.getId(), type, mode);
+ if (!valid) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_invalidRequiredStep,
+ NLS.bind(Messages.ContextStepGroup_error_step, step.getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_requiredStep, dependency),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // Step is valid -> recursively check required steps.
+ checkForDependenciesValid(candidateStep, type, mode);
+ }
+ }
+ }
+
+ /**
+ * Convenience method returning a unique instance of the step
+ * identified by the given id.
+ *
+ * @param id The step id. Must not be <code>null</code>.
+ * @return The step instance or <code>null</code>.
+ */
+ protected IContextStep getStep(String id) {
+ Assert.isNotNull(id);
+ return StepperManager.getInstance().getStepExtManager().getStep(id, true);
+ }
+
+ /**
+ * Convenience method returning a unique instance of the step
+ * group identified by the given id.
+ *
+ * @param id The step id. Must not be <code>null</code>.
+ * @return The step group instance or <code>null</code>.
+ */
+ protected IContextStepGroup getStepGroup(String id) {
+ Assert.isNotNull(id);
+ return StepperManager.getInstance().getStepGroupExtManager().getStepGroup(id, true);
+ }
+
+ /**
+ * Returns if or if not the step identified by the given id is valid.
+ * <p>
+ * <b>Note:</b> The default implementation returns always <code>true</code>.
+ *
+ * @param id The step id. Must not be <code>null</code>.
+ * @param type The type id. Must not be <code>null</code>.
+ * @param mode The mode. Must not be <code>null</code>.
+ *
+ * @return <code>True</code> if the step is valid, <code>false</code> otherwise.
+ */
+ protected boolean isValidStep(String id, String type, String mode) {
+ return true;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroupable.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroupable.java
new file mode 100644
index 000000000..9486f248b
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/ContextStepGroupable.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.extensions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable;
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+
+/**
+ * Context step groupable implementation.
+ */
+public class ContextStepGroupable implements IContextStepGroupable {
+ private String secondaryId = null;
+ private boolean disabled = false;
+ private boolean hidden = false;
+ private boolean removable = true;
+ private boolean singleton = false;
+ private final List<String> dependencies = new ArrayList<String>();
+
+ private IExecutableExtension extension;
+
+ /**
+ * Constructor.
+ *
+ * @param extension The grouped extension. Must not be <code>null</code>.
+ */
+ public ContextStepGroupable(IExecutableExtension extension) {
+ this(extension, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param extension The grouped extension. Must not be <code>null</code>.
+ * @param secondaryId The groupable secondaryId or <code>null</code>.
+ */
+ public ContextStepGroupable(IExecutableExtension extension, String secondaryId) {
+ super();
+ setExtension(extension);
+ setSecondaryId(secondaryId);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable#getExtension()
+ */
+ @Override
+ public IExecutableExtension getExtension() {
+ return extension;
+ }
+
+ /**
+ * Set the grouped extension instance.
+ *
+ * @param extension The grouped extension instance. Must not be <code>null</code>.
+ */
+ public void setExtension(IExecutableExtension extension) {
+ Assert.isNotNull(extension);
+ this.extension = extension;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable#getSecondaryId()
+ */
+ @Override
+ public String getSecondaryId() {
+ return secondaryId;
+ }
+
+ /**
+ * Steps the groupable secondary id. The primary id is the unique id of the extension.
+ *
+ * @param secondaryId The grouped extension secondary id or <code>null</code>.
+ */
+ public void setSecondaryId(String secondaryId) {
+ this.secondaryId = secondaryId;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable#isDisabled()
+ */
+ @Override
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ /**
+ * Sets if or if not the step is disabled.
+ * <p>
+ * The default value is <code>false</code> and can be changed exactly once to <code>true</code>.
+ * Once set to <code>true</code> it must not be changeable anymore.
+ *
+ * @param disabled Specify <code>true</code> if to disable the step, <code>false</code> otherwise.
+ */
+ public void setDisabled(boolean disabled) {
+ Assert.isTrue(this.disabled == false);
+ this.disabled = disabled;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable#isHidden()
+ */
+ @Override
+ public boolean isHidden() {
+ return hidden;
+ }
+
+ /**
+ * Sets if or if not the step is hidden from the user.
+ * <p>
+ * The default value is <code>false</code> and can be changed exactly once to <code>true</code>.
+ * Once set to <code>true</code> it must not be changeable anymore.
+ *
+ * @param hidden Specify <code>true</code> if to hide the step, <code>false</code> otherwise.
+ */
+ public void setHidden(boolean hidden) {
+ Assert.isTrue(this.hidden == false);
+ this.hidden = hidden;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable#isRemovable()
+ */
+ @Override
+ public boolean isRemovable() {
+ return removable;
+ }
+
+ /**
+ * Sets if or if not the step can be removed from a step group by the user.
+ * <p>
+ * The default value is <code>true</code> and can be changed exactly once to <code>false</code>.
+ * Once set to <code>false</code> it must not be changeable anymore.
+ *
+ * @param removable Specify <code>True</code> if the step can be removed, <code>false</code> otherwise.
+ */
+ public void setRemovable(boolean removable) {
+ Assert.isTrue(this.removable == true);
+ this.removable = removable;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable#isSingleton()
+ */
+ @Override
+ public boolean isSingleton() {
+ return singleton;
+ }
+
+ /**
+ * Sets if or if not the launch step is a singleton. Singleton steps can occur in step groups
+ * only once. Multiple occurrences are forbidden.
+ *
+ * @param singleton Specify <code>true</code> if the step is a singleton, <code>false</code> otherwise.
+ */
+ public void setSingleton(boolean singleton) {
+ Assert.isTrue(this.singleton == false);
+ this.singleton = singleton;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroupable#getDependencies()
+ */
+ @Override
+ public String[] getDependencies() {
+ return dependencies.toArray(new String[dependencies.size()]);
+ }
+
+ /**
+ * Sets the list of dependencies. The dependencies of a groupable are checked on execution. If
+ * one of the listed dependencies have not been executed before, the execution of the groupable
+ * will fail.
+ * <p>
+ * The context step or context step group id might be fully qualified using the form
+ * <code>&quot;primaryId##secondaryId</code>. The <code>secondaryId</code> is optional.
+ *
+ * @param dependencies The list of dependencies. Must not be <code>null</code>.
+ */
+ public void setDependencies(String[] dependencies) {
+ Assert.isNotNull(dependencies);
+ this.dependencies.clear();
+ this.dependencies.addAll(Arrays.asList(dependencies));
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder buffer = new StringBuilder(getClass().getSimpleName());
+ buffer.append(" (" + getExtension().getLabel() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append(": "); //$NON-NLS-1$
+ buffer.append("id = " + getExtension().getId()); //$NON-NLS-1$
+ buffer.append(", secondaryId = " + getSecondaryId()); //$NON-NLS-1$
+ return buffer.toString();
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContext.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContext.java
new file mode 100644
index 000000000..264ff6d44
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContext.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.core.runtime.IAdaptable;
+
+/**
+ * Interface to be implemented by objects representing a context for a step.
+ */
+public interface IContext extends IAdaptable {
+
+ /**
+ * Returns the context id.
+ *
+ * @return The context id or <code>null</code>.
+ */
+ public String getContextId();
+
+ /**
+ * Returns a name/label to be used within the UI to represent this context
+ * to the user.
+ *
+ * @return The name or <code>null</code>.
+ */
+ public String getContextName();
+
+ /**
+ * Returns a possible multi-line string providing detail information
+ * about the context which shall be included in failure messages.
+ *
+ * @return The context information or <code>null</code>.
+ */
+ public String getContextInfo();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextManipulator.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextManipulator.java
new file mode 100644
index 000000000..61bb81817
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextManipulator.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+/**
+ * A step or step group capable of modifying the context the steps or step
+ * groups are operating on.
+ */
+public interface IContextManipulator {
+
+ /**
+ * The suffix to append to the full qualified step id to
+ * get the delayed status object.
+ */
+ public final static String CONTEXT_ID = "contextId"; //$NON-NLS-1$
+
+ /**
+ * The suffix to append to the full qualified step id to
+ * get the delayed status object.
+ */
+ public final static String CONTEXT = "context"; //$NON-NLS-1$
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStep.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStep.java
new file mode 100644
index 000000000..f7a1e359e
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStep.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * A single step associated with a context.
+ * <p>
+ * Context steps are assumed to be asynchronous. If the context step execution
+ * finished, the passed in <b>callback must be invoked</b>. The parent launch
+ * stepper suspend the step sequence execution till the callback is invoked.
+ * <p>
+ * Context steps signals the execution state to the parent launch stepper via
+ * the <code>IStatus</code> object passed to the callback as first argument.
+ * The status object is mandatory and cannot be <code>null</code>. If the step
+ * execution succeeds, an status with severity {@link IStatus#OK} is expected.
+ */
+public interface IContextStep extends IExecutableExtension {
+
+ /**
+ * Additional data property for ICallback.
+ */
+ public static final String CALLBACK_PROPERTY_DATA = "data"; //$NON-NLS-1$
+
+ /**
+ * Executes the context step logic.
+ *
+ * @param context The context. Must not be <code>null</code>.
+ * @param data The data giving object. Must not be <code>null</code>.
+ * @param fullQualifiedId The full qualified id for this step. Must not be <code>null</code>.
+ * @param monitor The progress monitor. Must not be <code>null</code>.
+ * @param callback The callback to invoke if finished. Must not be <code>null</code>.
+ */
+ public void execute(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor, ICallback callback);
+
+ /**
+ * Returns the number of total work the step is consuming.
+ *
+ * @return The number of total work or {@link IProgressMonitor#UNKNOWN}.
+ */
+ public int getTotalWork(IContext context, IPropertiesContainer data);
+
+ /**
+ * Returns the list of required context step or context step group id's. The
+ * execution of a context step fails if not all of the required steps are
+ * available or have not been executed before.
+ * <p>
+ * If the listed required steps have dependencies on their own, these dependencies
+ * are implicitly inherited.
+ *
+ * @return The list of required context step or context step group id's or an empty list.
+ */
+ public String[] getDependencies();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepExecutor.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepExecutor.java
new file mode 100644
index 000000000..f5a977ca1
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepExecutor.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * A step executor.
+ */
+public interface IContextStepExecutor {
+
+ /**
+ * Executes the associated step.
+ *
+ * @param step The step to execute. Must not be <code>null</code>.
+ * @param id The full qualified step id. Must not be <code>null</code>.
+ * @param context The context. Must not be <code>null</code>.
+ * @param data The data. Must not be <code>null</code>.
+ * @param monitor The progress monitor. Must not be <code>null</code>.
+ *
+ * @throws CoreException if the execution cannot be continue. The associated status should describe the failure cause.
+ */
+ public void execute(IContextStep step, IFullQualifiedId id, IContext context, IPropertiesContainer data, IProgressMonitor monitor) throws CoreException;
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroup.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroup.java
new file mode 100644
index 000000000..8e1aca910
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroup.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+
+
+/**
+ * A step group.
+ * <p>
+ * A step group is a set of single steps or other step groups.
+ */
+public interface IContextStepGroup extends IExecutableExtension {
+
+ /**
+ * Returns if or if not the step group is locked for user modifications.
+ *
+ * @return <code>True</code> if locked for user modifications, <code>false</code> otherwise.
+ */
+ public boolean isLocked();
+
+ /**
+ * Returns the list of steps or step groups enlisted in the group for the specified stepper,
+ * type and sub type.
+ *
+ * @param type The type id. Must be not <code>null</code>.
+ * @param subType The sub type Must be not <code>null</code>.
+ *
+ * @return The list of steps and step groups or an empty array.
+ *
+ * @throws CoreException If the steps cannot be determined.
+ */
+ public IContextStepGroupable[] getSteps(String type, String subType) throws CoreException;
+
+ /**
+ * Return the step group iterator or <code>null</code>. The step group iterator can be used to
+ * generate loops and conditions for a step group.
+ */
+ public IContextStepGroupIterator getStepGroupIterator();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupIterator.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupIterator.java
new file mode 100644
index 000000000..2d1da0289
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupIterator.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * A step group iterator.
+ */
+public interface IContextStepGroupIterator extends IExecutableExtension {
+
+ /**
+ * Initialize the iterator.
+ *
+ * @param context The context. Must be not <code>null</code>.
+ * @param data The data. Must be not <code>null</code>.
+ * @param fullQualifiedId The full qualified id for this step. Must be not <code>null</code>.
+ * @param monitor The progress monitor. Must be not <code>null</code>.
+ */
+ public void initialize(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor);
+
+ /**
+ * Return the number of calculated iterations. If the iterator was not initialized,
+ * <code>-1</code> is returned.
+ */
+ public int getNumIterations();
+
+ /**
+ * Check if there is a next iteration possible.
+ *
+ * @param context The context. Must be not <code>null</code>.
+ * @param data The data. Must be not <code>null</code>.
+ * @param fullQualifiedId The full qualified id for this step. Must be not <code>null</code>.
+ * @param monitor The progress monitor. Must be not <code>null</code>.
+ * @return <code>true</code> if another iteration is possible.
+ */
+ public boolean hasNext(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor);
+
+ /**
+ * Set the next iteration to the data using the full qualified id.
+ *
+ * @param context The context. Must be not <code>null</code>.
+ * @param data The data. Must be not <code>null</code>.
+ * @param fullQualifiedId The full qualified id for this step. Must be not <code>null</code>.
+ * @param monitor The progress monitor. Must be not <code>null</code>.
+ * @throws CoreException
+ */
+ public void next(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) throws CoreException;
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupable.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupable.java
new file mode 100644
index 000000000..89e21f93a
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IContextStepGroupable.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+
+/**
+ * A step groupable.
+ */
+public interface IContextStepGroupable {
+
+ /**
+ * Returns the grouped extension instance.
+ *
+ * @return The grouped extension instance.
+ */
+ public IExecutableExtension getExtension();
+
+ /**
+ * Returns the groupable secondary id. The primary id is the unique id of the extension.
+ *
+ * @return The groupable secondary id or <code>null</code>.
+ */
+ public String getSecondaryId();
+
+ /**
+ * Returns if or if not the step is a singleton. Singleton steps can occur in step groups only
+ * once. Multiple occurrences are forbidden.
+ *
+ * @return <code>True</code> if the step is a singleton, <code>false</code> otherwise.
+ */
+ public boolean isSingleton();
+
+ /**
+ * Returns if or if not the step can be removed from a step group by the user.
+ * <p>
+ * The default value is <code>true</code> and can be changed exactly once to <code>false</code>.
+ * Once set to <code>false</code> it must not be changeable anymore.
+ *
+ * @return <code>True</code> if the step can be removed, <code>false</code> otherwise.
+ */
+ public boolean isRemovable();
+
+ /**
+ * Returns if or if not the step is hidden from the user.
+ * <p>
+ * The default value is <code>false</code> and can be changed exactly once to <code>true</code>.
+ * Once set to <code>true</code> it must not be changeable anymore.
+ *
+ * @return <code>True</code> if the step is hidden, <code>false</code> otherwise.
+ */
+ public boolean isHidden();
+
+ /**
+ * Returns if or if not the step is disabled.
+ * <p>
+ * The default value is <code>false</code> and can be changed exactly once to <code>true</code>.
+ * Once set to <code>true</code> it must not be changeable anymore.
+ *
+ * @return <code>True</code> if the step is disable, <code>false</code> otherwise.
+ */
+ public boolean isDisabled();
+
+ /**
+ * Returns the list of dependencies. The dependencies of a groupable are checked on execution.
+ * If one of the listed dependencies have not been executed before, the execution of the
+ * groupable will fail.
+ * <p>
+ * The launch step or launch step group id might be fully qualified using the form
+ * <code>&quot;primaryId##secondaryId</code>. The <code>secondaryId</code> is optional.
+ *
+ * @return The list of dependencies or an empty list.
+ */
+ public String[] getDependencies();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedContextStep.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedContextStep.java
new file mode 100644
index 000000000..a13e1a54d
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedContextStep.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * Extended single step providing additional life cycle methods.
+ */
+public interface IExtendedContextStep extends IContextStep {
+
+ /**
+ * Returns if or if not this step can have multiple references within step groups. If
+ * <code>true</code> is returned, the step can occur exactly once per step group. This method
+ * effects all defined step groups and overwrite individual step settings.
+ * <p>
+ * The default implementation returns <code>false</code>.
+ *
+ * @return <code>True</code> if the step can be referenced only ones per step group,
+ * <code>false</code> otherwise.
+ */
+ public boolean isSingleton();
+
+ /**
+ * Initialize the step from the given data.
+ *
+ * @param context The context. Must not be <code>null</code>.
+ * @param data The data. Must not be <code>null</code>.
+ * @param fullQualifiedId The full qualified id for this step. Must not be <code>null</code>.
+ * @param monitor The progress monitor. Must not be <code>null</code>.
+ */
+ public void initializeFrom(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor);
+
+ /**
+ * Validate execution conditions.
+ * <p>
+ * This method is called from
+ * {@link #execute(IContext, Object, IFullQualifiedId, IProgressMonitor, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)}
+ * after the step initialization. If any execution condition is not fulfilled, the method should
+ * throw an {@link CoreException} to signal the failure.
+ *
+ * @param context The context. Must not be <code>null</code>.
+ * @param data The data. Must not be <code>null</code>.
+ * @param fullQualifiedId The full qualified id for this step. Must not be <code>null</code>.
+ * @param monitor The progress monitor. Must not be <code>null</code>.
+ *
+ * @throws CoreException if the execution cannot be continue. The associated status should describe the failure cause.
+ */
+ public void validateExecute(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Cleanup intermediate data of the step.
+ * <p>
+ * This method will be called at the end of each step execution.
+ *
+ * @param context The context. Must not be <code>null</code>.
+ * @param data The data. Must not be <code>null</code>.
+ * @param fullQualifiedId The full qualified id for this step. Must not be <code>null</code>.
+ * @param monitor The progress monitor. Must not be <code>null</code>.
+ */
+ public void cleanup(IContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor);
+
+ /**
+ * Called from the stepper engine once an error occurred during the stepping. Gives
+ * each step, completed previously to the error, the possibility to rollback
+ * whatever the step did.
+ * <p>
+ * <b>Note:</b> It is not guaranteed that the shared step data hasn't been overwritten
+ * in the meanwhile by multiple invocation of the same step. If a
+ * step supports multiple invocations, the implementer of the step is
+ * required to identify all the step data to rollback by himself.
+ *
+ * @param context The context. Must not be <code>null</code>.
+ * @param data The data. Must not be <code>null</code>.
+ * @param status The status of the last step executed and that caused the rollback.
+ * @param fullQualifiedId The full qualified id for this step. Must not be <code>null</code>.
+ * @param monitor The progress monitor. Must not be <code>null</code>.
+ * @param callback The callback to invoke if finished. Must not be <code>null</code>.
+ */
+ public void rollback(IContext context, IPropertiesContainer data, IStatus status, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor, ICallback callback);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IFullQualifiedId.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IFullQualifiedId.java
new file mode 100644
index 000000000..765f85e81
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IFullQualifiedId.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+/**
+ * A unique, hierarchically id used by steps, step groups and others.
+ */
+public interface IFullQualifiedId {
+
+ /**
+ * Get the parent id or <code>null</code> if this is the root.
+ *
+ * @return The parent id or <code>null</code>.
+ */
+ public IFullQualifiedId getParentId();
+
+ /**
+ * Creates a new id using this id as the parent.
+ *
+ * @param type The type of the new child.
+ * @param id The id for the new child.
+ * @param secondaryId The secondary id of the new child.
+ * @return The new created full qualified id.
+ */
+ public IFullQualifiedId createChildId(String type, String id, String secondaryId);
+
+ /**
+ * Get the type of this id.
+ *
+ * @return The type.
+ */
+ public String getType();
+
+ /**
+ * Get the id of this node.
+ *
+ * @return The id.
+ */
+ public String getId();
+
+ /**
+ * Get the secondary id of this node or <code>null</code>
+ * if there is no secondary id.
+ *
+ * @return The secondary id or <code>null</code>.
+ */
+ public String getSecondaryId();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepper.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepper.java
new file mode 100644
index 000000000..346181568
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepper.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.tcf.te.runtime.interfaces.IConditionTester;
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+
+/**
+ * A stepper.
+ * <p>
+ * Stepper are executing a set of steps and/or step groups read from a given type for the current
+ * sub type. The stepper is responsible for handling any exceptions which occurred during step
+ * execution.
+ * <p>
+ * Stepper are synchronous where steps are asynchronous.
+ * <p>
+ * Stepper must run in worker threads.
+ */
+public interface IStepper extends IExecutableExtension {
+
+ public static final String ID_TYPE_STEPPER_ID = "Stepper"; //$NON-NLS-1$
+ public static final String ID_TYPE_CONTEXT_ID = "Context"; //$NON-NLS-1$
+ public static final String ID_TYPE_STEP_GROUP_ID = "StepGroup"; //$NON-NLS-1$
+ public static final String ID_TYPE_STEP_GROUP_ITERATION_ID = "StepGroupIteration"; //$NON-NLS-1$
+ public static final String ID_TYPE_STEP_ID = "Step"; //$NON-NLS-1$
+
+ /**
+ * Condition Tester to test for finished execution of the associated stepper.
+ */
+ public static class ExecutionFinishedConditionTester implements IConditionTester {
+ private final IStepper stepper;
+
+ /**
+ * Constructor.
+ *
+ * @param stepper The stepper. Must not be <code>null</code>.
+ */
+ public ExecutionFinishedConditionTester(IStepper stepper) {
+ Assert.isNotNull(stepper);
+ this.stepper = stepper;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#cleanup()
+ */
+ @Override
+ public void cleanup() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#isConditionFulfilled()
+ */
+ @Override
+ public boolean isConditionFulfilled() {
+ return stepper.isFinished();
+ }
+ }
+
+ /**
+ * Initialize the stepper for a run. This method must be called before <i><code>execute()</code>
+ * </i>. Once the stepper finished the execution, the initialization is reseted and must be
+ * renewed before <i><code>execute()</code></i> can be called again.
+ *
+ * @param data The data. Must not be <code>null</code>.
+ * @param fullQualifiedId The full qualified id of this stepper.
+ * @param monitor The progress monitor. Must not be <code>null</code>.
+ *
+ * @throws IllegalStateException If called if the stepper is in initialized state already.
+ */
+ public void initialize(IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) throws IllegalStateException;
+
+ /**
+ * Returns if or if not the stepper got initialized for a new run.
+ * <p>
+ * The <i><code>execute()</code></i> method cannot be called if the stepper is not correctly
+ * initialized for each run. The initialized state can be set only by calling the <i>
+ * <code>initialize(...)</code></i> method. <i> <code>cleanup()</code></i> will reset the
+ * initialized state back to uninitialized.
+ *
+ * @return <code>True</code> if initialized, <code>false</code> otherwise.
+ */
+ public boolean isInitialized();
+
+ /**
+ * Executes the configured steps. The method is synchronous and must return only if all steps
+ * finished or an exception occurred.
+ * <p>
+ * Steps are assumed to be asynchronous. The stepper implementor must wait for callback(s) to be
+ * invoked by the step implementor(s) before the sequence can continue.
+ * <p>
+ * <b>Note:</b> Waiting for the step callback must not block the UI thread.
+ *
+ * @throws CoreException In case the execution fails or is canceled.
+ */
+ public void execute() throws CoreException;
+
+ /**
+ * Returns if or if not the stepper finished the execution.
+ *
+ * @return <code>True</code> if the execution is finished, <code>false</code> otherwise.
+ */
+ public boolean isFinished();
+
+ /**
+ * Cleanup and reset the stepper into a defined state.
+ */
+ public void cleanup();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IVariantDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IVariantDelegate.java
new file mode 100644
index 000000000..f6efb45c7
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IVariantDelegate.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces;
+
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+
+/**
+ * The variant delegate is providing variants to the main modes. Variants can influence the executed
+ * steps or step groups.
+ */
+public interface IVariantDelegate extends IExecutableExtension {
+
+ /**
+ * Returns the valid mode variants for the current context The returned list of variants is
+ * probed in the returned order.
+ *
+ * @param context The context. Must not be <code>null</code>.
+ * @param data The data. Must not be <code>null</code>.
+ *
+ * @return The valid variants or an empty array.
+ */
+ public String[] getValidVariants(IContext context, IPropertiesContainer data);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/tracing/ITraceIds.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/tracing/ITraceIds.java
new file mode 100644
index 000000000..4f526483d
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/tracing/ITraceIds.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.interfaces.tracing;
+
+/**
+ * Stepper Runtime plug-in trace slot identifiers.
+ */
+public interface ITraceIds {
+
+ /**
+ * If activated, trace information about step execution is printed out.
+ */
+ public static final String TRACE_STEPPING = "trace/stepping"; //$NON-NLS-1$
+
+ /**
+ * If activated, profile information about step execution is printed out.
+ */
+ public static final String PROFILE_STEPPING = "profile/stepping"; //$NON-NLS-1$
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepExtensionPointManager.java
new file mode 100644
index 000000000..55fb31408
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepExtensionPointManager.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.internal.extensions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStep;
+import org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
+
+/**
+ * Step extension point manager implementation.
+ */
+public class StepExtensionPointManager extends AbstractExtensionPointManager<IContextStep> {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getExtensionPointId()
+ */
+ @Override
+ protected String getExtensionPointId() {
+ return "org.eclipse.tcf.te.runtime.stepper.steps"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getConfigurationElementName()
+ */
+ @Override
+ protected String getConfigurationElementName() {
+ return "step"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the list of all contributed steps.
+ *
+ * @param unique If <code>true</code>, the method returns new instances for each
+ * contributed step.
+ *
+ * @return The list of contributed steps, or an empty array.
+ */
+ public IContextStep[] getSteps(boolean unique) {
+ List<IContextStep> contributions = new ArrayList<IContextStep>();
+ Collection<ExecutableExtensionProxy<IContextStep>> delegates = getExtensions().values();
+ for (ExecutableExtensionProxy<IContextStep> delegate : delegates) {
+ IContextStep instance = unique ? delegate.newInstance() : delegate.getInstance();
+ if (instance != null && !contributions.contains(instance)) {
+ contributions.add(instance);
+ }
+ }
+
+ return contributions.toArray(new IContextStep[contributions.size()]);
+ }
+
+ /**
+ * Returns the step identified by its unique id. If no step with the specified id is registered,
+ * <code>null</code> is returned.
+ *
+ * @param id The unique id of the step or <code>null</code>
+ * @param unique If <code>true</code>, the method returns new instances of the step contribution.
+ *
+ * @return The step instance or <code>null</code>.
+ */
+ public IContextStep getStep(String id, boolean unique) {
+ Assert.isNotNull(id);
+ IContextStep contribution = null;
+ if (getExtensions().containsKey(id)) {
+ ExecutableExtensionProxy<IContextStep> proxy = getExtensions().get(id);
+ // Get the extension instance
+ contribution = unique ? proxy.newInstance() : proxy.getInstance();
+ }
+
+ return contribution;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionPointManager.java
new file mode 100644
index 000000000..aaa9a55a8
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionPointManager.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.internal.extensions;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup;
+import org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
+
+/**
+ * Step group extension manager implementation.
+ */
+public class StepGroupExtensionPointManager extends AbstractExtensionPointManager<IContextStepGroup> {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getExtensionPointId()
+ */
+ @Override
+ protected String getExtensionPointId() {
+ return "org.eclipse.tcf.te.runtime.stepper.stepGroups"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getConfigurationElementName()
+ */
+ @Override
+ protected String getConfigurationElementName() {
+ return "stepGroup"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#doCreateExtensionProxy(org.eclipse.core.runtime.IConfigurationElement)
+ */
+ @Override
+ protected ExecutableExtensionProxy<IContextStepGroup> doCreateExtensionProxy(IConfigurationElement element) throws CoreException {
+ return new StepGroupExtensionProxy(element);
+ }
+
+ /**
+ * Returns the step group identified by its unique id. If no step group with the specified id is
+ * registered, <code>null</code> is returned.
+ *
+ * @param id The step group unique id. Must not be <code>null</code>
+ * @param unique If <code>true</code>, the method returns new instances of the step group contribution.
+ *
+ * @return The step group instance or <code>null</code>.
+ */
+ public IContextStepGroup getStepGroup(String id, boolean unique) {
+ Assert.isNotNull(id);
+ IContextStepGroup contribution = null;
+ if (getExtensions().containsKey(id)) {
+ ExecutableExtensionProxy<IContextStepGroup> proxy = getExtensions().get(id);
+ // Get the extension instance
+ contribution = unique ? proxy.newInstance() : proxy.getInstance();
+ }
+
+ return contribution;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#doStoreExtensionTo(java.util.Map, org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy, org.eclipse.core.runtime.IConfigurationElement)
+ */
+ @Override
+ protected void doStoreExtensionTo(Map<String, ExecutableExtensionProxy<IContextStepGroup>> extensions, ExecutableExtensionProxy<IContextStepGroup> candidate, IConfigurationElement element) throws CoreException {
+ Assert.isNotNull(extensions);
+ Assert.isNotNull(candidate);
+ Assert.isNotNull(element);
+
+ // If no extension with this id had been registered before, register now.
+ if (!extensions.containsKey(candidate.getId())) {
+ extensions.put(candidate.getId(), candidate);
+ }
+ else if (extensions.get(candidate.getId()) instanceof StepGroupExtensionProxy) {
+ StepGroupExtensionProxy proxy = (StepGroupExtensionProxy)extensions.get(candidate.getId());
+ proxy.addGroupExtension(element);
+ }
+ else {
+ super.doStoreExtensionTo(extensions, candidate, element);
+ }
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionProxy.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionProxy.java
new file mode 100644
index 000000000..91839ff4c
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepGroupExtensionProxy.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.internal.extensions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.tcf.te.runtime.stepper.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.stepper.extensions.ContextStepGroup;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IContextStepGroup;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
+
+/**
+ * Step group extension proxy implementation.
+ */
+public class StepGroupExtensionProxy extends ExecutableExtensionProxy<IContextStepGroup> {
+ private List<IConfigurationElement> groupExtensions = new ArrayList<IConfigurationElement>();
+
+ /**
+ * Constructor.
+ *
+ * @param element The configuration element. Must not be <code>null</code>.
+ */
+ public StepGroupExtensionProxy(IConfigurationElement element) throws CoreException {
+ super(element);
+ }
+
+ /**
+ * Add a duplicate group extension that should be used to extend the launch group.
+ *
+ * @param element The configuration element. Must not be <code>null</code>.
+ */
+ public void addGroupExtension(IConfigurationElement element) {
+ Assert.isNotNull(element);
+ groupExtensions.add(element);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy#newInstance()
+ */
+ @Override
+ public IContextStepGroup newInstance() {
+ // Create the instance
+ ContextStepGroup instance = new ContextStepGroup();
+ // and initialize
+ try {
+ instance.setInitializationData(getConfigurationElement(), getConfigurationElement().getName(), null);
+ for (IConfigurationElement groupExtension : groupExtensions) {
+ instance.doSetInitializationData(groupExtension, groupExtension.getName(), null);
+ }
+ } catch (CoreException e) {
+ // initialization failed -> reset instance
+ Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(e.getStatus());
+ instance = null;
+ }
+ return instance;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepperExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepperExtensionPointManager.java
new file mode 100644
index 000000000..f7d46cec0
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/internal/extensions/StepperExtensionPointManager.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.internal.extensions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper;
+import org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
+
+/**
+ * Stepper extension point manager implementation.
+ */
+public class StepperExtensionPointManager extends AbstractExtensionPointManager<IStepper> {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getExtensionPointId()
+ */
+ @Override
+ protected String getExtensionPointId() {
+ return "org.eclipse.tcf.te.runtime.stepper.steppers"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getConfigurationElementName()
+ */
+ @Override
+ protected String getConfigurationElementName() {
+ return "stepper"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the list of all contributed stepper.
+ *
+ * @param unique If <code>true</code>, the method returns new instances for each
+ * contributed stepper.
+ *
+ * @return The list of contributed stepper, or an empty array.
+ */
+ public IStepper[] getStepper(boolean unique) {
+ List<IStepper> contributions = new ArrayList<IStepper>();
+ Collection<ExecutableExtensionProxy<IStepper>> delegates = getExtensions().values();
+ for (ExecutableExtensionProxy<IStepper> delegate : delegates) {
+ IStepper instance = unique ? delegate.newInstance() : delegate.getInstance();
+ if (instance != null && !contributions.contains(instance)) {
+ contributions.add(instance);
+ }
+ }
+
+ return contributions.toArray(new IStepper[contributions.size()]);
+ }
+
+ /**
+ * Returns the stepper identified by its unique id. If no stepper with the specified id is registered,
+ * <code>null</code> is returned.
+ *
+ * @param id The unique id of the stepper or <code>null</code>
+ * @param unique If <code>true</code>, the method returns new instances of the stepper contribution.
+ *
+ * @return The stepper instance or <code>null</code>.
+ */
+ public IStepper getStepper(String id, boolean unique) {
+ Assert.isNotNull(id);
+ IStepper contribution = null;
+ if (getExtensions().containsKey(id)) {
+ ExecutableExtensionProxy<IStepper> proxy = getExtensions().get(id);
+ // Get the extension instance
+ contribution = unique ? proxy.newInstance() : proxy.getInstance();
+ }
+
+ return contribution;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.java
new file mode 100644
index 000000000..db90f107f
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.stepper.nls;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Stepper Runtime plugin externalized strings management.
+ */
+public class Messages extends NLS {
+
+ // The plug-in resource bundle name
+ private static final String BUNDLE_NAME = "org.eclipse.tcf.te.runtime.stepper.nls.Messages"; //$NON-NLS-1$
+
+ /**
+ * Static constructor.
+ */
+ static {
+ // Load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ // **** Declare externalized string id's down here *****
+
+ public static String AbstractContextStep_error_missingRequiredAttribute;
+ public static String AbstractContextStep_warning_stepFinishedWithWarnings;
+
+ public static String AbstractContextStepper_error_typeAndSubtype;
+ public static String AbstractContextStepper_error_stepGroup;
+ public static String AbstractContextStepper_error_step;
+ public static String AbstractContextStepper_error_referencedBaseGroup;
+ public static String AbstractContextStepper_error_referencedStepOrGroup;
+ public static String AbstractContextStepper_error_requiredStepOrGroup;
+ public static String AbstractContextStepper_error_requiredStep;
+ public static String AbstractContextStepper_error_initializeNotCalled;
+ public static String AbstractContextStepper_error_missingStepGroup;
+ public static String AbstractContextStepper_multiStatus_finishedWithWarnings;
+ public static String AbstractContextStepper_multiStatus_finishedWithErrors;
+ public static String AbstractContextStepper_error_missingRequiredStep;
+ public static String AbstractContextStepper_error_requiredStepNotExecuted;
+
+ public static String ContextStepGroup_error_missingBaseStepGroup;
+ public static String ContextStepGroup_error_missingReferencedStep;
+ public static String ContextStepGroup_error_missingRequiredStep;
+ public static String ContextStepGroup_error_invalidRequiredStep;
+ public static String ContextStepGroup_error_multipleSingletonOccurrences;
+ public static String ContextStepGroup_error_typeAndMode;
+ public static String ContextStepGroup_error_step;
+ public static String ContextStepGroup_error_stepGroup;
+ public static String ContextStepGroup_error_requiredStep;
+ public static String ContextStepGroup_error_referencedBaseGroup;
+ public static String ContextStepGroup_error_referencedStepOrGroup;
+ public static String ContextStepGroup_error_requiredStepOrGroup;
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.properties
new file mode 100644
index 000000000..fa6e72872
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.properties
@@ -0,0 +1,36 @@
+#
+# org.eclipse.tcf.te.runtime.stepper
+# Externalized Strings.
+#
+
+AbstractContextStep_error_missingRequiredAttribute=Required attribute "{0}" missing for extension "{1}"!
+AbstractContextStep_warning_stepFinishedWithWarnings=Step ''{0}'' finished with warnings.
+
+AbstractContextStepper_error_typeAndSubtype=Type:\n\t{0}\nSubtype:\n\t{1}
+AbstractContextStepper_error_stepGroup=Step group:\n\t{0}
+AbstractContextStepper_error_step=Step:\n\t{0}
+AbstractContextStepper_error_referencedBaseGroup=Referenced Base Step Group:\n\t{0}
+AbstractContextStepper_error_referencedStepOrGroup=Referenced Step or Step Group:\n\t{0}
+AbstractContextStepper_error_requiredStepOrGroup=Required Step or Step Group:\n\t{0}
+AbstractContextStepper_error_requiredStep=Required Step:\n\t{0}
+AbstractContextStepper_error_initializeNotCalled=initialize(...) must be called before execute()!
+AbstractContextStepper_error_missingStepGroup=Execution failed. No steps configured for ''{0}''.
+AbstractContextStepper_multiStatus_finishedWithWarnings=''{0}'' completed with warnings or information.
+AbstractContextStepper_multiStatus_finishedWithErrors=''{0}'' failed.
+AbstractContextStepper_error_missingRequiredStep=Step execution failed. \
+Required step or step group does not exist.\n\n{0}\n{1}\n\n{2}
+AbstractContextStepper_error_requiredStepNotExecuted=Step execution failed. \
+Required step or step group not executed before.\n\n{0}\n{1}\n\n{2}
+
+ContextStepGroup_error_missingBaseStepGroup=Cannot determine steps for execution. Referenced base step group does not exist.\n\n{0}\n{1}\n\n{2}
+ContextStepGroup_error_missingReferencedStep=Cannot determine steps for execution. Referenced step or step group does not exist.\n\n{0}\n{1}\n\n{2}
+ContextStepGroup_error_missingRequiredStep=Invalid step. Required step or step group does not exist.\n\n{0}\n{1}\n\n{2}
+ContextStepGroup_error_invalidRequiredStep=Invalid step. Required step is invalid.\n\n{0}\n{1}\n\n{2}
+ContextStepGroup_error_multipleSingletonOccurrences=Cannot determine steps for execution. Only one reference allowed.\n\n{0}\n{1}\n\n{2}
+ContextStepGroup_error_typeAndMode=Type:\n\t{0}\nMode:\n\t{1}
+ContextStepGroup_error_step=Step:\n\t{0}
+ContextStepGroup_error_stepGroup=Step group:\n\t{0}
+ContextStepGroup_error_requiredStep=Required Step:\n\t{0}
+ContextStepGroup_error_referencedBaseGroup=Referenced Base Step Group:\n\t{0}
+ContextStepGroup_error_referencedStepOrGroup=Referenced Step or Step Group:\n\t{0}
+ContextStepGroup_error_requiredStepOrGroup=Required Step or Step Group:\n\t{0}

Back to the top