Bug 270989 Context refactoring
diff --git a/bundles/org.eclipse.e4.core.services/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.core.services/META-INF/MANIFEST.MF
index 24ca6bf..119940a 100644
--- a/bundles/org.eclipse.e4.core.services/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.e4.core.services/META-INF/MANIFEST.MF
@@ -13,6 +13,5 @@
  org.eclipse.e4.core.services.context,
  org.eclipse.e4.core.services.context.spi,
  org.eclipse.e4.core.services.internal.context;x-internal:=true,
- org.eclipse.e4.core.services.osgi,
  org.eclipse.e4.internal.core.services.osgi;x-internal:=true
 Bundle-Activator: org.eclipse.e4.internal.core.services.osgi.Activator
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/EclipseContextFactory.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/EclipseContextFactory.java
index 807b1e7..3e67d13 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/EclipseContextFactory.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/EclipseContextFactory.java
@@ -11,9 +11,10 @@
 
 package org.eclipse.e4.core.services.context;
 
+import org.eclipse.e4.core.services.context.spi.IContextConstants;
 import org.eclipse.e4.core.services.context.spi.IEclipseContextStrategy;
 import org.eclipse.e4.core.services.internal.context.EclipseContext;
-import org.eclipse.e4.internal.core.services.osgi.OSGiServiceContext;
+import org.eclipse.e4.internal.core.services.osgi.OSGiContextStrategy;
 import org.osgi.framework.BundleContext;
 
 /**
@@ -44,6 +45,8 @@
 	 * @return A context containing all OSGi services
 	 */
 	public static IEclipseContext createServiceContext(BundleContext bundleContext) {
-		return new OSGiServiceContext(bundleContext);
+		IEclipseContext result = new EclipseContext(null, new OSGiContextStrategy(bundleContext));
+		result.set(IContextConstants.DEBUG_STRING, "OSGi context for bundle: " + bundleContext.getBundle().getSymbolicName()); //$NON-NLS-1$
+		return result;
 	}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IComputedValue.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IComputedValue.java
deleted file mode 100644
index 54cfbba..0000000
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IComputedValue.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * 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.context;
-
-import org.eclipse.e4.core.services.context.spi.ComputedValue;
-
-/**
- * A computed value instance is a place holder for an object that has not yet
- * been created. These place holders can be stored as values in an {@link IEclipseContext}, 
- * allowing the concrete value they represent to be computed lazily only when requested.
- * 
- * @noimplement This interface is not intended to be implemented by clients. Computed
- * value implementations must subclass {@link ComputedValue} instead.
- */
-public interface IComputedValue {
-	/**
-	 * Computes and returns the concrete value that this place holder represents
-	 * 
-	 * @param context The context in which to perform the value computation.
-	 * @param arguments The arguments required to compute the value, or
-	 * <code>null</code> if no arguments are applicable
-	 * @return The concrete value.
-	 */
-	public Object compute(IEclipseContext context, Object[] arguments);
-
-}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IContextFunction.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IContextFunction.java
new file mode 100644
index 0000000..33adbdb
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IContextFunction.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.context;
+
+import org.eclipse.e4.core.services.context.spi.ContextFunction;
+
+/**
+ * A context function encapsulates evaluation of some code within an {@link IEclipseContext}.
+ * The result of the function must be derived purely from the provided arguments and
+ * context objects, and must be free from side-effects other than the function's return value.
+ * In particular, the function must be idempotent - subsequent invocations of the same function
+ * with the same inputs must produce the same result.
+ * <p>
+ * A common use for context functions is as a place holder for an object that has not yet
+ * been created. These place holders can be stored as values in an {@link IEclipseContext}, 
+ * allowing the concrete value they represent to be computed lazily only when requested.
+ * </p>
+ * 
+ * @see IEclipseContext#set(String, Object)
+ * @noimplement This interface is not intended to be implemented by clients. Function
+ * implementations must subclass {@link ContextFunction} instead.
+ */
+public interface IContextFunction {
+	/**
+	 * Evaluates the function based on the provided arguments and context to produce
+	 * a consistent result.
+	 * 
+	 * @param context The context in which to perform the value computation.
+	 * @param arguments The arguments required to compute the value, or
+	 * <code>null</code> if no arguments are applicable
+	 * @return The concrete value.
+	 */
+	public Object compute(IEclipseContext context, Object[] arguments);
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IEclipseContext.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IEclipseContext.java
index 2e778e9..0717989 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IEclipseContext.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/IEclipseContext.java
@@ -11,7 +11,7 @@
 
 package org.eclipse.e4.core.services.context;
 
-import org.eclipse.e4.core.services.context.spi.ComputedValue;
+import org.eclipse.e4.core.services.context.spi.ContextFunction;
 import org.eclipse.e4.core.services.context.spi.IRunAndTrack;
 
 /**
@@ -52,9 +52,9 @@
 	 * <code>null</code> if no such value is defined or computable by this
 	 * context, or if the assigned value is <code>null</code>.
 	 * <p>
-	 * If the value associated with this name is an {@link IComputedValue}, this
+	 * If the value associated with this name is an {@link IContextFunction}, this
 	 * method will evaluate
-	 * {@link IComputedValue#compute(IEclipseContext, Object[])} with zero
+	 * {@link IContextFunction#compute(IEclipseContext, Object[])} with zero
 	 * arguments.
 	 * </p>
 	 * 
@@ -69,9 +69,9 @@
 	 * <code>null</code> if no such value is defined or computable by this
 	 * context.
 	 * <p>
-	 * If the value associated with this name is an {@link IComputedValue}, this
+	 * If the value associated with this name is an {@link IContextFunction}, this
 	 * method will evaluate
-	 * {@link IComputedValue#compute(IEclipseContext, Object[])} with the
+	 * {@link IContextFunction#compute(IEclipseContext, Object[])} with the
 	 * provided arguments.
 	 * </p>
 	 * 
@@ -109,10 +109,10 @@
 
 	/**
 	 * Sets a value to be associated with a given name in this context. The
-	 * value may be an arbitrary object, or it may be a {@link ComputedValue}.
-	 * In the case of a computed value, subsequent invocations of
+	 * value may be an arbitrary object, or it may be an {@link IContextFunction}.
+	 * In the case of a function, subsequent invocations of
 	 * {@link #get(String)} with the same name will invoke
-	 * {@link IComputedValue#compute(IEclipseContext, Object[])} to obtain the
+	 * {@link IContextFunction#compute(IEclipseContext, Object[])} to obtain the
 	 * value. The value may be <code>null</code>.
 	 * <p>
 	 * Removal can never affect a parent context, so it is possible that a
@@ -123,13 +123,8 @@
 	 * @param name
 	 *            The name to store a value for
 	 * @param value
-	 *            The value to be stored, or a {@link ComputedValue} that can
+	 *            The value to be stored, or a {@link ContextFunction} that can
 	 *            return the stored value.
 	 */
 	public void set(String name, Object value);
-
-	/**
-	 * Disposes of this context.
-	 */
-	public void dispose();
 }
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ComputedValue.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ContextFunction.java
similarity index 69%
rename from bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ComputedValue.java
rename to bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ContextFunction.java
index cf464cb..82c4afb 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ComputedValue.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ContextFunction.java
@@ -10,15 +10,19 @@
  *******************************************************************************/
 package org.eclipse.e4.core.services.context.spi;
 
+import org.eclipse.e4.core.services.context.IContextFunction;
 import org.eclipse.e4.core.services.context.IEclipseContext;
 
-import org.eclipse.e4.core.services.context.IComputedValue;
-
 /**
  * The base class for all computed value implementations. Clients may subclass
- * this class.
+ * this class. See the class comment of {@link IContextFunction} for specific
+ * rules that must be followed by function implementations.
+ * <p>
+ * This class is intended to be subclassed by clients.
+ * </p>
+ * @see IContextFunction
  */
