FELIX-366 Bound Service Replacement incorrect
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@576795 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/DependencyManager.java
index 5680401..39b9b21 100644
--- a/scr/src/main/java/org/apache/felix/scr/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/DependencyManager.java
@@ -107,6 +107,10 @@
//---------- ServiceListener interface ------------------------------------
+ /**
+ * Called when a registered service changes state. In the case of service
+ * modification the service is assumed to be removed and added again.
+ */
public void serviceChanged( ServiceEvent event )
{
switch ( event.getType() )
@@ -127,6 +131,17 @@
}
+ /**
+ * Called by the {@link #serviceChanged(ServiceEvent)} method if a new
+ * service is registered with the system or if a registered service has been
+ * modified.
+ * <p>
+ * Depending on the component state and dependency configuration, the
+ * component may be activated, re-activated or the service just be provided.
+ *
+ * @param reference The reference to the service newly registered or
+ * modified.
+ */
private void serviceAdded( ServiceReference reference )
{
// if the component is currently unsatisfied, it may become satisfied
@@ -162,6 +177,18 @@
}
+ /**
+ * Called by the {@link #serviceChanged(ServiceEvent)} method if an existing
+ * service is unregistered from the system or if a registered service has
+ * been modified.
+ * <p>
+ * Depending on the component state and dependency configuration, the
+ * component may be deactivated, re-activated, the service just be unbound
+ * with or without a replacement service.
+ *
+ * @param reference The reference to the service unregistering or being
+ * modified.
+ */
private void serviceRemoved( ServiceReference reference )
{
// check whether we are bound to that service, do nothing if not
@@ -214,18 +241,12 @@
// the component instance to unbind/bind services
Object instance = m_componentManager.getInstance();
- // call the unbind method if one is defined
- if ( m_dependencyMetadata.getUnbind() != null )
- {
- invokeUnbindMethod( instance, reference );
- }
-
- // if binding to another service fails for a singleton
- // reference, we have to deactivate the component
+ // try to bind a replacement service first if this is a unary
+ // cardinality reference and a replacement is available.
if ( !m_dependencyMetadata.isMultiple() )
{
- // in the unexpected case that rebinding fails, we will
- // deactivate the component
+ // if the dependency is mandatory and no replacement is
+ // available, bind returns false and we deactivate
if ( !bind( instance ) )
{
m_componentManager.getActivator().log(
@@ -234,9 +255,17 @@
+ m_dependencyMetadata.getName() + "/" + m_dependencyMetadata.getInterface()
+ " not satisfied", m_componentManager.getComponentMetadata(), null );
m_componentManager.deactivate();
-
+
+ // abort here we do not need to do more
+ return;
}
}
+
+ // call the unbind method if one is defined
+ if ( m_dependencyMetadata.getUnbind() != null )
+ {
+ invokeUnbindMethod( instance, reference );
+ }
}
}
}
@@ -254,7 +283,10 @@
//---------- Service tracking support -------------------------------------
/**
- * Stops using this dependency manager
+ * Disposes off this dependency manager by removing as a service listener
+ * and ungetting all services, which are still kept in the list of our
+ * bound services. This list will not be empty if the service lookup
+ * method is used by the component to access the service.
*/
void close()
{
@@ -398,7 +430,20 @@
}
- // TODO
+ /**
+ * Adds the {@link #BOUND_SERVICE_SENTINEL} object as a pseudo service to
+ * the map of bound services. This method allows keeping track of services
+ * which have been bound but not retrieved from the service registry, which
+ * is the case if the bind method is called with a ServiceReference instead
+ * of the service object itself.
+ * <p>
+ * We have to keep track of all services for which we called the bind
+ * method to be able to call the unbind method in case the service is
+ * unregistered.
+ *
+ * @param serviceReference The reference to the service being marked as
+ * bound.
+ */
private void bindService( ServiceReference serviceReference )
{
m_bound.put( serviceReference, BOUND_SERVICE_SENTINEL );