Bug 344704 - 'Paste Repository Path' command hijacks Ctrl+V forever
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java
index 9f82eec..293c20c 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java
@@ -11,13 +11,19 @@
 package org.eclipse.ui.internal.contexts;
 
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Iterator;
 import javax.inject.Inject;
 import org.eclipse.core.commands.contexts.Context;
 import org.eclipse.core.commands.contexts.ContextManager;
 import org.eclipse.core.commands.contexts.IContextManagerListener;
+import org.eclipse.core.expressions.EvaluationResult;
 import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
 import org.eclipse.e4.ui.services.EContextService;
+import org.eclipse.e4.ui.workbench.modeling.ExpressionContext;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.ISourceProvider;
 import org.eclipse.ui.ISources;
@@ -34,6 +40,8 @@
  */
 public final class ContextService implements IContextService {
 
+	private HashMap<IContextActivation, UpdateExpression> activationToRat = new HashMap<IContextActivation, ContextService.UpdateExpression>();
+
 	/**
 	 * The central authority for determining which context we should use.
 	 */
@@ -48,6 +56,9 @@
 	@Inject
 	private EContextService contextService;
 
+	@Inject
+	private IEclipseContext eclipseContext;
+
 	/**
 	 * The persistence class for this context service.
 	 */
@@ -87,6 +98,36 @@
 		return activateContext(contextId, null);
 	}
 
+	private class UpdateExpression extends RunAndTrack {
+		boolean updating = true;
+
+		private String contextId;
+		private Expression expression;
+
+		public UpdateExpression(String contextId, Expression expression) {
+			this.contextId = contextId;
+			this.expression = expression;
+		}
+
+		@Override
+		public boolean changed(IEclipseContext context) {
+			if (!updating) {
+				return false;
+			}
+			ExpressionContext ctx = new ExpressionContext(eclipseContext.getActiveLeaf());
+			try {
+				if (expression.evaluate(ctx) != EvaluationResult.FALSE) {
+					contextService.activateContext(contextId);
+				} else {
+					contextService.deactivateContext(contextId);
+				}
+			} catch (CoreException e) {
+				contextService.deactivateContext(contextId);
+			}
+			return updating;
+		}
+	}
+
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -99,7 +140,13 @@
 		final IContextActivation activation = new ContextActivation(contextId,
 				expression, this);
 		contextAuthority.activateContext(activation);
-		contextService.activateContext(contextId);
+		if (expression == null) {
+			contextService.activateContext(contextId);
+		} else {
+			final UpdateExpression runnable = new UpdateExpression(contextId, expression);
+			activationToRat.put(activation, runnable);
+			eclipseContext.runAndTrack(runnable);
+		}
 		return activation;
 	}
 
@@ -151,6 +198,10 @@
 	 */
 	public final void deactivateContext(final IContextActivation activation) {
 		if (activation != null && activation.getContextService() == this) {
+			final UpdateExpression rat = activationToRat.remove(activation);
+			if (rat != null) {
+				rat.updating = false;
+			}
 			contextService.deactivateContext(activation.getContextId());
 			contextAuthority.deactivateContext(activation);
 		}