ARIES-2059 Component properties are sometimes merged in the incorrect order

Signed-off-by: Raymond Augé <rotty3000@apache.org>
diff --git a/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ConfigurationListener.java b/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ConfigurationListener.java
index bb54353..3f8154e 100644
--- a/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ConfigurationListener.java
+++ b/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/ConfigurationListener.java
@@ -38,7 +38,7 @@
 import org.osgi.service.log.Logger;
 import org.osgi.util.promise.Promise;
 
-public class ConfigurationListener extends Phase implements org.osgi.service.cm.ConfigurationListener {
+public class ConfigurationListener extends Phase implements org.osgi.service.cm.SynchronousConfigurationListener {
 
 	public static class Builder {
 
@@ -104,6 +104,8 @@
 
 	@Override
 	public void configurationEvent(ConfigurationEvent event) {
+		_log.debug(l -> l.debug("ConfigurationEvent for {}:{}", event.getPid(), type(event)));
+
 		next.map(next -> (Component)next).ifPresent(
 			next -> next.configurationTemplates().stream().filter(
 				t -> Predicates.isMatchingConfiguration(event).test(t)
@@ -111,6 +113,8 @@
 				t -> {
 					String eventString = Arrays.asList(event.getPid(), event.getFactoryPid(), type(event)).toString();
 
+					_log.debug(l -> l.debug("CCR Event {} matches {} because of {}", eventString, _component.template().name, _component.template().configurations));
+
 					Promise<Boolean> result = containerState.submit(
 						Op.of(Mode.OPEN, Type.CONFIGURATION_EVENT, eventString),
 						() -> {
diff --git a/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Discovery.java b/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Discovery.java
index 71f8d18..4202f5f 100644
--- a/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Discovery.java
+++ b/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Discovery.java
@@ -14,13 +14,14 @@
 
 package org.apache.aries.cdi.container.internal.container;
 
+import static java.util.stream.Collectors.toList;
+
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -31,6 +32,8 @@
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.context.Dependent;
@@ -72,12 +75,14 @@
 import org.osgi.service.cdi.annotations.ComponentScoped;
 import org.osgi.service.cdi.annotations.FactoryComponent;
 import org.osgi.service.cdi.annotations.PID;
+import org.osgi.service.cdi.annotations.PIDs;
 import org.osgi.service.cdi.annotations.Reference;
 import org.osgi.service.cdi.annotations.SingleComponent;
 import org.osgi.service.cdi.reference.BindBeanServiceObjects;
 import org.osgi.service.cdi.reference.BindService;
 import org.osgi.service.cdi.reference.BindServiceReference;
 import org.osgi.service.cdi.runtime.dto.template.ComponentTemplateDTO;
+import org.osgi.service.log.Logger;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -111,6 +116,7 @@
 
 	public Discovery(ContainerState containerState) {
 		_containerState = containerState;
+		_log = _containerState.ccrLogs().getLogger(getClass());
 		_beansModel = _containerState.beansModel();
 		_containerTemplate = _containerState.containerDTO().template.components.get(0);
 
@@ -308,8 +314,8 @@
 	}
 
 	void discoverActivations(OSGiBean osgiBean, Class<?> declaringClass, final Annotated component,
-							 AnnotatedMember<?> producer, Class<? extends Annotation> scope,
-							 List<String> serviceTypeNames) {
+							AnnotatedMember<?> producer, Class<? extends Annotation> scope,
+							List<String> serviceTypeNames) {
 		String className = declaringClass.getName();
 
 		if (!_containerTemplate.beans.contains(className)) {
@@ -371,7 +377,13 @@
 		componentTemplate.references = new CopyOnWriteArrayList<>();
 		componentTemplate.type = componentType;
 
-		annotated.getAnnotations(PID.class).stream().forEach(
+		List<PID> pids = annotated.getAnnotations(PIDs.class).stream().flatMap(ps -> Stream.of(ps.value())).collect(Collectors.toList());
+
+		if (pids.isEmpty()) {
+			pids = annotated.getAnnotations(PID.class).stream().collect(toList());
+		}
+
+		pids.forEach(
 			PID -> {
 				String pid = PID.value();
 
@@ -390,6 +402,11 @@
 				configurationTemplate.policy = PID.policy();
 
 				componentTemplate.configurations.add(configurationTemplate);
+
+				_log.debug(l -> l.debug(
+					"Added specified configuration {}:{}:{} to {}",
+					configurationTemplate.pid, configurationTemplate.policy,
+					configurationTemplate.maximumCardinality, configurationTemplate.declaringClass));
 			}
 		);
 
@@ -403,6 +420,11 @@
 				configurationTemplate.policy = ConfigurationPolicy.OPTIONAL;
 
 				componentTemplate.configurations.add(configurationTemplate);
+
+				_log.debug(l -> l.debug(
+					"Added default configuration {}:{}:{} to {}",
+					configurationTemplate.pid, configurationTemplate.policy,
+					configurationTemplate.maximumCardinality, configurationTemplate.declaringClass));
 			}
 		}
 		else {
@@ -418,6 +440,11 @@
 			configurationTemplate.policy = ConfigurationPolicy.REQUIRED;
 
 			componentTemplate.configurations.add(configurationTemplate);
+
+			_log.debug(l -> l.debug(
+				"Added factory configuration {}:{}:{} to {}",
+				configurationTemplate.pid, configurationTemplate.policy,
+				configurationTemplate.maximumCardinality, configurationTemplate.declaringClass));
 		}
 
 		componentTemplate.beans.add(declaringClass.getName());
@@ -504,6 +531,7 @@
 	private final Set<OSGiBean> _componentScoped = new HashSet<>();
 	private final ComponentTemplateDTO _containerTemplate;
 	private final ContainerState _containerState;
+	private final Logger _log;
 	private final boolean _trim;
 	private final List<Exclude> _excludes;
 
diff --git a/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ExtendedComponentInstanceDTO.java b/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ExtendedComponentInstanceDTO.java
index bfcd685..1bf268a 100644
--- a/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ExtendedComponentInstanceDTO.java
+++ b/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ExtendedComponentInstanceDTO.java
@@ -14,7 +14,7 @@
 
 package org.apache.aries.cdi.container.internal.model;
 
-import static org.apache.aries.cdi.container.internal.util.Filters.*;
+import static org.apache.aries.cdi.container.internal.util.Filters.asFilter;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -274,11 +274,16 @@
 	}
 
 	public Map<String, Object> componentProperties(Map<String, Object> others) {
+		_log.debug(l -> l.debug("ComponentProperties: merging"));
+
 		Map<String, Object> props = new HashMap<>();
 		if (others != null) {
 			props.putAll(others);
+			_log.debug(l -> l.debug("ComponentProperties: others {}", props));
 		}
 		props.putAll(template.properties);
+		_log.debug(l -> l.debug("ComponentProperties: template {}", props));
+
 		List<String> servicePids = new ArrayList<>();
 
 		for (ConfigurationTemplateDTO t : template.configurations) {
@@ -295,6 +300,7 @@
 					);
 
 					props.putAll(copy);
+					_log.debug(l -> l.debug("ComponentProperties: config {}:{}:{} {}", t.pid, t.policy, t.maximumCardinality, props));
 				}
 			);
 		}
@@ -304,6 +310,7 @@
 		}
 		props.put("component.id", _componentId);
 		props.put("component.name", template.name);
+		_log.debug(l -> l.debug("ComponentProperties: final {}", props));
 
 		return props;
 	}