Author: fmeschbe
Date: Wed Apr 25 16:07:17 2012
New Revision: 1330377

URL: http://svn.apache.org/viewvc?rev=1330377&view=rev
Log:
FELIX-3480 Make sure events from configurations during service registration can 
also be dispatched to synchronous configuration listeners.

Added:
    
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/SynchronousTestListener.java
    
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/TestListener.java
Modified:
    
felix/sandbox/fmeschbe/configadmin-R5/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
    
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
    
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.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=1330377&r1=1330376&r2=1330377&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 16:07:17 2012
@@ -719,7 +719,38 @@ public class ConfigurationManager implem
     private ServiceReference getServiceReference()
     {
         ServiceRegistration reg = configurationAdminRegistration;
-        return ( reg != null ) ? reg.getReference() : null;
+        if (reg != null) {
+            return reg.getReference();
+        }
+
+        // probably called for firing an event during service registration
+        // since we didn't get the service registration yet we use the
+        // service registry to get our service reference
+        BundleContext context = bundleContext;
+        if ( context != null )
+        {
+            try
+            {
+                ServiceReference[] refs = context.getServiceReferences( 
ConfigurationAdmin.class.getName(), null );
+                if ( refs != null )
+                {
+                    for ( int i = 0; i < refs.length; i++ )
+                    {
+                        if ( refs[i].getBundle().getBundleId() == 
context.getBundle().getBundleId() )
+                        {
+                            return refs[i];
+                        }
+                    }
+                }
+            }
+            catch ( InvalidSyntaxException e )
+            {
+                // unexpected since there is no filter
+            }
+        }
+
+        // service references
+        return null;
     }
 
 
@@ -1910,6 +1941,7 @@ public class ConfigurationManager implem
 
         private final Bundle[] listenerProvider;
 
+        private ConfigurationEvent event;
 
         private FireConfigurationEvent( final int type, final String pid, 
final String factoryPid)
         {
@@ -1940,15 +1972,13 @@ public class ConfigurationManager implem
 
         void fireSynchronousEvents()
         {
-            if ( hasConfigurationEventListeners() )
+            if ( hasConfigurationEventListeners() && getServiceReference() != 
null )
             {
-                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 );
+                        sendEvent( i );
                     }
                 }
             }
@@ -1979,37 +2009,39 @@ public class ConfigurationManager implem
 
         public void run()
         {
-            final String typeName = getTypeName();
-            final ConfigurationEvent event = createEvent();
-
             for ( int i = 0; i < listeners.length; i++ )
             {
-                sendEvent( typeName, i, event );
+                sendEvent( i );
             }
         }
 
+
         public String toString()
         {
             return "Fire ConfigurationEvent: pid=" + pid;
         }
 
 
-        private ConfigurationEvent createEvent()
+        private ConfigurationEvent getConfigurationEvent()
         {
-            return new ConfigurationEvent( getServiceReference(), type, 
factoryPid, pid );
+            if ( event == null )
+            {
+                this.event = new ConfigurationEvent( getServiceReference(), 
type, factoryPid, pid );
+            }
+            return event;
         }
 
 
-        private void sendEvent( final String typeName, final int serviceIndex, 
final ConfigurationEvent event )
+        private void sendEvent( final int serviceIndex )
         {
             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] ) } );
+                    { getTypeName(), pid, ConfigurationManager.toString( 
listenerReferences[serviceIndex] ) } );
 
                 try
                 {
-                    listeners[serviceIndex].configurationEvent( event );
+                    listeners[serviceIndex].configurationEvent( 
getConfigurationEvent() );
                 }
                 catch ( Throwable t )
                 {

Modified: 
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=1330377&r1=1330376&r2=1330377&view=diff
==============================================================================
--- 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
 (original)
+++ 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/ConfigurationListenerTest.java
 Wed Apr 25 16:07:17 2012
@@ -22,8 +22,8 @@ package org.apache.felix.cm.integration;
 import java.io.IOException;
 import java.util.Hashtable;
 
-import junit.framework.TestCase;
-
+import org.apache.felix.cm.integration.helper.SynchronousTestListener;
+import org.apache.felix.cm.integration.helper.TestListener;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
@@ -31,7 +31,6 @@ import org.osgi.framework.ServiceRegistr
 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)
@@ -170,92 +169,4 @@ public class ConfigurationListenerTest e
             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
-    {
-    }
 }

Modified: 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java?rev=1330377&r1=1330376&r2=1330377&view=diff
==============================================================================
--- 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java
 (original)
+++ 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/FELIX2813_ConfigurationAdminStartupTest.java
 Wed Apr 25 16:07:17 2012
@@ -23,8 +23,9 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
-import junit.framework.TestCase;
 
