Modify pom files to use correct version.
Add ManagedService management in the Configuration Handler (the PID of the Managed Service can be specified both in the component type or in the component instance configuration).
Add ManagedService tests in the test suite


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@645516 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/pom.xml b/ipojo/core/pom.xml
index 7506e82..113e48d 100644
--- a/ipojo/core/pom.xml
+++ b/ipojo/core/pom.xml
@@ -31,22 +31,22 @@
 	<version>0.7.6-SNAPSHOT</version>
 	<dependencies>
 		<dependency>
-			<groupId>${pom.groupId}</groupId>
+			<groupId>org.apache.felix</groupId>
 			<artifactId>org.osgi.core</artifactId>
 			<version>1.0.0</version>
 		</dependency>
 		<dependency>
-			<groupId>${pom.groupId}</groupId>
+			<groupId>org.apache.felix</groupId>
 			<artifactId>org.osgi.compendium</artifactId>
 			<version>1.0.0</version>
 		</dependency>
 		<dependency>
-			<groupId>${pom.groupId}</groupId>
+			<groupId>org.apache.felix</groupId>
 			<artifactId>org.apache.felix.ipojo.metadata</artifactId>
 			<version>0.7.6-SNAPSHOT</version>
 		</dependency>
 		<dependency>
-			<groupId>${pom.groupId}</groupId>
+			<groupId>org.apache.felix</groupId>
 			<artifactId>org.apache.felix.ipojo.manipulator</artifactId>
 			<version>0.7.6-SNAPSHOT</version>
 		</dependency>
@@ -109,7 +109,7 @@
 			<plugin>
 				<groupId>org.apache.felix</groupId>
 				<artifactId>maven-ipojo-plugin</artifactId>
-				<version>${pom.version}</version>
+				<version>0.7.6-SNAPSHOT</version>
 				<executions>
 					<execution>
 						<goals>
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 ef89f07..ae7fe39 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
@@ -35,12 +35,15 @@
 import org.apache.felix.ipojo.parser.MethodMetadata;
 import org.apache.felix.ipojo.parser.PojoMetadata;
 import org.apache.felix.ipojo.util.Property;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
 
 /**
  * Handler managing the Configuration Admin.
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class ConfigurationHandler extends PrimitiveHandler {
+public class ConfigurationHandler extends PrimitiveHandler implements ManagedService {
 
     /**
      * List of the configurable fields.
@@ -67,6 +70,18 @@
      * should the component propagate configuration ?
      */
     private boolean m_isConfigurable;
