FELIX-37000: if configuration policy = require, then wait for configuration availability before registering the 
component factory. Also update target properties when configuration policy and configuration is updated and state is 
disabled or unsatisfied. Updated test accordingly.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1399033 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index 6648abb..5d6c5e4 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -78,8 +78,14 @@
      * supplied as the base configuration for each component instance created
      * by the {@link #newInstance(Dictionary)} method.
      */
-    private Dictionary m_configuration;
-
+    private volatile Dictionary m_configuration;
+    
+    /**
+     * Flag telling if our component factory is configured.
+     * We are configured when configuration policy is required and we have received the
+     * config admin properties, or when configuration policy is optional or ignored.
+     */
+    public volatile boolean m_isConfigured;
 
     public ComponentFactoryImpl( BundleComponentActivator activator, ComponentMetadata metadata )
     {
@@ -205,7 +211,7 @@
 
     public boolean hasConfiguration()
     {
-        return m_configuration != null;
+        return m_isConfigured;
     }
 
 
@@ -322,7 +328,57 @@
     {
         if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
         {
-            m_configuration = configuration;
+            log( LogService.LOG_INFO, "Configuration PID updated for Component Factory", null );
+
+            // Ignore the configuration is our policy is 'ignore'
+            if ( getComponentMetadata().isConfigurationIgnored() )
+            {
+                return;
+            }
+            
+            boolean release = obtainReadLock( "ComponentFactoryImpl.configurationUpdated" );
+            try
+            {
+                // Store the config admin configuration
+                m_configuration = configuration;
+                
+                // We are now configured from config admin.
+                m_isConfigured = true;
+                
+                // if configuration is required and if we not active (that is: either disabled or unsatisfied),
+                // Then we then must activate our dependency target filters.
+                // Please check  AbstractComponentManager.enableDependencyManagers() method, which doesn't set
+                // target filters in case the configuration is required.
+                
+                log( LogService.LOG_INFO, "Current ComponentFactory state={0}", new Object[]
+                    { getState() }, null );
+
+                if ( ( getState() == STATE_DISABLED || getState() == STATE_UNSATISFIED ) && configuration != null
+                    && getComponentMetadata().isConfigurationRequired() )
+                {
+                    // Enable dependency managers, and also update any target filters from config admin. 
+                    log( LogService.LOG_DEBUG, "Updating target filters", null );                    
+                    super.updateTargets( m_configuration ); 
+                }
+                
+                // unsatisfied component and required configuration may change targets
+                // to satisfy references. Or the configuration was just required.
+
+                if ( getState() == STATE_UNSATISFIED && configuration != null
+                    && getComponentMetadata().isConfigurationRequired() )
+                {                   
+                    // try to activate our component factory, if all dependnecies are satisfied
+                    log( LogService.LOG_DEBUG, "Attempting to activate unsatisfied component", null );
+                    activateInternal();
+                }
+            }
+            finally
+            {
+                if (release) 
+                {
+                    releaseReadLock( "ComponentFactoryImpl.configurationUpdated" );
+                }
+            }
         }
         else
         {
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 b7c2dae..05727c1 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
@@ -260,29 +260,25 @@
         component.enable();
         delay();
 
-        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
         TestCase.assertNull( SimpleComponent.INSTANCE );
 
+        // At this point, since we don't have created the configuration, then the ComponentFactory
+        // should not be available.
+        
+        ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNull( refs );
+        
         // supply configuration now and ensure active
         configure( componentname );
-        delay();
-        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
-        TestCase.assertNull( SimpleComponent.INSTANCE );
+        delay();        
 
-        // 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(), "("
+        refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
             + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
         TestCase.assertNotNull( refs );
         TestCase.assertEquals( 1, refs.length );
@@ -299,7 +295,7 @@
         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 ) );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );                        
 
         final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
         TestCase.assertNotNull( instanceMap );
@@ -328,7 +324,6 @@
         TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
     }
 
-
     @Test
     public void test_component_factory_reference() throws InvalidSyntaxException
     {