FELIX-1922 test ComponentFactory does not require configuration
FELIX-1942 test ComponentFactory instances are never reactivated

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@890254 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java
index 3eae933..e5ca1c0 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java
@@ -41,6 +41,8 @@
 public class ComponentFactoryTest extends ComponentTestBase
 {
 
+    private static final String PROP_NAME_FACTORY = ComponentTestBase.PROP_NAME + ".factory";
+
     static
     {
         // uncomment to enable debugging of this test class
@@ -76,13 +78,13 @@
         TestCase.assertNotNull( factory );
 
         Hashtable<String, String> props = new Hashtable<String, String>();
-        props.put( PROP_NAME, PROP_NAME );
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
         final ComponentInstance instance = factory.newInstance( props );
         TestCase.assertNotNull( instance );
 
         TestCase.assertNotNull( instance.getInstance() );
         TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
-        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
 
         final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
         TestCase.assertNotNull( instanceMap );
@@ -91,8 +93,30 @@
         final Object instanceManager = getFieldValue( instance, "m_componentManager" );
         TestCase.assertTrue( instanceMap.containsValue( instanceManager ) );
 
+        // check registered components
+        final Component[] allFactoryComponents = findComponentsByName( componentname );
+        TestCase.assertNotNull( allFactoryComponents );
+        TestCase.assertEquals( 2, allFactoryComponents.length );
+        for ( int i = 0; i < allFactoryComponents.length; i++ )
+        {
+            final Component c = allFactoryComponents[i];
+            if ( c.getId() == component.getId() )
+            {
+                TestCase.assertEquals( Component.STATE_FACTORY, c.getState() );
+            }
+            else if ( c.getId() == SimpleComponent.INSTANCE.m_id )
+            {
+                TestCase.assertEquals( Component.STATE_ACTIVE, c.getState() );
+            }
+            else
+            {
+                TestCase.fail( "Unexpected Component " + c );
+            }
+        }
+
         instance.dispose();
         TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
 
         TestCase.assertEquals( 0, instanceMap.size() );
         TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
@@ -129,13 +153,13 @@
         TestCase.assertNotNull( factory );
 
         Hashtable<String, String> props = new Hashtable<String, String>();
-        props.put( PROP_NAME, PROP_NAME );
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
         final ComponentInstance instance = factory.newInstance( props );
         TestCase.assertNotNull( instance );
 
         TestCase.assertNotNull( instance.getInstance() );
         TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
-        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
 
         final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
         TestCase.assertNotNull( instanceMap );
@@ -156,6 +180,7 @@
 
         instance.dispose();
         TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
 
         TestCase.assertEquals( 0, instanceMap.size() );
         TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
@@ -190,13 +215,16 @@
         TestCase.assertNotNull( factory );
 
         Hashtable<String, String> props = new Hashtable<String, String>();
-        props.put( PROP_NAME, PROP_NAME );
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
         props.put( SimpleComponent.PROP_ACTIVATE_FAILURE, "Requested Failure" );
-        try {
+        try
+        {
             final ComponentInstance instance = factory.newInstance( props );
             TestCase.assertNotNull( instance );
-            TestCase.fail("Expected newInstance method to fail with ComponentException");
-        } catch (ComponentException ce) {
+            TestCase.fail( "Expected newInstance method to fail with ComponentException" );
+        }
+        catch ( ComponentException ce )
+        {
             // this is expected !
         }
 
@@ -205,4 +233,95 @@
         TestCase.assertTrue( instanceMap.isEmpty() );
         TestCase.assertNull( SimpleComponent.INSTANCE );
     }
+
+
+    @Test
+    public void test_component_factory_require_configuration() throws InvalidSyntaxException
+    {
+        final String componentname = "factory.component.configuration";
+        final String componentfactory = "factory.component.factory.configuration";
+
+        // ensure there is no configuration for the component
+        deleteConfig( componentname );
+        delay();
+
+        final Component component = findComponentByName( componentname );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // supply configuration now and ensure active
+        configure( componentname );
+        delay();
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // ensure component factory still active if config is deleted
+        deleteConfig( componentname );
+        delay();
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // supply configuration now and ensure active
+        configure( componentname );
+        delay();
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // get the component factory service
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        // create an instance
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        final Object instanceObject = instance.getInstance();
+        TestCase.assertNotNull( instanceObject );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instanceObject );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
+        TestCase.assertNotNull( instanceMap );
+        TestCase.assertEquals( 1, instanceMap.size() );
+
+        final Object instanceManager = getFieldValue( instance, "m_componentManager" );
+        TestCase.assertTrue( instanceMap.containsValue( instanceManager ) );
+
+        // delete config, ensure factory still active and component instance, not changed
+        deleteConfig( componentname );
+        delay();
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
+        TestCase.assertEquals( instanceObject, instance.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE ); // component is deactivated
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+
+        // with removal of the factory, the created instance should also be removed
+        TestCase.assertEquals( 0, instanceMap.size() );
+        TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
+    }
+
 }
diff --git a/scr/src/test/resources/integration_test_simple_components.xml b/scr/src/test/resources/integration_test_simple_components.xml
index 25e5c36..c6e90f0 100644
--- a/scr/src/test/resources/integration_test_simple_components.xml
+++ b/scr/src/test/resources/integration_test_simple_components.xml
@@ -88,5 +88,13 @@
         factory="factory.component.factory" >
         <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
     </scr:component>
+    
+    <!-- Component Factory Instances, requiring configuration -->
+    <scr:component name="factory.component.configuration"
+        enabled="false"
+        configuration-policy="require"
+        factory="factory.component.factory.configuration" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+    </scr:component>
 
 </components>