felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r1330159 - in /felix/sandbox/fmeschbe/configadmin-R5/src: main/java/org/apache/felix/cm/impl/ConfigurationManager.java test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
Date Wed, 25 Apr 2012 08:50:30 GMT
Author: fmeschbe
Date: Wed Apr 25 08:50:30 2012
New Revision: 1330159

URL: http://svn.apache.org/viewvc?rev=1330159&view=rev
Log:
FELIX-3480 Implement support for SynchronousConfigurationListener

Added:
    felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
Modified:
    felix/sandbox/fmeschbe/configadmin-R5/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java

Modified: felix/sandbox/fmeschbe/configadmin-R5/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/fmeschbe/configadmin-R5/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java?rev=1330159&r1=1330158&r2=1330159&view=diff
==============================================================================
--- felix/sandbox/fmeschbe/configadmin-R5/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
(original)
+++ felix/sandbox/fmeschbe/configadmin-R5/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
Wed Apr 25 08:50:30 2012
@@ -635,6 +635,7 @@ public class ConfigurationManager implem
     void fireConfigurationEvent( int type, String pid, String factoryPid )
     {
         FireConfigurationEvent event = new FireConfigurationEvent( type, pid, factoryPid
);
+        event.fireSynchronousEvents();
         if ( event.hasConfigurationEventListeners() )
         {
             eventThread.schedule( event );
@@ -1937,6 +1938,23 @@ public class ConfigurationManager implem
         }
 
 
+        void fireSynchronousEvents()
+        {
+            if ( hasConfigurationEventListeners() )
+            {
+                final String typeName = getTypeName();
+                final ConfigurationEvent event = createEvent();
+                for ( int i = 0; i < this.listeners.length; i++ )
+                {
+                    if ( this.listeners[i] instanceof SynchronousConfigurationListener )
+                    {
+                        sendEvent( typeName, i, event );
+                    }
+                }
+            }
+        }
+
+
         boolean hasConfigurationEventListeners()
         {
             return this.listenerReferences != null;
@@ -1962,26 +1980,11 @@ public class ConfigurationManager implem
         public void run()
         {
             final String typeName = getTypeName();
-            final ConfigurationEvent event = new ConfigurationEvent( getServiceReference(),
type, factoryPid, pid );
+            final ConfigurationEvent event = createEvent();
 
             for ( int i = 0; i < listeners.length; i++ )
             {
-                if ( listenerProvider[i].getState() == Bundle.ACTIVE )
-                {
-                    log( LogService.LOG_DEBUG, "Sending {0} event for {1} to {2}", new Object[]
-                        { typeName, pid, ConfigurationManager.toString( listenerReferences[i]
) } );
-
-                    try
-                    {
-                        listeners[i].configurationEvent( event );
-                    }
-                    catch ( Throwable t )
-                    {
-                        log( LogService.LOG_ERROR, "Unexpected problem delivering configuration
event to {0}",
-                            new Object[]
-                                { ConfigurationManager.toString( listenerReferences[i] ),
t } );
-                    }
-                }
+                sendEvent( typeName, i, event );
             }
         }
 
@@ -1989,6 +1992,36 @@ public class ConfigurationManager implem
         {
             return "Fire ConfigurationEvent: pid=" + pid;
         }
+
+
+        private ConfigurationEvent createEvent()
+        {
+            return new ConfigurationEvent( getServiceReference(), type, factoryPid, pid );
+        }
+
+
+        private void sendEvent( final String typeName, final int serviceIndex, final ConfigurationEvent
event )
+        {
+            if ( listenerProvider[serviceIndex].getState() == Bundle.ACTIVE && this.listeners[serviceIndex]
!= null )
+            {
+                log( LogService.LOG_DEBUG, "Sending {0} event for {1} to {2}", new Object[]
+                    { typeName, pid, ConfigurationManager.toString( listenerReferences[serviceIndex]
) } );
+
+                try
+                {
+                    listeners[serviceIndex].configurationEvent( event );
+                }
+                catch ( Throwable t )
+                {
+                    log( LogService.LOG_ERROR, "Unexpected problem delivering configuration
event to {0}", new Object[]
+                        { ConfigurationManager.toString( listenerReferences[serviceIndex]
), t } );
+                }
+                finally
+                {
+                    this.listeners[serviceIndex] = null;
+                }
+            }
+        }
     }
 
     private static class ManagedServiceTracker extends ServiceTracker

Added: felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java?rev=1330159&view=auto
==============================================================================
--- felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
(added)
+++ felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
Wed Apr 25 08:50:30 2012
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.cm.integration;
+
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.ServiceRegistration;
+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)
+public class ConfigurationListenerTest extends ConfigurationTestBase
+{
+
+    static
+    {
+        // uncomment to enable debugging of this test class
+        // paxRunnerVmOption = DEBUG_VM_OPTION;
+    }
+
+
+    @Test
+    public void test_async_listener() throws IOException
+    {
+        final String pid = "test_listener";
+        final TestListener testListener = new TestListener();
+        final ServiceRegistration listener = this.bundleContext.registerService( ConfigurationListener.class.getName(),
+            testListener, null );
+        int eventCount = 0;
+
+        Configuration config = configure( pid, null, false );
+        try
+        {
+            delay();
+            testListener.assertNoEvent();
+
+            config.update( new Hashtable<String, Object>()
+            {
+                {
+                    put( "x", "x" );
+                }
+            } );
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, true, ++eventCount
);
+
+            config.update( new Hashtable<String, Object>()
+            {
+                {
+                    put( "x", "x" );
+                }
+            } );
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, true, ++eventCount
);
+
+            config.setBundleLocation( "new_Location" );
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_LOCATION_CHANGED, pid, null,
true, ++eventCount );
+
+            config.update();
+            testListener.assertNoEvent();
+
+            config.delete();
+            config = null;
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_DELETED, pid, null, true, ++eventCount
);
+        }
+        finally
+        {
+            if ( config != null )
+            {
+                try
+                {
+                    config.delete();
+                }
+                catch ( IOException ioe )
+                {
+                    // ignore
+                }
+            }
+
+            listener.unregister();
+        }
+    }
+
+
+    @Test
+    public void test_sync_listener() throws IOException
+    {
+        final String pid = "test_listener";
+        Configuration config = configure( pid, null, false );
+        final TestListener testListener = new SynchronousTestListener();
+        final ServiceRegistration listener = this.bundleContext.registerService( ConfigurationListener.class.getName(),
+            testListener, null );
+        int eventCount = 0;
+        try
+        {
+            delay();
+            testListener.assertNoEvent();
+
+            config.update( new Hashtable<String, Object>()
+            {
+                {
+                    put( "x", "x" );
+                }
+            } );
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, false, ++eventCount
);
+
+            config.update( new Hashtable<String, Object>()
+            {
+                {
+                    put( "x", "x" );
+                }
+            } );
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_UPDATED, pid, null, false, ++eventCount
);
+
+            config.setBundleLocation( "new_Location" );
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_LOCATION_CHANGED, pid, null,
false, ++eventCount );
+
+            config.update();
+            testListener.assertNoEvent();
+
+            config.delete();
+            config = null;
+            delay();
+            testListener.assertEvent( ConfigurationEvent.CM_DELETED, pid, null, false, ++eventCount
);
+        }
+        finally
+        {
+            if ( config != null )
+            {
+                try
+                {
+                    config.delete();
+                }
+                catch ( IOException ioe )
+                {
+                    // ignore
+                }
+            }
+
+            listener.unregister();
+        }
+    }
+
+    private static class TestListener implements ConfigurationListener
+    {
+
+        private final Thread mainThread;
+
+        private ConfigurationEvent event;
+
+        private Thread eventThread;
+
+        private int numberOfEvents;
+
+
+        TestListener()
+        {
+            this.mainThread = Thread.currentThread();
+            this.numberOfEvents = 0;
+        }
+
+
+        public void configurationEvent( final ConfigurationEvent event )
+        {
+            this.numberOfEvents++;
+
+            if ( this.event != null )
+            {
+                throw new IllegalStateException( "Untested event to be replaced: " + this.event.getType()
+ "/"
+                    + this.event.getPid() );
+            }
+
+            this.event = event;
+            this.eventThread = Thread.currentThread();
+        }
+
+
+        void resetNumberOfEvents()
+        {
+            this.numberOfEvents = 0;
+        }
+
+
+        void assertEvent( final int type, final String pid, final String factoryPid, final
boolean expectAsync,
+            final int numberOfEvents )
+        {
+            try
+            {
+                TestCase.assertNotNull( "Expecting an event", this.event );
+                TestCase.assertEquals( "Expecting event type " + type, type, this.event.getType()
);
+                TestCase.assertEquals( "Expecting pid " + pid, pid, this.event.getPid() );
+                if ( factoryPid == null )
+                {
+                    TestCase.assertNull( "Expecting no factoryPid", this.event.getFactoryPid()
);
+                }
+                else
+                {
+                    TestCase.assertEquals( "Expecting factory pid " + factoryPid, factoryPid,
+                        this.event.getFactoryPid() );
+                }
+
+                TestCase.assertEquals( "Expecting " + numberOfEvents + " events", numberOfEvents,
+                    this.numberOfEvents );
+
+                if ( expectAsync )
+                {
+                    TestCase.assertNotSame( "Expecting asynchronous event", this.mainThread,
this.eventThread );
+                }
+                else
+                {
+                    TestCase.assertSame( "Expecting synchronous event", this.mainThread,
this.eventThread );
+                }
+            }
+            finally
+            {
+                this.event = null;
+                this.eventThread = null;
+            }
+        }
+
+
+        void assertNoEvent()
+        {
+            TestCase.assertNull( this.event );
+        }
+    }
+
+    private static class SynchronousTestListener extends TestListener implements SynchronousConfigurationListener
+    {
+    }
+}



Mime
View raw message