FELIX-3657 problem 3, remove component instance from dependency manager and make service changes apply to all instances managed by a ServiceFactoryComponentManager
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1381866 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 106a997..9ad7321 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -854,6 +854,12 @@
}
}
+ abstract void update( DependencyManager dependencyManager, ServiceReference ref );
+
+ abstract void invokeBindMethod( DependencyManager dependencyManager, ServiceReference reference );
+
+ abstract void invokeUnbindMethod( DependencyManager dependencyManager, ServiceReference oldRef );
+
public static class RefPair
{
private final ServiceReference ref;
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index eac74f9..4636809 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -34,6 +34,7 @@
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentException;
import org.osgi.service.component.ComponentFactory;
@@ -274,6 +275,21 @@
return true;
}
+ void update( DependencyManager dependencyManager, ServiceReference ref )
+ {
+ throw new IllegalStateException( "Should not be called" );
+ }
+
+ void invokeBindMethod( DependencyManager dependencyManager, ServiceReference reference )
+ {
+ throw new IllegalStateException( "Should not be called" );
+ }
+
+ void invokeUnbindMethod( DependencyManager dependencyManager, ServiceReference oldRef )
+ {
+ throw new IllegalStateException( "Should not be called" );
+ }
+
//---------- Component interface
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index a6cd92c..6c5e195 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -21,7 +21,6 @@
import java.security.Permission;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
@@ -68,9 +67,6 @@
// the number of matching services registered in the system
private volatile int m_size;
- // the object on which the bind/undind methods are to be called
- private volatile Object m_componentInstance;
-
// the bind method
private volatile BindMethod m_bind;
@@ -220,7 +216,7 @@
else
{
// update the service binding due to the new properties
- update( ref );
+ m_componentManager.update( this, ref );
}
break;
@@ -356,7 +352,7 @@
if ( m_dependencyMetadata.isMultiple() || !isBound() )
{
// bind the service, getting it if required
- invokeBindMethod( reference );
+ m_componentManager.invokeBindMethod( this, reference );
}
else if ( !isReluctant() )
{
@@ -365,8 +361,8 @@
ServiceReference oldRef = ( ServiceReference ) bound.keySet().iterator().next();
if ( reference.compareTo( oldRef ) > 0 )
{
- invokeBindMethod( reference );
- invokeUnbindMethod( oldRef );
+ m_componentManager.invokeBindMethod( this, reference );
+ m_componentManager.invokeUnbindMethod( this, oldRef );
}
}
}
@@ -477,14 +473,14 @@
}
else
{
- invokeBindMethod( ref );
+ m_componentManager.invokeBindMethod( this, ref );
}
}
// call the unbind method if one is defined
if ( m_dependencyMetadata.getUnbind() != null )
{
- invokeUnbindMethod( reference );
+ m_componentManager.invokeUnbindMethod( this, reference );
}
// make sure the service is returned
@@ -983,27 +979,20 @@
}
- boolean open( Object instance, Map parameters )
+ boolean open( Object componentInstance, Map parameters )
{
- m_componentInstance = instance;
- return bind(parameters);
+ return bind( componentInstance, parameters);
}
/**
* Revoke all bindings. This method cannot throw an exception since it must
* try to complete all that it can
+ * @param componentInstance
*/
- void close( )
+ void close( Object componentInstance )
{
- try
- {
- unbind( getBoundServiceReferences() );
- }
- finally
- {
- m_componentInstance = null;
- }
+ unbind( componentInstance, getBoundServiceReferences() );
}
//returns Map<ServiceReference, Object[]>
@@ -1082,7 +1071,7 @@
* @return true if the dependency is satisfied and at least the minimum
* number of services could be bound. Otherwise false is returned.
*/
- private boolean bind( Map parameters )
+ private boolean bind( Object componentInstance, Map parameters )
{
// If no references were received, we have to check if the dependency
// is optional, if it is not then the dependency is invalid
@@ -1096,7 +1085,7 @@
// if no bind method is configured or if this is a delayed component,
// we have nothing to do and just signal success
- if ( m_componentInstance == null || m_dependencyMetadata.getBind() == null )
+ if ( componentInstance == null || m_dependencyMetadata.getBind() == null )
{
return true;
}
@@ -1113,7 +1102,7 @@
for ( Iterator i = parameters.entrySet().iterator(); i.hasNext(); )
{
Map.Entry entry = ( Map.Entry ) i.next();
- if ( invokeBindMethod( ( AbstractComponentManager.RefPair ) entry.getValue() ) )
+ if ( invokeBindMethod( componentInstance, ( AbstractComponentManager.RefPair ) entry.getValue() ) )
{
success = true;
}
@@ -1132,18 +1121,18 @@
/**
* Handles an update in the service reference properties of a bound service.
* <p>
- * This just calls the {@link #invokeUpdatedMethod(ServiceReference)}
+ * This just calls the {@link #invokeUpdatedMethod(Object, org.osgi.framework.ServiceReference)}
* method if the method has been configured in the component metadata. If
* the method is not configured, this method does nothing.
*
+ * @param componentInstance
* @param ref The <code>ServiceReference</code> representing the updated
- * service.
*/
- private void update( final ServiceReference ref )
+ void update( Object componentInstance, final ServiceReference ref )
{
if ( m_dependencyMetadata.getUpdated() != null )
{
- invokeUpdatedMethod( ref );
+ invokeUpdatedMethod( componentInstance, ref );
}
}
@@ -1152,19 +1141,19 @@
* Revoke the given bindings. This method cannot throw an exception since
* it must try to complete all that it can
*/
- private void unbind( ServiceReference[] boundRefs )
+ private void unbind( Object componentInstance, ServiceReference[] boundRefs )
{
if ( boundRefs != null )
{
// only invoke the unbind method if there is an instance (might be null
// in the delayed component situation) and the unbind method is declared.
- boolean doUnbind = m_componentInstance != null && m_dependencyMetadata.getUnbind() != null;
+ boolean doUnbind = componentInstance != null && m_dependencyMetadata.getUnbind() != null;
for ( int i = 0; i < boundRefs.length; i++ )
{
if ( doUnbind )
{
- invokeUnbindMethod( boundRefs[i] );
+ invokeUnbindMethod( componentInstance, boundRefs[i] );
}
// unget the service, we call it here since there might be a
@@ -1176,10 +1165,10 @@
}
}
- private boolean invokeBindMethod( ServiceReference ref )
+ boolean invokeBindMethod( Object componentInstance, ServiceReference ref )
{
//event driven, and we already checked this ref is not yet handled.
- if ( m_componentInstance != null )
+ if ( componentInstance != null )
{
Map dependencyMap = m_componentManager.getDependencyMap();
if ( dependencyMap != null )
@@ -1196,7 +1185,7 @@
BundleContext bundleContext = m_componentManager.getActivator().getBundleContext();
AbstractComponentManager.RefPair refPair = m_bind.getServiceObject( ref, bundleContext );
deps.put( ref, refPair );
- return invokeBindMethod( refPair );
+ return invokeBindMethod( componentInstance, refPair );
}
return false;
}
@@ -1217,6 +1206,8 @@
* If the reference is singular and a service has already been bound to the
* component this method has no effect and just returns <code>true</code>.
*
+ *
+ * @param componentInstance
* @param refPair the service reference, service object tuple.
*
* @return true if the service should be considered bound. If no bind
@@ -1225,15 +1216,15 @@
* be handed over to the bind method but the service cannot be
* retrieved using the service reference.
*/
- private boolean invokeBindMethod( AbstractComponentManager.RefPair refPair )
+ private boolean invokeBindMethod( Object componentInstance, AbstractComponentManager.RefPair refPair )
{
// The bind method is only invoked if the implementation object is not
// null. This is valid for both immediate and delayed components
- if( m_componentInstance != null )
+ if( componentInstance != null )
{
if ( m_bind != null )
{
- MethodResult result = m_bind.invoke( m_componentInstance, refPair, MethodResult.VOID );
+ MethodResult result = m_bind.invoke( componentInstance, refPair, MethodResult.VOID );
if ( result == null )
{
return false;
@@ -1263,17 +1254,17 @@
/**
* Calls the updated method.
*
+ * @param componentInstance
* @param ref A service reference corresponding to the service whose service
- * registration properties have been updated
*/
- private void invokeUpdatedMethod( final ServiceReference ref )
+ private void invokeUpdatedMethod( Object componentInstance, final ServiceReference ref )
{
// The updated method is only invoked if the implementation object is not
// null. This is valid for both immediate and delayed components
- if ( m_componentInstance != null )
+ if ( componentInstance != null )
{
AbstractComponentManager.RefPair refPair = ( AbstractComponentManager.RefPair ) ((Map )m_componentManager.getDependencyMap().get( this )).get( ref );
- MethodResult methodResult = m_updated.invoke( m_componentInstance, refPair, MethodResult.VOID );
+ MethodResult methodResult = m_updated.invoke( componentInstance, refPair, MethodResult.VOID );
if ( methodResult != null)
{
m_componentManager.setServiceProperties( methodResult );
@@ -1297,17 +1288,17 @@
* to the component this method has no effect and just returns
* <code>true</code>.
*
+ * @param componentInstance
* @param ref A service reference corresponding to the service that will be
- * unbound
*/
- private void invokeUnbindMethod( final ServiceReference ref )
+ void invokeUnbindMethod( Object componentInstance, final ServiceReference ref )
{
// The unbind method is only invoked if the implementation object is not
// null. This is valid for both immediate and delayed components
- if ( m_componentInstance != null )
+ if ( componentInstance != null )
{
AbstractComponentManager.RefPair refPair = ( AbstractComponentManager.RefPair ) ((Map )m_componentManager.getDependencyMap().get( this )).get( ref );
- MethodResult methodResult = m_unbind.invoke( m_componentInstance, refPair, MethodResult.VOID );
+ MethodResult methodResult = m_unbind.invoke( componentInstance, refPair, MethodResult.VOID );
if ( methodResult != null )
{
m_componentManager.setServiceProperties( methodResult );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index 1c2c93a..cab784d 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -36,6 +36,7 @@
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentContext;
@@ -225,7 +226,7 @@
while ( it.hasNext() )
{
dm = ( DependencyManager ) it.next();
- dm.close();
+ dm.close( implementationObject );
}
return null;
@@ -250,7 +251,7 @@
while ( it.hasNext() )
{
DependencyManager dm = ( DependencyManager ) it.next();
- dm.close();
+ dm.close( implementationObject );
}
return null;
@@ -291,7 +292,7 @@
while ( it.hasNext() )
{
DependencyManager dm = ( DependencyManager ) it.next();
- dm.close();
+ dm.close( implementationObject );
}
// 3. Release all references
@@ -308,6 +309,21 @@
return Active.getInstance();
}
+ void update( DependencyManager dependencyManager, ServiceReference ref )
+ {
+ dependencyManager.update( m_implementationObject, ref );
+ }
+
+ void invokeBindMethod( DependencyManager dependencyManager, ServiceReference reference )
+ {
+ dependencyManager.invokeBindMethod( m_implementationObject, reference);
+ }
+
+ void invokeUnbindMethod( DependencyManager dependencyManager, ServiceReference oldRef )
+ {
+ dependencyManager.invokeUnbindMethod( m_implementationObject, oldRef);
+ }
+
protected void setFactoryProperties( Dictionary dictionary )
{
m_factoryProperties = copyTo( null, dictionary );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
index 514e501..063fd33 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
@@ -20,11 +20,13 @@
import java.util.IdentityHashMap;
+import java.util.Iterator;
import org.apache.felix.scr.impl.BundleComponentActivator;
import org.apache.felix.scr.impl.config.ComponentHolder;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentContext;
@@ -193,6 +195,33 @@
}
}
+ void update( DependencyManager dependencyManager, ServiceReference ref )
+ {
+ for ( Iterator it = serviceContexts.keySet().iterator(); it.hasNext(); )
+ {
+ Object implementationObject = it.next();
+ dependencyManager.update( implementationObject, ref );
+ }
+ }
+
+ void invokeBindMethod( DependencyManager dependencyManager, ServiceReference reference )
+ {
+ for ( Iterator it = serviceContexts.keySet().iterator(); it.hasNext(); )
+ {
+ Object implementationObject = it.next();
+ dependencyManager.invokeBindMethod( implementationObject, reference);
+ }
+ }
+
+ void invokeUnbindMethod( DependencyManager dependencyManager, ServiceReference oldRef )
+ {
+ for ( Iterator it = serviceContexts.keySet().iterator(); it.hasNext(); )
+ {
+ Object implementationObject = it.next();
+ dependencyManager.invokeUnbindMethod( implementationObject, oldRef);
+ }
+ }
+
//---------- Component interface
public ComponentInstance getComponentInstance()