+    
+    /**
+     * Service Registration to publish the service registration.
+     */
+    private ServiceRegistration m_sr;
+    
+    /**
+     * Managed Service PID.
+     * This PID must be different from the instance name if the instance was created 
+     * with the Configuration Admin.
+     */
+    private String m_managedServicePID;
 
     /**
      * Initialize the component type.
@@ -160,12 +175,19 @@
 
         // Check if the component is dynamically configurable
         m_isConfigurable = false;
-       
         String propa = confs[0].getAttribute("propagation");
         if (propa != null && propa.equalsIgnoreCase("true")) {
             m_isConfigurable = true;
             m_toPropagate = configuration;
         }
+        
+        // Check if the component support ConfigurationADmin reconfiguration
+        m_managedServicePID = confs[0].getAttribute("pid"); // Look inside the component type description
+        String instanceMSPID = (String) configuration.get("managed.service.pid"); // Look inside the instance configuration.
+        if (instanceMSPID != null) {
+            m_managedServicePID = instanceMSPID;
+        }
+        
 
         for (int i = 0; configurables != null && i < configurables.length; i++) {
             String fieldName = configurables[i].getAttribute("field");
@@ -201,7 +223,10 @@
       * @see org.apache.felix.ipojo.Handler#stop()
       */
     public void stop() {
-        // Nothing to do.
+        if (m_sr != null) {
+            m_sr.unregister();
+            m_sr = null;
+        }
     }
 
     /**
@@ -220,50 +245,16 @@
             }
             reconfigure(m_toPropagate);
         }
+        
+        if (m_managedServicePID != null && m_sr == null) {
+            Properties props = new Properties();
+            props.put(Constants.SERVICE_PID, m_managedServicePID);
+            props.put("instance.name", getInstanceManager().getInstanceName());
+            props.put("factory.name", getInstanceManager().getFactory().getFactoryName());
+            m_sr = getInstanceManager().getContext().registerService(ManagedService.class.getName(), this, props);
+        }
     }
 
-//    /**
-//     * Setter Callback Method.
-//     * Check if the modified field is a configurable property to update the value.
-//     * @param pojo : the pojo object on which the field is accessed
-//     * @param fieldName : field name
-//     * @param value : new value
-//     * @see org.apache.felix.ipojo.Handler#onSet(Object, java.lang.String, java.lang.Object)
-//     */
-//    public void onSet(Object pojo, String fieldName, Object value) {
-//        // Verify that the field name correspond to a configurable property
-//        for (int i = 0; i < m_configurableProperties.length; i++) {
-//            Property prop = m_configurableProperties[i];
-//            if (prop.hasField() && prop.getField().equals(fieldName)) {
-//                // Check if the value has changed
-//                if (prop.getValue() == null || !prop.getValue().equals(value)) {
-//                    prop.setValue(value); // Change the value
-//                }
-//            }
-//        }
-//        // Else do nothing
-//    }
-//
-//    /**
-//     * Getter Callback Method.
-//     * Check if the field is a configurable property to push the stored value.
-//     * @param pojo : the pojo object on which the field is accessed
-//     * @param fieldName : field name
-//     * @param value : value pushed by the previous handler
-//     * @return the stored value or the previous value.
-//     * @see org.apache.felix.ipojo.Handler#onGet(Object,
-//     * java.lang.String, java.lang.Object)
-//     */
-//    public Object onGet(Object pojo, String fieldName, Object value) {
-//        // Check if the field is a configurable property
-//        for (int i = 0; i < m_configurableProperties.length; i++) {
-//            if (fieldName.equals(m_configurableProperties[i].getField())) { 
-//                return m_configurableProperties[i].getValue(); 
-//            }
-//        }
-//        return value;
-//    }
-
     /**
      * Handler state changed.
      * @param state : the new instance state.
@@ -329,22 +320,24 @@
             // Check if the name is a configurable property
             for (int i = 0; i < m_configurableProperties.length; i++) {
                 if (m_configurableProperties[i].getName().equals(name)) {
-                    // Check if the value has changed
-                    if (m_configurableProperties[i].getValue() == null || !m_configurableProperties[i].getValue().equals(value)) {
-                        if (m_configurableProperties[i].hasField()) {
-                            getInstanceManager().onSet(null, m_configurableProperties[i].getField(), value); // dispatch that the value has changed
-                        }
-                        if (m_configurableProperties[i].hasMethod()) {
+                    if (m_configurableProperties[i].hasField()) {
+                        if (m_configurableProperties[i].getValue() == null || ! m_configurableProperties[i].getValue().equals(value)) {
                             m_configurableProperties[i].setValue(value);
-                            m_configurableProperties[i].invoke(null); // Call on all created pojo objects.
+                            getInstanceManager().onSet(null, m_configurableProperties[i].getField(), m_configurableProperties[i].getValue()); // Notify other handler of the field value change.
+                            if (m_configurableProperties[i].hasMethod()) {
+                                m_configurableProperties[i].invoke(null); // Call on all created pojo objects.
+                            }
                         }
+                    } else if (m_configurableProperties[i].hasMethod()) { // Method but no field
+                        m_configurableProperties[i].setValue(value);
+                        m_configurableProperties[i].invoke(null); // Call on all created pojo objects.
                     }
                     found = true;
                     break;
                 }
             }
-            if (!found) {
-                // The property is not a configurable property
+            if (!found) { 
+                // The property is not a configurable property, at it to the toPropagate list.
                 toPropagate.put(name, value);
             }
         }
@@ -353,8 +346,10 @@
         if (m_providedServiceHandler != null && !toPropagate.isEmpty()) {
             m_providedServiceHandler.removeProperties(m_propagated);
 
-            // Remove the name props
+            // Remove the name, the pid and the managed service pid props
             toPropagate.remove("name");
+            toPropagate.remove("managed.service.pid");
+            toPropagate.remove(Constants.SERVICE_PID);
 
             m_providedServiceHandler.addProperties(toPropagate);
             m_propagated = toPropagate;
@@ -375,4 +370,15 @@
         }
     }
 
+    /**
+     * Managed Service method.
+     * This method is called when the instance is reconfigured by the ConfigurationAdmin.
+     * @param arg0 : 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);
+    }
+
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
index 948b66b..3c11693 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
@@ -40,17 +40,18 @@
     /**

      * Name of the property (filed name if not set).

      */

