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