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() {