Start working on FELIX-2636 Cannot control the validity of an iPOJO instance using a configuration property
The issue seems to be fixed.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1005546 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 70e61d7..374dca0 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
@@ -291,6 +291,7 @@
         // Get the provided service handler :
         m_providedServiceHandler = (ProvidedServiceHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":provides");
 
+
         // Propagation
         if (m_mustPropagate) {
             for (int i = 0; i < m_configurableProperties.size(); i++) {
@@ -302,6 +303,15 @@
             reconfigure(m_toPropagate);
         }
 
+
+        // Give initial values
+        for (int i = 0; i < m_configurableProperties.size(); i++) {
+        	Property prop = (Property) m_configurableProperties.get(i);
+        	if (prop.hasField() && prop.getValue() != Property.NO_VALUE && prop.getValue() != null) {
+        		getInstanceManager().onSet(null, prop.getField(), prop.getValue());
+        	}
+        }
+
         if (m_managedServicePID != null && m_sr == null) {
             Properties props = new Properties();
             props.put(Constants.SERVICE_PID, m_managedServicePID);
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
index a97411a..08bdbe2 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
@@ -1,4 +1,4 @@
-/* 

+/*

  * Licensed to the Apache Software Foundation (ASF) under one

  * or more contributor license agreements.  See the NOTICE file

  * distributed with this work for additional information

@@ -35,11 +35,15 @@
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

  */

 public class ControllerHandler extends PrimitiveHandler {

-    

+

     /**

      * Actual handler (i.e. field value) state

      */

     private boolean m_state;

+	/**

+	 * The controller field name.

+	 */

+	private String m_field;

 

     /**

      * Configure method.

@@ -51,28 +55,40 @@
      */

     public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {

         Element[] controller = metadata.getElements("controller");

-        String field = controller[0].getAttribute("field");   

-        getInstanceManager().register(new FieldMetadata(field, "boolean"), this);

+        m_field = controller[0].getAttribute("field");

+        getInstanceManager().register(new FieldMetadata(m_field, "boolean"), this);

     }

 

     /**

      * Start method.

-     * Nothing to do.

+     * This methods initializes the controller value.

      * @see org.apache.felix.ipojo.Handler#start()

      */

-    public void start() { 

-        m_state = true;

+    public void start() {

+    	// On start we should ask for the value

+    	Object o = getInstanceManager().getFieldValue(m_field);

+    	if (o == null || ! (o instanceof Boolean)) {

+    		m_state = true;

+    	} else {

+    		m_state = ((Boolean) o).booleanValue();

+    	}

+

+    	if ( ! m_state) {

+    		setValidity(false);

+    	}

     }

 

     /**

      * Stop method.

-     * Nothing to do. 

+     * Nothing to do.

      * @see org.apache.felix.ipojo.Handler#stop()

      */

-    public void stop() { 

+    public void stop() {

         // Nothing to do.

     }

-    

+

+

+

     /**

      * GetterCallback.

      * @param pojo : the pojo object on which the field is accessed

@@ -82,13 +98,13 @@
      * @return : the handler state.

      */

     public Object onGet(Object pojo, String field, Object value) {

-        if (m_state) { 

+        if (m_state) {

             return Boolean.TRUE;

         } else {

             return Boolean.FALSE;

         }

     }

-    

+

     /**

      * SetterCallback.

      * @param pojo : the pojo object on which the field is accessed

@@ -103,8 +119,10 @@
                 m_state = newValue;

                 if (m_state) {

                     ((InstanceManager) getHandlerManager()).setState(ComponentInstance.VALID);

+                    setValidity(true);

                 } else {

                     ((InstanceManager) getHandlerManager()).setState(ComponentInstance.INVALID);

+                    setValidity(false);

                 }

             }

         } else {

@@ -112,7 +130,7 @@
             getInstanceManager().stop();

         }

     }

-    

+

     /**

      * Initialize the component factory.

      * The controller field is checked to avoid configure check.

@@ -129,13 +147,13 @@
         if (field == null) {

             throw new ConfigurationException("Lifecycle controller : the controller element needs to contain a field attribute");

         }

-        

+

         PojoMetadata method = getFactory().getPojoMetadata();

         FieldMetadata fieldMetadata = method.getField(field);

         if (fieldMetadata == null) {

             throw new ConfigurationException("Lifecycle controller : The field " + field + " does not exist in the implementation class");

         }

-        

+

         if (!fieldMetadata.getFieldType().equalsIgnoreCase("boolean")) {

             throw new ConfigurationException("Lifecycle controller : The field " + field + " must be a boolean (" + fieldMetadata.getFieldType() + " found)");

         }

diff --git a/ipojo/tests/core/lifecycle-controller/pom.xml b/ipojo/tests/core/lifecycle-controller/pom.xml
index 867ac13..eb23da1 100644
--- a/ipojo/tests/core/lifecycle-controller/pom.xml
+++ b/ipojo/tests/core/lifecycle-controller/pom.xml
@@ -118,6 +118,17 @@
 											<property name="conf" field="m_conf" method="setConf" />

 										</properties>

 									 </component>

+

+									 <component

+										classname="org.apache.felix.ipojo.test.scenarios.component.ConfigurableLifecycleControllerTest"

+										name="LFC-Test-Configurable" architecture="true">

+										<provides />

+										<!-- The property and the controller share the same field -->

+										<controller field="m_state" />

+										<properties>

+											<property name="state" field="m_state" />

+										</properties>

+									 </component>

 								 </ipojo>

 								 ]]>

 							</metadata>

@@ -133,6 +144,25 @@
 					<target>1.4</target>

 				</configuration>

 			</plugin>

+			<plugin>

+	        <groupId>org.apache.felix</groupId>

+	        <artifactId>maven-junit4osgi-plugin

+	        </artifactId>

+	        <version>1.1.0-SNAPSHOT</version>

+	        <executions>

+	          <execution>

+	            <goals>

+	              <goal>test</goal>

+	            </goals>

+	            <configuration>

+	              <logService>false</logService>

+	              <configuration>

+	              <org.osgi.http.port>8083</org.osgi.http.port>

+	              </configuration>

+	            </configuration>

+	          </execution>

+	        </executions>

+      		</plugin>

 		</plugins>

 	</build>

-</project>

+</project>
\ No newline at end of file
diff --git a/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/component/ConfigurableLifecycleControllerTest.java b/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/component/ConfigurableLifecycleControllerTest.java
new file mode 100644
index 0000000..05d2cdf
--- /dev/null
+++ b/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/component/ConfigurableLifecycleControllerTest.java
@@ -0,0 +1,41 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.felix.ipojo.test.scenarios.component;

+

+import java.util.Properties;

+

+import org.apache.felix.ipojo.test.scenarios.lfc.service.CheckService;

+

+public class ConfigurableLifecycleControllerTest implements CheckService {

+

+	// This is both a property and the controller.

+    private boolean m_state;

+

+    public boolean check() {

+        return m_state;

+    }

+

+    public Properties getProps() {

+       Properties props = new Properties();

+       props.put("state", new Boolean(m_state));

+       return props;

+    }

+

+}

+

diff --git a/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/lfc/ConfigurableLifeCycleControllerTest.java b/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/lfc/ConfigurableLifeCycleControllerTest.java
new file mode 100644
index 0000000..d70dbae
--- /dev/null
+++ b/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/lfc/ConfigurableLifeCycleControllerTest.java
@@ -0,0 +1,197 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.felix.ipojo.test.scenarios.lfc;

+

+import java.util.Properties;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.MissingHandlerException;

+import org.apache.felix.ipojo.UnacceptableConfiguration;

+import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;

+import org.apache.felix.ipojo.test.scenarios.lfc.service.CheckService;

+import org.apache.felix.ipojo.test.scenarios.util.Utils;

+import org.osgi.framework.ServiceReference;

+

+/**

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ConfigurableLifeCycleControllerTest extends OSGiTestCase {

+

+    private ComponentInstance under;

+

+    private Factory factory;

+

+    public void setUp() {

+        factory = Utils.getFactoryByName(getContext(), "LFC-Test-Configurable");

+    }

+

+    public void testValidThenInvalid() throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {

+        Properties props = new Properties();

+        props.put("instance.name","under1");

+        props.put("state", "true");

+        under = factory.createComponentInstance(props);

+

+        // The conf is correct, the PS must be provided

+        ServiceReference ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under1");

+        assertNotNull("Check service availability -1", ref);

+        CheckService cs = (CheckService) getContext().getService(ref);

+        assertTrue("Check state 1", cs.check());

+        getContext().ungetService(ref);

+        cs = null;

+

+        // Reconfigure the instance

+        props.put("state", "false"); // Bar is a bad conf

+        try {

+            factory.reconfigure(props);

+        } catch (Exception e) {

+            fail("The reconfiguration is not unacceptable and seems unacceptable : " + props);

+        }

+

+        // The instance should now be invalid

+        ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under1");

+        assertNull("Check service availability -2", ref);

+

+        // Reconfigure the instance with a valid configuration

+        props.put("state", "true");

+        try {

+            factory.reconfigure(props);

+        } catch (Exception e) {

+            fail("The reconfiguration is not unacceptable and seems unacceptable (2) : " + props);

+        }

+

+        ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under1");

+        assertNotNull("Check service availability -3", ref);

+        cs = (CheckService) getContext().getService(ref);

+        assertTrue("Check state 2", cs.check());

+        getContext().ungetService(ref);

+        cs = null;

+

+        under.dispose();

+    }

+

+    public void testInValidThenValid() throws Exception {

+        Properties props = new Properties();

+        props.put("instance.name","under1");

+        props.put("state", "false");

+        under = factory.createComponentInstance(props);

+

+        // The instance should now be invalid

+        ServiceReference ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under1");

+        assertNull("Check service availability -2", ref);

+

+        // Reconfigure the instance

+        props.put("state", "true"); // Bar is a bad conf

+        try {

+            factory.reconfigure(props);

+        } catch (Exception e) {

+            fail("The reconfiguration is not unacceptable and seems unacceptable : " + props);

+        }

+

+//        Object[] objects = Utils.getServiceObjects(context, Architecture.class.getName(), null);

+//        for (int i = 0; i < objects.length; i++) {

+//        	Architecture a = (Architecture) objects[i];

+//        	System.out.println(a.getInstanceDescription().getDescription());

+//        }

+

+        ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under1");

+        assertNotNull("Check service availability -1", ref);

+        CheckService cs = (CheckService) getContext().getService(ref);

+        assertTrue("Check state 1", cs.check());

+        getContext().ungetService(ref);

+        cs = null;

+

+        // Reconfigure the instance

+        props.put("state", "false"); // Bar is a bad conf

+        try {

+            factory.reconfigure(props);

+        } catch (Exception e) {

+            fail("The reconfiguration is not unacceptable and seems unacceptable : " + props);

+        }

+

+        // The instance should now be invalid

+        ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under1");

+        assertNull("Check service availability -2", ref);

+

+        // Reconfigure the instance with a valid configuration

+        props.put("state", "true");

+        try {

+            factory.reconfigure(props);

+        } catch (Exception e) {

+            fail("The reconfiguration is not unacceptable and seems unacceptable (2) : " + props);

+        }

+

+        ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under1");

+        assertNotNull("Check service availability -3", ref);

+        cs = (CheckService) getContext().getService(ref);

+        assertTrue("Check state 2", cs.check());

+        getContext().ungetService(ref);

+        cs = null;

+

+        under.dispose();

+    }

+

+//    /**

+//     * This test must be removed as it is not compliant with OSGi. It unregisters a service during the creation of the

+//     * service instance, so the returned object is null.

+//     */

+//    public void notestTwo() {

+//        Properties props = new Properties();

+//        props.put("conf", "bar");

+//        props.put("instance.name","under2");

+//        under = Utils.getComponentInstance(getContext(), "LFC-Test", props);

+//

+//        // The conf is incorrect, but the test can appears only when the object is created : the PS must be provided

+//        ServiceReference ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under2");

+//        assertNotNull("Check service availability -1", ref);

+//

+//        System.out.println("CS received : " + getContext().getService(ref));

+//        CheckService cs = (CheckService) getContext().getService(ref);

+//        assertNotNull("Assert CS not null", cs);

+//        try {

+//            assertFalse("Check state (false)", cs.check());

+//        } catch (Throwable e) {

+//            e.printStackTrace();

+//            fail(e.getMessage());

+//        }

+//

+//        // As soon as the instance is created, the service has to disappear :

+//        ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under2");

+//        assertNull("Check service availability -2", ref);

+//

+//        // Reconfigure the instance with a correct configuration

+//        props.put("conf", "foo");

+//        try {

+//            factory.reconfigure(props);

+//        } catch (Exception e) {

+//            fail("The reconfiguration is not unacceptable and seems unacceptable : " + props);

+//        }

+//

+//        ref = Utils.getServiceReferenceByName(getContext(), CheckService.class.getName(), "under2");

+//        assertNotNull("Check service availability -3", ref);

+//        cs = (CheckService) getContext().getService(ref);

+//        assertTrue("Check state ", cs.check());

+//        getContext().ungetService(ref);

+//        cs = null;

+//

+//        under.dispose();

+//    }

+

+}

diff --git a/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/lfc/LifeCycleControllerTestSuite.java b/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/lfc/LifeCycleControllerTestSuite.java
index 9ed3bd8..80ce329 100644
--- a/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/lfc/LifeCycleControllerTestSuite.java
+++ b/ipojo/tests/core/lifecycle-controller/src/main/java/org/apache/felix/ipojo/test/scenarios/lfc/LifeCycleControllerTestSuite.java
@@ -1,4 +1,4 @@
-/* 

+/*

  * Licensed to the Apache Software Foundation (ASF) under one

  * or more contributor license agreements.  See the NOTICE file

  * distributed with this work for additional information

@@ -30,6 +30,7 @@
         OSGiTestSuite ots = new OSGiTestSuite("Lifecycle Controller Test Suite", bc);

         ots.addTestSuite( LifeCycleControllerTest.class);

         ots.addTestSuite( ImmediateLifeCycleControllerTest.class);

+        ots.addTestSuite(ConfigurableLifeCycleControllerTest.class);

         return ots;

     }