Bug 264539 [context] Fixes for dynamic behavior - removals
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ContextInjectionFactory.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ContextInjectionFactory.java
index b2a3426..5e0eea9 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ContextInjectionFactory.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ContextInjectionFactory.java
@@ -22,11 +22,11 @@
 	}
 	
 	static public void inject(Object object, IEclipseContext context) {
-		inject(object, context, null, null, null);
+		inject(object, context, null, null);
 	}
 	
-	static public void inject(Object object, IEclipseContext context, String fieldPrefix, String setMethodPrefix, String removeMethodPrefix) {
-		ContextInjectionImpl injector = new ContextInjectionImpl(fieldPrefix, setMethodPrefix, removeMethodPrefix);
+	static public void inject(Object object, IEclipseContext context, String fieldPrefix, String setMethodPrefix) {
+		ContextInjectionImpl injector = new ContextInjectionImpl(fieldPrefix, setMethodPrefix);
 		injector.injectInto(object, context);
 	}
 	
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/IJavaInjection.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/IJavaInjection.java
index 43ba7bb..7e2a954 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/IJavaInjection.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/IJavaInjection.java
@@ -14,42 +14,23 @@
 
 import org.eclipse.e4.core.services.context.IEclipseContextAware;
 
-// XXX add conversion of dashes
+// XXX implement conversion of dashes
 /**
- * This interface represents a hierarchical context with dependency injection capabilities. 
- * The context might have number of objects associated with it. For instance, a context might 
- * include log, status, and preferences. We'll call such associated objects "services" 
- * (through they don't have to be OSGi services).
- * <p>
- * Objects are associated with the context using names. For instance, a logging
- * service can have a name "log" and the code to add it could look like:
- * <pre>
- * 	context.addObject("log", loggingService);
- * </pre> 
- * </p><p> 
- * The context can be injected into an object. During injection context attempts to find
- * fields and methods in the user objects that correspond to the names of associated 
- * services.
- * <pre>
- * 	context.injectInto(myObject);
- * </pre> 
- * </p><p> 
+ * An Eclipse context can be injected into an object using 
+ * {@link ContextInjectionFactory#inject(Object, IEclipseContext)}.
+ * The Java injection will try to find fields and methods in the user objects that correspond 
+ * to the names of the services present in the context.
+ * <p> 
  * The matching is done using {@link #FIELD_PREFIX} for fields, {@link #SET_METHOD_PREFIX}
  * for methods. For the "log" example, injection will attempt to find field "equinoxLog" or method
  * "setLog()" that could accept associated service. (The field's prefix can be overridden
  * by the context.)
  * </p><p>
- * Multiple objects can be added under a single name. In this case the setter method will be called
- * multiple times, ones for each associated service. 
- * </p><p>
- * The contexts can be created as in a hierarchical fashion with child contexts inheriting associated
- * services from their parents and allowing services to be overridden for children.
- * </p><p>
  * Generally speaking, name matching is case-sensitive. However, for convenience, when matching 
  * service names to fields or methods:
  * <ul>
  * <li>Capitalization of the first character of the service name is ignored. For instance, the "log" name 
- * will match both "equinoxLog" and "equinoxlog" fields.</li>
+ * will match both "diLog" and "dilog" fields.</li>
  * <li>Dashes in the names ("-") are removed, and the next character is capitalized. 
  * For instance, "log-general" will match "equinoxLogGeneral"</li> 
  * </ul>   
@@ -57,7 +38,7 @@
  * The injection of values is generally done as a number of calls. User objects that want to have 
  * an ability to finalize the injected data (for instance, to perform calculations based on multiple
  * injected values) might want to place such calculations into a method 
- * <code>public void equinoxContextSet(IEquinoxContext context) {...}</code>.
+ * <code>public void contextSet(IEquinoxContext context) {...}</code>.
  * </p><p>
  * This method will be called as a last step in the injection process. For convenience, the signature
  * of this method can be found in the {@link IEclipseContextAware} interface. (User objects don't have to 
@@ -89,15 +70,6 @@
 	public String SET_METHOD_PREFIX = "set"; //$NON-NLS-1$
 
 	/**
-	 * Default prefix for the methods to be called when an object is removed from the context. 
-	 * <p>
-	 * For example, if the object named "log" was removed from the context,
-	 * the method "removeLog" will be called.
-	 * </p> 
-	 */
-	public String REMOVE_METHOD_PREFIX = "remove"; //$NON-NLS-1$
-
-	/**
 	 * The name of the method to be called when a context is injected into the object.
 	 * <p>
 	 * This method will be called after all other injection calls are done. As such it can be
@@ -108,14 +80,4 @@
 	 * @see IEclipseContextAware#contextSet(IEclipseContext)
 	 */
 	static public final String CONTEXT_SET_METHOD = "contextSet"; //$NON-NLS-1$
-
-	/**
-	 * The name of the method to be called when a context previously injected in the object
-	 * has been disposed.
-	 * <p>
-	 * For convenience the definition of this method is present in the {@link IEclipseContextAware} interface.
-	 * </p>
-	 * @see IEclipseContextAware#contextDisposed(IEclipseContext)
-	 */
-	static public final String CONTEXT_DISPOSED_METHOD = "contextDisposed"; //$NON-NLS-1$
 }
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextInjectionImpl.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextInjectionImpl.java
index 85f6d1e..ff6ecec 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextInjectionImpl.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextInjectionImpl.java
@@ -14,21 +14,18 @@
 import org.eclipse.e4.core.services.context.IEclipseContext;
 import org.eclipse.e4.core.services.context.spi.IJavaInjection;
 
