FELIX-3233 Ensure canReceive is called with non-null Bundle argument and log if ServiceReference.getBundle() becomes null before handling the update (this can happen in race-condition situations where the service is unregistered before the update is [asynchronously] processed).
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1203153 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
index 9c0cb74..df05299 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
@@ -1114,7 +1114,7 @@
{
if ( location == null )
{
- log( LogService.LOG_DEBUG, "canReceive=true; bundle={0}; configuration:(unbound)", new Object[]
+ log( LogService.LOG_DEBUG, "canReceive=true; bundle={0}; configuration=(unbound)", new Object[]
{ bundle.getLocation() } );
return true;
}
@@ -1655,18 +1655,27 @@
for ( int i = 0; i < srList.length; i++ )
{
final ServiceReference ref = srList[i];
-
- // CM 1.4 / 104.13.2.2
- if ( !canReceive( ref.getBundle(), configBundleLocation ) )
+ final Bundle refBundle = ref.getBundle();
+ if ( refBundle == null )
{
+ log( LogService.LOG_DEBUG,
+ "Service {0} seems to be unregistered concurrently (not providing configuration)",
+ new Object[]
+ { ConfigurationManager.toString( ref ) } );
+ }
+ else if ( canReceive( refBundle, configBundleLocation ) )
+ {
+ helper.provide( ref );
+ }
+ else
+ {
+ // CM 1.4 / 104.13.2.2
log( LogService.LOG_ERROR,
"Cannot use configuration {0} for {1}: No visibility to configuration bound to {2}",
new Object[]
{ config.getPid(), ConfigurationManager.toString( ref ), configBundleLocation } );
- continue;
}
- helper.provide( ref );
}
}
else if ( isLogEnabled( LogService.LOG_DEBUG ) )
@@ -1721,10 +1730,26 @@
for ( int i = 0; i < srList.length; i++ )
{
final ServiceReference sr = srList[i];
- if ( canReceive( sr.getBundle(), configLocation ) )
+ final Bundle srBundle = sr.getBundle();
+ if ( srBundle == null )
+ {
+ log( LogService.LOG_DEBUG,
+ "Service {0} seems to be unregistered concurrently (not removing configuration)",
+ new Object[]
+ { ConfigurationManager.toString( sr ) } );
+ }
+ else if ( canReceive( srBundle, configLocation ) )
{
helper.remove( sr );
}
+ else
+ {
+ // CM 1.4 / 104.13.2.2
+ log( LogService.LOG_ERROR,
+ "Cannot remove configuration {0} for {1}: No visibility to configuration bound to {2}",
+ new Object[]
+ { config.getPid(), ConfigurationManager.toString( sr ), configLocation } );
+ }
}
}
@@ -1770,15 +1795,29 @@
ServiceReference[] srList = helper.getServices( );
if ( srList != null )
{
- // make sure the config is dynamically bound to the first
- // service if it has been unbound causing this update
- config.tryBindLocation( srList[0].getBundle().getLocation() );
-
for ( int i = 0; i < srList.length; i++ )
{
final ServiceReference sr = srList[i];
- final boolean wasVisible = canReceive( sr.getBundle(), oldLocation );
- final boolean isVisible = canReceive( sr.getBundle(), config.getBundleLocation() );
+
+ final Bundle srBundle = sr.getBundle();
+ if ( srBundle == null )
+ {
+ log( LogService.LOG_DEBUG,
+ "Service {0} seems to be unregistered concurrently (not processing)", new Object[]
+ { ConfigurationManager.toString( sr ) } );
+ continue;
+ }
+
+ final boolean wasVisible = canReceive( srBundle, oldLocation );
+ final boolean isVisible = canReceive( srBundle, config.getBundleLocation() );
+
+ // make sure the config is dynamically bound to the first
+ // service if the config has been unbound causing this update
+ if ( isVisible )
+ {
+ config.tryBindLocation( srBundle.getLocation() );
+ }
+
if ( wasVisible && !isVisible )
{
// call deleted method