Avoid the architecture service to publish non-service interfaces (FieldInterceptor and MethodInterceptor)
Handle correctly ManagedService configuration deletion.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@645864 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
index ae7fe39..0bb6ab3 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
@@ -24,7 +24,6 @@
 
 import org.apache.felix.ipojo.ConfigurationException;
 import org.apache.felix.ipojo.HandlerFactory;
-import org.apache.felix.ipojo.InstanceManager;
 import org.apache.felix.ipojo.PrimitiveHandler;
 import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
 import org.apache.felix.ipojo.architecture.PropertyDescription;
@@ -57,19 +56,29 @@
     private ProvidedServiceHandler m_providedServiceHandler;
 
     /**
-     * Properties propagated at the last "updated".
+     * Properties propagated during the last instance "update".
      */
-    private Dictionary m_propagated = new Properties();
+    private Dictionary m_propagatedFromInstance = new Properties();
 
     /**
      * Properties to propagate.
      */
     private Dictionary m_toPropagate = new Properties();
+    
+    /**
+     * Properties propagated from the configuration admin.
+     */
+    private Dictionary m_propagatedFromCA;
+    
+    /**
+     * Check if the instance was already reconfigured by the configuration admin.
+     */
+    private boolean m_configurationAlreadyPushed;
 
     /**
      * should the component propagate configuration ?
      */
-    private boolean m_isConfigurable;
+    private boolean m_mustPropagate;
     
     /**
      * Service Registration to publish the service registration.
@@ -174,11 +183,11 @@
         Element[] configurables = confs[0].getElements("Property");
 
         // Check if the component is dynamically configurable
-        m_isConfigurable = false;
+        m_mustPropagate = false;
         String propa = confs[0].getAttribute("propagation");
         if (propa != null && propa.equalsIgnoreCase("true")) {
-            m_isConfigurable = true;
-            m_toPropagate = configuration;
+            m_mustPropagate = true;
+            m_toPropagate = configuration; // Instance configuration to propagate.
         }
         
         // Check if the component support ConfigurationADmin reconfiguration
@@ -219,10 +228,11 @@
 
     /**
       * Stop method.
+      * This method is synchronized to avoid the configuration admin pushing a configuration during the un-registration.
       * Do nothing.
       * @see org.apache.felix.ipojo.Handler#stop()
       */
