FELIX-3410 Apply patch by David Jencks (thanks) and add
integration test proving functionality
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1344812 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index 29d2945..2bc619f 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -448,8 +448,10 @@
// clear the current properties to force using the configuration data
m_properties = null;
+ // unsatisfied component and non-ignored configuration may change targets
+ // to satisfy references
if ( getState() == STATE_UNSATISFIED && configuration != null
- && getComponentMetadata().isConfigurationRequired() )
+ && !getComponentMetadata().isConfigurationIgnored() )
{
activateInternal();
return;
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
index b589301..309e25c 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
@@ -23,6 +23,7 @@
import org.apache.felix.scr.Component;
import org.apache.felix.scr.integration.components.SimpleComponent;
+import org.apache.felix.scr.integration.components.SimpleServiceImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
@@ -228,6 +229,91 @@
@Test
+ public void test_SimpleComponent_dynamic_configuration_with_required_service()
+ {
+ final String targetProp = "ref.target";
+ final String filterProp = "required";
+ final SimpleServiceImpl service = SimpleServiceImpl.create( bundleContext, "sample" ).setFilterProperty( filterProp );
+ try
+ {
+ final String pid = "DynamicConfigurationComponentWithRequiredReference";
+ final Component component = findComponentByName( pid );
+
+ deleteConfig( pid );
+ delay();
+
+ TestCase.assertNotNull( component );
+ TestCase.assertFalse( component.isDefaultEnabled() );
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ TestCase.assertNull( SimpleComponent.INSTANCE );
+
+ component.enable();
+ delay();
+
+ // mandatory ref missing --> component unsatisfied
+ TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+
+ // dynamically configure without the correct target
+ configure( pid );
+ delay();
+
+ // mandatory ref missing --> component unsatisfied
+ TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+
+ // dynamically configure with correct target
+ theConfig.put( targetProp, "(filterprop=" + filterProp + ")" );
+ configure( pid );
+ delay();
+
+ TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+ TestCase.assertNotNull( SimpleComponent.INSTANCE );
+ TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+ TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+
+ final SimpleComponent instance = SimpleComponent.INSTANCE;
+
+ configure( pid );
+ delay();
+
+ // same instance after reconfiguration
+ TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+ TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+ TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+ TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+
+ // reconfigure without target --> unsatisifed
+ theConfig.remove( targetProp );
+ configure( pid );
+ delay();
+
+ // mandatory ref missing --> component unsatisfied
+ TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+
+ deleteConfig( pid );
+ delay();
+
+ // mandatory ref missing --> component unsatisfied
+ TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+
+ component.disable();
+ delay();
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ TestCase.assertNull( SimpleComponent.INSTANCE );
+ }
+ finally
+ {
+ theConfig.remove( targetProp );
+ if ( service != null )
+ {
+ service.drop();
+ }
+ }
+ }
+
+
+ @Test
public void test_SimpleComponent_factory_configuration()
{
final String factoryPid = "FactoryConfigurationComponent";
@@ -392,10 +478,10 @@
final Component[] threeConfigs21 = findComponentsByName( factoryPid );
TestCase.assertNotNull( threeConfigs21 );
TestCase.assertEquals( 3, threeConfigs21.length );
+ TestCase.assertEquals( 1, SimpleComponent.INSTANCES.size() );
TestCase.assertEquals( Component.STATE_ACTIVE, threeConfigs21[0].getState() );
TestCase.assertEquals( Component.STATE_DISABLED, threeConfigs21[1].getState() );
TestCase.assertEquals( Component.STATE_DISABLED, threeConfigs21[2].getState() );
- TestCase.assertEquals( 1, SimpleComponent.INSTANCES.size() );
TestCase.assertTrue( SimpleComponent.INSTANCES.containsKey( threeConfigs21[0].getId() ) );
TestCase.assertFalse( SimpleComponent.INSTANCES.containsKey( threeConfigs21[1].getId() ) );
TestCase.assertFalse( SimpleComponent.INSTANCES.containsKey( threeConfigs21[2].getId() ) );
diff --git a/scr/src/test/resources/integration_test_simple_components.xml b/scr/src/test/resources/integration_test_simple_components.xml
index d1410cb..e1b710d 100644
--- a/scr/src/test/resources/integration_test_simple_components.xml
+++ b/scr/src/test/resources/integration_test_simple_components.xml
@@ -50,6 +50,22 @@
<property name="service.pid" value="DynamicConfigurationComponent" />
</scr:component>
+ <!-- component dynamically updates configuration with a required reference plus target-->
+ <scr:component name="DynamicConfigurationComponentWithRequiredReference"
+ enabled="false" modified="configure">
+ <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+ <property name="service.pid" value="DynamicConfigurationComponentWithRequiredReference" />
+ <reference
+ name="ref"
+ interface="org.apache.felix.scr.integration.components.SimpleService"
+ cardinality="1..1"
+ policy="dynamic"
+ bind="bindSimpleService"
+ unbind="unbindSimpleService"
+ target="(filterprop=__nothing__)"
+ />
+ </scr:component>
+
<!-- component instances created by factory configuration -->
<scr:component name="FactoryConfigurationComponent"
enabled="false"