FELIX-3596 ConfigurationEvents should only be synchronously delivered to listeners registered as SynchronousConfigurationEventListener (this is a service interface not a marker interface). Adapted test cases to verify async delivery to SynchronousConfigurationEventListener implementations registered as ConfigurationEventListener services.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1361527 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 9eccab3..b0d1ba4 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
@@ -135,6 +135,9 @@
// the ConfigurationEvent listeners
private ServiceTracker configurationListenerTracker;
+ // the synchronous ConfigurationEvent listeners
+ private ServiceTracker syncConfigurationListenerTracker;
+
// service tracker for managed services
private ManagedServiceTracker managedServiceTracker;
@@ -221,6 +224,9 @@
// configurationlistener support
configurationListenerTracker = new ServiceTracker( bundleContext, ConfigurationListener.class.getName(), null );
configurationListenerTracker.open();
+ syncConfigurationListenerTracker = new ServiceTracker( bundleContext,
+ SynchronousConfigurationListener.class.getName(), null );
+ syncConfigurationListenerTracker.open();
// initialize the asynchonous updater thread
ThreadGroup tg = new ThreadGroup( "Configuration Admin Service" );
@@ -330,6 +336,11 @@
configurationListenerTracker.close();
}
+ if ( syncConfigurationListenerTracker != null )
+ {
+ syncConfigurationListenerTracker.close();
+ }
+
if ( logTracker != null )
{
logTracker.close();
@@ -734,16 +745,32 @@
void fireConfigurationEvent( int type, String pid, String factoryPid )
{
- FireConfigurationEvent event = new FireConfigurationEvent( type, pid, factoryPid );
- event.fireSynchronousEvents();
- if ( event.hasConfigurationEventListeners() )
+ // prevent event senders
+ FireConfigurationEvent asyncSender = new FireConfigurationEvent( this.configurationListenerTracker, type, pid,
+ factoryPid );
+ FireConfigurationEvent syncSender = new FireConfigurationEvent( this.syncConfigurationListenerTracker, type,
+ pid, factoryPid );
+
+ // send synchronous events
+ if ( syncSender.hasConfigurationEventListeners() )
{
- eventThread.schedule( event );
+ syncSender.run();
+ }
+ else
+ {
+ log( LogService.LOG_DEBUG, "No SynchronousConfigurationListeners to send {0} event to.", new Object[]
+ { syncSender.getTypeName() } );
+ }
+
+ // schedule asynchronous events
+ if ( asyncSender.hasConfigurationEventListeners() )
+ {
+ eventThread.schedule( asyncSender );
}
else
{
log( LogService.LOG_DEBUG, "No ConfigurationListeners to send {0} event to.", new Object[]
- { event.getTypeName() } );
+ { asyncSender.getTypeName() } );
}
}
@@ -1890,13 +1917,13 @@
private ConfigurationEvent event;
- private FireConfigurationEvent( final int type, final String pid, final String factoryPid)
+ private FireConfigurationEvent( final ServiceTracker listenerTracker, final int type, final String pid, final String factoryPid)
{
this.type = type;
this.pid = pid;
this.factoryPid = factoryPid;
- final ServiceReference[] srs = configurationListenerTracker.getServiceReferences();
+ final ServiceReference[] srs = listenerTracker.getServiceReferences();
if ( srs == null || srs.length == 0 )
{
this.listenerReferences = null;
@@ -1910,28 +1937,13 @@
this.listenerProvider = new Bundle[srs.length];
for ( int i = 0; i < srs.length; i++ )
{
- this.listeners[i] = ( ConfigurationListener ) configurationListenerTracker.getService( srs[i] );
+ this.listeners[i] = ( ConfigurationListener ) listenerTracker.getService( srs[i] );
this.listenerProvider[i] = srs[i].getBundle();
}
}
}
- void fireSynchronousEvents()
- {
- if ( hasConfigurationEventListeners() && getServiceReference() != null )
- {
- for ( int i = 0; i < this.listeners.length; i++ )
- {
- if ( this.listeners[i] instanceof SynchronousConfigurationListener )
- {
- sendEvent( i );
- }
- }
- }
- }
-
-
boolean hasConfigurationEventListeners()
{
return this.listenerReferences != null;
diff --git a/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java b/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
index 3301a19..4961d00 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
@@ -31,6 +31,7 @@
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.cm.SynchronousConfigurationListener;
@RunWith(JUnit4TestRunner.class)
@@ -113,14 +114,27 @@
{
final String pid = "test_listener";
Configuration config = configure( pid, null, false );
+
+ // Synchronous listener expecting synchronous events being
+ // registered as a SynchronousConfigurationListener
final TestListener testListener = new SynchronousTestListener();
- final ServiceRegistration listener = this.bundleContext.registerService( ConfigurationListener.class.getName(),
- testListener, null );
+ final ServiceRegistration listener = this.bundleContext.registerService(
+ SynchronousConfigurationListener.class.getName(), testListener, null );
+
+ // Synchronous listener expecting asynchronous events being
+ // registered as a regular ConfigurationListener
+ final TestListener testListenerAsync = new SynchronousTestListener();
+ final ServiceRegistration listenerAsync = this.bundleContext.registerService(
+ ConfigurationListener.class.getName(), testListenerAsync, null );
+
int eventCount = 0;
+ int eventCountAsync = 0;
+
try
{
delay();
testListener.assertNoEvent();
+ testListenerAsync.assertNoEvent();
config.update( new Hashtable<String, Object>()
{
@@ -130,6 +144,7 @@
} );
delay();
testListener.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, false, ++eventCount );
+ testListenerAsync.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, true, ++eventCountAsync );
config.update( new Hashtable<String, Object>()
{
@@ -139,18 +154,22 @@
} );
delay();
testListener.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, false, ++eventCount );
+ testListenerAsync.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, true, ++eventCountAsync );
config.setBundleLocation( "new_Location" );
delay();
testListener.assertEvent( ConfigurationEvent.CM_LOCATION_CHANGED, pid, null, false, ++eventCount );
+ testListenerAsync.assertEvent( ConfigurationEvent.CM_LOCATION_CHANGED, pid, null, true, ++eventCountAsync );
config.update();
testListener.assertNoEvent();
+ testListenerAsync.assertNoEvent();
config.delete();
config = null;
delay();
testListener.assertEvent( ConfigurationEvent.CM_DELETED, pid, null, false, ++eventCount );
+ testListenerAsync.assertEvent( ConfigurationEvent.CM_DELETED, pid, null, true, ++eventCountAsync );
}
finally
{
@@ -167,6 +186,7 @@
}
listener.unregister();
+ listenerAsync.unregister();
}
}
}
diff --git a/configadmin/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java b/configadmin/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java
index 988f192..c69e47c 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java
@@ -38,6 +38,7 @@
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.cm.SynchronousConfigurationListener;
@RunWith(JUnit4TestRunner.class)
@@ -62,7 +63,9 @@
final TestListener listener = new TestListener();
bundleContext.registerService( ConfigurationListener.class.getName(), listener, null );
final TestListener syncListener = new SynchronousTestListener();
- bundleContext.registerService( ConfigurationListener.class.getName(), syncListener, null );
+ bundleContext.registerService( SynchronousConfigurationListener.class.getName(), syncListener, null );
+ final TestListener syncListenerAsync = new SynchronousTestListener();
+ bundleContext.registerService( ConfigurationListener.class.getName(), syncListenerAsync, null );
bundleContext.addServiceListener( this, "(" + Constants.OBJECTCLASS + "=" + ConfigurationAdmin.class.getName()
+ ")" );
@@ -95,6 +98,7 @@
delay();
listener.assertEvent( ConfigurationEvent.CM_UPDATED, "test", null, true, 1 );
syncListener.assertEvent( ConfigurationEvent.CM_UPDATED, "test", null, false, 1 );
+ syncListenerAsync.assertEvent( ConfigurationEvent.CM_UPDATED, "test", null, true, 1 );
}