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;
}