-// TBD userObjects bound with this context are stored as weak references.
 /**
  * The first character of the service name is not case-sensitive; rest is case-sensitive:
- * iSetLog <-> Log <-> log
+ * <default_prefix>Log <-> Log <-> log
  */
 public class ContextInjectionImpl implements IJavaInjection {
 
 	abstract private class Processor {
 
-		protected IEclipseContext context;
 		protected boolean isSetter;
-
-		public Processor(IEclipseContext context, boolean isSetter) {
+		
+		public Processor(boolean isSetter) {
 			this.isSetter = isSetter;
-			this.context = context;
 		}
 
 		// true if a field was set 
@@ -37,147 +34,53 @@
 		// true if a field was set 
 		abstract void processField(Field field);
 		
-		protected String findKey(String key) {
-			if (context.containsKey(key)) // priority goes to exact match
-				return key; 
-			// alternate capitalization of the first char if possible
-			String candidate = altKey(key);
-			if (candidate == null) // no alternative spellings
-				return null; 
-			if (context.containsKey(candidate))
-				return candidate; 
-			return null; // means "not set"; differentiate from null values
-		}
-		
-		protected boolean keyMatches(String key1, String key2) {
-			if (key1 == null && key2 == null)
-				return true;
-			if (key1 == null || key2 == null)
-				return false;
-			if (key1.equals(key2))
-				return true;
-			String candidate = altKey(key2);
-			if (candidate == null) // no alternative spellings
-				return false; 
-			return key1.equals(candidate);
-		}
-		
-		/**
-		 * Calculates alternative spelling of the key: "log" <-> "Log", if any.
-		 * Returns null if there is no alternate.
-		 */
-		protected String altKey(String key) {
-			if (key.length() == 0)
-				return null;
-			char firstChar = key.charAt(0);
-			String candidate = null;
-			if (Character.isUpperCase(firstChar)) {
-				firstChar = Character.toLowerCase(firstChar);
-				if (key.length() == 1)
-					candidate = Character.toString(firstChar);
-				else
-					candidate = Character.toString(firstChar) + key.substring(1);
-			} else if (Character.isLowerCase(firstChar)) {
-				firstChar = Character.toUpperCase(firstChar);
-					if (key.length() == 1)
-						candidate = Character.toString(firstChar);
-					else
-						candidate = Character.toString(firstChar) + key.substring(1);
-			}
-			return candidate;
-		}
 	}
-
+	
 	final static private String JAVA_OBJECT = "java.lang.Object"; //$NON-NLS-1$
 	final static private Class[] contextNotifySignature = new Class[] {IEclipseContext.class};
 
 	final protected String fieldPrefix;
 	final protected String setMethodPrefix;
-	final protected String setRemovePrefix;
 
 	final protected int fieldPrefixLength;
 
 	public ContextInjectionImpl() {
-		this(FIELD_PREFIX, SET_METHOD_PREFIX, REMOVE_METHOD_PREFIX);
+		this(FIELD_PREFIX, SET_METHOD_PREFIX);
 	}
 
-	public ContextInjectionImpl(String fieldPrefix, String setMethodPrefix, String setRemovePrefix) {
+	public ContextInjectionImpl(String fieldPrefix, String setMethodPrefix) {
 		this.fieldPrefix = (fieldPrefix != null) ? fieldPrefix : FIELD_PREFIX;
 		this.setMethodPrefix = (setMethodPrefix != null) ? setMethodPrefix : SET_METHOD_PREFIX;
-		this.setRemovePrefix = (setRemovePrefix != null) ? setRemovePrefix : REMOVE_METHOD_PREFIX;
 
 		fieldPrefixLength = this.fieldPrefix.length();
 	}
 
 	public void injectInto(final Object userObject, final IEclipseContext context) {
 
-		final Processor processor = new Processor(context, true /*setter*/) {
+		final Processor processor = new Processor(true /*setter*/) {
 			public void processField(final Field field) {
 				final String candidateName = field.getName();
 				if (!candidateName.startsWith(fieldPrefix))
 					return;
-				context.runAndTrack(new Runnable() {
-					public void run() {
-						String key = findKey(candidateName.substring(fieldPrefixLength));
-						if (key == null) // value not set in the context
-							return;
-						Object value = context.get(key);
-						setField(userObject, field, value);
-					}
-				}, "Java reflection injection");
+				FieldLink link = new FieldLink(userObject, context, candidateName.substring(fieldPrefixLength), field);
+				context.runAndTrack(link, "Java Field Reflection Injection");
 			}
 
 			public void processMethod(final Method method) {
 				final String candidateName = method.getName();
 				if (!candidateName.startsWith(SET_METHOD_PREFIX))
 					return;
-				context.runAndTrack(new Runnable() {
-					public void run() {
-						final String key = findKey(candidateName.substring(SET_METHOD_PREFIX.length()));
-						if (key == null) // value not set in the context
-							return; 
-						Class[] parameterTypes = method.getParameterTypes();
-						Object value = context.get(key, parameterTypes);
-						setMethod(userObject, method, value);
-					}
-				}, "Java reflection injection");
+				MethodLink link = new MethodLink(userObject, context, candidateName.substring(SET_METHOD_PREFIX.length()), method);
+				context.runAndTrack(link, "Java Method Reflection Injection");
 			}
 		};
 		
 		walkClassHierarchy(userObject.getClass(), processor);
-
+		
 		// trigger post-injection processing
 		notifyUserMethod(CONTEXT_SET_METHOD, userObject, context);
 	}
 
-	protected void notifyUserObject(final IEclipseContext context, final Object userObject, final String serviceName, final Object value, boolean isSetter) {
-		final String methodPrefix = (isSetter) ? setMethodPrefix : setRemovePrefix;
-
-		Processor processor = new Processor(context, isSetter) {
-			public void processField(Field field) {
-				String candidateName = field.getName();
-				if (!candidateName.startsWith(fieldPrefix))
-					return;
-				String candidate = candidateName.substring(fieldPrefix.length());
-				if (!keyMatches(serviceName, candidate))
-					return;
-				setField(userObject, field, (isSetter) ? value : null);
-			}
-
-			public void processMethod(Method method) {
-				String candidateName = method.getName();
-				if (!candidateName.startsWith(methodPrefix))
-					return;
-				String candidate = candidateName.substring(methodPrefix.length());
-				if (!keyMatches(serviceName, candidate))
-					return;
-				setMethod(userObject, method, value);
-			}
-		};
-
-		walkClassHierarchy(userObject.getClass(), processor);
-	}
-
 	/**
 	 * For setters: we set fields first, them methods.
 	 * Otherwise, clear methods first, fields next 
@@ -212,74 +115,6 @@
 		}
 	}
 
-	protected String internalCase(String name) {
-		char firstChar = name.charAt(0);
-		if (!Character.isUpperCase(firstChar))
-			return name;
-
-		// convert first char to the lower case for internal use
-		firstChar = Character.toLowerCase(firstChar);
-		if (name.length() == 1)
-			return Character.toString(firstChar);
-		return Character.toString(firstChar) + name.substring(1);
-	}
-
-	protected boolean setField(Object userObject, Field field, Object value) {
-		if ((value != null) && !field.getType().isAssignableFrom(value.getClass())) {
-			// TBD add debug option
-			return false;
-		}
-
-		boolean wasAccessible = true;
-		if (!field.isAccessible()) {
-			field.setAccessible(true);
-			wasAccessible = false;
-		}
-		try {
-			field.set(userObject, value);
-		} catch (IllegalArgumentException e) {
-			logWarning(field, e);
-			return false;
-		} catch (IllegalAccessException e) {
-			logWarning(field, e);
-			return false;
-		} finally {
-			if (!wasAccessible)
-				field.setAccessible(false);
-		}
-		return true;
-	}
-
-	protected boolean setMethod(Object userObject, Method method, Object value) {
-		Class[] parameterTypes = method.getParameterTypes();
-		if (parameterTypes.length != 1)
-			return false;
-		if ((value != null) && !parameterTypes[0].isAssignableFrom(value.getClass()))
-			return false;
-
-		boolean wasAccessible = true;
-		if (!method.isAccessible()) {
-			method.setAccessible(true);
-			wasAccessible = false;
-		}
-		try {
-			method.invoke(userObject, new Object[] {value});
-		} catch (IllegalArgumentException e) {
-			logWarning(method, e);
-			return false;
-		} catch (IllegalAccessException e) {
-			logWarning(method, e);
-			return false;
-		} catch (InvocationTargetException e) {
-			logWarning(method, e);
-			return false;
-		} finally {
-			if (!wasAccessible)
-				method.setAccessible(false);
-		}
-		return true;
-	}
-
 	private void notifyUserMethod(String methodName, Object userObject, IEclipseContext newContext) {
 		// perform post-injection processing
 		Class objectClass = userObject.getClass();
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/FieldLink.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/FieldLink.java
new file mode 100644
index 0000000..aa4578a
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/FieldLink.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.core.services.internal.context;
+
+import java.lang.reflect.Field;
+
+import org.eclipse.e4.core.services.context.IEclipseContext;
+
+public class FieldLink extends ObjectLink {
+	
+	private Field field;	// TBD this should be wrapped into a WeakReference but then class gets unloaded 
+	// due to the current part implementation
+	
+	public FieldLink(Object userObject, IEclipseContext context, String candidateName, Field field) {
+		super(userObject, context, candidateName);
+		this.field = field;
+	}
+	
+	public void run() {
+//		Field field = (Field)fieldRef.get();
+//		if (field == null)
+//			return;
+		String key = findKey(candidateName);
+		if (key == null) { // value not set in the context
+			if (isSet) { // value has been removed from the context
+				setField(field, null);
+				isSet = false;
+			}
+			return;
+		}
+		Object value = context.get(key);
+		isSet = setField(field, value);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/MethodLink.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/MethodLink.java
new file mode 100644
index 0000000..d8cc4c1
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/MethodLink.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.core.services.internal.context;
+
+import java.lang.reflect.Method;
+
+import org.eclipse.e4.core.services.context.IEclipseContext;
+
+public class MethodLink extends ObjectLink {
+	
+	private Method method;	// TBD this should be wrapped into a WeakReference but then class gets unloaded 
+							// due to the current part implementation
+	
+	public MethodLink(Object userObject, IEclipseContext context, String candidateName, Method method) {
+		super(userObject, context, candidateName);
+		this.method = method;
+	}
+	
+	public void run() {
+//		Method method = (Method) methodRef.get();
+//		if (method == null)
+//			return;
+		String key = findKey(candidateName);
+		if (key == null) { // value not set in the context
+			if (isSet) { // value has been removed from the context
+				setMethod(method, null);
+				isSet = false;
+			}
+			return;
+		}
+		Class[] parameterTypes = method.getParameterTypes();
+		Object value = context.get(key,parameterTypes);
+		isSet = setMethod(method, value);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ObjectLink.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ObjectLink.java
new file mode 100644
index 0000000..eb688ed
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ObjectLink.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.core.services.internal.context;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.e4.core.services.context.IEclipseContext;
+
+abstract public class ObjectLink implements Runnable {
+	
+	protected WeakReference userObjectRef;
+	protected IEclipseContext context;
+	protected String candidateName;
+	
+	protected boolean isSet;
+	
+	public ObjectLink(Object userObject, IEclipseContext context, String candidateName) {
+		this.context = context;
+		this.userObjectRef = new WeakReference(userObject);
+		this.candidateName = candidateName;
+		isSet = false;
+	}
+	
+	protected String findKey(String key) {
+		if (context.containsKey(key)) // priority goes to exact match
+			return key; 
+		// alternate capitalization of the first char if possible
+		String candidate = altKey(key);
+		if (candidate == null) // no alternative spellings
+			return null; 
+		if (context.containsKey(candidate))
+			return candidate; 
+		return null; // means "not set"; differentiate from null values
+	}
+	
+	protected boolean keyMatches(String key1, String key2) {
+		if (key1 == null && key2 == null)
+			return true;
+		if (key1 == null || key2 == null)
+			return false;
+		if (key1.equals(key2))
+			return true;
+		String candidate = altKey(key2);
+		if (candidate == null) // no alternative spellings
+			return false; 
+		return key1.equals(candidate);
+	}
+	
+	/**
+	 * Calculates alternative spelling of the key: "log" <-> "Log", if any.
+	 * Returns null if there is no alternate.
+	 */
+	protected String altKey(String key) {
+		if (key.length() == 0)
+			return null;
+		char firstChar = key.charAt(0);
+		String candidate = null;
+		if (Character.isUpperCase(firstChar)) {
+			firstChar = Character.toLowerCase(firstChar);
+			if (key.length() == 1)
+				candidate = Character.toString(firstChar);
+			else
+				candidate = Character.toString(firstChar) + key.substring(1);
+		} else if (Character.isLowerCase(firstChar)) {
+			firstChar = Character.toUpperCase(firstChar);
+				if (key.length() == 1)
+					candidate = Character.toString(firstChar);
+				else
+					candidate = Character.toString(firstChar) + key.substring(1);
+		}
+		return candidate;
+	}
+	
+	protected boolean setField(Field field, Object value) {
+		if ((value != null) && !field.getType().isAssignableFrom(value.getClass())) {
+			// TBD add debug option
+			return false;
+		}
+		Object userObject = userObjectRef.get();
+		if (userObject == null)
+			return false;
+
+		boolean wasAccessible = true;
+		if (!field.isAccessible()) {
+			field.setAccessible(true);
+			wasAccessible = false;
+		}
+		try {
+			field.set(userObject, value);
+		} catch (IllegalArgumentException e) {
+			logWarning(field, e);
+			return false;
+		} catch (IllegalAccessException e) {
+			logWarning(field, e);
+			return false;
+		} finally {
+			if (!wasAccessible)
+				field.setAccessible(false);
+		}
+		return true;
+	}
+
+	protected boolean setMethod(Method method, Object value) {
+		Class[] parameterTypes = method.getParameterTypes();
+		if (parameterTypes.length != 1)
+			return false;
+		if ((value != null) && !parameterTypes[0].isAssignableFrom(value.getClass()))
+			return false;
+		
+		Object userObject = userObjectRef.get();
+		if (userObject == null)
+			return false;
+
+		boolean wasAccessible = true;
+		if (!method.isAccessible()) {
+			method.setAccessible(true);
+			wasAccessible = false;
+		}
+		try {
+			method.invoke(userObject, new Object[] {value});
+		} catch (IllegalArgumentException e) {
+			logWarning(method, e);
+			return false;
+		} catch (IllegalAccessException e) {
+			logWarning(method, e);
+			return false;
+		} catch (InvocationTargetException e) {
+			logWarning(method, e);
+			return false;
+		} finally {
+			if (!wasAccessible)
+				method.setAccessible(false);
+		}
+		return true;
+	}
+
+	private void logWarning(Object destination, Exception e) {
+		System.out.println("Injection failed " + destination.toString());
+		if (e != null)
+			e.printStackTrace();
+		// TBD convert this into real logging
+		//		String msg = NLS.bind("Injection failed", destination.toString());
+		//		RuntimeLog.log(new Status(IStatus.WARNING, IRuntimeConstants.PI_COMMON, 0, msg, e));
+	}
+}
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ContextDynamicTest.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ContextDynamicTest.java
index 4d76787..3bdf85b 100644
--- a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ContextDynamicTest.java
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ContextDynamicTest.java
@@ -79,12 +79,6 @@
 		assertEquals(1, userObject.setObjectCalled);
 		assertNull(userObject.getStringViaMethod());
 		assertEquals(testObjectViaMethod, userObject.getObjectViaMethod());
-
-		// dispose context
-// TBD we currently don't have dispose functionality
-//		context.dispose();
-//		assertNull(userObject.getContext());
-//		assertTrue(userObject.isDisposed());
 	}
 
 	/**
@@ -133,7 +127,8 @@
 		// add check
 		assertNull(userObject.getInteger());
 		assertEquals(testString, userObject.getString());
-		assertEquals(1, userObject.setStringCalled);
+		// 2: the same setter method is called on set and remove
+		assertEquals(2, userObject.setStringCalled);
 		assertEquals(1, userObject.setObjectCalled);
 		assertNull(userObject.getStringViaMethod());
 		assertEquals(testObjectViaMethod, userObject.getObjectViaMethod());
@@ -150,73 +145,8 @@
 
 		// check post processing
 		assertTrue(userObject.isFinalized());
-
-		// check disposal
-		assertFalse(userObject.isDisposed());
-		// TBD we currently don't have dispose functionality
-//		context.dispose();
-//		assertTrue(userObject.isDisposed());
 	}
 
-	/**
-	 * Tests context being disposed using reflection
-	 */
-//	public synchronized void testDisposal() {
-//		// create context
-//		IEclipseContext context = EclipseContextFactory.create(null);
-//		ObjectContextAware userObject = new ObjectContextAware();
-//		ContextInjectionFactory.inject(userObject, context);
-//
-//		// check post processing
-//		assertTrue(userObject.isFinalized());
-//		assertFalse(userObject.isDisposed());
-//		assertEquals(context, userObject.getEquinoxContext());
-
-		// check disposal
-		// TBD we currently don't have dispose functionality
-//		context.dispose();
-//
-//		assertTrue(userObject.isDisposed());
-//		assertTrue(userObject.isFinalized());
-//		assertNull(userObject.getEquinoxContext());
-//	}
-
-	/**
-	 * Tests parent context being disposed
-	 */
-//	public synchronized void testDisposalParent() {
-		// create context
-		// TBD we currently don't have dispose functionality
-//		IEclipseContext parentContext = EclipseContextFactory.create(null);
-//		IEclipseContext context1 = parentContext.newChild(null);
-//		IEclipseContext context11 = context1.newChild(null);
-//		IEclipseContext context2 = parentContext.newChild(null);
-//
-//		ObjectBasic userObject1 = new ObjectBasic();
-//		ContextInjectionFactory.inject(userObject1, context1);
-//
-//		ObjectBasic userObject11 = new ObjectBasic();
-//		ContextInjectionFactory.inject(userObject11, context11);
-//
-//		ObjectBasic userObject2 = new ObjectBasic();
-//		ContextInjectionFactory.inject(userObject2, context2);
-//
-//		// check post processing
-//		assertTrue(userObject1.isFinalized());
-//		assertTrue(userObject11.isFinalized());
-//		assertTrue(userObject2.isFinalized());
-//
-//		assertFalse(userObject1.isDisposed());
-//		assertFalse(userObject11.isDisposed());
-//		assertFalse(userObject2.isDisposed());
-//
-//		// check disposal
-//		parentContext.dispose();
-//		assertTrue(userObject1.isDisposed());
-//		assertTrue(userObject11.isDisposed());
-//		assertTrue(userObject2.isDisposed());
-//	}
-
 	public static Test suite() {
 		return new TestSuite(ContextDynamicTest.class);
 	}
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServicesTestSuite.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServicesTestSuite.java
index e42cc42..5e68a4c 100644
--- a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServicesTestSuite.java
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServicesTestSuite.java
@@ -26,5 +26,6 @@
 		addTestSuite(EclipseContextTest.class);
 		addTestSuite(ServiceContextTest.class);
 		addTestSuite(ContextInjectionTest.class);
+		addTestSuite(ContextDynamicTest.class);
 	}
 }