+import org.apache.felix.cm.integration.helper.SynchronousTestListener;
+import org.apache.felix.cm.integration.helper.TestListener;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
@@ -41,14 +42,9 @@ import org.osgi.service.cm.Configuration
 
 
 @RunWith(JUnit4TestRunner.class)
-public class FELIX2813_ConfigurationAdminStartupTest extends 
ConfigurationTestBase implements ServiceListener,
-    ConfigurationListener
+public class FELIX2813_ConfigurationAdminStartupTest extends 
ConfigurationTestBase implements ServiceListener
 {
 
-    private Object lock = new Object();
-    private boolean eventSeen;
-
-
     @Test
     public void testAddConfigurationWhenConfigurationAdminStarts() throws 
InvalidSyntaxException, BundleException
     {
@@ -64,13 +60,13 @@ public class FELIX2813_ConfigurationAdmi
             }
         }
 
-        bundleContext.registerService( ConfigurationListener.class.getName(), 
this, null );
+        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.addServiceListener( this, "(" + Constants.OBJECTCLASS + 
"=" + ConfigurationAdmin.class.getName()
             + ")" );
 
-        // ensure we do not have a false positive below
-        eventSeen = false;
-
         for ( Bundle bundle : bundles )
         {
             bundle.start();
@@ -97,26 +93,9 @@ public class FELIX2813_ConfigurationAdmi
          * assumed to have failed. This will rather generate false negatives
          * (on slow machines) than false positives.
          */
-        synchronized ( lock )
-        {
-            if ( !eventSeen )
-            {
-                try
-                {
-                    lock.wait( 2000 );
-                }
-                catch ( InterruptedException ie )
-                {
-                    // don't care ...
-                }
-            }
-
-            if ( !eventSeen )
-            {
-                TestCase.fail( "ConfigurationEvent not received within 2 
seconds since bundle start" );
-            }
-        }
-
+        delay();
+        listener.assertEvent( ConfigurationEvent.CM_UPDATED, "test", null, 
true, 1 );
+        syncListener.assertEvent( ConfigurationEvent.CM_UPDATED, "test", null, 
false, 1 );
     }
 
 
@@ -138,17 +117,4 @@ public class FELIX2813_ConfigurationAdmi
             }
         }
     }
-
-
-    public void configurationEvent( ConfigurationEvent event )
-    {
-        if ( "test".equals( event.getPid() ) )
-        {
-            synchronized ( lock )
-            {
-                eventSeen = true;
-                lock.notifyAll();
-            }
-        }
-    }
 }

Added: 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/SynchronousTestListener.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/SynchronousTestListener.java?rev=1330377&view=auto
==============================================================================
--- 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/SynchronousTestListener.java
 (added)
+++ 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/SynchronousTestListener.java
 Wed Apr 25 16:07:17 2012
@@ -0,0 +1,27 @@
+/*
+ * 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.helper;
+
+
+import org.osgi.service.cm.SynchronousConfigurationListener;
+
+
+public class SynchronousTestListener extends TestListener implements 
SynchronousConfigurationListener
+{
+}
\ No newline at end of file

Added: 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/TestListener.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/TestListener.java?rev=1330377&view=auto
==============================================================================
--- 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/TestListener.java
 (added)
+++ 
felix/sandbox/fmeschbe/configadmin-R5/src/test/java/org/apache/felix/cm/integration/helper/TestListener.java
 Wed Apr 25 16:07:17 2012
@@ -0,0 +1,124 @@
+/*
+ * 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.helper;
+
+
+import junit.framework.TestCase;
+
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+
+
+public class TestListener implements ConfigurationListener
+{
+
+    private final Thread mainThread;
+
+    private ConfigurationEvent event;
+
+    private Thread eventThread;
+
+    private int numberOfEvents;
+
+    {
+        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;
+    }
+
+
+    /**
+     * Asserts an expected event has arrived since the last call to
+     * {@link #assertEvent(int, String, String, boolean, int)} and
+     * {@link #assertNoEvent()}.
+     *
+     * @param type The expected event type
+     * @param pid The expected PID of the event
+     * @param factoryPid The expected factory PID of the event or
+     *      <code>null</code> if no factory PID is expected
+     * @param expectAsync Whether the event is expected to have been
+     *      provided asynchronously
+     * @param numberOfEvents The number of events to have arrived in total
+     */
+    public 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;
+        }
+    }
+
+
+    /**
+     * Fails if an event has been received since the last call to
+     * {@link #assertEvent(int, String, String, boolean, int)} or
+     * {@link #assertNoEvent()}.
+     */
+    public void assertNoEvent()
+    {
+        TestCase.assertNull( this.event );
+    }
+}
\ No newline at end of file


Reply via email to