-    private String m_name;

+    private final String m_name;

 

     /**

      * Field of the property.

+     * Cannot change once set.

      */

-    private String m_field;

+    private final String m_field;

 

     /**

      * Setter method of the property.

      */

-    private Callback m_method;

+    private final Callback m_method;

 

     /**

      * Value of the property.

@@ -60,17 +61,17 @@
     /**

      * Type of the property.

      */

-    private Class m_type;

+    private final Class m_type;

 

     /**

      * Handler object on to use the logger.

      */

-    private Handler m_handler;

+    private final Handler m_handler;

     

     /**

      * Instance Manager.

      */

-    private InstanceManager m_manager;

+    private final InstanceManager m_manager;

 

     /**

      * Configurable Property Constructor. At least the method or the field need

@@ -100,7 +101,6 @@
             m_name = name;

         }

         

-        m_field = field;

         m_type = computeType(type, manager.getGlobalContext());

         if (value != null) {

             m_value = create(m_type, value);

@@ -108,6 +108,8 @@
 

         if (method != null) {

             m_method = new Callback(method, new String[] { m_type.getName() }, false, manager);

+        } else {

+            m_method = null;

         }

 

     }

@@ -242,7 +244,7 @@
         return m_field != null;

     }

 

-    public Object getValue() {

+    public synchronized Object getValue() {

         return m_value;

     }

 

@@ -251,20 +253,23 @@
      * @param value : the new value.

      */

     public void setValue(Object value) {

-        // Is the object is directly assignable to the property, affect it.

-        if (isAssignable(m_type, value)) {

-            m_value = value;

-        } else {

-            // If the object is a String, we must recreate the object from the String form

-            if (value instanceof String) {

-                try {

-                    m_value = create(m_type, (String) value);

-                } catch (ConfigurationException e) {

-                    throw new ClassCastException("Incompatible type for the property " + m_name + " : " + e.getMessage());

-                }

+        synchronized (this) {

+            // Is the object is directly assignable to the property, affect it.

+            if (isAssignable(m_type, value)) {

+                m_value = value;

             } else {

-                // Error, the given property cannot be injected.

-                throw new ClassCastException("Incompatible type for the property " + m_name + " " + m_type.getName() + " expected, " + value.getClass() + " received");

+                // If the object is a String, we must recreate the object from the String form

+                if (value instanceof String) {

+                    try {

+                        m_value = create(m_type, (String) value);

+                    } catch (ConfigurationException e) {

+                        throw new ClassCastException("Incompatible type for the property " + m_name + " : " + e.getMessage());

+                    }

+                } else {

+                    // Error, the given property cannot be injected.

+                    throw new ClassCastException("Incompatible type for the property " + m_name + " " + m_type.getName() + " expected, " 

+                                                 + value.getClass() + " received");

+                }

             }

         }

     }

@@ -427,7 +432,7 @@
      * @param instance : the created object (could be null

      * @see org.apache.felix.ipojo.Handler#onCreation(java.lang.Object)

      */

-    public void invoke(Object instance) {

+    public synchronized void invoke(Object instance) {

         try {

             if (instance == null) {

                 m_method.call(new Object[] { m_value });

@@ -466,7 +471,8 @@
      * @see org.apache.felix.ipojo.FieldInterceptor#onSet(java.lang.Object, java.lang.String, java.lang.Object)

      */

     public void onSet(Object pojo, String fieldName, Object value) {

-        setValue(value);

-        

+        if (m_value == null || ! m_value.equals(value)) {

+            setValue(value);

+        }

     }

 }