Merge "Bug 385193: JavaDoc completed, online docu added, filesystem example added to docu"
diff --git a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/features/impl/AbstractFeatureProvider.java b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/features/impl/AbstractFeatureProvider.java
index a45bfe7..4755ebe 100644
--- a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/features/impl/AbstractFeatureProvider.java
+++ b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/features/impl/AbstractFeatureProvider.java
@@ -13,6 +13,7 @@
  *    mwenz - Bug 356218 - Added hasDoneChanges updates to update diagram feature
  *                         and called features via editor command stack to check it
  *    mwenz - Bug 367204 - Correctly return the added PE inAbstractFeatureProvider's addIfPossible method
+ *    fvelasco - Bug 391506 - Canceling a feature with OperationCanceledException provoked an extra undo
  *
  * </copyright>
  *
@@ -231,16 +232,8 @@
 		IUpdateFeature updateFeature = getUpdateFeature(context);
 		if (updateFeature != null) {
 			IDiagramEditor diagramEditor = getDiagramTypeProvider().getDiagramEditor();
-			try {
-				diagramEditor.executeFeature(updateFeature, context);
-			} catch (Exception e) {
-				// Wrap in RuintimeException (handled by all callers)
-				if (e instanceof RuntimeException) {
-					throw (RuntimeException) e;
-				} else {
-					throw new RuntimeException(e);
-				}
-			}
+			diagramEditor.executeFeature(updateFeature, context);
+			b = true;
 		}
 		IReason reason = new Reason(b);
 		if (info) {
@@ -259,17 +252,8 @@
 		ILayoutFeature layoutSemanticsFeature = getLayoutFeature(context);
 		if (layoutSemanticsFeature != null) {
 			IDiagramEditor diagramEditor = getDiagramTypeProvider().getDiagramEditor();
-			try {
-				diagramEditor.executeFeature(layoutSemanticsFeature, context);
-				b = true;
-			} catch (Exception e) {
-				// Wrap in RuntimeException (handled by all callers)
-				if (e instanceof RuntimeException) {
-					throw (RuntimeException) e;
-				} else {
-					throw new RuntimeException(e);
-				}
-			}
+			diagramEditor.executeFeature(layoutSemanticsFeature, context);
+			b = true;
 		}
 		IReason res = new Reason(b);
 		if (info) {
@@ -327,18 +311,9 @@
 		if (canAdd(context).toBoolean()) {
 			IAddFeature feature = getAddFeature(context);
 			IDiagramEditor diagramEditor = getDiagramTypeProvider().getDiagramEditor();
-			try {
-				Object result = diagramEditor.executeFeature(feature, context);
-				if (result instanceof PictogramElement) {
-					returnValue = (PictogramElement) result;
-				}
-			} catch (Exception e) {
-				// Wrap in RuintimeException (handled by all callers)
-				if (e instanceof RuntimeException) {
-					throw (RuntimeException) e;
-				} else {
-					throw new RuntimeException(e);
-				}
+			Object result = diagramEditor.executeFeature(feature, context);
+			if (result instanceof PictogramElement) {
+				returnValue = (PictogramElement) result;
 			}
 		}
 		if (info) {
diff --git a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/internal/command/CommandExec.java b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/internal/command/CommandExec.java
index 5dc766b..7bccbc4 100644
--- a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/internal/command/CommandExec.java
+++ b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/internal/command/CommandExec.java
@@ -12,7 +12,7 @@
  *    mwenz - Bug 340627 - Features should be able to indicate cancellation
  *    mwenz - Bug 356218 - Added hasDoneChanges updates to update diagram feature
  *                         and called features via editor command stack to check it
- *
+ *    fvelasco - Bug 391506 - Cancelling a feature with OperationCanceledException provoked an extra undo
  * </copyright>
  *
  *******************************************************************************/
@@ -59,7 +59,7 @@
 	 *            the transactional editingDomain
 	 * @return true, if successful
 	 */
-	public boolean executeCommand(ICommand command, TransactionalEditingDomain editingDomain) throws Exception {
+	public boolean executeCommand(ICommand command, TransactionalEditingDomain editingDomain) {
 		commandExecutionDepth2++;
 		long start = System.currentTimeMillis();
 
@@ -81,14 +81,9 @@
 		boolean ret;
 		CommandStack commandStack = editingDomain.getCommandStack();
 
-		try {
-			GFPreparableCommand gfRecordingCommand = new GFPreparableCommand(editingDomain, command);
-			commandStack.execute(gfRecordingCommand); // gfRecordingCommand.execute();
-			ret = gfRecordingCommand.getExecutionResult();
-		} catch (Exception ex) {
-			commandStack.undo();
-			throw ex;
-		}
+		GFPreparableCommand gfRecordingCommand = new GFPreparableCommand(editingDomain, command);
+		commandStack.execute(gfRecordingCommand); // gfRecordingCommand.execute();
+		ret = gfRecordingCommand.getExecutionResult();
 
 		long stop = System.currentTimeMillis();
 
@@ -133,7 +128,7 @@
 	 * @param context
 	 *            the context
 	 */
-	public static void executeFeatureWithContext(IFeature feature, IContext context) throws Exception {
+	public static void executeFeatureWithContext(IFeature feature, IContext context) {
 		GenericFeatureCommandWithContext genericFeatureCommandWithContext = new GenericFeatureCommandWithContext(feature, context);
 		TransactionalEditingDomain editingDomain = feature.getFeatureProvider().getDiagramTypeProvider().getDiagramEditor()
 				.getEditingDomain();
diff --git a/tests/org.eclipse.graphiti.bot.tests/src/org/eclipse/graphiti/bot/tests/GFInteractionComponentTests.java b/tests/org.eclipse.graphiti.bot.tests/src/org/eclipse/graphiti/bot/tests/GFInteractionComponentTests.java
index 2b559e5..8b9b1b8 100644
--- a/tests/org.eclipse.graphiti.bot.tests/src/org/eclipse/graphiti/bot/tests/GFInteractionComponentTests.java
+++ b/tests/org.eclipse.graphiti.bot.tests/src/org/eclipse/graphiti/bot/tests/GFInteractionComponentTests.java
@@ -1160,6 +1160,62 @@
 	}
 
 	@Test
+	public void testCancelConnection() throws Exception {
+		final int x = 100;
+		final int y = 100;
+		final DiagramEditor diagramEditor = openDiagram(ITestConstants.DIAGRAM_TYPE_ID_SKETCH);
+
+		syncExec(new VoidResult() {
+			public void run() {
+				IDiagramTypeProvider dtp = diagramEditor.getDiagramTypeProvider();
+				IFeatureProvider fp = dtp.getFeatureProvider();
+				CommandStack commandStack = diagramEditor.getEditDomain().getCommandStack();
+				ICreateFeature[] createFeatures = fp.getCreateFeatures();
+				for (ICreateFeature createFeature : createFeatures) {
+					if ("Rectangle".equals(createFeature.getName())) {
+						Rectangle rectangle = new Rectangle(x, y, 100, 100);
+						ICreateContext createContext = createCreateContext(dtp.getDiagram(), rectangle);
+						Command createCommand = new CreateModelObjectCommand(getConfigProviderMock(dtp, diagramEditor),
+								createFeature, createContext, rectangle);
+						commandStack.execute(createCommand);
+						rectangle = new Rectangle(x + 200, y, 100, 100);
+						createContext = createCreateContext(dtp.getDiagram(), rectangle);
+						createCommand = new CreateModelObjectCommand(getConfigProviderMock(dtp, diagramEditor),
+								createFeature, createContext, rectangle);
+						commandStack.execute(createCommand);
+					}
+				}
+			}
+
+		});
+		Thread.sleep(DELAY);
+
+		Diagram diagram = diagramEditor.getDiagramTypeProvider().getDiagram();
+		assertTrue(diagram.getConnections().isEmpty());
+
+		syncExec(new VoidResult() {
+			public void run() {
+				// activate create-freeform-connection tool
+				try {
+					SketchCreateFreeformConnectionFeature.setCancelling(true);
+					ed.getGefEditor().activateTool("free");
+					ed.getGefEditor().drag(150, 150, 350, 150);
+					ed.getGefEditor().click(350, 150);
+				} finally {
+					SketchCreateFreeformConnectionFeature.setCancelling(false);
+				}
+			}
+		});
+		Thread.sleep(DELAY);
+
+		assertTrue(diagram.getConnections().isEmpty());
+
+		CommandStack commandStack = diagramEditor.getEditDomain().getCommandStack();
+		assertFalse(commandStack.canRedo());
+		page.shutdownEditor(diagramEditor);
+	}
+
+	@Test
 	public void testResizeAndPosition() throws Exception {
 		final int x = 100;
 		final int y = 100;
diff --git a/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/features/create/SketchCreateFreeformConnectionFeature.java b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/features/create/SketchCreateFreeformConnectionFeature.java
index c66895e..db3ebef 100644
--- a/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/features/create/SketchCreateFreeformConnectionFeature.java
+++ b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/features/create/SketchCreateFreeformConnectionFeature.java
@@ -15,6 +15,7 @@
  *******************************************************************************/
 package org.eclipse.graphiti.testtool.sketch.features.create;
 
+import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.graphiti.features.IFeatureProvider;
 import org.eclipse.graphiti.mm.pictograms.Connection;
 import org.eclipse.graphiti.services.Graphiti;
@@ -24,6 +25,16 @@
  */
 public class SketchCreateFreeformConnectionFeature extends AbstractSketchCreateSimpleConnectionFeature {
 
+	private static boolean cancel = false;
+
+	public static void setCancelling(boolean cancel) {
+		SketchCreateFreeformConnectionFeature.cancel = cancel;
+	}
+
+	public static boolean isCancelling() {
+		return cancel;
+	}
+
 	/**
 	 * Instantiates a new sketch create freeform connection feature.
 	 * 
@@ -40,6 +51,8 @@
 
 	@Override
 	protected Connection createConnection() {
+		if (isCancelling())
+			throw new OperationCanceledException();
 		return Graphiti.getPeCreateService().createFreeFormConnection(getDiagram());
 	}
 }