Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Schwarz2013-04-09 11:34:28 +0000
committerTobias Schwarz2013-04-09 11:35:13 +0000
commitc4d1ff0c3cf8d73fcdf57e7a3c269c0a4bf34553 (patch)
tree81f7c107c32884fd117f4bae5ea391c91a6c57dd /target_explorer
parent1ea76786fb48d778e7b7dd3fc4b6417875225899 (diff)
downloadorg.eclipse.tcf-c4d1ff0c3cf8d73fcdf57e7a3c269c0a4bf34553.tar.gz
org.eclipse.tcf-c4d1ff0c3cf8d73fcdf57e7a3c269c0a4bf34553.tar.xz
org.eclipse.tcf-c4d1ff0c3cf8d73fcdf57e7a3c269c0a4bf34553.zip
Target Explorer: add watchdog when stepper is canceled and on rollback
Diffstat (limited to 'target_explorer')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/delegates/LaunchConfigurationDelegate.java3
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepExecutor.java27
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepGroup.java4
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedStep.java92
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStep.java241
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.java2
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/nls/Messages.properties1
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/stepper/Stepper.java1497
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/steps/AbstractStep.java12
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java680
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java72
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties28
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/steps/OpenChannelStep.java2
13 files changed, 1334 insertions, 1327 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/delegates/LaunchConfigurationDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/delegates/LaunchConfigurationDelegate.java
index 5612da668..7eab7db2f 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/delegates/LaunchConfigurationDelegate.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/delegates/LaunchConfigurationDelegate.java
@@ -41,7 +41,6 @@ import org.eclipse.tcf.te.launch.core.lm.interfaces.ICommonLaunchAttributes;
import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate;
import org.eclipse.tcf.te.launch.core.nls.Messages;
import org.eclipse.tcf.te.launch.core.persistence.projects.ReferencedProjectsPersistenceDelegate;
-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.stepper.interfaces.IStepContext;
@@ -144,8 +143,6 @@ public class LaunchConfigurationDelegate extends org.eclipse.debug.core.model.La
// Execute
stepper.execute();
- // Wait for the stepper to be finished
- ExecutorsUtil.waitAndExecute(0, new IStepper.ExecutionFinishedConditionTester(stepper));
} catch (CoreException e) {
// We have to catch the CoreException here as we do want to open the
// launch configurations dialog on ERROR only.
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepExecutor.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepExecutor.java
index 590c56e73..f9cfb6d4d 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepExecutor.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepExecutor.java
@@ -25,7 +25,6 @@ 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.stepper.activator.CoreBundleActivator;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedStep;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStep;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext;
@@ -64,10 +63,10 @@ public class StepExecutor implements IStepExecutor {
* @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepExecutor#execute(org.eclipse.tcf.te.runtime.stepper.interfaces.IStep, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
- public final void execute(IStep step, IFullQualifiedId id, final IStepContext context, final IPropertiesContainer data, IProgressMonitor progress) throws CoreException {
+ public final void execute(final IStep step, IFullQualifiedId id, final IStepContext context, final IPropertiesContainer data, IProgressMonitor progress) throws CoreException {
Assert.isNotNull(step);
Assert.isNotNull(id);
- // Assert.isNotNull(context);
+ Assert.isNotNull(context);
Assert.isNotNull(data);
Assert.isNotNull(progress);
@@ -79,7 +78,7 @@ public class StepExecutor implements IStepExecutor {
+ " ***", //$NON-NLS-1$
0, ITraceIds.PROFILE_STEPPING, IStatus.WARNING, this);
- int ticksToUse = (step instanceof IExtendedStep) ? ((IExtendedStep)step).getTotalWork(context, data) : IProgressMonitor.UNKNOWN;
+ int ticksToUse = step.getTotalWork(context, data);
progress = ProgressHelper.getProgressMonitor(progress, ticksToUse);
ProgressHelper.beginTask(progress, step.getLabel(), ticksToUse);
@@ -89,23 +88,13 @@ public class StepExecutor implements IStepExecutor {
// 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 IExtendedStep) {
- IExtendedStep extendedStep = (IExtendedStep)step;
-
- // IExtendedStep 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.initializeFrom(context, data, id, progress);
+ step.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));
+ ExecutorsUtil.waitAndExecute(0, callback.getDoneConditionTester(progress, step.getCancelTimeout()));
// Check the status of the step
normalizeStatus(step, id, context, data, callback.getStatus());
@@ -136,9 +125,7 @@ public class StepExecutor implements IStepExecutor {
}
// Give the step a chance for cleanup
- if (step instanceof IExtendedStep) {
- ((IExtendedStep)step).cleanup(context, data, id, progress);
- }
+ step.cleanup(context, data, id, progress);
long endTime = System.currentTimeMillis();
CoreBundleActivator.getTraceHandler().trace("StepExecutor#execute: *** DONE (" + step.getLabel() + ")", //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepGroup.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepGroup.java
index a753f2604..d00ba8a68 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepGroup.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/extensions/StepGroup.java
@@ -32,7 +32,6 @@ import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
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.IExtendedStep;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStep;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepGroup;
@@ -398,8 +397,7 @@ public class StepGroup extends ExecutableExtension implements IStepGroup {
// 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 IExtendedStep
- && ((IExtendedStep)step.getExtension()).isSingleton());
+ || (step.getExtension() instanceof IStep && ((IStep)step.getExtension()).isSingleton());
if (checkFailed) {
break;
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedStep.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedStep.java
deleted file mode 100644
index 962541ea5..000000000
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IExtendedStep.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2012 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.IAdaptable;
-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 IExtendedStep extends IStep {
-
- /**
- * 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(IStepContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor);
-
- /**
- * Validate execution conditions.
- * <p>
- * This method is called from
- * {@link #execute(IAdaptable, IPropertiesContainer, IFullQualifiedId, IProgressMonitor, 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(IStepContext 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(IStepContext 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(IStepContext 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/IStep.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStep.java
index 1f91fe001..872268c2d 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStep.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStep.java
@@ -1,80 +1,161 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2012 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 java.util.Map;
-
-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.
- * <p>
- * Steps are assumed to be asynchronous. If the step execution finished, the passed in <b>callback
- * must be invoked</b>. The parent stepper suspend the step sequence execution till the callback is
- * invoked.
- * <p>
- * Steps signals the execution state to the parent 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 IStep 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(IStepContext 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(IStepContext 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();
-
- /**
- * Set additional parameters for this step
- * @param parameters
- */
- public void setParameters(Map<String,String> parameters);
-
- /**
- * Returns a map of additional parameters given through the parameters section in the Reference section of a StepGroups.
- * @return The parameters of an empty Map.
- */
- public Map<String,String> getParameters();
-}
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 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 java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+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.
+ * <p>
+ * Steps are assumed to be asynchronous. If the step execution finished, the passed in <b>callback
+ * must be invoked</b>. The parent stepper suspend the step sequence execution till the callback is
+ * invoked.
+ * <p>
+ * Steps signals the execution state to the parent 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 IStep 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(IStepContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor, ICallback callback);
+
+ /**
+ * 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(IStepContext context, IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor);
+
+ /**
+ * Validate execution conditions.
+ * <p>
+ * This method is called from
+ * {@link #execute(IAdaptable, IPropertiesContainer, IFullQualifiedId, IProgressMonitor, 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(IStepContext 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(IStepContext 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.
+ * <p>
+ * IProgressMonitor.worked(int) should not be used for the given progress monitor. Setting sub task labels is ok.
+ *
+ * @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(IStepContext context, IPropertiesContainer data, IStatus status, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor, ICallback callback);
+
+ /**
+ * Get the timeout in milliseconds to wait for finish
+ * when the progress monitor was canceled.
+ * If a step should not have a timeout and handles the cancel itself return -1.
+ * @return Timeout in milliseconds.
+ */
+ public int getCancelTimeout();
+
+ /**
+ * Returns the number of total work the step is consuming.
+ *
+ * @return The number of total work or {@link IProgressMonitor#UNKNOWN}.
+ */
+ public int getTotalWork(IStepContext 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();
+
+ /**
+ * Set additional parameters for this step
+ * @param parameters
+ */
+ public void setParameters(Map<String,String> parameters);
+
+ /**
+ * Returns a map of additional parameters given through the parameters section in the Reference section of a StepGroups.
+ * @return The parameters of an empty Map.
+ */
+ public Map<String,String> getParameters();
+}
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
index b80750d0f..3a78f8ae7 100644
--- 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
@@ -64,4 +64,6 @@ public class Messages extends NLS {
public static String StepExecutor_warning_stepFailed;
public static String StepExecutor_error_stepFailed;
public static String StepExecutor_stepFailed_debugInfo;
+ public static String StepExecutor_warning_rollbackTimeout;
+
}
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
index b8040ba9b..3c4f7ff66 100644
--- 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
@@ -49,3 +49,4 @@ StepExecutor_error_stepFailed=Step finished with this error: {0}\n\n\
Context: {1}\n\{2}\n\
Step: {3}
StepExecutor_stepFailed_debugInfo=Debug info:\n{0}
+StepExecutor_warning_rollbackTimeout=Step rollback was aborted due to timeout.
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/stepper/Stepper.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/stepper/Stepper.java
index e8a91e33a..57d307918 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/stepper/Stepper.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/stepper/Stepper.java
@@ -1,759 +1,738 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2012 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.stepper;
-
-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.NullProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.osgi.util.NLS;
-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.stepper.FullQualifiedId;
-import org.eclipse.tcf.te.runtime.stepper.StepperManager;
-import org.eclipse.tcf.te.runtime.stepper.activator.CoreBundleActivator;
-import org.eclipse.tcf.te.runtime.stepper.extensions.StepExecutor;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedStep;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IStep;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepExecutor;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepGroup;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepGroupIterator;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepGroupable;
-import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper;
-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.utils.ProgressHelper;
-import org.eclipse.tcf.te.runtime.utils.StatusHelper;
-
-/**
- * An abstract stepper implementation.
- */
-public class Stepper implements IStepper {
-
- private boolean initialized = false;
- private boolean finished = false;
- private IPropertiesContainer data = null;
- private IFullQualifiedId fullQualifiedId = null;
- private IProgressMonitor monitor = null;
- private IStepContext context = null;
- private boolean cancelable = true;
- private String stepGroupId = null;
- private String name = null;
-
- /**
- * Internal helper describing a fully executed step.
- */
- protected final class ExecutedContextStep {
- final IFullQualifiedId id;
- final IStep step;
-
- public ExecutedContextStep(IFullQualifiedId id, IStep step) {
- this.id = id;
- this.step = step;
- }
- }
-
- /**
- * Constructor.
- */
- public Stepper() {
- super();
- }
-
- /**
- * Constructor.
- *
- * @param name The name of this stepper.
- */
- public Stepper(String name) {
- super();
- this.name = name;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#getId()
- */
- @Override
- public String getId() {
- return getClass().getName();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#getLabel()
- */
- @Override
- public String getLabel() {
- return name != null && name.trim().length() > 0 ? name.trim() : getId();
- }
-
- /**
- * Returns the id of the step group to execute by the stepper.
- *
- * @return The step group id.
- */
- protected String getStepGroupId() {
- return stepGroupId;
- }
-
- /**
- * Returns the step group for the given step group id.
- *
- * @param The step group id. Must not be <code>null</code>:
- * @return The step group or <code>null</code>.
- */
- protected IStepGroup getStepGroup(String id) {
- Assert.isNotNull(id);
-
- CoreBundleActivator.getTraceHandler().trace("SingleContextStepper#getStepGroup:" //$NON-NLS-1$
- + " id = '" + id + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
-
- return StepperManager.getInstance().getStepGroupExtManager().getStepGroup(id, false);
- }
-
- /**
- * Creates a new instance of the step executor to use for executing a step.
- *
- * @param step The step. Must not be <code>null</code>.
- * @param secondaryId The secondary id or <code>null</code>.
- * @param fullQualifiedStepId The fully qualified step id. Must not be <code>null</code>.
- *
- * @return The step executor instance.
- */
- protected IStepExecutor doCreateStepExecutor(IStep step, String secondaryId, IFullQualifiedId fullQualifiedStepId) {
- Assert.isNotNull(step);
- Assert.isNotNull(fullQualifiedStepId);
- return new StepExecutor();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#initialize(org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext, java.lang.String, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.core.runtime.IProgressMonitor)
- */
- @Override
- public final void initialize(IStepContext context, String stepGroupId, IPropertiesContainer data, IProgressMonitor monitor) throws IllegalStateException {
- Assert.isNotNull(context);
- Assert.isNotNull(stepGroupId);
- Assert.isNotNull(data);
-
- // Assert stepper is not in use
- if (isInitialized()) {
- throw new IllegalStateException("Stepper instance already initialized!"); //$NON-NLS-1$
- }
-
- // set the initial stepper attributes
- this.context = context;
- this.stepGroupId = stepGroupId;
- this.data = data;
- this.monitor = monitor != null ? monitor : new NullProgressMonitor();
- this.fullQualifiedId = new FullQualifiedId(IStepper.ID_TYPE_STEP_CONTEXT_ID, context.getId(), context.getSecondaryId());
-
- // but not finished yet
- this.finished = false;
-
- // call the hook for the subclasses to initialize themselves
- onInitialize(this.data, fullQualifiedId, this.monitor);
-
- setInitialized();
-
- CoreBundleActivator.getTraceHandler().trace("Stepper#initialize:" //$NON-NLS-1$
- + " data = " + data, //$NON-NLS-1$
- 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
- }
-
- /**
- * Hook for subclasses to overwrite if subclasses wants to initialize their own state.
- *
- * @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>.
- */
- protected void onInitialize(IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) {
- Assert.isNotNull(data);
- Assert.isNotNull(monitor);
- }
-
- /**
- * 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;
- }
-
- /**
- * Get the active context.
- *
- * @return The active context or <code>null</code>.
- */
- protected IStepContext getContext() {
- return context;
- }
-
- /**
- * Get the context id.
- *
- * @return The context id or <code>null</code>.
- */
- protected String getContextId() {
- return context != null ? context.getId() : null;
- }
-
- /**
- * 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;
- }
-
- /* (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
- context = null;
- data = null;
- monitor = null;
- fullQualifiedId = null;
- finished = false;
- initialized = false;
- }
-
- /* (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("Stepper#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.Stepper_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.Stepper_multiStatus_finishedWithWarnings, getLabel()), 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("Stepper#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 step group id
- String stepGroupId = getStepGroupId();
-
- // If no step group id is available, throw an exception
- if (stepGroupId == null) {
- throw new CoreException(new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
- NLS.bind(Messages.Stepper_error_missingStepGroupId, getLabel())));
- }
-
- // Get the step group
- IStepGroup stepGroup = getStepGroup(stepGroupId);
-
- // If no step group could be found, throw an exception
- if (stepGroup == null) {
- throw new CoreException(new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
- NLS.bind(Messages.Stepper_error_missingStepGroup, stepGroupId)));
- }
-
- // Initialize the progress monitor
- getMonitor().beginTask(stepGroup.getLabel(), calculateTotalWork(stepGroup));
-
- IFullQualifiedId fullQualifiedId = getFullQualifiedId().createChildId(ID_TYPE_STEPPER_ID, getId(), 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 stepGroupId The step group. Must not be <code>null</code>.
- * @param statusContainer A list holding the warnings occurred during the execution. Must not be
- * <code>null</code>.
- * @param executedSteps A list holding the id's of the steps executed before. Must not be
- * <code>null</code>.
- * @param fullQualifiedGroupId The hierarchy of all parent step group id's separated by "::".
- * Must not be <code>null</code>.
- *
- * @throws CoreException If the execution fails.
- */
- private void executeStepGroup(IStepGroup 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("Stepper#executeStepGroup: step group: '" + stepGroup.getLabel() + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
-
- // Resolve the steps to execute
- IStepGroupable[] groupables = stepGroup.getSteps(getContext());
-
- IStepGroupIterator iterator = stepGroup.getStepGroupIterator();
- IFullQualifiedId fullQualifiedIterationId = fullQualifiedGroupId;
- int iteration = 0;
-
- if (iterator != null) {
- iterator.initialize(getContext(), getData(), fullQualifiedGroupId, getMonitor());
- }
- boolean next = iterator == null || iterator.hasNext(getContext(), getData(), fullQualifiedGroupId, getMonitor());
-
- while (next) {
- if (iterator != null) {
- fullQualifiedIterationId = fullQualifiedGroupId.getParentId().createChildId(ID_TYPE_STEP_GROUP_ID, stepGroup.getId(), "" + iteration); //$NON-NLS-1$
- iterator.next(getContext(), getData(), fullQualifiedIterationId, getMonitor());
- }
- // Execute the steps or step groups.
- for (IStepGroupable groupable : groupables) {
- executeGroupable(groupable, statusContainer, executedSteps, fullQualifiedIterationId);
- }
- iteration++;
- next = iterator != null && iterator.hasNext(getContext(), getData(), fullQualifiedGroupId, getMonitor());
- }
- }
-
- /**
- * Executes a step groupable. The groupable might encapsulate a step or a step group.
- *
- * @param step The step groupable. Must not be <code>null</code>.
- * @param statusContainer A list holding the warnings occurred during the execution. Must not be
- * <code>null</code>.
- * @param executedSteps A list holding the id's of the steps executed before. Must not be
- * <code>null</code>.
- * @param fullQualifiedParentId The hierarchy of all parent step group id's separated by "::".
- * Must not be <code>null</code>.
- *
- * @throws CoreException If the execution failed.
- */
- private void executeGroupable(IStepGroupable 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("Stepper#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 IStepGroup) {
- 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((IStepGroup) groupable.getExtension(), statusContainer, executedSteps, id);
- }
- else if (groupable.getExtension() instanceof IStep) {
- // 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.
- IStep step = (IStep) groupable.getExtension();
-
- IFullQualifiedId id = fullQualifiedParentId.createChildId(ID_TYPE_STEP_ID, step.getId(), groupable.getSecondaryId());
-
- // Create the step executor now
- IStepExecutor executor = doCreateStepExecutor(step, groupable.getSecondaryId(), id);
- Assert.isNotNull(executor);
-
- try {
- executedSteps.add(new ExecutedContextStep(id, step));
- // Invoke the executor now
- executor.execute(step, id, getContext(), getData(), getMonitor());
- }
- 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 not be <code>null</code>.
- * @param executedSteps A list holding the id's of the steps executed before. Must not be
- * <code>null</code>.
- *
- * @throws CoreException If a dependency has not been executed before.
- */
- protected void checkForDependenciesExecuted(IStepGroupable 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 IStep) {
- dependencies.addAll(Arrays.asList(((IStep) 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.Stepper_error_requiredStepNotExecuted,
- NLS.bind(groupable.getExtension() instanceof IStep ? Messages.Stepper_error_step : Messages.Stepper_error_stepGroup,
- groupable.getExtension().getId()),
- NLS.bind(Messages.Stepper_error_requiredStepOrGroup, dependency), ""))); //$NON-NLS-1$
- }
-
- // 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 IExtendedStep} 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 IExtendedStep) {
- IExtendedStep step = (IExtendedStep) executedStep.step;
- step.rollback(getContext(), 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 stepGroupId The step group. Must not be <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(IStepGroup stepGroup) throws CoreException {
- Assert.isNotNull(stepGroup);
-
- int totalWork = 0;
-
- // Loop the group steps and summarize the returned total work
- IStepGroupable[] groupables = stepGroup.getSteps(getContext());
- for (IStepGroupable groupable : groupables) {
- int work = groupable.getExtension() instanceof IStep ? ((IStep) groupable
- .getExtension()).getTotalWork(getContext(), getData()) : groupable
- .getExtension() instanceof IStepGroup ? calculateTotalWork((IStepGroup) 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 not be <code>null</code>.
- * @param statusContainer The list of non-severe status objects. Must not be <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.Stepper_multiStatus_finishedWithErrors, getLabel()), null);
- for (IStatus stat : statusContainer) {
- multiStatus.merge(stat);
- }
- // Re-throw via a new CoreException
- coreException = new CoreException(multiStatus);
- }
- }
-
- return coreException;
- }
-}
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 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.stepper;
+
+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.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+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.stepper.FullQualifiedId;
+import org.eclipse.tcf.te.runtime.stepper.StepperManager;
+import org.eclipse.tcf.te.runtime.stepper.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.stepper.extensions.StepExecutor;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStep;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepExecutor;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepGroup;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepGroupIterator;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepGroupable;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper;
+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.utils.StatusHelper;
+
+/**
+ * An abstract stepper implementation.
+ */
+public class Stepper implements IStepper {
+
+ private boolean initialized = false;
+ private boolean finished = false;
+ private IPropertiesContainer data = null;
+ private IFullQualifiedId fullQualifiedId = null;
+ private IProgressMonitor monitor = null;
+ private IStepContext context = null;
+ private boolean cancelable = true;
+ private String stepGroupId = null;
+ private String name = null;
+
+ /**
+ * Internal helper describing a fully executed step.
+ */
+ protected final class ExecutedContextStep {
+ final IFullQualifiedId id;
+ final IStep step;
+
+ public ExecutedContextStep(IFullQualifiedId id, IStep step) {
+ this.id = id;
+ this.step = step;
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ public Stepper() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of this stepper.
+ */
+ public Stepper(String name) {
+ super();
+ this.name = name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#getId()
+ */
+ @Override
+ public String getId() {
+ return getClass().getName();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#getLabel()
+ */
+ @Override
+ public String getLabel() {
+ return name != null && name.trim().length() > 0 ? name.trim() : getId();
+ }
+
+ /**
+ * Returns the id of the step group to execute by the stepper.
+ *
+ * @return The step group id.
+ */
+ protected String getStepGroupId() {
+ return stepGroupId;
+ }
+
+ /**
+ * Returns the step group for the given step group id.
+ *
+ * @param The step group id. Must not be <code>null</code>:
+ * @return The step group or <code>null</code>.
+ */
+ protected IStepGroup getStepGroup(String id) {
+ Assert.isNotNull(id);
+
+ CoreBundleActivator.getTraceHandler().trace("SingleContextStepper#getStepGroup:" //$NON-NLS-1$
+ + " id = '" + id + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+
+ return StepperManager.getInstance().getStepGroupExtManager().getStepGroup(id, false);
+ }
+
+ /**
+ * Creates a new instance of the step executor to use for executing a step.
+ *
+ * @param step The step. Must not be <code>null</code>.
+ * @param secondaryId The secondary id or <code>null</code>.
+ * @param fullQualifiedStepId The fully qualified step id. Must not be <code>null</code>.
+ *
+ * @return The step executor instance.
+ */
+ protected IStepExecutor doCreateStepExecutor(IStep step, String secondaryId, IFullQualifiedId fullQualifiedStepId) {
+ Assert.isNotNull(step);
+ Assert.isNotNull(fullQualifiedStepId);
+ return new StepExecutor();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepper#initialize(org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext, java.lang.String, org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer, org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public final void initialize(IStepContext context, String stepGroupId, IPropertiesContainer data, IProgressMonitor monitor) throws IllegalStateException {
+ Assert.isNotNull(context);
+ Assert.isNotNull(stepGroupId);
+ Assert.isNotNull(data);
+
+ // Assert stepper is not in use
+ if (isInitialized()) {
+ throw new IllegalStateException("Stepper instance already initialized!"); //$NON-NLS-1$
+ }
+
+ // set the initial stepper attributes
+ this.context = context;
+ this.stepGroupId = stepGroupId;
+ this.data = data;
+ this.monitor = monitor != null ? monitor : new NullProgressMonitor();
+ this.fullQualifiedId = new FullQualifiedId(IStepper.ID_TYPE_STEP_CONTEXT_ID, context.getId(), context.getSecondaryId());
+
+ // but not finished yet
+ this.finished = false;
+
+ // call the hook for the subclasses to initialize themselves
+ onInitialize(this.data, fullQualifiedId, this.monitor);
+
+ setInitialized();
+
+ CoreBundleActivator.getTraceHandler().trace("Stepper#initialize:" //$NON-NLS-1$
+ + " data = " + data, //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ }
+
+ /**
+ * Hook for subclasses to overwrite if subclasses wants to initialize their own state.
+ *
+ * @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>.
+ */
+ protected void onInitialize(IPropertiesContainer data, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor) {
+ Assert.isNotNull(data);
+ Assert.isNotNull(monitor);
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Get the active context.
+ *
+ * @return The active context or <code>null</code>.
+ */
+ protected IStepContext getContext() {
+ return context;
+ }
+
+ /**
+ * Get the context id.
+ *
+ * @return The context id or <code>null</code>.
+ */
+ protected String getContextId() {
+ return context != null ? context.getId() : null;
+ }
+
+ /**
+ * 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;
+ }
+
+ /* (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
+ context = null;
+ data = null;
+ monitor = null;
+ fullQualifiedId = null;
+ finished = false;
+ initialized = false;
+ }
+
+ /* (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("Stepper#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.Stepper_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.Stepper_multiStatus_finishedWithWarnings, getLabel()), 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("Stepper#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 step group id
+ String stepGroupId = getStepGroupId();
+
+ // If no step group id is available, throw an exception
+ if (stepGroupId == null) {
+ throw new CoreException(new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
+ NLS.bind(Messages.Stepper_error_missingStepGroupId, getLabel())));
+ }
+
+ // Get the step group
+ IStepGroup stepGroup = getStepGroup(stepGroupId);
+
+ // If no step group could be found, throw an exception
+ if (stepGroup == null) {
+ throw new CoreException(new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
+ NLS.bind(Messages.Stepper_error_missingStepGroup, stepGroupId)));
+ }
+
+ // Initialize the progress monitor
+ getMonitor().beginTask(stepGroup.getLabel(), calculateTotalWork(stepGroup));
+
+ IFullQualifiedId fullQualifiedId = getFullQualifiedId().createChildId(ID_TYPE_STEPPER_ID, getId(), 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 stepGroupId The step group. Must not be <code>null</code>.
+ * @param statusContainer A list holding the warnings occurred during the execution. Must not be
+ * <code>null</code>.
+ * @param executedSteps A list holding the id's of the steps executed before. Must not be
+ * <code>null</code>.
+ * @param fullQualifiedGroupId The hierarchy of all parent step group id's separated by "::".
+ * Must not be <code>null</code>.
+ *
+ * @throws CoreException If the execution fails.
+ */
+ private void executeStepGroup(IStepGroup 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("Stepper#executeStepGroup: step group: '" + stepGroup.getLabel() + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+
+ // Resolve the steps to execute
+ IStepGroupable[] groupables = stepGroup.getSteps(getContext());
+
+ IStepGroupIterator iterator = stepGroup.getStepGroupIterator();
+ IFullQualifiedId fullQualifiedIterationId = fullQualifiedGroupId;
+ int iteration = 0;
+
+ if (iterator != null) {
+ iterator.initialize(getContext(), getData(), fullQualifiedGroupId, getMonitor());
+ }
+ boolean next = iterator == null || iterator.hasNext(getContext(), getData(), fullQualifiedGroupId, getMonitor());
+
+ while (next) {
+ if (iterator != null) {
+ fullQualifiedIterationId = fullQualifiedGroupId.getParentId().createChildId(ID_TYPE_STEP_GROUP_ID, stepGroup.getId(), "" + iteration); //$NON-NLS-1$
+ iterator.next(getContext(), getData(), fullQualifiedIterationId, getMonitor());
+ }
+ // Execute the steps or step groups.
+ for (IStepGroupable groupable : groupables) {
+ executeGroupable(groupable, statusContainer, executedSteps, fullQualifiedIterationId);
+ }
+ iteration++;
+ next = iterator != null && iterator.hasNext(getContext(), getData(), fullQualifiedGroupId, getMonitor());
+ }
+ }
+
+ /**
+ * Executes a step groupable. The groupable might encapsulate a step or a step group.
+ *
+ * @param step The step groupable. Must not be <code>null</code>.
+ * @param statusContainer A list holding the warnings occurred during the execution. Must not be
+ * <code>null</code>.
+ * @param executedSteps A list holding the id's of the steps executed before. Must not be
+ * <code>null</code>.
+ * @param fullQualifiedParentId The hierarchy of all parent step group id's separated by "::".
+ * Must not be <code>null</code>.
+ *
+ * @throws CoreException If the execution failed.
+ */
+ private void executeGroupable(IStepGroupable 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("Stepper#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 IStepGroup) {
+ 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((IStepGroup) groupable.getExtension(), statusContainer, executedSteps, id);
+ }
+ else if (groupable.getExtension() instanceof IStep) {
+ // 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.
+ IStep step = (IStep) groupable.getExtension();
+
+ IFullQualifiedId id = fullQualifiedParentId.createChildId(ID_TYPE_STEP_ID, step.getId(), groupable.getSecondaryId());
+
+ // Create the step executor now
+ IStepExecutor executor = doCreateStepExecutor(step, groupable.getSecondaryId(), id);
+ Assert.isNotNull(executor);
+
+ try {
+ executedSteps.add(new ExecutedContextStep(id, step));
+ // Invoke the executor now
+ executor.execute(step, id, getContext(), getData(), getMonitor());
+ }
+ 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 not be <code>null</code>.
+ * @param executedSteps A list holding the id's of the steps executed before. Must not be
+ * <code>null</code>.
+ *
+ * @throws CoreException If a dependency has not been executed before.
+ */
+ protected void checkForDependenciesExecuted(IStepGroupable 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 IStep) {
+ dependencies.addAll(Arrays.asList(((IStep) 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.Stepper_error_requiredStepNotExecuted,
+ NLS.bind(groupable.getExtension() instanceof IStep ? Messages.Stepper_error_step : Messages.Stepper_error_stepGroup,
+ groupable.getExtension().getId()),
+ NLS.bind(Messages.Stepper_error_requiredStepOrGroup, dependency), ""))); //$NON-NLS-1$
+ }
+
+ // 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.
+ *
+ * @param executedSteps The list of executed steps.
+ * @param progress The progress monitor.
+ */
+ protected final void rollback(final List<ExecutedContextStep> executedSteps, final IStatus rollBackStatus, IProgressMonitor progress) {
+ Assert.isNotNull(executedSteps);
+
+
+ while (!executedSteps.isEmpty()) {
+ ExecutedContextStep executedStep = executedSteps.remove(executedSteps.size() - 1);
+ Callback callback = new Callback();
+ progress.setTaskName("Rollback " + executedStep.step.getLabel()); //$NON-NLS-1$
+ executedStep.step.rollback(getContext(), getData(), rollBackStatus, executedStep.id, progress, callback);
+ ExecutorsUtil.waitAndExecute(60000, callback.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 stepGroupId The step group. Must not be <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(IStepGroup stepGroup) throws CoreException {
+ Assert.isNotNull(stepGroup);
+
+ int totalWork = 0;
+
+ // Loop the group steps and summarize the returned total work
+ IStepGroupable[] groupables = stepGroup.getSteps(getContext());
+ for (IStepGroupable groupable : groupables) {
+ int work = groupable.getExtension() instanceof IStep ? ((IStep) groupable
+ .getExtension()).getTotalWork(getContext(), getData()) : groupable
+ .getExtension() instanceof IStepGroup ? calculateTotalWork((IStepGroup) 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 not be <code>null</code>.
+ * @param statusContainer The list of non-severe status objects. Must not be <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.Stepper_multiStatus_finishedWithErrors, getLabel()), 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/steps/AbstractStep.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/steps/AbstractStep.java
index d1b7316a4..371505a75 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/steps/AbstractStep.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/steps/AbstractStep.java
@@ -27,7 +27,6 @@ import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
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.IExtendedStep;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStep;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepAttributes;
@@ -37,7 +36,7 @@ import org.eclipse.tcf.te.runtime.stepper.nls.Messages;
/**
* An abstract step implementation.
*/
-public abstract class AbstractStep extends ExecutableExtension implements IExtendedStep {
+public abstract class AbstractStep extends ExecutableExtension implements IStep {
// List of string id's of the step dependencies.
private final List<String> dependencies = new ArrayList<String>();
@@ -178,4 +177,13 @@ public abstract class AbstractStep extends ExecutableExtension implements IExten
return activeContext;
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IExtendedStep#getCancelTimeout()
+ */
+ @Override
+ public int getCancelTimeout() {
+ // default timeout is 1 minute
+ return 60000;
+ }
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java
index edeb6fd49..be9ed0348 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java
@@ -1,320 +1,360 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2012 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.callback;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.eclipse.core.runtime.Assert;
-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.activator.CoreBundleActivator;
-import org.eclipse.tcf.te.runtime.interfaces.IConditionTester;
-import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
-import org.eclipse.tcf.te.runtime.properties.PropertiesContainer;
-import org.eclipse.tcf.te.runtime.utils.ProgressHelper;
-
-/**
- * Default implementation of the <code>ICallback</code> interface.
- */
-public class Callback extends PropertiesContainer implements ICallback {
-
- protected static final String PROPERTY_PARENT_CALLBACK = "parentCallback"; //$NON-NLS-1$
- protected static final String PROPERTY_PROGRESS_MONITOR = "progressMonitor"; //$NON-NLS-1$
- protected static final String PROPERTY_PROGRESS_TICKS = "progressTicks"; //$NON-NLS-1$
- protected static final String PROPERTY_IS_DONE = "isDone"; //$NON-NLS-1$
- protected static final String PROPERTY_STATUS = "status"; //$NON-NLS-1$
-
- /**
- * Property: Asynchronous operations can store a result to the callback
- * object they invoke once the operation has been finished.
- */
- protected static final String PROPERTY_RESULT = "result"; //$NON-NLS-1$
-
-
- private static final String[] PROPERTY_KEYS_NOT_TO_COPY = {
- PROPERTY_PARENT_CALLBACK, PROPERTY_PROGRESS_MONITOR,
- PROPERTY_PROGRESS_TICKS, PROPERTY_IS_DONE, PROPERTY_STATUS
- };
- private static final List<String> PROPERTY_KEYS_NOT_TO_COPY_LIST = Arrays.asList(PROPERTY_KEYS_NOT_TO_COPY);
-
- /**
- * Condition tester for ExecutorsUtil to check whether the callback is done
- * or the {@link IProgressMonitor} is canceled.
- */
- private class CallbackDoneConditionTester implements IConditionTester {
- final ICallback callback;
- final IProgressMonitor monitor;
-
- /**
- * Constructor.
- *
- * @param callback
- * The callback to check. Must not be <code>null</code>.
- * @param monitor
- * The progress monitor to check.
- */
- public CallbackDoneConditionTester(ICallback callback, IProgressMonitor monitor) {
- Assert.isNotNull(callback);
- this.callback = callback;
- this.monitor = monitor;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#isConditionFulfilled()
- */
- @Override
- public boolean isConditionFulfilled() {
- if (monitor == null) {
- return callback.isDone();
- }
- return monitor.isCanceled() || callback.isDone();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#cleanup()
- */
- @Override
- public void cleanup() {
- }
- }
-
- /**
- * Constructor.
- */
- public Callback() {
- this(null);
- }
-
- /**
- * Constructor to wrap a parent callback.
- *
- * @param parentCallback
- * The parent callback.
- */
- public Callback(ICallback parentCallback) {
- this(null, -1, parentCallback);
- }
-
- /**
- * Constructor to handle a progress monitor.
- *
- * @param monitor
- * The progress monitor.
- * @param ticksToUse
- * The ticks to add when done.
- */
- public Callback(IProgressMonitor monitor, int ticksToUse) {
- this(monitor, ticksToUse, null);
- }
-
- /**
- * Constructor to handle a progress monitor and wrap a parent callback.
- *
- * @param monitor
- * The progress monitor.
- * @param ticksToUse
- * The ticks to add when done.
- * @param parentCallback
- * The parent callback.
- */
- public Callback(IProgressMonitor monitor, int ticksToUse, ICallback parentCallback) {
- super();
- setProperty(PROPERTY_PARENT_CALLBACK, parentCallback);
- setProperty(PROPERTY_PROGRESS_MONITOR, monitor);
- setProperty(PROPERTY_PROGRESS_TICKS, ticksToUse);
- }
-
- /**
- * Get a condition tester for this callback.
- *
- * @param monitor
- * The progress monitor or <code>null</code>.
- * @return The condition tester.
- */
- public final IConditionTester getDoneConditionTester(IProgressMonitor monitor) {
- return new CallbackDoneConditionTester(this, monitor);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#done(java.lang.Object, org.eclipse.core.runtime.IStatus)
- */
- @Override
- public final void done(Object caller, IStatus status) {
- Assert.isNotNull(status);
-
- if (isDone()) {
- CoreBundleActivator.getTraceHandler().trace("WARNING: callback called twice!!", 1, this); //$NON-NLS-1$
- return;
- }
-
- setProperty(PROPERTY_IS_DONE, null);
- setProperty(PROPERTY_STATUS, checkStatusIntegrity(status));
-
- internalDone(caller, status);
-
- if (getProperty(PROPERTY_IS_DONE) == null) {
- setProperty(PROPERTY_IS_DONE, true);
- }
-
- if (isDone()) {
- if (getProperty(PROPERTY_PROGRESS_MONITOR) instanceof IProgressMonitor) {
- IProgressMonitor progress = ((IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR));
- if (!progress.isCanceled() && getStatus().getSeverity() != IStatus.CANCEL) {
- int ticks = getIntProperty(PROPERTY_PROGRESS_TICKS);
- if (ticks > 0) {
- progress.worked(ticks);
- } else if (ticks == ProgressHelper.PROGRESS_DONE) {
- progress.done();
- }
- }
- }
-
- ICallback parentCallback = (ICallback) getProperty(PROPERTY_PARENT_CALLBACK);
- if (parentCallback != null) {
- if (parentCallback.isDone()) {
- CoreBundleActivator.getTraceHandler().trace("WARNING: parent callback called twice!!", 1, this); //$NON-NLS-1$
- }
- else {
- copyProperties(this, parentCallback);
- if (!ProgressHelper.isCancelOrError(this,
- getStatus(),
- (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR),
- parentCallback)) {
- parentCallback.done(caller, getStatus());
- }
- }
- }
- }
- }
-
- /**
- * Copy the properties from the given source callback to the given
- * destination callback.
- *
- * @param source
- * The source callback. Must not be <code>null</code>.
- * @param destination
- * The destination callback. Must not be <code>null</code> and
- * not yet done.
- */
- public static final void copyProperties(ICallback source, ICallback destination) {
- Assert.isNotNull(source);
- Assert.isNotNull(destination);
- Assert.isTrue(!destination.isDone());
-
- for (String key : source.getProperties().keySet()) {
- if (!PROPERTY_KEYS_NOT_TO_COPY_LIST.contains(key)) {
- destination.setProperty(key, source.getProperty(key));
- }
- }
- Assert.isTrue(!destination.isDone());
- }
-
- /**
- * Checks the status integrity.
- *
- * @param status
- * The status or <code>null</code>.
- * @return The checked status.
- */
- private IStatus checkStatusIntegrity(IStatus status) {
- if (status == null) status = Status.OK_STATUS;
-
- if (status.getSeverity() == IStatus.CANCEL && status.getException() == null) {
- status = new Status(IStatus.CANCEL, status.getPlugin(),
- status.getMessage(), new OperationCanceledException(status.getMessage()));
- }
-
- if (status.getSeverity() == IStatus.WARNING && status.getException() == null) {
- status = new Status(IStatus.WARNING, status.getPlugin(),
- status.getMessage(), new Exception(status.getMessage()));
- }
-
- if (status.getSeverity() == IStatus.ERROR && status.getException() == null) {
- status = new Status(IStatus.ERROR, status.getPlugin(),
- status.getMessage(), new Exception(status.getMessage()));
- }
-
- return status;
- }
-
- /**
- * Return the progress monitor or <code>null</code>.
- */
- protected final IProgressMonitor getProgressMonitor() {
- return (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR);
- }
-
- /**
- * Internal callback done.
- *
- * @param caller
- * The caller.
- * @param status
- * The status.
- */
- protected void internalDone(Object caller, IStatus status) {
- }
-
- /**
- * Return the result on done.
- */
- public final IStatus getStatus() {
- IStatus status = (IStatus) getProperty(PROPERTY_STATUS);
- if (status == null && getProperty(PROPERTY_PROGRESS_MONITOR) instanceof IProgressMonitor) {
- IProgressMonitor monitor = (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR);
- if (monitor.isCanceled()) {
- return checkStatusIntegrity(Status.CANCEL_STATUS);
- }
- }
-
- return checkStatusIntegrity(status);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#isDone()
- */
- @Override
- public final boolean isDone() {
- return getBooleanProperty(PROPERTY_IS_DONE);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#addParentCallback(org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
- */
- @Override
- public void addParentCallback(ICallback callback) {
- if (getProperty(PROPERTY_PARENT_CALLBACK) instanceof ICallback) {
- ICallback parentCallback = (ICallback) getProperty(PROPERTY_PARENT_CALLBACK);
- parentCallback.addParentCallback(callback);
- } else {
- setProperty(PROPERTY_PARENT_CALLBACK, callback);
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#setResult(java.lang.Object)
- */
- @Override
- public void setResult(Object result) {
- setProperty(PROPERTY_RESULT, result);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#getResult()
- */
- @Override
- public Object getResult() {
- return getProperty(PROPERTY_RESULT);
- }
-}
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 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.callback;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+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.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.interfaces.IConditionTester;
+import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
+import org.eclipse.tcf.te.runtime.nls.Messages;
+import org.eclipse.tcf.te.runtime.properties.PropertiesContainer;
+import org.eclipse.tcf.te.runtime.utils.ProgressHelper;
+import org.eclipse.tcf.te.runtime.utils.StatusHelper;
+
+/**
+ * Default implementation of the <code>ICallback</code> interface.
+ */
+public class Callback extends PropertiesContainer implements ICallback {
+
+ protected static final String PROPERTY_PARENT_CALLBACK = "parentCallback"; //$NON-NLS-1$
+ protected static final String PROPERTY_PROGRESS_MONITOR = "progressMonitor"; //$NON-NLS-1$
+ protected static final String PROPERTY_PROGRESS_TICKS = "progressTicks"; //$NON-NLS-1$
+ protected static final String PROPERTY_IS_DONE = "isDone"; //$NON-NLS-1$
+ protected static final String PROPERTY_STATUS = "status"; //$NON-NLS-1$
+
+ /**
+ * Property: Asynchronous operations can store a result to the callback
+ * object they invoke once the operation has been finished.
+ */
+ protected static final String PROPERTY_RESULT = "result"; //$NON-NLS-1$
+
+
+ private static final String[] PROPERTY_KEYS_NOT_TO_COPY = {
+ PROPERTY_PARENT_CALLBACK, PROPERTY_PROGRESS_MONITOR,
+ PROPERTY_PROGRESS_TICKS, PROPERTY_IS_DONE, PROPERTY_STATUS
+ };
+ private static final List<String> PROPERTY_KEYS_NOT_TO_COPY_LIST = Arrays.asList(PROPERTY_KEYS_NOT_TO_COPY);
+
+ /**
+ * Condition tester for ExecutorsUtil to check whether the callback is done
+ * or the {@link IProgressMonitor} is canceled.
+ */
+ private class CallbackDoneConditionTester implements IConditionTester {
+ final ICallback callback;
+ final IProgressMonitor monitor;
+ int cancelTimeout = -1;
+ long cancelTime = -1;
+
+ /**
+ * Constructor.
+ *
+ * @param callback The callback to check. Must not be <code>null</code>.
+ * @param monitor The progress monitor to check or <code>null</code>.
+ */
+ public CallbackDoneConditionTester(ICallback callback, IProgressMonitor monitor) {
+ this(callback, monitor, -1);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param callback The callback to check. Must not be <code>null</code>.
+ * @param monitor The progress monitor to check or <code>null</code>.
+ * @param cancelTimeout Timeout in milliseconds to wait for callback.isDone() when progress monitor was canceled.
+ */
+ public CallbackDoneConditionTester(ICallback callback, IProgressMonitor monitor, int cancelTimeout) {
+ Assert.isNotNull(callback);
+ this.callback = callback;
+ this.monitor = monitor;
+ this.cancelTimeout = cancelTimeout;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#isConditionFulfilled()
+ */
+ @Override
+ public boolean isConditionFulfilled() {
+ if (monitor == null)
+ return callback.isDone();
+
+ // handle cancel timeout
+ if (cancelTimeout > 0 && !callback.isDone() && monitor.isCanceled()) {
+ if (cancelTime == -1) {
+ cancelTime = System.currentTimeMillis();
+ monitor.subTask("Cancelling..."); //$NON-NLS-1$
+ }
+ else {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - cancelTime) >= cancelTimeout) {
+ callback.done(this, StatusHelper.getStatus(new OperationCanceledException(Messages.Callback_warning_cancelTimeout)));
+ return true;
+ }
+ }
+ }
+
+ return callback.isDone();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#cleanup()
+ */
+ @Override
+ public void cleanup() {
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ public Callback() {
+ this(null);
+ }
+
+ /**
+ * Constructor to wrap a parent callback.
+ *
+ * @param parentCallback
+ * The parent callback.
+ */
+ public Callback(ICallback parentCallback) {
+ this(null, -1, parentCallback);
+ }
+
+ /**
+ * Constructor to handle a progress monitor.
+ *
+ * @param monitor
+ * The progress monitor.
+ * @param ticksToUse
+ * The ticks to add when done.
+ */
+ public Callback(IProgressMonitor monitor, int ticksToUse) {
+ this(monitor, ticksToUse, null);
+ }
+
+ /**
+ * Constructor to handle a progress monitor and wrap a parent callback.
+ *
+ * @param monitor
+ * The progress monitor.
+ * @param ticksToUse
+ * The ticks to add when done.
+ * @param parentCallback
+ * The parent callback.
+ */
+ public Callback(IProgressMonitor monitor, int ticksToUse, ICallback parentCallback) {
+ super();
+ setProperty(PROPERTY_PARENT_CALLBACK, parentCallback);
+ setProperty(PROPERTY_PROGRESS_MONITOR, monitor);
+ setProperty(PROPERTY_PROGRESS_TICKS, ticksToUse);
+ }
+
+ /**
+ * Get a condition tester for this callback.
+ *
+ * @param monitor The progress monitor to check or <code>null</code>.
+ * @return The condition tester.
+ */
+ public final IConditionTester getDoneConditionTester(IProgressMonitor monitor) {
+ return new CallbackDoneConditionTester(this, monitor);
+ }
+
+ /**
+ * Get a condition tester for this callback.
+ *
+ * @param monitor The progress monitor to check or <code>null</code>.
+ * @param cancelTimeout Timeout in milliseconds to wait for callback.isDone() when progress monitor was canceled.
+ * @return The condition tester.
+ */
+ public final IConditionTester getDoneConditionTester(IProgressMonitor monitor, int cancelTimeout) {
+ return new CallbackDoneConditionTester(this, monitor, cancelTimeout);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#done(java.lang.Object, org.eclipse.core.runtime.IStatus)
+ */
+ @Override
+ public final void done(Object caller, IStatus status) {
+ Assert.isNotNull(status);
+
+ if (isDone()) {
+ if (getStatus() != null && getStatus().getSeverity() != IStatus.CANCEL)
+ CoreBundleActivator.getTraceHandler().trace("WARNING: callback called twice!!", 1, this); //$NON-NLS-1$
+ return;
+ }
+
+ setProperty(PROPERTY_IS_DONE, null);
+ setProperty(PROPERTY_STATUS, checkStatusIntegrity(status));
+
+ internalDone(caller, status);
+
+ if (getProperty(PROPERTY_IS_DONE) == null) {
+ setProperty(PROPERTY_IS_DONE, true);
+ }
+
+ if (isDone()) {
+ if (getProperty(PROPERTY_PROGRESS_MONITOR) instanceof IProgressMonitor) {
+ IProgressMonitor progress = ((IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR));
+ if (!progress.isCanceled() && getStatus().getSeverity() != IStatus.CANCEL) {
+ int ticks = getIntProperty(PROPERTY_PROGRESS_TICKS);
+ if (ticks > 0) {
+ progress.worked(ticks);
+ } else if (ticks == ProgressHelper.PROGRESS_DONE) {
+ progress.done();
+ }
+ }
+ }
+
+ ICallback parentCallback = (ICallback) getProperty(PROPERTY_PARENT_CALLBACK);
+ if (parentCallback != null) {
+ if (parentCallback.isDone()) {
+ CoreBundleActivator.getTraceHandler().trace("WARNING: parent callback called twice!!", 1, this); //$NON-NLS-1$
+ }
+ else {
+ copyProperties(this, parentCallback);
+ if (!ProgressHelper.isCancelOrError(this,
+ getStatus(),
+ (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR),
+ parentCallback)) {
+ parentCallback.done(caller, getStatus());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Copy the properties from the given source callback to the given
+ * destination callback.
+ *
+ * @param source
+ * The source callback. Must not be <code>null</code>.
+ * @param destination
+ * The destination callback. Must not be <code>null</code> and
+ * not yet done.
+ */
+ public static final void copyProperties(ICallback source, ICallback destination) {
+ Assert.isNotNull(source);
+ Assert.isNotNull(destination);
+ Assert.isTrue(!destination.isDone());
+
+ for (String key : source.getProperties().keySet()) {
+ if (!PROPERTY_KEYS_NOT_TO_COPY_LIST.contains(key)) {
+ destination.setProperty(key, source.getProperty(key));
+ }
+ }
+ Assert.isTrue(!destination.isDone());
+ }
+
+ /**
+ * Checks the status integrity.
+ *
+ * @param status
+ * The status or <code>null</code>.
+ * @return The checked status.
+ */
+ private IStatus checkStatusIntegrity(IStatus status) {
+ if (status == null) status = Status.OK_STATUS;
+
+ if (status.getSeverity() == IStatus.CANCEL && status.getException() == null) {
+ status = new Status(IStatus.CANCEL, status.getPlugin(),
+ status.getMessage(), new OperationCanceledException(status.getMessage()));
+ }
+
+ if (status.getSeverity() == IStatus.WARNING && status.getException() == null) {
+ status = new Status(IStatus.WARNING, status.getPlugin(),
+ status.getMessage(), new Exception(status.getMessage()));
+ }
+
+ if (status.getSeverity() == IStatus.ERROR && status.getException() == null) {
+ status = new Status(IStatus.ERROR, status.getPlugin(),
+ status.getMessage(), new Exception(status.getMessage()));
+ }
+
+ return status;
+ }
+
+ /**
+ * Return the progress monitor or <code>null</code>.
+ */
+ protected final IProgressMonitor getProgressMonitor() {
+ return (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR);
+ }
+
+ /**
+ * Internal callback done.
+ *
+ * @param caller
+ * The caller.
+ * @param status
+ * The status.
+ */
+ protected void internalDone(Object caller, IStatus status) {
+ }
+
+ /**
+ * Return the result on done.
+ */
+ public final IStatus getStatus() {
+ IStatus status = (IStatus) getProperty(PROPERTY_STATUS);
+ if (status == null && getProperty(PROPERTY_PROGRESS_MONITOR) instanceof IProgressMonitor) {
+ IProgressMonitor monitor = (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR);
+ if (monitor.isCanceled()) {
+ return checkStatusIntegrity(Status.CANCEL_STATUS);
+ }
+ }
+
+ return checkStatusIntegrity(status);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#isDone()
+ */
+ @Override
+ public final boolean isDone() {
+ return getBooleanProperty(PROPERTY_IS_DONE);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#addParentCallback(org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
+ */
+ @Override
+ public void addParentCallback(ICallback callback) {
+ if (getProperty(PROPERTY_PARENT_CALLBACK) instanceof ICallback) {
+ ICallback parentCallback = (ICallback) getProperty(PROPERTY_PARENT_CALLBACK);
+ parentCallback.addParentCallback(callback);
+ } else {
+ setProperty(PROPERTY_PARENT_CALLBACK, callback);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#setResult(java.lang.Object)
+ */
+ @Override
+ public void setResult(Object result) {
+ setProperty(PROPERTY_RESULT, result);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#getResult()
+ */
+ @Override
+ public Object getResult() {
+ return getProperty(PROPERTY_RESULT);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java
index bd95b364f..92e82cfd7 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java
@@ -1,35 +1,37 @@
-/*******************************************************************************
- * 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.nls;
-
-import org.eclipse.osgi.util.NLS;
-
-/**
- * Target Explorer 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.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 Extension_error_missingRequiredAttribute;
- public static String Extension_error_duplicateExtension;
- public static String Extension_error_invalidExtensionPoint;
-}
+/*******************************************************************************
+ * 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.nls;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Target Explorer 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.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 Extension_error_missingRequiredAttribute;
+ public static String Extension_error_duplicateExtension;
+ public static String Extension_error_invalidExtensionPoint;
+
+ public static String Callback_warning_cancelTimeout;
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties
index 31e029738..30dd6118f 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties
@@ -1,13 +1,15 @@
-###############################################################################
-# Copyright (c) 2012 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
-###############################################################################
-
-Extension_error_missingRequiredAttribute=Required attribute "{0}" missing for extension "{1}"!
-Extension_error_duplicateExtension=Duplicate extension with id ''{0}''. Ignoring duplicated contribution from contributor ''{1}''!
-Extension_error_invalidExtensionPoint=Failed to instantiate the executable extension from extension point ''{0}''.
+###############################################################################
+# Copyright (c) 2012 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
+###############################################################################
+
+Extension_error_missingRequiredAttribute=Required attribute "{0}" missing for extension "{1}"!
+Extension_error_duplicateExtension=Duplicate extension with id ''{0}''. Ignoring duplicated contribution from contributor ''{1}''!
+Extension_error_invalidExtensionPoint=Failed to instantiate the executable extension from extension point ''{0}''.
+
+Callback_warning_cancelTimeout=Step cancellation was aborted due to timeout.
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/steps/OpenChannelStep.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/steps/OpenChannelStep.java
index 5d902c2cc..bfa638548 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/steps/OpenChannelStep.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/steps/OpenChannelStep.java
@@ -18,6 +18,7 @@ import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
import org.eclipse.tcf.te.runtime.stepper.StepperAttributeUtil;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IFullQualifiedId;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext;
+import org.eclipse.tcf.te.runtime.utils.ProgressHelper;
import org.eclipse.tcf.te.runtime.utils.StatusHelper;
import org.eclipse.tcf.te.tcf.core.Tcf;
import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager;
@@ -62,6 +63,7 @@ public class OpenChannelStep extends AbstractPeerStep {
public void rollback(IStepContext context, IPropertiesContainer data, IStatus status, IFullQualifiedId fullQualifiedId, IProgressMonitor monitor, ICallback callback) {
IChannel channel = (IChannel)StepperAttributeUtil.getProperty(ITcfStepAttributes.ATTR_CHANNEL, fullQualifiedId, data);
if (channel != null && channel.getState() != IChannel.STATE_CLOSED) {
+ ProgressHelper.setSubTaskName(monitor, "Closing TCF channel"); //$NON-NLS-1$
Tcf.getChannelManager().closeChannel(channel);
}
super.rollback(context, data, status, fullQualifiedId, monitor, callback);

Back to the top