-    public void stop() {
+    public synchronized void stop() {
         if (m_sr != null) {
             m_sr.unregister();
             m_sr = null;
@@ -231,15 +241,16 @@
 
     /**
      * Start method.
+     * This method is synchronized to avoid the config admin pushing a configuration before ending the method.
      * Propagate properties if the propagation is activated.
      * @see org.apache.felix.ipojo.Handler#start()
      */
-    public void start() {
+    public synchronized void start() {
         // Get the provided service handler :
         m_providedServiceHandler = (ProvidedServiceHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":provides");
 
         // Propagation
-        if (m_isConfigurable) {
+        if (m_mustPropagate) {
             for (int i = 0; i < m_configurableProperties.length; i++) {
                 m_toPropagate.put(m_configurableProperties[i].getName(), m_configurableProperties[i].getValue());
             }
@@ -255,21 +266,21 @@
         }
     }
 
-    /**
-     * Handler state changed.
-     * @param state : the new instance state.
-     * @see org.apache.felix.ipojo.CompositeHandler#stateChanged(int)
-     */
-    public void stateChanged(int state) {
-        if (state == InstanceManager.VALID) {
-            start();
-            return;
-        }
-        if (state == InstanceManager.INVALID) {
-            stop();
-            return;
-        }
-    }
+//    /**
+//     * Handler state changed.
+//     * @param state : the new instance state.
+//     * @see org.apache.felix.ipojo.CompositeHandler#stateChanged(int)
+//     */
+//    public void stateChanged(int state) {
+//        if (state == InstanceManager.VALID) {
+//            start();
+//            return;
+//        }
+//        if (state == InstanceManager.INVALID) {
+//            stop();
+//            return;
+//        }
+//    }
 
     /**
      * Add the given property metadata to the property metadata list.
@@ -310,7 +321,19 @@
      * @param configuration : the new configuration
      * @see org.apache.felix.ipojo.Handler#reconfigure(java.util.Dictionary)
      */
-    public void reconfigure(Dictionary configuration) {
+    public synchronized void reconfigure(Dictionary configuration) {      
+        Properties props = reconfigureProperties(configuration);
+        propagate(props, m_propagatedFromInstance);
+        m_propagatedFromInstance = props;
+    }
+    
+    /**
+     * Reconfigured configuration properties and returns non matching properties.
+     * When called, it must hold the monitor lock.
+     * @param configuration : new configuration
+     * @return the properties that does not match with configuration properties
+     */
+    private Properties reconfigureProperties(Dictionary configuration) {        
         Properties toPropagate = new Properties();
         Enumeration keysEnumeration = configuration.keys();
         while (keysEnumeration.hasMoreElements()) {
@@ -342,17 +365,29 @@
             }
         }
 
-        // Propagation of the properties to service registrations :
-        if (m_providedServiceHandler != null && !toPropagate.isEmpty()) {
-            m_providedServiceHandler.removeProperties(m_propagated);
+        return toPropagate;
 
-            // Remove the name, the pid and the managed service pid props
-            toPropagate.remove("name");
-            toPropagate.remove("managed.service.pid");
-            toPropagate.remove(Constants.SERVICE_PID);
+    }
+    
+    /**
+     * Removes the old properties from the provided services and propagate new properties.
+     * @param newProps : new properties to propagate
+     * @param oldProps : old properties to remove
+     */
+    private void propagate(Dictionary newProps, Dictionary oldProps) {
+        if (m_mustPropagate && m_providedServiceHandler != null) {
+            if (oldProps != null) {
+                m_providedServiceHandler.removeProperties(oldProps);
+            }
 
-            m_providedServiceHandler.addProperties(toPropagate);
-            m_propagated = toPropagate;
+            if (newProps != null) {
+                // Remove the name, the pid and the managed service pid props
+                newProps.remove("name");
+                newProps.remove("managed.service.pid");
+                newProps.remove(Constants.SERVICE_PID);
+                // Propagation of the properties to service registrations :
+                m_providedServiceHandler.addProperties(newProps);
+            }
         }
     }
 
@@ -373,12 +408,24 @@
     /**
      * Managed Service method.
      * This method is called when the instance is reconfigured by the ConfigurationAdmin.
-     * @param arg0 : pushed configuration.
+     * When called, it must hold the monitor lock.
+     * @param conf : pushed configuration.
      * @throws org.osgi.service.cm.ConfigurationException the reconfiguration failed.
      * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
      */
-    public void updated(Dictionary arg0) throws org.osgi.service.cm.ConfigurationException {
-        reconfigure(arg0);
+    public synchronized void updated(Dictionary conf) throws org.osgi.service.cm.ConfigurationException {
+        if (conf == null && ! m_configurationAlreadyPushed) {
+            return; // First call
+        } else if (conf != null) { // Configuration push
+            Properties props = reconfigureProperties(conf);
+            propagate(props, m_propagatedFromCA);
+            m_propagatedFromCA = props;
+            m_configurationAlreadyPushed = true;
+        } else if (conf == null && m_configurationAlreadyPushed) { // Configuration deletion
+            propagate(null, m_propagatedFromCA);
+            m_propagatedFromCA = null;
+            m_configurationAlreadyPushed = false;
+        }
     }
 
 }
diff --git a/ipojo/core/src/main/resources/metadata.xml b/ipojo/core/src/main/resources/metadata.xml
index 3163416..89911da 100644
--- a/ipojo/core/src/main/resources/metadata.xml
+++ b/ipojo/core/src/main/resources/metadata.xml
@@ -20,7 +20,7 @@
 	<handler

 		classname="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler"

 		name="architecture" architecture="false">

-		<provides>

+		<provides interface="org.apache.felix.ipojo.architecture.Architecture">

 			<property field="m_name" name="instance.name" value="" />

 		</provides>

 	</handler>