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