You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2011/11/17 12:17:50 UTC

svn commit: r1203153 - in /felix/trunk/configadmin/src: main/java/org/apache/felix/cm/impl/ConfigurationManager.java test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java

Author: fmeschbe
Date: Thu Nov 17 11:17:50 2011
New Revision: 1203153

URL: http://svn.apache.org/viewvc?rev=1203153&view=rev
Log:
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).

Modified:
    felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java

Modified: felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java?rev=1203153&r1=1203152&r2=1203153&view=diff
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java (original)
+++ felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java Thu Nov 17 11:17:50 2011
@@ -1114,7 +1114,7 @@ public class ConfigurationManager implem
     {
         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 @@ public class ConfigurationManager implem
                 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 @@ public class ConfigurationManager implem
                 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 @@ public class ConfigurationManager implem
             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

Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java?rev=1203153&r1=1203152&r2=1203153&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java Thu Nov 17 11:17:50 2011
@@ -82,6 +82,8 @@ public class ConfigurationBindingTest ex
     {
         String pid = "test_configuration_unbound_on_uninstall";
         configure( pid );
+
+        delay(); // for the event to be distributed
         configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
 
         // ensure configuration is unbound