Modified: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Constants.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Constants.java?rev=1807424&r1=1807423&r2=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Constants.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Constants.java
 Tue Sep  5 22:01:11 2017
@@ -28,22 +28,26 @@ public class Constants {
        public static final Set<String> CDI_URIS = 
Sets.immutableHashSet(CDI10_URI);
 
        public static final String ARRAY_ELEMENT = "array";
-       public static final String BEAN_CLASS_ATTRIBUTE = "beanClass";
-       public static final String BEAN_ELEMENT = "bean";
-       public static final String BEANS_ELEMENT = "beans";
+       public static final String CARDINALITY_ATTRIBUTE = "cardinality";
        public static final String CLASS_ATTRIBUTE = "class";
+       public static final String COMPONENT_ELEMENT = "component";
        public static final String CONFIGURATION_ELEMENT = "configuration";
+       public static final String CONFIGURATION_PID_ATTRIBUTE = 
"configuration-pid";
+       public static final String CONFIGURATION_POLICY_ATTRIBUTE = 
"configuration-policy";
        public static final String INTERFACE_ATTRIBUTE = "interface";
        public static final String LIST_ELEMENT = "list";
        public static final String NAME_ATTRIBUTE = "name";
-       public static final String PID_ATTRIBUTE = "pid";
+       public static final String POLICY_ATTRIBUTE = "policy";
+       public static final String POLICY_OPTION_ATTRIBUTE = "policy-option";
        public static final String PROPERTY_ELEMENT = "property";
        public static final String PROVIDE_ELEMENT = "provide";
        public static final String REFERENCE_ELEMENT = "reference";
-       public static final String REQUIRED_ATTRIBUTE = "required";
-       public static final String SERVICE_ELEMENT = "service";
+       public static final String SCOPE_ATTRIBUTE= "scope";
+       public static final String SERVICE_ATTRIBUTE = "service";
+       public static final String SERVICE_SCOPE_ATTRIBUTE = "service-scope";
        public static final String SET_ELEMENT = "set";
        public static final String TARGET_ATTRIBUTE = "target";
+       public static final String TYPE_ATTRIBUTE = "type";
        public static final String VALUE_ATTRIBUTE = "value";
        public static final String VALUE_ELEMENT = "value";
        public static final String VALUE_TYPE_ATTRIBUTE = "value-type";

Copied: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Context.java
 (from r1806482, 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase.java)
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Context.java?p2=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Context.java&p1=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase.java&r1=1806482&r2=1807424&rev=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Context.java
 Tue Sep  5 22:01:11 2017
@@ -12,12 +12,17 @@
  * limitations under the License.
  */
 
-package org.apache.aries.cdi.container.internal.container;
+package org.apache.aries.cdi.container.internal.model;
 
-public interface Phase {
+import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
 
-       public void close();
+public abstract class Context {
 
-       public void open();
+       public abstract <T> T getService(ServiceReference<T> reference);
+
+       public abstract <T> ServiceObjects<T> 
getServiceObjects(ServiceReference<T> reference);
+
+       public abstract <T> boolean ungetService(ServiceReference<T> reference);
 
 }

Copied: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Model.java
 (from r1806482, 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/AbstractModel.java)
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Model.java?p2=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Model.java&p1=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/AbstractModel.java&r1=1806482&r2=1807424&rev=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/AbstractModel.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Model.java
 Tue Sep  5 22:01:11 2017
@@ -16,9 +16,9 @@ package org.apache.aries.cdi.container.i
 
 import org.xml.sax.Attributes;
 
-public class AbstractModel {
+public class Model {
 
-       boolean getBoolean(String uri, String localName, Attributes attributes, 
boolean defaultValue) {
+       public static boolean getBoolean(String uri, String localName, 
Attributes attributes, boolean defaultValue) {
                String value = getValue(uri, localName, attributes);
 
                if (value == null) {
@@ -28,7 +28,11 @@ public class AbstractModel {
                return Boolean.parseBoolean(value);
        }
 
-       String getValue(String uri, String localName, Attributes attributes) {
+       public static String getValue(String uri, String localName, Attributes 
attributes) {
+               return getValue(uri, localName, attributes, "");
+       }
+
+       public static String getValue(String uri, String localName, Attributes 
attributes, String defaultValue) {
                String value = attributes.getValue(uri, localName);
 
                if (value == null) {
@@ -39,7 +43,29 @@ public class AbstractModel {
                        value = value.trim();
                }
 
+               if (value == null) {
+                       return defaultValue;
+               }
+
                return value;
        }
 
+       public static String[] getValues(String uri, String localName, 
Attributes attributes) {
+               return getValues(uri, localName, attributes, new String[0]);
+       }
+
+       public static String[] getValues(String uri, String localName, 
Attributes attributes, String[] defaultValue) {
+               String value = getValue(uri, localName, attributes, "");
+
+               if (value.length() == 0) {
+                       return defaultValue;
+               }
+
+               return value.split("\\s+");
+       }
+
+       private Model() {
+               // TODO Auto-generated constructor stub
+       }
+
 }

Modified: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/OSGiBeansHandler.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/OSGiBeansHandler.java?rev=1807424&r1=1807423&r2=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/OSGiBeansHandler.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/OSGiBeansHandler.java
 Tue Sep  5 22:01:11 2017
@@ -15,9 +15,10 @@
 package org.apache.aries.cdi.container.internal.model;
 
 import static 
org.apache.aries.cdi.container.internal.model.Constants.ARRAY_ELEMENT;
-import static 
org.apache.aries.cdi.container.internal.model.Constants.BEAN_ELEMENT;
-import static org.apache.aries.cdi.container.internal.model.Constants.CDI_URIS;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.CLASS_ATTRIBUTE;
+import static 
org.apache.aries.cdi.container.internal.model.Constants.CDI10_URI;
+import static org.apache.aries.cdi.container.internal.model.Constants.CDI_URIS;
+import static 
org.apache.aries.cdi.container.internal.model.Constants.COMPONENT_ELEMENT;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.CONFIGURATION_ELEMENT;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.INTERFACE_ATTRIBUTE;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.LIST_ELEMENT;
@@ -25,30 +26,37 @@ import static org.apache.aries.cdi.conta
 import static 
org.apache.aries.cdi.container.internal.model.Constants.PROPERTY_ELEMENT;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.PROVIDE_ELEMENT;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.REFERENCE_ELEMENT;
-import static 
org.apache.aries.cdi.container.internal.model.Constants.SERVICE_ELEMENT;
+import static 
org.apache.aries.cdi.container.internal.model.Constants.SERVICE_ATTRIBUTE;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.SET_ELEMENT;
+import static 
org.apache.aries.cdi.container.internal.model.Constants.TYPE_ATTRIBUTE;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.VALUE_ATTRIBUTE;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.VALUE_ELEMENT;
 import static 
org.apache.aries.cdi.container.internal.model.Constants.VALUE_TYPE_ATTRIBUTE;
 
 import java.net.URL;
-import java.util.ArrayList;
 import java.util.Formatter;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import org.apache.aries.cdi.container.internal.component.ComponentModel;
+import 
org.apache.aries.cdi.container.internal.configuration.ConfigurationModel;
+import org.apache.aries.cdi.container.internal.reference.ReferenceModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
 public class OSGiBeansHandler extends DefaultHandler {
 
-       public OSGiBeansHandler(List<URL> beanDescriptorURLs) {
+       public OSGiBeansHandler(List<URL> beanDescriptorURLs, ClassLoader 
classLoader) {
                _beanDescriptorURLs = beanDescriptorURLs;
+               _classLoader = classLoader;
        }
 
        public BeansModel createBeansModel() {
-               return new BeansModel(
-                       _beanClasses, _configurationModels, _referenceModels, 
_serviceModels, _beanDescriptorURLs);
+               return new BeansModel(_components, _beanDescriptorURLs);
        }
 
        @Override
@@ -65,14 +73,31 @@ public class OSGiBeansHandler extends De
                if (matches(ARRAY_ELEMENT, uri, localName) && (_propertyValue 
== null)) {
                        _collectionType = CollectionType.ARRAY;
                }
-               if (matches(BEAN_ELEMENT, uri, localName)) {
-                       _beanClass = 
attributes.getValue(CLASS_ATTRIBUTE).trim();
-                       if (!_beanClasses.contains(_beanClass)) {
-                               _beanClasses.add(_beanClass);
+               if (matches(COMPONENT_ELEMENT, uri, localName)) {
+                       try {
+                               Class<?> clazz = _classLoader.loadClass(
+                                       Model.getValue(CDI10_URI, 
CLASS_ATTRIBUTE, attributes));
+
+                               _componentModel = new 
ComponentModel.Builder(clazz).attributes(attributes);
+                       }
+                       catch (ClassNotFoundException cnfe) {
+                               if (_log.isErrorEnabled()) {
+                                       _log.error("CDIe - {}", 
cnfe.getMessage(), cnfe);
+                               }
                        }
                }
                if (matches(CONFIGURATION_ELEMENT, uri, localName)) {
-                       _configurationModel = new 
ConfigurationModel(attributes);
+                       try {
+                               Class<?> clazz = _classLoader.loadClass(
+                                       Model.getValue(CDI10_URI, 
TYPE_ATTRIBUTE, attributes));
+
+                               _componentModel.configuration(new 
ConfigurationModel.Builder(clazz).attributes(attributes).build());
+                       }
+                       catch (ClassNotFoundException cnfe) {
+                               if (_log.isErrorEnabled()) {
+                                       _log.error("CDIe - {}", 
cnfe.getMessage(), cnfe);
+                               }
+                       }
                }
                if (matches(LIST_ELEMENT, uri, localName) && (_propertyValue == 
null)) {
                        _collectionType = CollectionType.LIST;
@@ -93,12 +118,20 @@ public class OSGiBeansHandler extends De
                }
                if (matches(PROVIDE_ELEMENT, uri, localName)) {
                        String value = 
attributes.getValue(INTERFACE_ATTRIBUTE).trim();
-                       _serviceModel.addProvide(value);                }
-               if (matches(REFERENCE_ELEMENT, uri, localName)) {
-                       _referenceModel = new ReferenceModel(attributes);
+                       _componentModel.provide(value);
                }
-               if (matches(SERVICE_ELEMENT, uri, localName)) {
-                       _serviceModel = new ServiceModel(_beanClass);
+               if (matches(REFERENCE_ELEMENT, uri, localName)) {
+                       try {
+                               Class<?> clazz = _classLoader.loadClass(
+                                       Model.getValue(CDI10_URI, 
SERVICE_ATTRIBUTE, attributes));
+
+                               _referenceModel = new 
ReferenceModel.Builder(attributes).service(clazz).build();
+                       }
+                       catch (ClassNotFoundException cnfe) {
+                               if (_log.isErrorEnabled()) {
+                                       _log.error("CDIe - {}", 
cnfe.getMessage(), cnfe);
+                               }
+                       }
                }
                if (matches(SET_ELEMENT, uri, localName) && (_propertyValue == 
null)) {
                        _collectionType = CollectionType.SET;
@@ -113,9 +146,10 @@ public class OSGiBeansHandler extends De
                if (matches(ARRAY_ELEMENT, uri, localName)) {
                        _collectionType = null;
                }
-               if (matches(CONFIGURATION_ELEMENT, uri, localName)) {
-                       _configurationModels.add(_configurationModel);
-                       _configurationModel = null;
+               if (matches(COMPONENT_ELEMENT, uri, localName)) {
+                       ComponentModel componentModel = _componentModel.build();
+                       
_components.put(componentModel.getBeanClass().getName(), componentModel);
+                       _componentModel = null;
                }
                if (matches(LIST_ELEMENT, uri, localName)) {
                        _collectionType = null;
@@ -127,7 +161,7 @@ public class OSGiBeansHandler extends De
                        if (_propertyValue != null) {
                                try (Formatter f = new Formatter()) {
                                        f.format("%s:%s=%s", _propertyName, 
_propertyType, _propertyValue);
-                                       _serviceModel.addProperty(f.toString());
+                                       _componentModel.property(f.toString());
                                }
                        }
                        _propertySB = null;
@@ -136,14 +170,9 @@ public class OSGiBeansHandler extends De
                        _propertyValue = null;
                }
                if (matches(REFERENCE_ELEMENT, uri, localName)) {
-                       _referenceModels.add(_referenceModel);
+                       _componentModel.reference(_referenceModel);
                        _referenceModel = null;
                }
-               if (matches(SERVICE_ELEMENT, uri, localName)) {
-                       _serviceModels.add(_serviceModel);
-                       _serviceModel = null;
-                       _beanClass = null;
-               }
                if (matches(SET_ELEMENT, uri, localName)) {
                        _collectionType = null;
                }
@@ -167,7 +196,7 @@ public class OSGiBeansHandler extends De
                        sb.append("=");
                        sb.append(_propertySB.toString().trim());
 
-                       _serviceModel.addProperty(sb.toString());
+                       _componentModel.property(sb.toString());
                        _propertySB = null;
                }
        }
@@ -183,19 +212,18 @@ public class OSGiBeansHandler extends De
                ARRAY, LIST, SET
        }
 
-       private String _beanClass;
-       private final List<String> _beanClasses = new ArrayList<String>();
+       private final static Logger _log = LoggerFactory.getLogger(
+               OSGiBeansHandler.class);
+
+       private final ClassLoader _classLoader;
+       private final Map<String, ComponentModel> _components = new HashMap<>();
        private final List<URL> _beanDescriptorURLs;
-       private ConfigurationModel _configurationModel;
-       private final List<ConfigurationModel> _configurationModels = new 
ArrayList<>();
        private String _propertyName;
        private StringBuilder _propertySB;
        private String _propertyType;
        private String _propertyValue;
        private CollectionType _collectionType;
        private ReferenceModel _referenceModel;
-       private final List<ReferenceModel> _referenceModels = new ArrayList<>();
-       private ServiceModel _serviceModel;
-       private final List<ServiceModel> _serviceModels = new ArrayList<>();
+       private ComponentModel.Builder _componentModel;
 
 }

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ObserverMethodAnnotated.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ObserverMethodAnnotated.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ObserverMethodAnnotated.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ObserverMethodAnnotated.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,58 @@
+package org.apache.aries.cdi.container.internal.model;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.ObserverMethod;
+
+import org.apache.aries.cdi.container.internal.util.Sets;
+import org.osgi.service.cdi.annotations.ServiceEvent;
+
+public class ObserverMethodAnnotated implements Annotated {
+
+       public ObserverMethodAnnotated(ObserverMethod<ServiceEvent<?>> 
observerMethod) {
+               _observerMethod = observerMethod;
+               _qualifiers = _observerMethod.getObservedQualifiers();
+       }
+
+       @Override
+       public boolean isAnnotationPresent(Class<? extends Annotation> 
annotationType) {
+               for (Annotation annotation : _qualifiers) {
+                       if (annotationType.isInstance(annotation)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       @Override
+       public Set<Type> getTypeClosure() {
+               return Sets.immutableHashSet(getBaseType());
+       }
+
+       @Override
+       public Type getBaseType() {
+               return _observerMethod.getObservedType();
+       }
+
+       @Override
+       public Set<Annotation> getAnnotations() {
+               return _qualifiers;
+       }
+
+       @Override
+       public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+               for (Annotation annotation : _qualifiers) {
+                       if (annotationType.isInstance(annotation)) {
+                               return (T)annotation;
+                       }
+               }
+               return null;
+       }
+
+       private final ObserverMethod<ServiceEvent<?>> _observerMethod;
+       private final Set<Annotation> _qualifiers;
+
+}
\ No newline at end of file

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Registrator.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Registrator.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Registrator.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Registrator.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,69 @@
+/**
+ * Licensed 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.aries.cdi.container.internal.model;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class Registrator<T> {
+
+       public abstract void registerService(String[] classNames, T service, 
Dictionary<String, ?> properties);
+
+       public void registerService(T service, Object... keyValues) {
+               if ((keyValues.length % 2) != 0) throw new 
IllegalArgumentException("keyValues must be [String, Object]+");
+
+               Dictionary<String, Object> properties = new Hashtable<>();
+
+               if (keyValues.length > 0) {
+                       for (int i = 0; i < keyValues.length; i += 2) {
+                               properties.put(String.valueOf(keyValues[i]), 
keyValues[i + 1]);
+                       }
+               }
+
+               registerService(null, service, properties);
+       }
+
+       public int size() {
+               return registrations.size();
+       }
+
+       public void close() {
+               registrations.removeIf(
+                       r -> {
+                               try {
+                                       r.unregister();
+                               }
+                               catch (IllegalStateException ise) {
+                                       if (_log.isTraceEnabled()) {
+                                               _log.trace("Service already 
unregistered {}", r);
+                                       }
+                               }
+
+                               return true;
+                       }
+               );
+       }
+
+       private static final Logger _log = 
LoggerFactory.getLogger(Registrator.class);
+
+       protected final List<ServiceRegistration<?>> registrations = new 
CopyOnWriteArrayList<>();
+
+}

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ServiceEventImpl.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ServiceEventImpl.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ServiceEventImpl.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ServiceEventImpl.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,55 @@
+/**
+ * Licensed 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.aries.cdi.container.internal.model;
+
+import org.osgi.service.cdi.annotations.ServiceEvent;
+
+public class ServiceEventImpl<T> implements ServiceEvent<T> {
+
+       public static enum Event { ADDING, MODIFIED, REMOVED }
+
+       private final T _t;
+       private final ServiceEventImpl.Event _event;
+
+       public ServiceEventImpl(T t, ServiceEventImpl.Event event) {
+               _t = t;
+               _event = event;
+       }
+
+       @Override
+       public ServiceEvent<T> adding(Consumer<T> consumer) {
+               if (_event == Event.ADDING) {
+                       consumer.accept(_t);
+               };
+               return this;
+       }
+
+       @Override
+       public ServiceEvent<T> modified(Consumer<T> consumer) {
+               if (_event == Event.MODIFIED) {
+                       consumer.accept(_t);
+               }
+               return this;
+       }
+
+       @Override
+       public ServiceEvent<T> removed(Consumer<T> consumer) {
+               if (_event == Event.REMOVED) {
+                       consumer.accept(_t);
+               }
+               return this;
+       }
+
+}
\ No newline at end of file

Copied: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Tracker.java
 (from r1806482, 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ServiceModel.java)
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Tracker.java?p2=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Tracker.java&p1=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ServiceModel.java&r1=1806482&r2=1807424&rev=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/ServiceModel.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/model/Tracker.java
 Tue Sep  5 22:01:11 2017
@@ -14,36 +14,34 @@
 
 package org.apache.aries.cdi.container.internal.model;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
-public class ServiceModel {
+import org.apache.aries.cdi.container.internal.reference.ReferenceCallback;
+import org.osgi.util.tracker.ServiceTracker;
 
-       public ServiceModel(String beanClass) {
-               _beanClass = beanClass;
-       }
+public abstract class Tracker {
 
-       public void addProvide(String className) {
-               _provides.add(className);
-       }
+       public abstract <T> void track(String targetFilter, ReferenceCallback 
callback);
 
-       public void addProperty(String property) {
-               _properties.add(property);
+       public int size() {
+               return trackers.size();
        }
 
-       public String getBeanClass() {
-               return _beanClass;
-       }
+       public void close() {
+               trackers.removeIf(
+                       t -> {
+                               t.close();
 
-       public String[] getProperties() {
-               return _properties.toArray(new String[0]);
+                               return true;
+                       }
+               );
        }
 
-       public List<String> getProvides() {
-               return _provides;
+       public void open() {
+               trackers.stream().forEach(t -> t.open());
        }
 
-       private final String _beanClass;
-       private List<String> _properties = new ArrayList<>();
-       private List<String> _provides = new ArrayList<>();
+       protected final List<ServiceTracker<Object, ?>> trackers = new 
CopyOnWriteArrayList<>();
+
 }

Copied: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase.java
 (from r1806482, 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase.java)
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase.java?p2=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase.java&p1=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase.java&r1=1806482&r2=1807424&rev=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase.java
 Tue Sep  5 22:01:11 2017
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package org.apache.aries.cdi.container.internal.container;
+package org.apache.aries.cdi.container.internal.phase;
 
 public interface Phase {
 

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Configuration.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Configuration.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Configuration.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Configuration.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,245 @@
+/**
+ * Licensed 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.aries.cdi.container.internal.phase;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
+
+import javax.enterprise.inject.spi.Extension;
+
+import org.apache.aries.cdi.container.internal.component.ComponentModel;
+import 
org.apache.aries.cdi.container.internal.configuration.ConfigurationCallback;
+import 
org.apache.aries.cdi.container.internal.configuration.ConfigurationManagedService;
+import org.apache.aries.cdi.container.internal.container.ContainerState;
+import org.jboss.weld.bootstrap.spi.Metadata;
+import org.osgi.framework.Constants;
+import org.osgi.service.cdi.CdiEvent;
+import org.osgi.service.cdi.annotations.Configuration;
+import org.osgi.service.cdi.annotations.ConfigurationPolicy;
+
+public class Phase_Configuration implements Phase {
+
+       public Phase_Configuration(
+               ContainerState containerState,
+               Collection<Metadata<Extension>> extensions) {
+
+               _containerState = containerState;
+               _extensions = extensions;
+
+               _componentModels = 
_containerState.beansModel().getComponentModels();
+       }
+
+       @Override
+       public void close() {
+               _lock.lock();
+
+               try {
+                       if (_nextPhase != null) {
+                               _nextPhase.close();
+
+                               _nextPhase = null;
+                       }
+
+                       _containerState.managedServiceRegistrator().close();
+
+                       _containerState.configurationCallbacks().clear();
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       @Override
+
+       public void open() {
+               _lock.lock();
+
+               try {
+                       
_containerState.fire(CdiEvent.Type.WAITING_FOR_CONFIGURATIONS);
+
+                       openConfigurations();
+
+                       callbacksInit();
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       boolean callbacksExist() {
+               return 
_containerState.configurationCallbacks().values().stream().flatMap(
+                       entry -> entry.values().stream()
+               ).findFirst().isPresent();
+       }
+
+       void callbacksInit() {
+               
_containerState.configurationCallbacks().values().stream().flatMap(
+                       valueMap -> valueMap.values().stream()
+               ).forEach(
+                       cc -> cc.init()
+               );
+       }
+
+       boolean callbacksResolved() {
+               return 
!_containerState.configurationCallbacks().values().stream().flatMap(
+                       valueMap -> valueMap.values().stream()
+               ).filter(
+                       c -> !c.resolved()
+               ).findFirst().isPresent();
+       }
+
+       void openConfigurations() {
+               Consumer<ConfigurationCallback> onAdd = cc -> {
+                       _lock.lock();
+                       try {
+                               if (callbacksResolved()) {
+                                       if ((_nextPhase != null)) {
+                                               _nextPhase.close();
+                                               _nextPhase = null;
+                                       }
+
+                                       if ((_nextPhase == null)) {
+                                               _nextPhase = new 
Phase_Reference(_containerState, _extensions);
+                                               _nextPhase.open();
+                                       }
+                               }
+                       }
+                       finally {
+                               _lock.unlock();
+                       }
+               },
+               onUpdate = cc -> {
+                       _lock.lock();
+                       try {
+                               _nextPhase.close();
+                               _nextPhase = new 
Phase_Reference(_containerState, _extensions);
+                               _nextPhase.open();
+                       }
+                       finally {
+                               _lock.unlock();
+                       }
+               },
+               onRemove = cc -> {
+                       _lock.lock();
+                       try {
+                               if (_nextPhase != null) {
+                                       _nextPhase.close();
+                               }
+                               if (!callbacksResolved()) {
+                                       _nextPhase = null;
+                                       
_containerState.fire(CdiEvent.Type.WAITING_FOR_CONFIGURATIONS);
+                               }
+                               else {
+                                       _nextPhase = new 
Phase_Reference(_containerState, _extensions);
+                                       _nextPhase.open();
+                               }
+                       }
+                       finally {
+                               _lock.unlock();
+                       }
+               };
+
+               _componentModels.stream().forEach(
+                       componentModel -> openConfigurations(componentModel, 
onAdd, onUpdate, onRemove)
+               );
+       }
+
+       void openConfigurations(
+               ComponentModel componentModel,
+               Consumer<ConfigurationCallback> onAdd,
+               Consumer<ConfigurationCallback> onUpdate,
+               Consumer<ConfigurationCallback> onRemove) {
+
+               _lock.lock();
+
+               try {
+                       componentModel.getConfigurations().stream().forEach(
+                               configurationModel -> 
Arrays.stream(configurationModel.getPid()).distinct().forEach(
+                                       pid -> {
+                                               if 
(Configuration.NAME.equals(pid)) {
+                                                       pid = 
componentModel.getName();
+                                               }
+
+                                               registerConfigurationCallback(
+                                                       componentModel, pid, 
onAdd, onUpdate, onRemove, configurationModel.getConfigurationPolicy());
+                                       }
+                               )
+                       );
+
+                       if 
(!_containerState.configurationCallbacks().containsKey(componentModel)) {
+
+                               // Add a default callback for every Component 
using it's name as pid.
+
+                               registerConfigurationCallback(
+                                       componentModel, 
componentModel.getName(), onAdd, onUpdate, onRemove, 
ConfigurationPolicy.OPTIONAL);
+                       }
+               }
+               catch (Exception e) {
+                       e.printStackTrace();
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       void registerConfigurationCallback(
+               ComponentModel componentModel,
+               String pid,
+               Consumer<ConfigurationCallback> onAdd,
+               Consumer<ConfigurationCallback> onUpdate,
+               Consumer<ConfigurationCallback> onRemove,
+               ConfigurationPolicy policy) {
+
+               Map<String, ConfigurationCallback> valueMap = 
_containerState.configurationCallbacks().computeIfAbsent(
+                       componentModel, k -> new LinkedHashMap<>());
+
+               ConfigurationCallback callback = valueMap.get(pid);
+
+               if ((callback == null) ||
+                       (policy == ConfigurationPolicy.REQUIRE)) {
+
+                       callback = new ConfigurationCallback.Builder().onAdd(
+                               onAdd
+                       ).onRemove(
+                               onRemove
+                       ).onUpdate(
+                               onUpdate
+                       ).pid(
+                               pid
+                       ).policy(
+                               policy
+                       ).build();
+
+                       valueMap.put(pid, callback);
+               }
+
+               _containerState.managedServiceRegistrator().registerService(
+                       new ConfigurationManagedService(pid, callback),
+                       Constants.SERVICE_PID, pid, "component.id", 
_counter.incrementAndGet());
+       }
+
+       private final Collection<ComponentModel> _componentModels;
+       private final ContainerState _containerState;
+       private final AtomicInteger _counter = new AtomicInteger();
+       private final Collection<Metadata<Extension>> _extensions;
+       private final Lock _lock = new ReentrantLock();
+       private volatile Phase _nextPhase;
+}
\ No newline at end of file

Copied: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Extension.java
 (from r1806482, 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_Extension.java)
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Extension.java?p2=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Extension.java&p1=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_Extension.java&r1=1806482&r2=1807424&rev=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/Phase_Extension.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Extension.java
 Tue Sep  5 22:01:11 2017
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package org.apache.aries.cdi.container.internal.container;
+package org.apache.aries.cdi.container.internal.phase;
 
 import java.util.Comparator;
 import java.util.List;
@@ -22,9 +22,14 @@ import java.util.concurrent.CopyOnWriteA
 
 import javax.enterprise.inject.spi.Extension;
 
+import org.apache.aries.cdi.container.internal.container.ContainerState;
+import org.apache.aries.cdi.container.internal.extension.ExtensionDependency;
+import org.apache.aries.cdi.container.internal.extension.ExtensionMetadata;
 import org.jboss.weld.bootstrap.spi.Metadata;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.wiring.BundleWire;
 import org.osgi.framework.wiring.BundleWiring;
@@ -37,20 +42,20 @@ import org.slf4j.LoggerFactory;
 
 public class Phase_Extension implements Phase {
 
-       public Phase_Extension(CdiContainerState cdiContainerState) {
-               _cdiContainerState = cdiContainerState;
-               _bundleContext = 
_cdiContainerState.getBundle().getBundleContext();
-               _extensionDependencies = findExtensionDependencies(
-                       
_cdiContainerState.getBundle().adapt(BundleWiring.class));
+       public Phase_Extension(ContainerState containerState) {
+               _containerState = containerState;
+               _bundleContext = _containerState.bundle().getBundleContext();
+
+               BundleWiring bundleWiring = 
_containerState.bundle().adapt(BundleWiring.class);
+
+               _extensionDependencies = 
findExtensionDependencies(bundleWiring);
                _extensions = new 
ConcurrentSkipListMap<>(Comparator.reverseOrder());
 
-               
_cdiContainerState.setExtensionDependencies(_extensionDependencies);
+               
_containerState.setExtensionDependencies(_extensionDependencies);
        }
 
        @Override
        public void close() {
-               _cdiContainerState.fire(CdiEvent.Type.DESTROYING);
-
                if (_extensionTracker != null) {
                        _extensionTracker.close();
 
@@ -61,32 +66,47 @@ public class Phase_Extension implements
 
                        _nextPhase = null;
                }
-
-               _cdiContainerState.fire(CdiEvent.Type.DESTROYED);
-
-               _cdiContainerState.close();
        }
 
        @Override
        public void open() {
-               _cdiContainerState.fire(CdiEvent.Type.CREATING);
-
                if (!_extensionDependencies.isEmpty()) {
-                       Filter filter = 
FilterBuilder.createExtensionFilter(_extensionDependencies);
+                       
_containerState.fire(CdiEvent.Type.WAITING_FOR_EXTENSIONS);
 
-                       
_cdiContainerState.fire(CdiEvent.Type.WAITING_FOR_EXTENSIONS, 
filter.toString());
+                       Filter filter = 
createExtensionFilter(_extensionDependencies);
 
                        _extensionTracker = new 
ServiceTracker<>(_bundleContext, filter, new ExtensionPhaseCustomizer());
 
                        _extensionTracker.open();
                }
                else {
-                       _nextPhase = new 
Phase_Configuration(_cdiContainerState, _extensions);
+                       _nextPhase = new Phase_Configuration(_containerState, 
_extensions.values());
 
                        _nextPhase.open();
                }
        }
 
+       Filter createExtensionFilter(List<ExtensionDependency> 
extentionDependencies) {
+               try {
+                       StringBuilder sb = new StringBuilder("(&(objectClass=" 
+ Extension.class.getName() + ")");
+
+                       if (extentionDependencies.size() > 1) sb.append("(|");
+
+                       for (ExtensionDependency dependency : 
extentionDependencies) {
+                               sb.append(dependency.toString());
+                       }
+
+                       if (extentionDependencies.size() > 1) sb.append(")");
+
+                       sb.append(")");
+
+                       return FrameworkUtil.createFilter(sb.toString());
+               }
+               catch (InvalidSyntaxException ise) {
+                       throw new RuntimeException(ise);
+               }
+       }
+
        List<ExtensionDependency> findExtensionDependencies(BundleWiring 
bundleWiring) {
                List<ExtensionDependency> extensionDependencies = new 
CopyOnWriteArrayList<>();
                List<BundleWire> requiredWires = 
bundleWiring.getRequiredWires(CdiConstants.CDI_EXTENSION_NAMESPACE);
@@ -110,9 +130,9 @@ public class Phase_Extension implements
        private static final Logger _log = 
LoggerFactory.getLogger(Phase_Extension.class);
 
        private final BundleContext _bundleContext;
-       private final CdiContainerState _cdiContainerState;
-       private final Map<ServiceReference<Extension>, Metadata<Extension>> 
_extensions;
+       private final ContainerState _containerState;
        private final List<ExtensionDependency> _extensionDependencies;
+       private final Map<ServiceReference<Extension>, Metadata<Extension>> 
_extensions;
        private Phase _nextPhase;
 
        private ServiceTracker<Extension, ExtensionDependency> 
_extensionTracker;
@@ -137,7 +157,7 @@ public class Phase_Extension implements
                        }
 
                        if ((trackedDependency != null) && 
_extensionDependencies.isEmpty()) {
-                               _nextPhase = new 
Phase_Configuration(_cdiContainerState, _extensions);
+                               _nextPhase = new 
Phase_Configuration(_containerState, _extensions.values());
 
                                _nextPhase.open();
                        }
@@ -154,13 +174,8 @@ public class Phase_Extension implements
 
                @Override
                public void removedService(ServiceReference<Extension> 
reference, ExtensionDependency extentionDependency) {
-                       if (_extensionDependencies.isEmpty()) {
-                               _nextPhase.close();
-
-                               _nextPhase = null;
+                       _extensionDependencies.add(extentionDependency);
 
-                               
_cdiContainerState.fire(CdiEvent.Type.WAITING_FOR_EXTENSIONS);
-                       }
                        _extensions.remove(reference);
 
                        try {
@@ -172,7 +187,13 @@ public class Phase_Extension implements
                                }
                        }
 
-                       _extensionDependencies.add(extentionDependency);
+                       if (!_extensionDependencies.isEmpty()) {
+                               _nextPhase.close();
+
+                               _nextPhase = null;
+
+                               
_containerState.fire(CdiEvent.Type.WAITING_FOR_EXTENSIONS);
+                       }
                }
 
        }

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Init.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Init.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Init.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Init.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,89 @@
+/**
+ * Licensed 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.aries.cdi.container.internal.phase;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.aries.cdi.container.internal.container.ContainerDiscovery;
+import org.apache.aries.cdi.container.internal.container.ContainerState;
+import org.apache.aries.cdi.container.internal.model.BeansModel;
+import org.apache.aries.cdi.container.internal.model.BeansModelBuilder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleWiring;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Phase_Init implements Phase {
+
+       public Phase_Init(Bundle bundle, ContainerState containerState) {
+               _containerState = containerState;
+
+               BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
+
+               BeansModel beansModel = new 
BeansModelBuilder(_containerState.classLoader(), bundleWiring).build();
+
+               _containerState.setBeansModel(beansModel);
+       }
+
+       @Override
+       public void close() {
+               _lock.lock();
+
+               try {
+                       _extensionPhase.close();
+
+                       _extensionPhase = null;
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       @Override
+       public void open() {
+               _lock.lock();
+
+               try {
+                       if (_log.isDebugEnabled()) {
+                               _log.debug("CDIe - Starting discovery phase on 
{}", _containerState);
+                       }
+
+                       ContainerDiscovery.discover(_containerState);
+
+                       if (_log.isDebugEnabled()) {
+                               _log.debug("CDIe - Finished discovery phase on 
{}", _containerState);
+                       }
+
+                       if (_log.isDebugEnabled()) {
+                               _log.debug("CDIe - Begin extension phase on 
{}", _containerState);
+                       }
+
+                       _extensionPhase = new Phase_Extension(_containerState);
+
+                       _extensionPhase.open();
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       private static final Logger _log = 
LoggerFactory.getLogger(Phase_Init.class);
+
+       private final ContainerState _containerState;
+       private volatile Phase _extensionPhase;
+       private final Lock _lock = new ReentrantLock();
+
+}
\ No newline at end of file

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Publish.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Publish.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Publish.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Publish.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,103 @@
+/**
+ * Licensed 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.aries.cdi.container.internal.phase;
+
+import java.util.Collection;
+
+import javax.enterprise.inject.spi.Extension;
+
+import org.apache.aries.cdi.container.internal.container.ContainerBootstrap;
+import org.apache.aries.cdi.container.internal.container.ContainerState;
+import org.jboss.weld.bootstrap.WeldBootstrap;
+import org.jboss.weld.bootstrap.spi.Metadata;
+import org.jboss.weld.manager.BeanManagerImpl;
+import org.osgi.service.cdi.CdiEvent;
+import org.osgi.service.cdi.annotations.ServiceScope;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Phase_Publish implements Phase {
+
+       public Phase_Publish(
+               ContainerState containerState,
+               Collection<Metadata<Extension>> extensions) {
+
+               _containerState = containerState;
+               _extensions = extensions;
+       }
+
+       @Override
+       public void close() {
+               _containerState.serviceRegistrator().close();
+               _containerState.beanManagerRegistrator().close();
+               _containerState.serviceComponents().clear();
+               _cb.shutdown();
+       }
+
+       @Override
+       public void open() {
+               _containerState.fire(CdiEvent.Type.SATISFIED);
+
+               try {
+                       _cb = new ContainerBootstrap(_containerState, 
_extensions);
+
+                       BeanManagerImpl beanManagerImpl = 
_cb.getBeanManagerImpl();
+                       WeldBootstrap bootstrap = _cb.getBootstrap();
+
+                       bootstrap.validateBeans();
+                       bootstrap.endInitialization();
+
+                       
_containerState.referenceCallbacks().values().stream().flatMap(
+                               map -> map.values().stream()
+                       ).forEach(
+                               callback -> callback.flush()
+                       );
+
+                       processServices(beanManagerImpl);
+
+                       
_containerState.beanManagerRegistrator().registerService(beanManagerImpl);
+
+                       _containerState.fire(CdiEvent.Type.CREATED);
+               }
+               catch (Exception e) {
+                       e.printStackTrace();
+               }
+       }
+
+       private void processServices(BeanManagerImpl beanManagerImpl) {
+               _containerState.serviceComponents().values().stream().filter(
+                       serviceDeclaration ->
+                               serviceDeclaration.getScope() == 
ServiceScope.BUNDLE ||
+                               serviceDeclaration.getScope() == 
ServiceScope.PROTOTYPE ||
+                               serviceDeclaration.getScope() == 
ServiceScope.SINGLETON
+               ).forEach(
+                       s -> {
+                               if (_log.isDebugEnabled()) {
+                                       _log.debug("CDIe - Publishing component 
{} as '{}' service.", s.getName(), s.getScope());
+                               }
+
+                               
_containerState.serviceRegistrator().registerService(
+                                       s.getClassNames(), 
s.getServiceInstance(), s.getServiceProperties());
+                       }
+               );
+       }
+
+       private static final Logger _log = 
LoggerFactory.getLogger(Phase_Publish.class);
+
+       private volatile ContainerBootstrap _cb;
+       private final ContainerState _containerState;
+       private final Collection<Metadata<Extension>> _extensions;
+
+}
\ No newline at end of file

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Reference.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Reference.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Reference.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/phase/Phase_Reference.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,193 @@
+/**
+ * Licensed 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.aries.cdi.container.internal.phase;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
+
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ObserverMethod;
+
+import org.apache.aries.cdi.container.internal.component.ComponentModel;
+import org.apache.aries.cdi.container.internal.container.ContainerState;
+import org.apache.aries.cdi.container.internal.reference.ReferenceCallback;
+import org.apache.aries.cdi.container.internal.reference.ReferenceModel;
+import org.jboss.weld.bootstrap.spi.Metadata;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cdi.CdiEvent;
+import org.osgi.service.cdi.annotations.ServiceEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Phase_Reference implements Phase {
+
+       public Phase_Reference(
+               ContainerState containerState,
+               Collection<Metadata<Extension>> extensions) {
+
+               _containerState = containerState;
+               _extensions = extensions;
+
+               _componentModels = 
_containerState.beansModel().getComponentModels();
+       }
+
+       @Override
+       public void close() {
+               _lock.lock();
+
+               try {
+                       if (_nextPhase != null) {
+                               _nextPhase.close();
+
+                               _nextPhase = null;
+                       }
+
+                       _containerState.tracker().close();
+
+                       _containerState.referenceCallbacks().clear();
+                       _containerState.referenceObservers().clear();
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       @Override
+       public void open() {
+               _lock.lock();
+
+               try {
+                       
_containerState.fire(CdiEvent.Type.WAITING_FOR_SERVICES);
+
+                       openReferences();
+
+                       _containerState.tracker().open();
+
+                       if (referencesResolved()) {
+                               if (_log.isDebugEnabled()) {
+                                       _log.debug("CDIe - There are no service 
dependencies. Moving on!");
+                               }
+
+                               _nextPhase = new Phase_Publish(_containerState, 
_extensions);
+
+                               _nextPhase.open();
+                       }
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       void openReferences() {
+               Consumer<ReferenceCallback> onAdd = r -> {
+                       if ((_nextPhase == null) && referencesResolved()) {
+                               _nextPhase = new Phase_Publish(_containerState, 
_extensions);
+                               _nextPhase.open();
+                       }
+               },
+               onUpdate = r -> {
+                       // TODO we may need to handle static greedy references 
by hard reset of _nextPhase
+               },
+               onRemove = r -> {
+                       if ((_nextPhase != null) && !referencesResolved()) {
+                               _nextPhase.close();
+                               _nextPhase = null;
+                               
_containerState.fire(CdiEvent.Type.WAITING_FOR_SERVICES);
+                       }
+               };
+
+               _componentModels.stream().forEach(
+                       componentModel -> openReferences(componentModel, onAdd, 
onUpdate, onRemove)
+               );
+       }
+
+       private void openReferences(
+               ComponentModel componentModel,
+               Consumer<ReferenceCallback> onAdd,
+               Consumer<ReferenceCallback> onUpdate,
+               Consumer<ReferenceCallback> onRemove) {
+
+               _lock.lock();
+
+               try {
+                       componentModel.getReferences().stream().forEach(
+                               referenceModel -> {
+                                       Map<String, ReferenceCallback> map = 
_containerState.referenceCallbacks().computeIfAbsent(
+                                               componentModel, k -> new 
LinkedHashMap<>());
+
+                                       ReferenceCallback callback = new 
ReferenceCallback.Builder(
+                                               componentModel, 
_containerState, _containerState.context()
+                                       ).cardinality(
+                                               referenceModel.getCardinality()
+                                       ).collectionType(
+                                               
referenceModel.getCollectionType()
+                                       ).name(
+                                               referenceModel.getName()
+                                       ).onAdd(
+                                               onAdd
+                                       ).onRemove(
+                                               onRemove
+                                       ).onUpdate(
+                                               onUpdate
+                                       ).build();
+
+                                       map.put(referenceModel.getName(), 
callback);
+
+                                       try {
+                                               String targetFilter = 
ReferenceModel.buildFilter(
+                                                       
referenceModel.getServiceClass(), referenceModel.getTarget(), 
referenceModel.getScope(), referenceModel.getQualifiers());
+
+                                               
_containerState.tracker().track(targetFilter, callback);
+                                       }
+                                       catch (InvalidSyntaxException ise) {
+                                               if (_log.isErrorEnabled()) {
+                                                       _log.error("CDIe - {}", 
ise.getMessage(), ise);
+                                               }
+                                       }
+                               }
+                       );
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       boolean referencesExist() {
+               return 
_containerState.referenceCallbacks().values().stream().flatMap(
+                       entry -> entry.values().stream()
+               ).findFirst().isPresent();
+       }
+
+       boolean referencesResolved() {
+               return 
!_containerState.referenceCallbacks().values().stream().flatMap(
+                       valueMap -> valueMap.values().stream()
+               ).filter(
+                       c -> !c.resolved()
+               ).findFirst().isPresent();
+       }
+
+       private static final Logger _log = 
LoggerFactory.getLogger(Phase_Reference.class);
+
+       private final Collection<ComponentModel> _componentModels;
+       private final ContainerState _containerState;
+       private final Collection<Metadata<Extension>> _extensions;
+       private final Lock _lock = new ReentrantLock(true);
+       private volatile Phase _nextPhase;
+
+}

Copied: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/Multiplicity.java
 (from r1806482, 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BindType.java)
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/Multiplicity.java?p2=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/Multiplicity.java&p1=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BindType.java&r1=1806482&r2=1807424&rev=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/container/BindType.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/Multiplicity.java
 Tue Sep  5 22:01:11 2017
@@ -12,8 +12,10 @@
  * limitations under the License.
  */
 
-package org.apache.aries.cdi.container.internal.container;
+package org.apache.aries.cdi.container.internal.reference;
 
-public enum BindType {
-       SERVICE, SERVICE_PROPERTIES, SERVICE_REFERENCE
-}
\ No newline at end of file
+public enum Multiplicity {
+
+       MULTIPLE, UNARY
+
+}

Copied: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceBean.java
 (from r1806482, 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/ConfigurationBean.java)
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceBean.java?p2=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceBean.java&p1=aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/ConfigurationBean.java&r1=1806482&r2=1807424&rev=1807424&view=diff
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/ConfigurationBean.java
 (original)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceBean.java
 Tue Sep  5 22:01:11 2017
@@ -12,13 +12,12 @@
  * limitations under the License.
  */
 
-package org.apache.aries.cdi.container.internal.bean;
+package org.apache.aries.cdi.container.internal.reference;
 
 import static org.apache.aries.cdi.container.internal.util.Reflection.cast;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
-import java.util.AbstractMap;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -26,52 +25,63 @@ import java.util.Set;
 
 import javax.enterprise.context.Dependent;
 import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Annotated;
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.Decorator;
 import javax.enterprise.inject.spi.InjectionPoint;
 import javax.inject.Named;
 
-import 
org.apache.aries.cdi.container.internal.container.ConfigurationDependency;
-import org.apache.aries.cdi.container.internal.literal.AnyLiteral;
-import org.apache.aries.cdi.container.internal.literal.DefaultLiteral;
-import org.apache.aries.cdi.container.internal.util.Conversions;
-import org.apache.aries.cdi.container.internal.util.Sets;
+import org.apache.aries.cdi.container.internal.component.ComponentModel;
+import org.apache.aries.cdi.container.internal.container.ContainerState;
 import org.jboss.weld.injection.CurrentInjectionPoint;
 import org.jboss.weld.injection.EmptyInjectionPoint;
 import org.jboss.weld.manager.BeanManagerImpl;
 import org.jboss.weld.util.Decorators;
+import org.osgi.service.cdi.annotations.ReferenceCardinality;
 
-public class ConfigurationBean implements Bean<Object> {
+public class ReferenceBean implements Bean<Object> {
 
-       public ConfigurationBean(
-               ConfigurationDependency configurationDependency, 
BeanManagerImpl beanManagerImpl, Type injectionPointType,
-               Set<Annotation> qualifiers) {
-
-               _configurationDependency = configurationDependency;
+       public ReferenceBean(
+               ContainerState containerState,
+               ReferenceModel referenceModel,
+               ComponentModel componentModel,
+               Annotated annotated,
+               Set<Annotation> qualifiers,
+               BeanManagerImpl beanManagerImpl) {
+
+               _containerState = containerState;
+               _referenceModel = referenceModel;
+               _componentModel = componentModel;
+               _qualifiers = qualifiers;
                _beanManagerImpl = beanManagerImpl;
-               _typesForMatchingBeansToInjectionPoints = 
Sets.immutableHashSet(injectionPointType, Object.class);
-               _currentInjectionPoint = 
_beanManagerImpl.getServices().get(CurrentInjectionPoint.class);
-               _qualifiers = Sets.hashSet(qualifiers, DefaultLiteral.INSTANCE, 
AnyLiteral.INSTANCE);
-
-               for (Annotation qualifier : _qualifiers) {
-                       if (qualifier.annotationType().equals(Named.class)) {
-                               _name = ((Named)qualifier).value();
-                       }
-               }
+
+               Named named = annotated.getAnnotation(Named.class);
+
+               _name = named != null ? named.value() : null;
        }
 
        @Override
        public Object create(CreationalContext<Object> creationalContext) {
-               return create0(creationalContext);
+               Object instance = _getInjectedInstance();
+               InjectionPoint ip = _getInjectionPoint();
+               if (ip == null) {
+                       return instance;
+               }
+               List<Decorator<?>> decorators = _getDecorators(ip);
+               if (decorators.isEmpty()) {
+                       return instance;
+               }
+               return Decorators.getOuterDelegate(
+                       cast(this), instance, creationalContext, 
cast(getBeanClass()), ip, _beanManagerImpl, decorators);
        }
 
        @Override
-       public void destroy(Object arg0, CreationalContext<Object> arg1) {
+       public void destroy(Object instance, CreationalContext<Object> 
creationalContext) {
        }
 
        @Override
        public Class<?> getBeanClass() {
-               return _configurationDependency.getBeanClass();
+               return _referenceModel.getBeanClass();
        }
 
        @Override
@@ -81,7 +91,7 @@ public class ConfigurationBean implement
 
        @Override
        public String getName() {
-               return _name;
+               return _name; //_referenceModel.getName();
        }
 
        @Override
@@ -101,7 +111,7 @@ public class ConfigurationBean implement
 
        @Override
        public Set<Type> getTypes() {
-               return _typesForMatchingBeansToInjectionPoints;
+               return _referenceModel.getTypes();
        }
 
        @Override
@@ -111,51 +121,59 @@ public class ConfigurationBean implement
 
        @Override
        public boolean isNullable() {
-               return false;
+               return _referenceModel.getCardinality() == 
ReferenceCardinality.OPTIONAL ? true : false;
        }
 
        @Override
        public String toString() {
-               return "ConfigurationBean[" + _currentInjectionPoint + "]";
+               return "ReferenceBean[" + _referenceModel + "]";
        }
 
-       protected <T> T create0(CreationalContext<T> creationalContext) {
-               Map<String, Object> map = new AbstractMap<String, Object>() {
+       private List<Decorator<?>> _getDecorators(InjectionPoint ip) {
+               return 
_beanManagerImpl.resolveDecorators(Collections.singleton(ip.getType()), 
getQualifiers());
+       }
 
-                       @Override
-                       public Set<java.util.Map.Entry<String, Object>> 
entrySet() {
-                               return 
_configurationDependency.getConfiguration().entrySet();
-                       }
+       private Object _getInjectedInstance() {
+               Object instance = null;
 
-               };
+               Map<String, ReferenceCallback> map = 
_containerState.referenceCallbacks().get(_componentModel);
 
-               T instance = 
cast(Conversions.c().convert(map).to(_configurationDependency.getBeanClass()));
-               InjectionPoint ip = getInjectionPoint(_currentInjectionPoint);
-               if (ip == null) {
-                       return instance;
-               }
-               List<Decorator<?>> decorators = getDecorators(ip);
-               if (decorators.isEmpty()) {
-                       return instance;
+               ReferenceCallback referenceCallback = 
map.get(_referenceModel.getName());
+
+               Type injectionPointType = 
_referenceModel.getInjectionPointType();
+
+               switch (_referenceModel.getCollectionType()) {
+                       case PROPERTIES:
+                               instance = 
referenceCallback.tracked().values().iterator().next();
+                               break;
+                       case REFERENCE:
+                               instance = 
referenceCallback.tracked().values().iterator().next();
+                               break;
+                       case SERVICE:
+                               instance = 
referenceCallback.tracked().values().iterator().next();
+                               break;
+                       case SERVICEOBJECTS:
+                               instance = 
referenceCallback.tracked().values().iterator().next();
+                               break;
+                       case TUPLE:
+                               instance = 
referenceCallback.tracked().values().iterator().next();
+                               break;
                }
-               return Decorators.getOuterDelegate(
-                       cast(this), instance, creationalContext, 
cast(getBeanClass()), ip, _beanManagerImpl, decorators);
-       }
 
-       protected List<Decorator<?>> getDecorators(InjectionPoint ip) {
-               return 
_beanManagerImpl.resolveDecorators(Collections.singleton(ip.getType()), 
getQualifiers());
+               return instance;
        }
 
-       protected InjectionPoint getInjectionPoint(CurrentInjectionPoint 
currentInjectionPoint) {
+       private InjectionPoint _getInjectionPoint() {
+               CurrentInjectionPoint currentInjectionPoint = 
_beanManagerImpl.getServices().get(CurrentInjectionPoint.class);
                InjectionPoint ip = currentInjectionPoint.peek();
                return EmptyInjectionPoint.INSTANCE.equals(ip) ? null : ip;
        }
 
        private final BeanManagerImpl _beanManagerImpl;
-       private final ConfigurationDependency _configurationDependency;
-       private final CurrentInjectionPoint _currentInjectionPoint;
-       private String _name;
+       private final ComponentModel _componentModel;
+       private final ContainerState _containerState;
+       private final String _name;
        private final Set<Annotation> _qualifiers;
-       private final Set<Type> _typesForMatchingBeansToInjectionPoints;
+       private final ReferenceModel _referenceModel;
 
-}
+}
\ No newline at end of file

Added: 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceCallback.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceCallback.java?rev=1807424&view=auto
==============================================================================
--- 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceCallback.java
 (added)
+++ 
aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceCallback.java
 Tue Sep  5 22:01:11 2017
@@ -0,0 +1,408 @@
+/**
+ * Licensed 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.aries.cdi.container.internal.reference;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
+
+import javax.enterprise.inject.spi.ObserverMethod;
+
+import org.apache.aries.cdi.container.internal.component.ComponentModel;
+import org.apache.aries.cdi.container.internal.container.ContainerState;
+import org.apache.aries.cdi.container.internal.model.CollectionType;
+import org.apache.aries.cdi.container.internal.model.Context;
+import org.apache.aries.cdi.container.internal.model.ServiceEventImpl;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cdi.annotations.ReferenceCardinality;
+import org.osgi.service.cdi.annotations.ServiceEvent;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class ReferenceCallback implements ServiceTrackerCustomizer<Object, 
Object> {
+
+       public static class Builder {
+
+               public Builder(Context context) {
+                       this(null, null, context);
+               }
+
+               public Builder(
+                       ComponentModel componentModel,
+                       ContainerState containerState,
+                       Context context) {
+
+                       Objects.requireNonNull(context);
+                       _componentModel = componentModel;
+                       _containerState = containerState;
+                       _context = context;
+               }
+
+               public ReferenceCallback build() {
+                       Objects.requireNonNull(_cardinality);
+                       Objects.requireNonNull(_collectionType);
+                       return new ReferenceCallback(_componentModel, 
_containerState, _context, _name, _cardinality, _collectionType, _onAdd, 
_onUpdate, _onRemove);
+               }
+
+               public Builder cardinality(ReferenceCardinality cardinality) {
+                       _cardinality = cardinality;
+                       return this;
+               }
+
+               public Builder collectionType(CollectionType collectionType) {
+                       _collectionType = collectionType;
+                       return this;
+               }
+
+               public Builder name(String name) {
+                       _name = name;
+                       return this;
+               }
+
+               public Builder onAdd(Consumer<ReferenceCallback> onAdd) {
+                       _onAdd = onAdd;
+                       return this;
+               }
+
+               public Builder onUpdate(Consumer<ReferenceCallback> onUpdate) {
+                       _onUpdate = onUpdate;
+                       return this;
+               }
+
+               public Builder onRemove(Consumer<ReferenceCallback> onRemove) {
+                       _onRemove = onRemove;
+                       return this;
+               }
+
+               private ReferenceCardinality _cardinality;
+               private CollectionType _collectionType;
+               private ComponentModel _componentModel;
+               private ContainerState _containerState;
+               private Context _context;
+               private String _name;
+               private Consumer<ReferenceCallback> _onAdd;
+               private Consumer<ReferenceCallback> _onUpdate;
+               private Consumer<ReferenceCallback> _onRemove;
+
+       }
+
+       private ReferenceCallback(
+               ComponentModel componentModel,
+               ContainerState containerState,
+               Context context,
+               String name,
+               ReferenceCardinality cardinality,
+               CollectionType collectionType,
+               Consumer<ReferenceCallback> onAdd,
+               Consumer<ReferenceCallback> onUpdate,
+               Consumer<ReferenceCallback> onRemove) {
+
+               _componentModel = Optional.ofNullable(componentModel);
+               _containerState = Optional.ofNullable(containerState);
+               _context = context;
+               _name = Optional.ofNullable(name);
+               _cardinality = cardinality;
+               _collectionType = collectionType;
+               _onAdd = Optional.ofNullable(onAdd);
+               _onUpdate = Optional.ofNullable(onUpdate);
+               _onRemove = Optional.ofNullable(onRemove);
+       }
+
+       Optional<ObserverMethod<ServiceEvent<?>>> observer() {
+               return _componentModel.flatMap(
+                       cm -> _containerState.flatMap(
+                               cs -> _name.flatMap(
+                                       n -> {
+                                               Map<String, 
ObserverMethod<ServiceEvent<?>>> map = cs.referenceObservers().computeIfAbsent(
+                                                       cm, k -> new 
LinkedHashMap<>());
+
+                                               return 
Optional.ofNullable(map.get(n));
+                                       }
+                               )
+                       )
+               );
+       }
+
+       @Override
+       public Object addingService(ServiceReference<Object> reference) {
+               _lock.lock();
+
+               try {
+                       Object instance;
+
+                       switch (_collectionType) {
+                               case PROPERTIES:
+                                       instance = new 
UnmodifiableMap(reference);
+                                       break;
+                               case REFERENCE:
+                                       instance = reference;
+                                       break;
+                               case SERVICEOBJECTS:
+                                       instance = 
_context.getServiceObjects(reference);
+                                       break;
+                               case TUPLE:
+                                       instance = new 
AbstractMap.SimpleImmutableEntry<Map<String, Object>, Object>(
+                                               new UnmodifiableMap(reference), 
_context.getService(reference));
+                                       break;
+                               default:
+                                       instance = 
_context.getService(reference);
+                                       break;
+                       }
+
+                       final Object object = instance;
+
+                       if (_queueing.get()) {
+                               _queue.put(reference, object);
+                       }
+                       else {
+                               _tracked.put(reference, object);
+
+                               observer().ifPresent(o -> 
o.notify(event(object, ServiceEventImpl.Event.ADDING)));
+                       }
+
+                       _onAdd.ifPresent(f -> f.accept(this));
+
+                       return instance;
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       public void flush() {
+               _lock.lock();
+
+               try {
+                       _queueing.set(false);
+
+                       _queue.entrySet().removeIf(
+                               entry -> {
+                                       _tracked.put(entry.getKey(), 
entry.getValue());
+
+                                       observer().ifPresent(o -> 
o.notify(event(entry.getValue(), ServiceEventImpl.Event.ADDING)));
+
+                                       return true;
+                               }
+                       );
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       @Override
+       public void modifiedService(ServiceReference<Object> reference, Object 
service) {
+               _lock.lock();
+
+               try {
+                       Object instance = null;
+
+                       switch (_collectionType) {
+                               case PROPERTIES:
+                                       instance = new 
UnmodifiableMap(reference);
+                                       break;
+                               case REFERENCE:
+                                       instance = reference;
+                                       break;
+                               case SERVICEOBJECTS:
+                                       break;
+                               case TUPLE:
+                                       @SuppressWarnings("unchecked")
+                                       Map.Entry<Map<String, Object>, Object> 
entry = (Map.Entry<Map<String, Object>, Object>)service;
+
+                                       instance = new 
AbstractMap.SimpleImmutableEntry<Map<String, Object>, Object>(
+                                               new UnmodifiableMap(reference), 
entry.getValue());
+                                       break;
+                               default:
+                                       break;
+                       }
+
+                       if (instance != null) {
+                               final Object object = instance;
+
+                               if (_queueing.get()) {
+                                       _queue.put(reference, object);
+                               }
+                               else {
+                                       _tracked.put(reference, object);
+
+                                       observer().ifPresent(o -> 
o.notify(event(object, ServiceEventImpl.Event.MODIFIED)));
+                               }
+                       }
+
+                       _onUpdate.ifPresent(f -> f.accept(this));
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       @Override
+       public void removedService(ServiceReference<Object> reference, Object 
service) {
+               _lock.lock();
+
+               try {
+                       _context.ungetService(reference);
+
+                       if (_queueing.get()) {
+                               _queue.remove(reference);
+                       }
+                       else {
+                               final Object instance = 
_tracked.remove(reference);
+
+                               observer().ifPresent(o -> 
o.notify(event(instance, ServiceEventImpl.Event.REMOVED)));
+                       }
+
+                       _onRemove.ifPresent(f -> f.accept(this));
+               }
+               finally {
+                       _lock.unlock();
+               }
+       }
+
+       <T> ServiceEvent<T> event(T t, ServiceEventImpl.Event event) {
+               return new ServiceEventImpl<T>(t, event);
+       }
+
+       public boolean resolved() {
+               if (((_cardinality == ReferenceCardinality.MANDATORY) ||
+                       (_cardinality == ReferenceCardinality.AT_LEAST_ONE))) {
+
+                       if (_queue.size() + _tracked.size() >= 1) {
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               return true;
+       }
+
+       public Map<ServiceReference<?>, Object> tracked() {
+               return _tracked;
+       }
+
+       private final ReferenceCardinality _cardinality;
+       private final CollectionType _collectionType;
+       private final Optional<ComponentModel> _componentModel;
+       private final Optional<ContainerState> _containerState;
+       private final Context _context;
+       private final Lock _lock = new ReentrantLock();
+       private final Optional<String> _name;
+       private final Optional<Consumer<ReferenceCallback>> _onAdd;
+       private final Optional<Consumer<ReferenceCallback>> _onUpdate;
+       private final Optional<Consumer<ReferenceCallback>> _onRemove;
+       private final AtomicBoolean _queueing = new AtomicBoolean(true);
+       private final Map<ServiceReference<?>, Object> _queue = new 
ConcurrentHashMap<>();
+       private final Map<ServiceReference<?>, Object> _tracked = new 
ConcurrentHashMap<>();
+
+       private static class UnmodifiableMap implements Map<String, Object> {
+
+               public UnmodifiableMap(ServiceReference<?> sr) {
+                       _sr = sr;;
+                       _keys = Arrays.asList(_sr.getPropertyKeys());
+               }
+
+               @Override
+               public int size() {
+                       return _keys.size();
+               }
+
+               @Override
+               public boolean isEmpty() {
+                       return _keys.isEmpty();
+               }
+
+               @Override
+               public boolean containsKey(Object key) {
+                       return _keys.contains(key);
+               }
+
+               @Override
+               public boolean containsValue(Object value) {
+                       return values().contains(value);
+               }
+
+               @Override
+               public Object get(Object key) {
+                       return _sr.getProperty((String)key);
+               }
+
+               @Override
+               public Object put(String key, Object value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               @Override
+               public Object remove(Object key) {
+                       throw new UnsupportedOperationException();
+               }
+
+               @Override
+               public void putAll(Map<? extends String, ? extends Object> m) {
+                       throw new UnsupportedOperationException();
+               }
+
+               @Override
+               public void clear() {
+                       throw new UnsupportedOperationException();
+               }
+
+               @Override
+               public Set<String> keySet() {
+                       return new HashSet<>(_keys);
+               }
+
+               @Override
+               public Collection<Object> values() {
+                       List<Object> values = new ArrayList<>();
+
+                       for (String key : _keys) {
+                               values.add(_sr.getProperty(key));
+                       }
+
+                       return Collections.unmodifiableCollection(values);
+               }
+
+               @Override
+               public Set<Entry<String, Object>> entrySet() {
+                       Set<Map.Entry<String, Object>> entries = new 
HashSet<>();
+
+                       for (String key : _keys) {
+                               entries.add(new 
AbstractMap.SimpleImmutableEntry<>(key, _sr.getProperty(key)));
+                       }
+
+                       return Collections.unmodifiableSet(entries);
+               }
+
+               private final ServiceReference<?> _sr;
+               private List<String> _keys;
+
+       }
+
+}


Reply via email to