-public abstract class ComputedValue implements IComputedValue {
+public abstract class ContextFunction implements IContextFunction {
 
 	/**
 	 * {@inheritDoc}
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ILookupStrategy.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ILookupStrategy.java
new file mode 100644
index 0000000..2fe53c5
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ILookupStrategy.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.context.spi;
+
+import org.eclipse.e4.core.services.context.IContextFunction;
+import org.eclipse.e4.core.services.context.IEclipseContext;
+
+/**
+ * A context strategy for looking up values that are not currently defined
+ * in a context. The lookup strategy is consulted by the context after
+ * looking for an already defined local value, but before delegating lookup
+ * to a parent context.
+ */
+public interface ILookupStrategy extends IEclipseContextStrategy {
+	/**
+	 * Looks up a value for the given name to be associated with the given context.
+	 * @param name The name of the context value to look up
+	 * @param context The context in which the lookup occurred
+	 * @return The value for the given name, or <code>null</code> if no
+	 * corresponding value could be found. The value may be an
+	 * {@link IContextFunction}.
+	 */
+	public Object lookup(String name, IEclipseContext context);
+
+	/**
+	 * Returns whether this strategy is able to return a value for the given name.
+	 * There is no guarantee that the result will predict a future invocation
+	 * of {@link #lookup(String, IEclipseContext)} on this same strategy,
+	 * due to the possibility of concurrent changes in this lookup strategy's
+	 * search scope.
+	 * 
+	 * @param name The name of the context value to look up
+	 * @param context The context in which the lookup occurred
+	 * @return <code>true</code> if this strategy is able to return a 
+	 * value for the given name, and <code>false</code> otherwise.
+	 */
+	public boolean containsKey(String name, IEclipseContext context);
+}
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/IEclipseContextScheduler.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ISchedulerStrategy.java
similarity index 61%
rename from bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/IEclipseContextScheduler.java
rename to bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ISchedulerStrategy.java
index d314436..58f0a02 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/IEclipseContextScheduler.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/context/spi/ISchedulerStrategy.java
@@ -13,16 +13,28 @@
 
 import org.eclipse.e4.core.services.context.IEclipseContext;
 
-public interface IEclipseContextScheduler extends IEclipseContextStrategy {
+/**
+ * A context strategy for queueing and invoking runnables that are tracking changes
+ * in the context. Implementations of this strategy must queue and invoke
+ * runnables in the order they are scheduled.
+ * 
+ * @see IEclipseContext#runAndTrack(Runnable, String)
+ */
+public interface ISchedulerStrategy extends IEclipseContextStrategy {
 
+	/**
+	 * Schedules a runnable for execution.
+	 * @param runnable The runnable to execute
+	 */
 	public void schedule(Runnable runnable);
 
 	/**
 	 * This is the same method but for more involved listeners. It should pass in 
 	 * the context that has been changed, name of the changed service, and the arguments.
 	 * 
-	 * @return false: the runnable no longer valid and needs to be cleaned up from the list
+	 * @return <code>true</code> if the runnable is still valid, or <code>false</code> 
+	 * to indicate this runnable is no longer valid and should be removed from the context.
 	 */
 	public boolean schedule(IEclipseContext context, IRunAndTrack runnable, String name, int eventType, Object[] args);
-	
+
 }
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextToObjectLink.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextToObjectLink.java
index 436b295..b630a39 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextToObjectLink.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ContextToObjectLink.java
@@ -13,26 +13,19 @@
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
+import java.lang.reflect.*;
+import java.util.*;
 import org.eclipse.e4.core.services.context.IEclipseContext;
 import org.eclipse.e4.core.services.context.spi.IContextConstants;
 import org.eclipse.e4.core.services.context.spi.IRunAndTrack;
 
 public class ContextToObjectLink implements IRunAndTrack, IContextConstants {
 
-	private static class PropertyChangeListenerImplementation implements
-			PropertyChangeListener {
+	private static class PropertyChangeListenerImplementation implements PropertyChangeListener {
 		private final String name;
 		private final IEclipseContext outputContext;
 
-		private PropertyChangeListenerImplementation(String name,
-				IEclipseContext outputContext) {
+		private PropertyChangeListenerImplementation(String name, IEclipseContext outputContext) {
 			this.name = name;
 			this.outputContext = outputContext;
 		}
@@ -75,18 +68,15 @@
 
 	protected List userObjects = new ArrayList(3); // start small
 
-	public ContextToObjectLink(IEclipseContext context, String fieldPrefix,
-			String setMethodPrefix) {
+	public ContextToObjectLink(IEclipseContext context, String fieldPrefix, String setMethodPrefix) {
 		this.context = context;
 		this.fieldPrefix = (fieldPrefix != null) ? fieldPrefix : INJECTION_FIELD_PREFIX;
-		this.setMethodPrefix = (setMethodPrefix != null) ? setMethodPrefix
-				: INJECTION_SET_METHOD_PREFIX;
+		this.setMethodPrefix = (setMethodPrefix != null) ? setMethodPrefix : INJECTION_SET_METHOD_PREFIX;
 
 		fieldPrefixLength = this.fieldPrefix.length();
 	}
 
-	public boolean notify(final IEclipseContext context, final String name,
-			final int eventType, final Object[] args) {
+	public boolean notify(final IEclipseContext context, final String name, final int eventType, final Object[] args) {
 		if (eventType == IRunAndTrack.DISPOSE) {
 			for (Iterator it = userObjects.iterator(); it.hasNext();) {
 				Object object = (Object) it.next();
@@ -97,66 +87,67 @@
 		Processor processor = new Processor(isSetter) {
 			void processField(final Field field, String injectName, boolean optional) {
 				switch (eventType) {
-				case IRunAndTrack.INITIAL:
-					String key = findKey(injectName, field.getType());
-					if (key != null) {
-						setField(args[0], field, context.get(key));
-					} else {
-						if (!optional) {
-							throw new IllegalStateException("Could not set " + field
-									+ " because of missing: " + injectName);
+					case IRunAndTrack.INITIAL :
+						String key = findKey(injectName, field.getType());
+						if (key != null) {
+							setField(args[0], field, context.get(key));
+						} else {
+							if (!optional) {
+								throw new IllegalStateException("Could not set " + field + " because of missing: " + injectName);
+							}
 						}
-					}
-					break;
-				case IRunAndTrack.ADDED:
-					if (keyMatches(name, injectName))
-						setField(userObject, field, context.get(findKey(name, field
-								.getType())));
-					break;
-				case IRunAndTrack.REMOVED:
-					if (keyMatches(name, injectName))
-						setField(userObject, field, null);
-					break;
-				case IRunAndTrack.DISPOSE:
-				default:
-					logWarning(userObject, new IllegalArgumentException(
-							"Unknown event type: " + eventType));
+						break;
+					case IRunAndTrack.ADDED :
+						String injectKey = findKey(name, field.getType());
+						if (injectKey != null)
+							setField(userObject, field, context.get(injectKey));
+						break;
+					case IRunAndTrack.REMOVED :
+						if (keyMatches(name, injectName) || field.getType().getName().equals(name))
+							setField(userObject, field, null);
+						break;
+					case IRunAndTrack.DISPOSE :
+					default :
+						logWarning(userObject, new IllegalArgumentException("Unknown event type: " + eventType));
 				}
 			}
 
 			void processMethod(final Method method, boolean optional) {
 				String candidateName = method.getName();
+				if (candidateName.length() <= setMethodPrefix.length())
+					return;
+				candidateName = candidateName.substring(setMethodPrefix.length());
+				Class[] parameterTypes = method.getParameterTypes();
+				//only inject methods with a single parameter
+				if (parameterTypes.length != 1)
+					return;
 				switch (eventType) {
-				case IRunAndTrack.INITIAL:
-					String key = findKey(candidateName
-							.substring(INJECTION_SET_METHOD_PREFIX.length()), method
-							.getParameterTypes()[0]);
-					if (key != null) {
-						setMethod(args[0], method, context.get(key, method
-								.getParameterTypes()));
-					} else {
-						if (!optional) {
-							throw new IllegalStateException("Could not invoke " + method
-									+ " because of missing: " + candidateName);
+					case IRunAndTrack.INITIAL :
+						//when initializing we want to inject every method that has a match in the context
+						String key = findKey(candidateName, parameterTypes[0]);
+						if (key != null) {
+							setMethod(userObject, method, context.get(key, parameterTypes));
+						} else {
+							if (!optional) {
+								throw new IllegalStateException("Could not invoke " + method + " because of missing: " + candidateName);
+							}
 						}
-					}
-					break;
-				case IRunAndTrack.ADDED:
-					if (keyMatches(name, candidateName
-							.substring(INJECTION_SET_METHOD_PREFIX.length())))
-						setMethod(userObject, method, context.get(findKey(name, method
-								.getParameterTypes()[0]), method.getParameterTypes()));
-					break;
-				case IRunAndTrack.REMOVED:
-					if (keyMatches(name, candidateName
-							.substring(INJECTION_SET_METHOD_PREFIX.length())))
-						setMethod(userObject, method, null);
-					break;
-				case IRunAndTrack.DISPOSE:
-					break;
-				default:
-					logWarning(userObject, new IllegalArgumentException(
-							"Unknown event type: " + eventType));
+						break;
+					case IRunAndTrack.ADDED :
+						//on add event, only inject the method corresponding to the added context key
+						if (keyMatches(name, candidateName)) {
+							key = findKey(name, parameterTypes[0]);
+							setMethod(userObject, method, context.get(key, parameterTypes));
+						}
+						break;
+					case IRunAndTrack.REMOVED :
+						if (keyMatches(name, candidateName))
+							setMethod(userObject, method, null);
+						break;
+					case IRunAndTrack.DISPOSE :
+						break;
+					default :
+						logWarning(userObject, new IllegalArgumentException("Unknown event type: " + eventType));
 				}
 			}
 
@@ -180,12 +171,9 @@
 			}
 
 			public void processOutMethod(Method m, final String name) {
-				final IEclipseContext outputContext = (IEclipseContext) context
-						.get("outputs");
+				final IEclipseContext outputContext = (IEclipseContext) context.get("outputs");
 				if (outputContext == null) {
-					throw new IllegalStateException(
-							"No output context available for @Out " + m + " in "
-									+ userObject);
+					throw new IllegalStateException("No output context available for @Out " + m + " in " + userObject);
 				}
 				if (eventType == IRunAndTrack.INITIAL) {
 					Object value;
@@ -201,16 +189,7 @@
 							value = m.invoke(userObject, new Object[0]);
 						}
 						outputContext.set(name, value);
-						userObject.getClass()
-								.getMethod(
-										"addPropertyChangeListener",
-										new Class[] { String.class,
-												PropertyChangeListener.class }).invoke(
-										userObject,
-										new Object[] {
-												name,
-												new PropertyChangeListenerImplementation(
-														name, outputContext) });
+						userObject.getClass().getMethod("addPropertyChangeListener", new Class[] {String.class, PropertyChangeListener.class}).invoke(userObject, new Object[] {name, new PropertyChangeListenerImplementation(name, outputContext)});
 					} catch (Exception ex) {
 						throw new RuntimeException(ex);
 					}
@@ -246,14 +225,11 @@
 		for (int i = 0; i < methods.length; i++) {
 			Method method = methods[i];
 			try {
-				Object[] annotations = (Object[]) method.getClass().getMethod(
-						"getAnnotations", new Class[0]).invoke(method, new Object[0]);
+				Object[] annotations = (Object[]) method.getClass().getMethod("getAnnotations", new Class[0]).invoke(method, new Object[0]);
 				for (int j = 0; j < annotations.length; j++) {
 					Object annotation = annotations[j];
 					try {
-						String annotationName = ((Class) annotation.getClass().getMethod(
-								"annotationType", new Class[0]).invoke(annotation,
-								new Object[0])).getName();
+						String annotationName = ((Class) annotation.getClass().getMethod("annotationType", new Class[0]).invoke(annotation, new Object[0])).getName();
 						if (annotationName.endsWith(".PreDestroy")) {
 							callDispose(object, method);
 							return;
@@ -341,8 +317,7 @@
 			processMethodsResult = processMethods(objectsClass, processor);
 			processFields(objectsClass, processor);
 		}
-		for (Iterator it = processMethodsResult.postConstructMethods.iterator(); it
-				.hasNext();) {
+		for (Iterator it = processMethodsResult.postConstructMethods.iterator(); it.hasNext();) {
 			Method m = (Method) it.next();
 			processor.processPostConstructMethod(m);
 		}
@@ -379,21 +354,15 @@
 			boolean inject = candidateName.startsWith(setMethodPrefix);
 			boolean optional = false;
 			try {
-				Object[] annotations = (Object[]) method.getClass().getMethod(
-						"getAnnotations", new Class[0]).invoke(method, new Object[0]);
+				Object[] annotations = (Object[]) method.getClass().getMethod("getAnnotations", new Class[0]).invoke(method, new Object[0]);
 				for (int j = 0; j < annotations.length; j++) {
 					Object annotation = annotations[j];
 					try {
-						String annotationName = ((Class) annotation.getClass().getMethod(
-								"annotationType", new Class[0]).invoke(annotation,
-								new Object[0])).getName();
-						if (annotationName.endsWith(".Inject")
-								|| annotationName.endsWith(".In")) {
+						String annotationName = ((Class) annotation.getClass().getMethod("annotationType", new Class[0]).invoke(annotation, new Object[0])).getName();
+						if (annotationName.endsWith(".Inject") || annotationName.endsWith(".In")) {
 							inject = true;
 							try {
-								optional = ((Boolean) annotation.getClass().getMethod(
-										"optional", new Class[0]).invoke(annotation,
-										new Object[0])).booleanValue();
+								optional = ((Boolean) annotation.getClass().getMethod("optional", new Class[0]).invoke(annotation, new Object[0])).booleanValue();
 							} catch (Exception e) {
 								e.printStackTrace();
 							}
@@ -425,31 +394,23 @@
 			Field field = fields[i];
 			String injectName = field.getName();
 			boolean inject = false;
-			boolean optional = false;
+			boolean optional = true;
 			try {
-				Object[] annotations = (Object[]) field.getClass().getMethod(
-						"getAnnotations", new Class[0]).invoke(field, new Object[0]);
+				Object[] annotations = (Object[]) field.getClass().getMethod("getAnnotations", new Class[0]).invoke(field, new Object[0]);
 				for (int j = 0; j < annotations.length; j++) {
 					Object annotation = annotations[j];
 					try {
-						String annotationName = ((Class) annotation.getClass().getMethod(
-								"annotationType", new Class[0]).invoke(annotation,
-								new Object[0])).getName();
-						if (annotationName.endsWith(".Inject")
-								|| annotationName.endsWith(".In")) {
+						String annotationName = ((Class) annotation.getClass().getMethod("annotationType", new Class[0]).invoke(annotation, new Object[0])).getName();
+						if (annotationName.endsWith(".Inject") || annotationName.endsWith(".In")) {
 							inject = true;
 							try {
-								optional = ((Boolean) annotation.getClass().getMethod(
-										"optional", new Class[0]).invoke(annotation,
-										new Object[0])).booleanValue();
+								optional = ((Boolean) annotation.getClass().getMethod("optional", new Class[0]).invoke(annotation, new Object[0])).booleanValue();
 							} catch (Exception e) {
 								e.printStackTrace();
 							}
 						} else if (annotationName.endsWith(".Named")) {
 							try {
-								injectName = (String) annotation.getClass().getMethod(
-										"value", new Class[0]).invoke(annotation,
-										new Object[0]);
+								injectName = (String) annotation.getClass().getMethod("value", new Class[0]).invoke(annotation, new Object[0]);
 							} catch (Exception e) {
 								e.printStackTrace();
 							}
@@ -457,9 +418,7 @@
 							inject = true;
 							String resourceName = null;
 							try {
-								resourceName = (String) annotation.getClass().getMethod(
-										"name", new Class[0]).invoke(annotation,
-										new Object[0]);
+								resourceName = (String) annotation.getClass().getMethod("name", new Class[0]).invoke(annotation, new Object[0]);
 							} catch (Exception e) {
 								logWarning(field, e);
 							}
@@ -580,7 +539,7 @@
 			wasAccessible = false;
 		}
 		try {
-			method.invoke(userObject, new Object[] { value });
+			method.invoke(userObject, new Object[] {value});
 		} catch (IllegalArgumentException e) {
 			logWarning(method, e);
 			return false;
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/EclipseContext.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/EclipseContext.java
index dff7858..eadc42e 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/EclipseContext.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/EclipseContext.java
@@ -11,32 +11,66 @@
 
 package org.eclipse.e4.core.services.internal.context;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.e4.core.services.context.IComputedValue;
+import java.util.*;
+import org.eclipse.e4.core.services.IDisposable;
+import org.eclipse.e4.core.services.context.IContextFunction;
 import org.eclipse.e4.core.services.context.IEclipseContext;
-import org.eclipse.e4.core.services.context.spi.IContextConstants;
-import org.eclipse.e4.core.services.context.spi.IEclipseContextScheduler;
-import org.eclipse.e4.core.services.context.spi.IEclipseContextStrategy;
-import org.eclipse.e4.core.services.context.spi.IRunAndTrack;
+import org.eclipse.e4.core.services.context.spi.*;
 
-public class EclipseContext implements IEclipseContext {
+public class EclipseContext implements IEclipseContext, IDisposable {
+
+	static class LookupKey {
+		Object[] arguments;
+		String name;
+
+		public LookupKey(String name, Object[] arguments) {
+			this.name = name;
+			this.arguments = arguments;
+		}
+
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null)
+				return false;
+			if (getClass() != obj.getClass())
+				return false;
+			LookupKey other = (LookupKey) obj;
+			if (!Arrays.equals(arguments, other.arguments))
+				return false;
+			if (name == null) {
+				if (other.name != null)
+					return false;
+			} else if (!name.equals(other.name))
+				return false;
+			return true;
+		}
+
+		public int hashCode() {
+			final int prime = 31;
+			int result = 1;
+			result = prime * result;
+			if (arguments != null) {
+				for (int i = 0; i < arguments.length; i++) {
+					Object arg = arguments[i];
+					result = prime * result + (arg == null ? 0 : arg.hashCode());
+				}
+			}
+			result = prime * result + ((name == null) ? 0 : name.hashCode());
+			return result;
+		}
+	}
 
 	static class TrackableComputation extends Computation implements Runnable {
-		Runnable runnable;
 		private final String name;
+		Runnable runnable;
 
 		TrackableComputation(Runnable runnable, String name) {
 			this.runnable = runnable;
 			this.name = name;
 		}
 
-		final protected void doHandleInvalid(IEclipseContext context, String name,
-				int eventType) {
+		final protected void doHandleInvalid(IEclipseContext context, String name, int eventType) {
 			if (eventType == IRunAndTrack.DISPOSE) {
 				return;
 			}
@@ -70,14 +104,12 @@
 			this.runnable = runnable;
 		}
 
-		final protected void doHandleInvalid(IEclipseContext context, String name,
-				int eventType) {
+		final protected void doHandleInvalid(IEclipseContext context, String name, int eventType) {
 			((EclipseContext) context).schedule(this, name, eventType, null); // XXX
 			// IEclipseContext
 		}
 
-		public boolean notify(IEclipseContext context, String name, int eventType,
-				Object[] args) {
+		public boolean notify(IEclipseContext context, String name, int eventType, Object[] args) {
 			Computation oldComputation = (Computation) currentComputation.get();
 			currentComputation.set(this);
 			boolean result = true;
@@ -91,13 +123,6 @@
 		}
 	}
 
-	private static final Object[] NO_ARGUMENTS = new Object[0];
-
-	private IEclipseContextStrategy strategy;
-
-	// TODO replace with variable on bundle-specific class
-	public static boolean DEBUG = false;
-
 	/**
 	 * TODO Can this really be static? Couldn't there be multiple computations
 	 * ongoing in a single thread? For example a computation could recursively
@@ -105,41 +130,49 @@
 	 */
 	static ThreadLocal currentComputation = new ThreadLocal();
 
+	// TODO replace with variable on bundle-specific class
+	public static boolean DEBUG = false;
+
+	private static final Object[] NO_ARGUMENTS = new Object[0];
+
 	Set listeners = new HashSet();
 
-	Map localValues = new HashMap();
 	Map localValueComputations = new HashMap();
+	Map localValues = new HashMap();
 
 	IEclipseContext parent;
 
+	private IEclipseContextStrategy strategy;
+
 	public EclipseContext(IEclipseContext parent, IEclipseContextStrategy strategy) {
 		this.parent = parent;
 		this.strategy = strategy;
 		set(IContextConstants.DEBUG_STRING, "Anonymous Context"); //$NON-NLS-1$
 	}
 
-	protected void schedule(Runnable runnable) {
-		if (runnable == null)
-			return;
-		if (strategy != null && strategy instanceof IEclipseContextScheduler)
-			((IEclipseContextScheduler) strategy).schedule(runnable);
-		else
-			runnable.run();
+	public boolean containsKey(String name) {
+		if (isSetLocally(name))
+			return true;
+		if (parent != null && parent.containsKey(name))
+			return true;
+		if (strategy instanceof ILookupStrategy) {
+			if (((ILookupStrategy) strategy).containsKey(name, this))
+				return true;
+		}
+		return false;
 	}
 
-	protected boolean schedule(IRunAndTrack runnable, String name, int eventType,
-			Object[] args) {
-		if (runnable == null)
-			return false;
-		if (eventType != IRunAndTrack.INITIAL && eventType != IRunAndTrack.DISPOSE
-				&& strategy != null && strategy instanceof IEclipseContextScheduler)
-			return ((IEclipseContextScheduler) strategy).schedule(this, runnable, name,
-					eventType, args);
-		return runnable.notify(this, name, eventType, args);
-	}
-
-	public Object getLocal(String name) {
-		return internalGet(this, name, null, true);
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.e4.core.services.context.IEclipseContext#dispose()
+	 */
+	public void dispose() {
+		Computation[] ls = (Computation[]) listeners.toArray(new Computation[listeners.size()]);
+		for (int i = 0; i < ls.length; i++) {
+			ls[i].handleInvalid(this, null, IRunAndTrack.DISPOSE);
+		}
+		if (strategy instanceof IDisposable)
+			((IDisposable) strategy).dispose();
 	}
 
 	public Object get(String name) {
@@ -150,128 +183,59 @@
 		return internalGet(this, name, arguments, false);
 	}
 
-	static class LookupKey {
-		String name;
-		Object[] arguments;
-
-		public LookupKey(String name, Object[] arguments) {
-			this.name = name;
-			this.arguments = arguments;
-		}
-
-		public int hashCode() {
-			final int prime = 31;
-			int result = 1;
-			result = prime * result;
-			if (arguments != null) {
-				for (int i = 0; i < arguments.length; i++) {
-					Object arg = arguments[i];
-					result = prime * result + (arg == null ? 0 : arg.hashCode());
-				}
-			}
-			result = prime * result + ((name == null) ? 0 : name.hashCode());
-			return result;
-		}
-
-		public boolean equals(Object obj) {
-			if (this == obj)
-				return true;
-			if (obj == null)
-				return false;
-			if (getClass() != obj.getClass())
-				return false;
-			LookupKey other = (LookupKey) obj;
-			if (!Arrays.equals(arguments, other.arguments))
-				return false;
-			if (name == null) {
-				if (other.name != null)
-					return false;
-			} else if (!name.equals(other.name))
-				return false;
-			return true;
-		}
+	public Object getLocal(String name) {
+		return internalGet(this, name, null, true);
 	}
 
-	protected Object internalGet(EclipseContext originatingContext, String name,
-			Object[] arguments, boolean local) {
+	protected Object internalGet(EclipseContext originatingContext, String name, Object[] arguments, boolean local) {
 		trackAccess(name);
 		LookupKey lookupKey = new LookupKey(name, arguments);
 		if (this == originatingContext) {
-			ValueComputation valueComputation = (ValueComputation) localValueComputations
-					.get(lookupKey);
+			ValueComputation valueComputation = (ValueComputation) localValueComputations.get(lookupKey);
 			if (valueComputation != null) {
 				return valueComputation.get(arguments);
 			}
 		}
+		//1. try for local value
 		Object result = localValues.get(name);
+
+		//2. try the local strategy
+		if (result == null && strategy instanceof ILookupStrategy)
+			result = ((ILookupStrategy) strategy).lookup(name, originatingContext);
+
+		//if we found something, compute the concrete value and return
 		if (result != null) {
-			if (result instanceof IComputedValue) {
+			if (result instanceof IContextFunction) {
 				if (EclipseContext.DEBUG)
-					System.out
-							.println("creating new value computation for " + name + " in " + this + " from " + originatingContext); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-				ValueComputation valueComputation = new ValueComputation(this,
-						originatingContext, name, ((IComputedValue) result));
-				originatingContext.localValueComputations
-						.put(lookupKey, valueComputation);
+					System.out.println("creating new value computation for " + name + " in " + this + " from " + originatingContext); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				ValueComputation valueComputation = new ValueComputation(this, originatingContext, name, ((IContextFunction) result));
+				originatingContext.localValueComputations.put(lookupKey, valueComputation);
 				result = valueComputation.get(arguments);
 			}
 			return result;
 		}
+		//3. delegate to parent
 		if (!local && parent != null) {
-			return ((EclipseContext) parent).internalGet(originatingContext, name,
-					arguments, local); // XXX IEclipseContext
+			return ((EclipseContext) parent).internalGet(originatingContext, name, arguments, local); // XXX IEclipseContext
 		}
 		return null;
 	}
 
 	protected void invalidate(String name, int eventType) {
 		if (EclipseContext.DEBUG)
-			System.out
-					.println("invalidating " + get(IContextConstants.DEBUG_STRING) + ',' + name); //$NON-NLS-1$
+			System.out.println("invalidating " + get(IContextConstants.DEBUG_STRING) + ',' + name); //$NON-NLS-1$
 		localValueComputations.remove(name);
-		Computation[] ls = (Computation[]) listeners.toArray(new Computation[listeners
-				.size()]);
+		Computation[] ls = (Computation[]) listeners.toArray(new Computation[listeners.size()]);
 		for (int i = 0; i < ls.length; i++) {
 			ls[i].handleInvalid(this, name, eventType);
 		}
 	}
 
-	public boolean containsKey(String name) {
-		return isSetLocally(name) || (parent != null && parent.containsKey(name));
-	}
-
 	private boolean isSetLocally(String name) {
 		trackAccess(name);
 		return localValues.containsKey(name);
 	}
 
-	public void runAndTrack(final Runnable runnable, String name) {
-		TrackableComputation computation = new TrackableComputation(runnable, name);
-		schedule(computation);
-	}
-
-	public void runAndTrack(final IRunAndTrack runnable, Object[] args) {
-		TrackableComputationExt computation = new TrackableComputationExt(runnable);
-		schedule(computation, null, IRunAndTrack.INITIAL, args);
-	}
-
-	public void set(String name, Object value) {
-		localValues.put(name, value);
-		Object old = localValueComputations.remove(name);
-		if (old instanceof ValueComputation) {
-			ValueComputation valueComputation = (ValueComputation) old;
-			valueComputation.clear(this, name);
-		}
-		invalidate(name, IRunAndTrack.ADDED);
-	}
-
-	private void trackAccess(String name) {
-		Computation computation = (Computation) currentComputation.get();
-		if (computation != null) {
-			computation.addDependency(this, name);
-		}
-	}
-
 	public void remove(String name) {
 		if (isSetLocally(name)) {
 			localValues.remove(name);
@@ -284,15 +248,54 @@
 		}
 	}
 
+	public void runAndTrack(final IRunAndTrack runnable, Object[] args) {
+		TrackableComputationExt computation = new TrackableComputationExt(runnable);
+		schedule(computation, null, IRunAndTrack.INITIAL, args);
+	}
+
+	public void runAndTrack(final Runnable runnable, String name) {
+		TrackableComputation computation = new TrackableComputation(runnable, name);
+		schedule(computation);
+	}
+
+	protected boolean schedule(IRunAndTrack runnable, String name, int eventType, Object[] args) {
+		if (runnable == null)
+			return false;
+		if (eventType != IRunAndTrack.INITIAL && eventType != IRunAndTrack.DISPOSE && strategy != null && strategy instanceof ISchedulerStrategy)
+			return ((ISchedulerStrategy) strategy).schedule(this, runnable, name, eventType, args);
+		return runnable.notify(this, name, eventType, args);
+	}
+
+	protected void schedule(Runnable runnable) {
+		if (runnable == null)
+			return;
+		if (strategy != null && strategy instanceof ISchedulerStrategy)
+			((ISchedulerStrategy) strategy).schedule(runnable);
+		else
+			runnable.run();
+	}
+
+	public void set(String name, Object value) {
+		localValues.put(name, value);
+		Object old = localValueComputations.remove(name);
+		if (old instanceof ValueComputation) {
+			ValueComputation valueComputation = (ValueComputation) old;
+			valueComputation.clear(this, name);
+		}
+		invalidate(name, IRunAndTrack.ADDED);
+	}
+
+	/**
+	 * Returns a string representation of this context for debugging purposes only.
+	 */
 	public String toString() {
 		return (String) get(IContextConstants.DEBUG_STRING);
 	}
 
-	public void dispose() {
-		Computation[] ls = (Computation[]) listeners.toArray(new Computation[listeners
-				.size()]);
-		for (int i = 0; i < ls.length; i++) {
-			ls[i].handleInvalid(this, null, IRunAndTrack.DISPOSE);
+	private void trackAccess(String name) {
+		Computation computation = (Computation) currentComputation.get();
+		if (computation != null) {
+			computation.addDependency(this, name);
 		}
 	}
 }
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ValueComputation.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ValueComputation.java
index 74af092..3cf2660 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ValueComputation.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/internal/context/ValueComputation.java
@@ -11,7 +11,7 @@
 
 package org.eclipse.e4.core.services.internal.context;
 
-import org.eclipse.e4.core.services.context.IComputedValue;
+import org.eclipse.e4.core.services.context.IContextFunction;
 import org.eclipse.e4.core.services.context.IEclipseContext;
 import org.eclipse.e4.core.services.context.spi.IRunAndTrack;
 
@@ -20,12 +20,12 @@
 	IEclipseContext context;
 	String name;
 	boolean valid;
-	IComputedValue computedValue;
+	IContextFunction computedValue;
 	EclipseContext originatingContext; // XXX IEclipseContext
 	private boolean computing; // cycle detection
 
 	public ValueComputation(IEclipseContext context, IEclipseContext originatingContext,
-			String name, IComputedValue computedValue) {
+			String name, IContextFunction computedValue) {
 		this.context = context;
 		this.originatingContext = (EclipseContext) originatingContext;
 		this.name = name;
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/osgi/IServiceAliasRegistry.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/osgi/IServiceAliasRegistry.java
deleted file mode 100644
index 24d055f..0000000
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/core/services/osgi/IServiceAliasRegistry.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * 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.osgi;
-
-/**
- * A service that allows clients to publish and retrieve simple names for services. This
- * is suitable for service injection so that client fields and methods can be simple names.
- */
-public interface IServiceAliasRegistry {
-	public static final String SERVICE_NAME = IServiceAliasRegistry.class.getName();
-
-	/**
-	 * Returns the service alias associated with the given qualified service name. If the registry
-	 * does not contain an alias for the qualified service name, the service name is returned.
-	 * @param serviceName The qualified service name
-	 * @return The service alias, or the provided service name
-	 */
-	public String findAlias(String serviceName);
-
-	/**
-	 * Registers an alias for a given service class name.
-	 * @param alias The service alias
-	 * @param clazz The fully qualified service class name
-	 */
-	public void registerAlias(String alias, String clazz);
-
-	/**
-	 * Returns the service class name associated with the given alias. If the registry
-	 * does not contain a qualified service name for the alias, the alias itself is returned.
-	 * @param alias The service alias
-	 * @return The qualified service class name, or the provided alias
-	 */
-	public String resolveAlias(String alias);
-
-	/**
-	 * Unregisters an alias for a given service class name
-	 * @param alias The service alias
-	 */
-	public void unregisterAlias(String alias);
-
-}
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/Activator.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/Activator.java
index 29269f0..564a634 100644
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/Activator.java
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/Activator.java
@@ -10,30 +10,18 @@
  *******************************************************************************/
 package org.eclipse.e4.internal.core.services.osgi;
 
-import org.osgi.framework.ServiceRegistration;
-
-import org.eclipse.e4.core.services.osgi.IServiceAliasRegistry;
-
-import org.osgi.framework.BundleContext;
-
 import org.osgi.framework.BundleActivator;
-
+import org.osgi.framework.BundleContext;
 
 /**
  * Bundle activator for e4 core services bundle.
  */
 public class Activator implements BundleActivator {
-	
-
-	private ServiceRegistration aliasRegistration;
 
 	public void start(BundleContext context) throws Exception {
-		aliasRegistration = context.registerService(IServiceAliasRegistry.SERVICE_NAME, new ServiceAliasRegistryImpl(), null);
-		
 	}
 
 	public void stop(BundleContext context) throws Exception {
-		aliasRegistration.unregister();
 	}
 
 }
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/OSGiContextStrategy.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/OSGiContextStrategy.java
new file mode 100644
index 0000000..d3410b0
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/OSGiContextStrategy.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.internal.core.services.osgi;
+
+import java.util.*;
+import org.eclipse.e4.core.services.IDisposable;
+import org.eclipse.e4.core.services.context.IEclipseContext;
+import org.eclipse.e4.core.services.context.spi.ILookupStrategy;
+import org.osgi.framework.*;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * A context strategy that provides access to OSGi services.
+ * <p>
+ * OSGi services are looked up by service class name.
+ */
+public class OSGiContextStrategy implements ILookupStrategy, IDisposable, ServiceTrackerCustomizer {
+	class ServiceData {
+		//the service name
+		String name;
+
+		ServiceTracker tracker;
+		//the contexts using this service (IEclipseContext -> null)
+		final Map users = new WeakHashMap();
+
+		ServiceData(String name) {
+			this.name = name;
+		}
+
+		public void addContext(IEclipseContext originatingContext) {
+			users.put(originatingContext, null);
+		}
+	}
+
+	private final BundleContext bundleContext;
+	/**
+	 * Map of String (service name) -> ServiceData
+	 */
+	private Map services = Collections.synchronizedMap(new HashMap());
+
+	public OSGiContextStrategy(BundleContext bc) {
+		super();
+		this.bundleContext = bc;
+	}
+
+	public Object addingService(ServiceReference reference) {
+		String name = serviceName(reference);
+		Object newValue = bundleContext.getService(reference);
+		if (newValue == null)
+			return null;
+		//for performance we store the concrete service object with each context that requested it
+		ServiceData data = (ServiceData) services.get(name);
+		for (Iterator it = data.users.keySet().iterator(); it.hasNext();)
+			((IEclipseContext) it.next()).set(name, newValue);
+		return newValue;
+	}
+
+	/**
+	 * Discards any services that are no longer used by any strongly
+	 * reachable contexts.
+	 */
+	private void cleanReferences() {
+		synchronized (services) {
+			for (Iterator it = services.values().iterator(); it.hasNext();) {
+				ServiceData data = (ServiceData) it.next();
+				//if there are no more references, discard the service
+				if (data.users.isEmpty()) {
+					data.tracker.close();
+					it.remove();
+				}
+			}
+		}
+	}
+
+	public boolean containsKey(String name, IEclipseContext context) {
+		cleanReferences();
+		return bundleContext.getServiceReference(name) != null;
+	}
+
+	public void dispose() {
+		synchronized (services) {
+			for (Iterator it = services.values().iterator(); it.hasNext();)
+				((ServiceData) it.next()).tracker.close();
+			services.clear();
+		}
+	}
+
+	public Object lookup(String name, IEclipseContext originatingContext) {
+		cleanReferences();
+		ServiceData data = (ServiceData) services.get(name);
+		if (data == null) {
+			data = new ServiceData(name);
+			data.tracker = new ServiceTracker(bundleContext, name, this);
+			services.put(name, data);
+			//just opening a tracker will cause values to be set by the tracker callback methods
+			data.tracker.open();
+		}
+		data.addContext(originatingContext);
+		return data.tracker.getService();
+	}
+
+	public void modifiedService(ServiceReference reference, Object service) {
+		String name = serviceName(reference);
+		ServiceData data = (ServiceData) services.get(name);
+		for (Iterator it = data.users.keySet().iterator(); it.hasNext();)
+			((IEclipseContext) it.next()).set(name, service);
+	}
+
+	public void removedService(ServiceReference reference, Object service) {
+		String name = serviceName(reference);
+		//must set to null rather than removing so injection continues to work
+		ServiceData data = (ServiceData) services.get(name);
+		for (Iterator it = data.users.keySet().iterator(); it.hasNext();)
+			((IEclipseContext) it.next()).set(name, null);
+		bundleContext.ungetService(reference);
+	}
+
+	/**
+	 * Returns the service name for a service reference
+	 */
+	private String serviceName(ServiceReference reference) {
+		return ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/OSGiServiceContext.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/OSGiServiceContext.java
deleted file mode 100644
index b4e0c05..0000000
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/OSGiServiceContext.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*******************************************************************************
- * 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.internal.core.services.osgi;
-
-import java.util.*;
-import org.eclipse.e4.core.services.IDisposable;
-import org.eclipse.e4.core.services.context.IEclipseContext;
-import org.eclipse.e4.core.services.context.spi.IContextConstants;
-import org.eclipse.e4.core.services.internal.context.EclipseContext;
-import org.eclipse.e4.core.services.osgi.IServiceAliasRegistry;
-import org.osgi.framework.*;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-/**
- * A context that provides access to OSGi services.
- * <p>
- * OSGi services can either be looked up by class name, or using a service alias
- * registered with an {@link IServiceAliasRegistry}.
- */
-public class OSGiServiceContext extends EclipseContext implements IDisposable, ServiceTrackerCustomizer {
-	class ServiceData {
-		//the service name
-		String name;
-
-		ServiceTracker tracker;
-		//the contexts using this service (IEclipseContext -> null)
-		final Map users = new WeakHashMap();
-
-		ServiceData(String name) {
-			this.name = name;
-		}
-
-		public void addContext(EclipseContext originatingContext) {
-			users.put(originatingContext, null);
-		}
-	}
-
-	private final BundleContext bundleContext;
-	private final ServiceTracker aliasRegistryTracker;
-	/**
-	 * Map of String (service name) -> ServiceData
-	 */
-	private Map services = Collections.synchronizedMap(new HashMap());
-
-	public OSGiServiceContext(BundleContext bc) {
-		super(null, null);
-		this.bundleContext = bc;
-		this.aliasRegistryTracker = new ServiceTracker(bc, IServiceAliasRegistry.SERVICE_NAME, null);
-		set(IContextConstants.DEBUG_STRING, "OSGi context for bundle: " + bc.getBundle().getSymbolicName()); //$NON-NLS-1$
-		aliasRegistryTracker.open();
-	}
-
-	public Object addingService(ServiceReference reference) {
-		String name = serviceName(reference);
-		String alias = unresolve(name);
-		Object newValue = bundleContext.getService(reference);
-		if (newValue == null)
-			return null;
-		//for performance we store the concrete service object with each context that requested it
-		ServiceData data = (ServiceData) services.get(alias);
-		for (Iterator it = data.users.keySet().iterator(); it.hasNext();)
-			((IEclipseContext) it.next()).set(alias, newValue);
-		return newValue;
-	}
-
-	/**
-	 * Discards any services that are no longer used by any strongly
-	 * reachable contexts.
-	 */
-	private void cleanReferences() {
-		synchronized (services) {
-			for (Iterator it = services.values().iterator(); it.hasNext();) {
-				ServiceData data = (ServiceData) it.next();
-				//if there are no more references, discard the service
-				if (data.users.isEmpty()) {
-					data.tracker.close();
-					it.remove();
-					remove(data.name);
-				}
-			}
-		}
-	}
-
-	public boolean containsKey(String name) {
-		cleanReferences();
-		String unresolved = unresolve(name);
-		String resolved = resolve(name);
-		return super.containsKey(unresolved) || bundleContext.getServiceReference(resolved) != null;
-	}
-
-	public void dispose() {
-		synchronized (services) {
-			for (Iterator it = services.values().iterator(); it.hasNext();)
-				((ServiceData) it.next()).tracker.close();
-			services.clear();
-		}
-		aliasRegistryTracker.close();
-	}
-
-	protected Object internalGet(EclipseContext originatingContext, String name, Object[] arguments, boolean local) {
-		cleanReferences();
-		String alias = unresolve(name);
-		String resolved = resolve(name);
-		//first see if we have already stored a value locally
-		Object result = super.internalGet(originatingContext, alias, arguments, local);
-		if (result != null)
-			return result;
-		ServiceData data = (ServiceData) services.get(alias);
-		if (data == null) {
-			data = new ServiceData(alias);
-			data.tracker = new ServiceTracker(bundleContext, resolved, this);
-			services.put(alias, data);
-			//just opening a tracker will cause values to be set by the tracker callback methods
-			data.tracker.open();
-		}
-		data.addContext(originatingContext);
-		return data.tracker.getService();
-	}
-
-	public void modifiedService(ServiceReference reference, Object service) {
-		String name = serviceName(reference);
-		String alias = unresolve(name);
-		ServiceData data = (ServiceData) services.get(alias);
-		for (Iterator it = data.users.keySet().iterator(); it.hasNext();)
-			((IEclipseContext) it.next()).set(alias, service);
-	}
-
-	public void removedService(ServiceReference reference, Object service) {
-		String name = serviceName(reference);
-		String alias = unresolve(name);
-		//must set to null rather than removing so injection continues to work
-		ServiceData data = (ServiceData) services.get(alias);
-		for (Iterator it = data.users.keySet().iterator(); it.hasNext();)
-			((IEclipseContext) it.next()).set(alias, null);
-		bundleContext.ungetService(reference);
-	}
-
-	/**
-	 * Returns the service alias for a resolved service name.
-	 * @param serviceName The resolved service name
-	 * @return The service alias
-	 */
-	private String unresolve(String serviceName) {
-		IServiceAliasRegistry registry = (IServiceAliasRegistry) aliasRegistryTracker.getService();
-		return registry == null ? serviceName : registry.findAlias(serviceName);
-	}
-
-	/**
-	 * Returns the service alias for a qualified name
-	 */
-	private String resolve(String alias) {
-		IServiceAliasRegistry registry = (IServiceAliasRegistry) aliasRegistryTracker.getService();
-		return registry == null ? alias : registry.resolveAlias(alias);
-	}
-
-	/**
-	 * Returns the service alias for a service reference
-	 */
-	private String serviceName(ServiceReference reference) {
-		return ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
-	}
-}
diff --git a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/ServiceAliasRegistryImpl.java b/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/ServiceAliasRegistryImpl.java
deleted file mode 100644
index dc132be..0000000
--- a/bundles/org.eclipse.e4.core.services/src/org/eclipse/e4/internal/core/services/osgi/ServiceAliasRegistryImpl.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * 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.internal.core.services.osgi;
-
-import java.util.*;
-import org.eclipse.e4.core.services.osgi.IServiceAliasRegistry;
-
-/**
- * 
- */
-public class ServiceAliasRegistryImpl implements IServiceAliasRegistry {
-	private Map registry = Collections.synchronizedMap(new HashMap());
-
-	public String findAlias(String serviceName) {
-		//create reverse lookup map if needed for performance
-		synchronized (registry) {
-			for (Iterator it = registry.entrySet().iterator(); it.hasNext();) {
-				Map.Entry entry = (Map.Entry) it.next();
-				if (entry.getValue().equals(serviceName))
-					return (String) entry.getKey();
-			}
-		}
-		return serviceName;
-	}
-
-	public void registerAlias(String alias, String clazz) {
-		registry.put(alias, clazz);
-	}
-
-	public String resolveAlias(String alias) {
-		String result = (String) registry.get(alias);
-		return result == null ? alias : result;
-	}
-
-	public void unregisterAlias(String alias) {
-		registry.remove(alias);
-	}
-
-}
diff --git a/tests/org.eclipse.e4.core.tests.services/META-INF/MANIFEST.MF b/tests/org.eclipse.e4.core.tests.services/META-INF/MANIFEST.MF
index 7824f07..6e6b310 100644
--- a/tests/org.eclipse.e4.core.tests.services/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.e4.core.tests.services/META-INF/MANIFEST.MF
@@ -7,5 +7,6 @@
 Require-Bundle: org.junit;bundle-version="3.8.2",
  org.eclipse.e4.core.services;bundle-version="0.9.0"
 Bundle-Activator: org.eclipse.e4.core.tests.services.TestActivator
-Import-Package: org.osgi.framework;version="1.5.0"
+Import-Package: org.eclipse.osgi.service.debug;version="1.1.0",
+ org.osgi.framework;version="1.5.0"
 Bundle-ActivationPolicy: lazy
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ComputedValueLimitationTest.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ComputedValueLimitationTest.java
index 4b32d16..cec0111 100644
--- a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ComputedValueLimitationTest.java
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ComputedValueLimitationTest.java
@@ -15,7 +15,7 @@
 import junit.framework.TestSuite;
 
 import org.eclipse.e4.core.services.context.EclipseContextFactory;
-import org.eclipse.e4.core.services.context.IComputedValue;
+import org.eclipse.e4.core.services.context.IContextFunction;
 import org.eclipse.e4.core.services.context.IEclipseContext;
 import org.eclipse.e4.core.services.context.spi.ContextInjectionFactory;
 
@@ -64,7 +64,7 @@
 		}
 	}
 	
-	public class CalcColor implements IComputedValue {
+	public class CalcColor implements IContextFunction {
 
 		public Object compute(IEclipseContext context, Object[] arguments) {
 			int useArg = ExtenralFactor.useChild();
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ContextExample.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ContextExample.java
new file mode 100644
index 0000000..6f83d6a
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ContextExample.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.text.NumberFormat;
+
+import org.eclipse.e4.core.services.context.*;
+import org.eclipse.e4.core.services.context.spi.ContextInjectionFactory;
+import org.eclipse.e4.core.tests.services.TestActivator;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ *
+ */
+public class ContextExample {
+	class Crayon {
+		@In
+		IPaletteService pallete;
+		public void draw() {
+			if (pallete == null)
+				System.out.println("No palette");
+			else
+				System.out.println("My pen is:  " + pallete.getColor());
+		}
+	}
+	static enum Color {
+		RED, BLUE, YELLOW, GREEN, ORANGE, PURPLE;
+	}
+	
+	interface IPaletteService {
+		public Color getColor();
+	}
+	class PaletteImpl implements IPaletteService{
+		private final Color color;
+		PaletteImpl(Color color) {
+			this.color = color;
+		}
+		public Color getColor() {
+			return color;
+		}
+	}
+
+	static class ComplementaryColor implements IContextFunction {
+		public Object compute(IEclipseContext context, Object[] arguments) {
+			switch ((Color) context.get("color")) {
+				case RED :
+					return Color.GREEN;
+				case GREEN :
+					return Color.RED;
+				case BLUE :
+					return Color.ORANGE;
+				case ORANGE :
+					return Color.BLUE;
+				case YELLOW :
+					return Color.PURPLE;
+				case PURPLE :
+					return Color.YELLOW;
+				default :
+					return null;
+			}
+		}
+	}
+
+	static class ResourceSelection implements IContextFunction {
+		public Object compute(IEclipseContext context, Object[] arguments) {
+			return null;
+		}
+	}
+
+	public static void main(String[] arguments) {
+		new ContextExample().price();
+	}
+
+	/**
+	 * 
+	 */
+	public void run() {
+		IEclipseContext parent = EclipseContextFactory.create();
+		parent.set("complement", new ComplementaryColor());
+		IEclipseContext context = EclipseContextFactory.create(parent, null);
+		context.set("color", Color.YELLOW);
+		Crayon crayon = new Crayon();
+		ContextInjectionFactory.inject(crayon, context);
+		crayon.draw();
+	}
+	
+	public void runWithService() {
+		ServiceRegistration reg = TestActivator.bundleContext.registerService(IPaletteService.class.getName(), new PaletteImpl(Color.BLUE), null);
+		IEclipseContext context = EclipseContextFactory.createServiceContext(TestActivator.bundleContext);
+		Crayon crayon = new Crayon();
+		ContextInjectionFactory.inject(crayon, context);
+		crayon.draw();
+		reg.unregister();
+		crayon.draw();
+		
+
+	}
+
+	public void run2() {
+		IEclipseContext parent = EclipseContextFactory.create();
+		parent.set("complement", new ComplementaryColor());
+		IEclipseContext child = EclipseContextFactory.create(parent, null);
+		child.set("color", Color.RED);
+		System.out.println(child.get("color"));
+		System.out.println(child.get("complement"));
+
+	}
+	public void run3() {
+//		IEclipseContext context = EclipseContextFactory.create();
+//		Object[] args = new Object[] {IResource.class};
+//		IResource[] resources = context.get("Selection", args);
+	}
+	double total = 0;
+	public void price() {
+		final IEclipseContext context = EclipseContextFactory.create();
+		context.set("price", 19.99);
+		context.set("tax", 0.05);
+		context.runAndTrack(new Runnable(){
+			public void run() {
+				total = (Double)context.get("price") * (1.0 + (Double)context.get("tax"));
+			}
+		}, "calculator");
+		print(total);
+		context.set("tax", 0.07);
+		print(total);
+	}
+
+	private void print(double price) {
+		System.out.println(NumberFormat.getCurrencyInstance().format(price));
+	}
+}
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/EclipseContextTest.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/EclipseContextTest.java
index 275db29..9cc3558 100644
--- a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/EclipseContextTest.java
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/EclipseContextTest.java
@@ -17,13 +17,13 @@
 
 public class EclipseContextTest extends TestCase {
 
-	private static class ComputedValueBar implements IComputedValue {
+	private static class ComputedValueBar implements IContextFunction {
 		public Object compute(IEclipseContext context, Object[] arguments) {
 			return context.get("bar");
 		}
 	}
 
-	private static class ConcatFunction implements IComputedValue {
+	private static class ConcatFunction implements IContextFunction {
 		public Object compute(IEclipseContext context, Object[] arguments) {
 			String separator = (String) context.get("separator");
 			StringBuffer result = new StringBuffer();
@@ -122,7 +122,7 @@
 		context.remove("foo");
 		assertEquals(3, runCounter);
 		assertEquals(null, value[0]);
-		context.set("foo", new IComputedValue() {
+		context.set("foo", new IContextFunction() {
 			public Object compute(IEclipseContext context, Object[] arguments) {
 				return context.get("bar");
 			}
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/In.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/In.java
new file mode 100644
index 0000000..b79fce2
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/In.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD })
+public @interface In {
+
+	boolean optional() default false;
+
+}
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/Out.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/Out.java
new file mode 100644
index 0000000..922415f
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/Out.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD })
+public @interface Out {
+
+	boolean optional() default false;
+
+}
diff --git a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServiceContextTest.java b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServiceContextTest.java
index bfe832e..fe41b26 100644
--- a/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServiceContextTest.java
+++ b/tests/org.eclipse.e4.core.tests.services/src/org/eclipse/e4/core/services/internal/context/ServiceContextTest.java
@@ -11,15 +11,14 @@
 
 package org.eclipse.e4.core.services.internal.context;
 
-import org.eclipse.e4.core.services.context.spi.IContextConstants;
-
 import junit.framework.TestCase;
 import org.eclipse.e4.core.services.IDisposable;
 import org.eclipse.e4.core.services.context.EclipseContextFactory;
 import org.eclipse.e4.core.services.context.IEclipseContext;
 import org.eclipse.e4.core.services.context.spi.ContextInjectionFactory;
-import org.eclipse.e4.core.services.osgi.IServiceAliasRegistry;
+import org.eclipse.e4.core.services.context.spi.IContextConstants;
 import org.eclipse.e4.core.tests.services.TestActivator;
+import org.eclipse.osgi.service.debug.DebugOptions;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 
@@ -27,12 +26,39 @@
  * Tests for contexts used in OSGi services.
  */
 public class ServiceContextTest extends TestCase {
+	class Crayon {
+		@In
+		IPaletteService palette;
+		public void draw() {
+			if (palette == null)
+				System.out.println("I'm out of ink!");
+			else
+				System.out.println("My ink is  " + palette.getColor());
+		}
+	}
+	static enum Color {
+		RED, BLUE, YELLOW, GREEN, ORANGE, PURPLE;
+	}
+	
+	interface IPaletteService {
+		public Color getColor();
+	}
+	class PaletteImpl implements IPaletteService{
+		private final Color color;
+		PaletteImpl(Color color) {
+			this.color = color;
+		}
+		public Color getColor() {
+			return color;
+		}
+	}
 	static class Printer {
-		PrintService di_Printer;
+		@Inject
+		PrintService printer;
 
 		public void print(String message) {
-			if (di_Printer != null)
-				di_Printer.print(message);
+			if (printer != null)
+				printer.print(message);
 			else
 				System.out.println(message);
 		}
@@ -44,12 +70,10 @@
 	protected void setUp() throws Exception {
 		super.setUp();
 		context = EclipseContextFactory.createServiceContext(TestActivator.bundleContext);
-		((IServiceAliasRegistry) context.get(IServiceAliasRegistry.SERVICE_NAME)).registerAlias("Printer", PrintService.SERVICE_NAME);
 	}
 	
 	@Override
 	protected void tearDown() throws Exception {
-		((IServiceAliasRegistry) context.get(IServiceAliasRegistry.SERVICE_NAME)).unregisterAlias("Printer");
 		if (context instanceof IDisposable) 
 			((IDisposable)context).dispose();
 		super.tearDown();
@@ -61,7 +85,7 @@
 	public void testServiceContextAsParent() {
 		IEclipseContext child = EclipseContextFactory.create(context, null);
 		child.set(IContextConstants.DEBUG_STRING, "child");
-		IServiceAliasRegistry service = (IServiceAliasRegistry) child.get(IServiceAliasRegistry.SERVICE_NAME);
+		DebugOptions service = (DebugOptions) child.get(DebugOptions.class.getName());
 		assertNotNull(service);
 	}
 	
@@ -80,7 +104,7 @@
 		userObject.print("another test");
 		//the string should be unchanged
 		assertEquals("1.1", "test", stringPrint1.toString());
-		assertNull("1.2", userObject.di_Printer);
+		assertNull("1.2", userObject.printer);
 
 		//register a different service implementation
 		StringPrintService stringPrint2 = new StringPrintService();
@@ -90,7 +114,7 @@
 		assertEquals("2.0", "test", stringPrint1.toString());
 		assertEquals("2.1", "yet another test", stringPrint2.toString());
 		reg2.unregister();
-		assertNull("2.2", userObject.di_Printer);
+		assertNull("2.2", userObject.printer);
 	}
 	
 	/**
@@ -109,6 +133,16 @@
 		assertNull("2.0", ref.getUsingBundles());
 		reg1.unregister();
 	}
+	
+	public void testServiceExample() {
+		ServiceRegistration reg = TestActivator.bundleContext.registerService(IPaletteService.class.getName(), new PaletteImpl(Color.BLUE), null);
+		IEclipseContext context = EclipseContextFactory.createServiceContext(TestActivator.bundleContext);
+		Crayon crayon = new Crayon();
+		ContextInjectionFactory.inject(crayon, context);
+		crayon.draw();
+		reg.unregister();
+		crayon.draw();
+	}
 
 	/**
 	 * Tests that OSGi services are released when the context that requested
@@ -132,7 +166,7 @@
 		System.runFinalization();
 		System.gc();
 		//must call a method on context to give it a chance to clean up its references
-		assertTrue("2.0", context.containsKey(IServiceAliasRegistry.SERVICE_NAME));
+		assertTrue("2.0", context.containsKey(DebugOptions.class.getName()));
 		assertNull("2.1", ref.getUsingBundles());
 		
 		reg1.unregister();
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 5e68a4c..61f2cd1 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
@@ -15,7 +15,7 @@
 import junit.framework.TestSuite;
 
 /**
- *
+ * Runs all e4 core service tests.
  */
 public class ServicesTestSuite extends TestSuite {
 	public static Test suite() {