FELIX-374 Register ManagedService on behalf of components to receive Configuration

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@580883 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
index c530daa..3bdd255 100644
--- a/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
@@ -221,7 +221,7 @@
      * method has to actually complete before other actions like bundle stopping
      * may continue.
      */
-    public final void dispose()
+    public void dispose()
     {
         disposeInternal();
     }
diff --git a/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
index 2291a5f..deb3a36 100644
--- a/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
@@ -115,6 +115,11 @@
         // also register with the factory PID
         props.put( Constants.SERVICE_PID, getComponentMetadata().getName() );
 
+        // descriptive service properties
+        props.put( Constants.SERVICE_DESCRIPTION, "ManagedServiceFactory for Factory Component"
+            + getComponentMetadata().getName() );
+        props.put( Constants.SERVICE_VENDOR, "Apache Software Foundation" );
+
         return props;
     }
 
@@ -148,16 +153,10 @@
             // keep a reference for future updates
             m_configuredServices.put( pid, cm );
         }
-        else
+        else if ( cm instanceof ImmediateComponentManager )
         {
-            if ( cm instanceof ImmediateComponentManager )
-            {
-                // inject current configuration before cycling
-                ( ( ImmediateComponentManager ) cm ).setFactoryProperties( configuration );
-            }
-
-            // reconfigure the component
-            cm.reconfigure();
+            // update the configuration as if called as ManagedService
+            ( ( ImmediateComponentManager ) cm ).updated( configuration );
         }
     }
 
diff --git a/scr/src/main/java/org/apache/felix/scr/ComponentRegistry.java b/scr/src/main/java/org/apache/felix/scr/ComponentRegistry.java
index 9591f63..e016856 100644
--- a/scr/src/main/java/org/apache/felix/scr/ComponentRegistry.java
+++ b/scr/src/main/java/org/apache/felix/scr/ComponentRegistry.java
@@ -19,16 +19,11 @@
 package org.apache.felix.scr;
 
 
-import java.util.Dictionary;
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.Map;
 
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationEvent;
-import org.osgi.service.cm.ConfigurationListener;
 import org.osgi.service.component.ComponentException;
 
 
@@ -37,7 +32,7 @@
  *
  * @author fmeschbe
  */
-public class ComponentRegistry implements ConfigurationListener
+public class ComponentRegistry
 {
 
     // Known and registered ComponentManager instances
@@ -54,11 +49,6 @@
     {
         m_componentNames = new HashMap();
         m_componentCounter = -1;
-
-        Dictionary props = new Hashtable();
-        props.put( Constants.SERVICE_DESCRIPTION, "Service Component Configuration Support" );
-        props.put( Constants.SERVICE_VENDOR, "Apache Software Foundation" );
-        registration = context.registerService( ConfigurationListener.class.getName(), this, props );
     }
 
 
@@ -72,19 +62,6 @@
     }
 
 
-    //---------- ConfigurationListener ----------------------------------------
-
-    public void configurationEvent( ConfigurationEvent configEvent )
-    {
-        String pid = configEvent.getPid();
-        ComponentManager cm = getComponent( pid );
-        if ( cm != null )
-        {
-            cm.reconfigure();
-        }
-    }
-
-
     //---------- ComponentManager registration support ------------------------
 
     long createComponentId()
diff --git a/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
index 6102bfe..eb98100 100644
--- a/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
@@ -19,14 +19,15 @@
 package org.apache.felix.scr;
 
 
-import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Dictionary;
+import java.util.Hashtable;
 import java.util.Iterator;
 
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.log.LogService;
@@ -37,7 +38,7 @@
  * implementation object's lifecycle.
  *
  */
-class ImmediateComponentManager extends AbstractComponentManager
+class ImmediateComponentManager extends AbstractComponentManager implements ManagedService
 {
     // the component ID
     private long m_componentId;
@@ -54,6 +55,15 @@
     // the component properties, also used as service properties
     private Dictionary m_properties;
 
+    // the managed service registration object created in the constructor
+    // to receive configuration from the Configuration Admin Service
+    // null, if this is a component created by a component factory
+    private ServiceRegistration m_managedServiceRegistration;
+
+    // the component properties from the Configuration Admin Service
+    // this is null, if none exist or none are provided
+    private Dictionary m_configurationProperties;
+
 
     /**
      * The constructor receives both the activator and the metadata
@@ -66,6 +76,44 @@
         super( activator, metadata );
 
         m_componentId = componentId;
+
+        // only register as ManagedService if not created by a Component Factory
+        if ( !getComponentMetadata().isFactory() )
+        {
+            Dictionary props = new Hashtable();
+            props.put( Constants.SERVICE_PID, getComponentMetadata().getName() );
+            props.put( Constants.SERVICE_DESCRIPTION, "ManagedService for Component "
+                + getComponentMetadata().getName() );
+            props.put( Constants.SERVICE_VENDOR, "Apache Software Foundation" );
+
+            m_managedServiceRegistration = activator.getBundleContext().registerService(
+                ManagedService.class.getName(), this, props );
+        }
+    }
+
+
+    /**
+     * Before doing real disposal, we also have to unregister the managed
+     * service which was registered when the instance was created.
+     */
+    public void dispose()
+    {
+        if ( m_managedServiceRegistration != null )
+        {
+            try
+            {
+                m_managedServiceRegistration.unregister();
+                m_managedServiceRegistration = null;
+            }
+            catch ( Throwable t )
+            {
+                getActivator().log( LogService.LOG_INFO, "Unexpected problem unregistering ManagedService",
+                    getComponentMetadata(), t );
+            }
+        }
+
+        // really dispose off this manager instance
+        super.dispose();
     }
 
 
@@ -295,23 +343,7 @@
             Dictionary props = copyTo( null, getComponentMetadata().getProperties() );
 
             // 2. overlay with Configuration Admin properties
-            ConfigurationAdmin ca = getActivator().getConfigurationAdmin();
-            if ( ca != null )
-            {
-                try
-                {
-                    Configuration cfg = ca.getConfiguration( getComponentMetadata().getName() );
-                    if ( cfg != null )
-                    {
-                        copyTo( props, cfg.getProperties() );
-                    }
-                }
-                catch ( IOException ioe )
-                {
-                    getActivator().log( LogService.LOG_ERROR, "Problem getting Configuration", getComponentMetadata(),
-                        ioe );
-                }
-            }
+            copyTo( props, m_configurationProperties );
 
             // 3. copy any component factory properties, not supported yet
             copyTo( props, m_factoryProperties );
@@ -326,4 +358,27 @@
         return m_properties;
     }
 
+
+    //---------- ManagedService interface
+
+    /**
+     * Called by the Configuration Admin Service to update the component with
+     * Configuration properties.
+     *
+     * @param configuration The configuration properties for the component from
+     *      the Configuration Admin Service or <code>null</code> if there is
+     *      no configuration or if the configuration has just been deleted.
+     */
+    public void updated( Dictionary configuration )
+    {
+        // store the properties
+        m_configurationProperties = configuration;
+
+        // reactivate the component to ensure it is provided with the
+        // configuration data
+        if ( ( getState() & ( STATE_ACTIVE | STATE_FACTORY | STATE_REGISTERED ) ) != 0 )
+        {
+            reactivate();
+        }
+    }
 }