Fix FELIX-4207 ipojo @Component with propagation set to true doesn't propagate properties
All not excluded properties must be propagated when the propagation is enabled.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1519937 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/ConfigurableFooProviderWithPropagation.java b/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/ConfigurableFooProviderWithPropagation.java
new file mode 100644
index 0000000..01898b7
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/ConfigurableFooProviderWithPropagation.java
@@ -0,0 +1,73 @@
+/*
+ * 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.runtime.core.components;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Property;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+
+import java.util.Properties;
+
+@Component(propagation = true)
+@Provides
+public class ConfigurableFooProviderWithPropagation implements FooService {
+
+ @Property
+ private String message;
+
+ @Property(name=".private")
+ private String myPrivateLife;
+
+ public boolean foo() {
+ return true;
+ }
+
+ public Properties fooProps() {
+ Properties props = new Properties();
+ if (message == null) {
+ props.put("message", "NULL");
+ } else {
+ props.put("message", message);
+ }
+ return props;
+ }
+
+ public boolean getBoolean() {
+ return false;
+ }
+
+ public double getDouble() {
+ return 0;
+ }
+
+ public int getInt() {
+ return 0;
+ }
+
+ public long getLong() {
+ return 0;
+ }
+
+ public Boolean getObject() {
+ return null;
+ }
+
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/main/resources/metadata.xml b/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/main/resources/metadata.xml
index 6affd5b..c9e02c0 100644
--- a/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/main/resources/metadata.xml
+++ b/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/main/resources/metadata.xml
@@ -37,5 +37,4 @@
</properties>
</component>
-
</ipojo>
diff --git a/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestPropagation.java b/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestPropagation.java
new file mode 100644
index 0000000..ba7bc79
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestPropagation.java
@@ -0,0 +1,92 @@
+/*
+ * 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.runtime.core;
+
+import org.apache.felix.ipojo.architecture.PropertyDescription;
+import org.apache.felix.ipojo.handlers.configuration.ConfigurationHandlerDescription;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.Test;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.ow2.chameleon.testing.helpers.Dumps;
+
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.util.Properties;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+/**
+ * Test for FELIX-4207 - ipojo @Component with propagation set to true doesn't propagate properties
+ */
+public class TestPropagation extends Common {
+
+ private String factoryName = "org.apache.felix.ipojo.runtime.core.components.ConfigurableFooProviderWithPropagation";
+
+ @Test
+ public void testPropagationFromConfigurationAdminWhenCreatingTheInstance() throws IOException {
+ Properties props = new Properties();
+ props.put("message", "message");
+ props.put("propagated", "propagated");
+ props.put(".private", "wow");
+
+ Configuration configuration = admin.createFactoryConfiguration(factoryName, "?");
+ configuration.update(props);
+
+ ServiceReference ref = osgiHelper.waitForService(FooService.class.getName(),
+ "(instance.name=" + configuration.getPid() + ")",
+ 1000);
+
+ // Check the propagation
+ assertEquals(ref.getProperty("propagated"), "propagated");
+ assertEquals(ref.getProperty("message"), "message");
+ assertNull(ref.getProperty(".private"));
+ assertNull(ref.getProperty("private"));
+
+ // Check the the .private property has the right value
+ ConfigurationHandlerDescription desc = (ConfigurationHandlerDescription) ipojoHelper.getArchitectureByName(configuration.getPid())
+ .getInstanceDescription().getHandlerDescription("org.apache.felix.ipojo:properties");
+ PropertyDescription prop = desc.getPropertyByName(".private");
+ assertEquals(prop.getValue(), "wow");
+
+ // Update the property
+ props.put("message", "message2");
+ props.put("propagated", "propagated2");
+ props.put(".private", "wow2");
+ configuration.update(props);
+
+ grace();
+
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), configuration.getPid());
+ // Check the propagation
+ assertEquals(ref.getProperty("propagated"), "propagated2");
+ assertEquals(ref.getProperty("message"), "message2");
+
+ desc = (ConfigurationHandlerDescription) ipojoHelper.getArchitectureByName(configuration.getPid())
+ .getInstanceDescription().getHandlerDescription("org.apache.felix.ipojo:properties");
+ prop = desc.getPropertyByName(".private");
+ assertEquals(prop.getValue(), "wow2");
+
+ configuration.delete();
+ }
+
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
index 267c1a5..60fcae2 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
@@ -92,7 +92,6 @@
* This method is called when a reconfiguration is completed.
*/
private Callback m_updated;
-
/**
* The configuration listeners.
*/
@@ -226,7 +225,7 @@
String key = (String) keys.nextElement();
// To conform with 'Property Propagation 104.4.4 (Config Admin spec)',
// we don't propagate properties starting with .
- if (!key.startsWith(".")) {
+ if (!excluded(key)) {
m_toPropagate.put(key, configuration.get(key));
}
}
@@ -360,7 +359,7 @@
// Security Check
if (SecurityHelper.hasPermissionToRegisterService(ManagedService.class.getName(),
- getInstanceManager().getContext()) && SecurityHelper.canRegisterService
+ getInstanceManager().getContext()) && SecurityHelper.canRegisterService
(getInstanceManager().getContext())) {
m_sr = getInstanceManager().getContext().registerService(ManagedService.class.getName(), this, props);
} else {
@@ -428,13 +427,16 @@
// Check if the name is a configurable property
for (Property prop : m_configurableProperties) {
if (prop.getName().equals(name)) {
- reconfigureProperty(prop, value);
+ Object v = reconfigureProperty(prop, value);
found = true;
+ if (m_mustPropagate && ! excluded(name)) {
+ toPropagate.put(name, v);
+ }
break; // Exit the search loop
}
}
- if (!found) {
- // The property is not a configurable property, add it to the toPropagate list.
+
+ if (!found && m_mustPropagate && ! excluded(name)) {
toPropagate.put(name, value);
}
}
@@ -450,6 +452,18 @@
}
/**
+ * Checks whether the property with this given name must not be propagated.
+ * @param name the name of the property
+ * @return {@code true} if the property must not be propagated
+ */
+ private boolean excluded(String name) {
+ return name.startsWith(".")
+ || Factory.INSTANCE_NAME_PROPERTY.equals(name)
+ || Factory.FACTORY_VERSION_PROPERTY.equals(name)
+ || "factory.name".equals(name);
+ }
+
+ /**
* Reconfigures the given property with the given value.
* This methods handles {@link org.apache.felix.ipojo.InstanceManager#onSet(Object, String, Object)}
* call and the callback invocation.
@@ -457,8 +471,9 @@
*
* @param prop the property object to reconfigure
* @param value the new value.
+ * @return the new property value
*/
- public void reconfigureProperty(Property prop, Object value) {
+ public Object reconfigureProperty(Property prop, Object value) {
if (prop.getValue() == null || !prop.getValue().equals(value)) {
prop.setValue(value);
if (prop.hasField()) {
@@ -470,6 +485,7 @@
}
}
}
+ return prop.getValue();
}
/**
@@ -680,7 +696,7 @@
* Remove the given listener from the configuration handler's list of listeners.
*
* @param listener the {@code ConfigurationListener} object to be removed
- * @throws NullPointerException if {@code listener} is {@code null}
+ * @throws NullPointerException if {@code listener} is {@code null}
* @throws NoSuchElementException if {@code listener} wasn't present the in configuration handler's list of listeners
*/
public void removeListener(ConfigurationListener listener) {
@@ -691,7 +707,7 @@
// We definitely cannot rely on listener's equals method...
// ...so we need to manually search for the listener, using ==.
int i = -1;
- for(int j = m_listeners.size() -1; j>=0 ; j--) {
+ for (int j = m_listeners.size() - 1; j >= 0; j--) {
if (m_listeners.get(j) == listener) {
// Found!
i = j;
@@ -726,9 +742,9 @@
} catch (Throwable e) {
// Failure inside a listener: put a warning on the logger, and continue
warn(String.format(
- "[%s] A ConfigurationListener has failed: %s",
- getInstanceManager().getInstanceName(),
- e.getMessage())
+ "[%s] A ConfigurationListener has failed: %s",
+ getInstanceManager().getInstanceName(),
+ e.getMessage())
, e);
}
}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandlerDescription.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandlerDescription.java
index 7455b0f..e543e18 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandlerDescription.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandlerDescription.java
@@ -103,6 +103,21 @@
public PropertyDescription[] getProperties() {
return m_properties;
}
+
+ /**
+ * Gets a property by name.
+ * @param name the property name
+ * @return the property description with the given name, {@code null} if there is no property with the given name.
+ * @since 1.10.2
+ */
+ public PropertyDescription getPropertyByName(String name) {
+ for (PropertyDescription desc :m_properties) {
+ if (name.equals(desc.getName())) {
+ return desc;
+ }
+ }
+ return null;
+ }
/**
* Gets the managed service pid.