You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ro...@apache.org on 2017/09/05 22:01:15 UTC
svn commit: r1807424 [4/8] - in /aries/trunk/cdi: ./ cdi-extender/
cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/
cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/bean/
cdi-extender/src/main/java/org/apache/aries/...
Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceModel.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceModel.java?rev=1807424&view=auto
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceModel.java (added)
+++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/reference/ReferenceModel.java Tue Sep 5 22:01:11 2017
@@ -0,0 +1,864 @@
+/**
+ * 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 static org.apache.aries.cdi.container.internal.model.Model.*;
+import static org.apache.aries.cdi.container.internal.util.Reflection.cast;
+import static java.lang.String.format;
+import static org.apache.aries.cdi.container.internal.model.Constants.CARDINALITY_ATTRIBUTE;
+import static org.apache.aries.cdi.container.internal.model.Constants.CDI10_URI;
+import static org.apache.aries.cdi.container.internal.model.Constants.NAME_ATTRIBUTE;
+import static org.apache.aries.cdi.container.internal.model.Constants.POLICY_ATTRIBUTE;
+import static org.apache.aries.cdi.container.internal.model.Constants.POLICY_OPTION_ATTRIBUTE;
+import static org.apache.aries.cdi.container.internal.model.Constants.SCOPE_ATTRIBUTE;
+import static org.apache.aries.cdi.container.internal.model.Constants.TARGET_ATTRIBUTE;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedParameter;
+
+import org.apache.aries.cdi.container.internal.model.CollectionType;
+import org.apache.aries.cdi.container.internal.util.Conversions;
+import org.apache.aries.cdi.container.internal.util.Maps;
+import org.apache.aries.cdi.container.internal.util.Sets;
+import org.apache.aries.cdi.container.internal.util.Types;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cdi.annotations.Reference;
+import org.osgi.service.cdi.annotations.ReferenceCardinality;
+import org.osgi.service.cdi.annotations.ReferencePolicy;
+import org.osgi.service.cdi.annotations.ReferencePolicyOption;
+import org.osgi.service.cdi.annotations.ReferenceScope;
+import org.osgi.service.cdi.annotations.ServiceEvent;
+import org.osgi.util.converter.TypeReference;
+import org.xml.sax.Attributes;
+
+public class ReferenceModel {
+
+ public static class Builder {
+
+ public Builder(Attributes attributes) {
+ _cardinality = _cardinality(attributes);
+ _name = _name(attributes);
+ _option = _option(attributes);
+ _policy = _policy(attributes);
+ _scope = _scope(attributes);
+ _target = _target(attributes);
+ }
+
+ public Builder(Set<Annotation> qualifiers) {
+ _qualifiers = qualifiers;
+ Reference reference = getQualifier(_qualifiers, Reference.class);
+ if (reference != null) {
+ _cardinality = reference.cardinality();
+ _name = reference.name();
+ _option = reference.policyOption();
+ _policy = reference.policy();
+ _scope = reference.scope();
+ _service = reference.service();
+ _target = reference.target();
+ }
+ }
+
+ public ReferenceModel build() {
+ if ((_annotated == null) && (_service == null)) {
+ throw new IllegalArgumentException(
+ "Either injectionPoint or service must be set!");
+ }
+
+ if (_annotated == null) {
+ _annotated = new ReferenceAnnotated(_service);
+ }
+
+ Type type = upwrapCDITypes(_annotated.getBaseType());
+
+ _policy = calculatePolicy(_policy);
+ _option = calculatePolicyOption(_option);
+ _scope = calculateScope(_scope);
+ Multiplicity multiplicity = calculateMultiplicity(_annotated.getBaseType());// we need the pure type to check "Instance"
+ _cardinality = calculateCardinality(_cardinality, multiplicity, type);
+ CollectionType collectionType = calculateCollectionType(type);
+ Class<?> beanClass = calculateBeanClass(type);
+ _service = calculateServiceClass(_service, _cardinality, collectionType, type, _annotated);
+ _name = calculateName(_name, _service, _annotated);
+
+ return new ReferenceModel(_service, _cardinality, _name, _policy, _option, _target, _scope, _qualifiers, beanClass, type, collectionType);
+ }
+
+ public Builder cardinality(ReferenceCardinality cardinality) {
+ _cardinality = cardinality;
+ return this;
+ }
+
+ public Builder annotated(Annotated annotated) {
+ _annotated = annotated;
+ return this;
+ }
+
+ public Builder name(String name) {
+ _name = name;
+ return this;
+ }
+
+ public Builder option(ReferencePolicyOption option) {
+ _option = option;
+ return this;
+ }
+
+ public Builder policy(ReferencePolicy policy) {
+ _policy = policy;
+ return this;
+ }
+
+ public Builder scope(ReferenceScope scope) {
+ _scope = scope;
+ return this;
+ }
+
+ public Builder service(Class<?> service) {
+ _service = service;
+ return this;
+ }
+
+ public Builder target(String target) {
+ _target = target;
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends Annotation> T getQualifier(
+ Set<Annotation> qualifiers, Class<T> clazz) {
+ for (Annotation annotation : qualifiers) {
+ if (clazz.isAssignableFrom(annotation.annotationType())) {
+ return (T)annotation;
+ }
+ }
+ return null;
+ }
+
+ private ReferenceCardinality _cardinality;
+ private Annotated _annotated;
+ private String _name;
+ private ReferencePolicyOption _option;
+ private ReferencePolicy _policy;
+ private Set<Annotation> _qualifiers;
+ private ReferenceScope _scope;
+ private Class<?> _service;
+ private String _target;
+
+ }
+
+ private ReferenceModel(
+ Class<?> service,
+ ReferenceCardinality cardinality,
+ String name,
+ ReferencePolicy policy,
+ ReferencePolicyOption option,
+ String target,
+ ReferenceScope scope,
+ Set<Annotation> qualifiers,
+ Class<?> beanClass,
+ Type injectionPointType,
+ CollectionType collectionType) {
+
+ _service = service;
+ _cardinality = cardinality;
+ _name = name;
+ _policy = policy;
+ _option = option;
+ _target = target;
+ _scope = scope;
+ _qualifiers = new LinkedHashSet<>();
+ if (qualifiers != null) {
+ _qualifiers.addAll(qualifiers);
+ }
+ _beanClass = beanClass;
+ _injectionPointType = injectionPointType;
+ _collectionType = collectionType;
+
+ _types = Sets.immutableHashSet(_injectionPointType, Object.class);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_beanClass == null) ? 0 : _beanClass.hashCode());
+ result = prime * result + ((_cardinality == null) ? 0 : _cardinality.hashCode());
+ result = prime * result + ((_name == null) ? 0 : _name.hashCode());
+ result = prime * result + ((_option == null) ? 0 : _option.hashCode());
+ result = prime * result + ((_policy == null) ? 0 : _policy.hashCode());
+ result = prime * result + ((_scope == null) ? 0 : _scope.hashCode());
+ result = prime * result + ((_service == null) ? 0 : _service.hashCode());
+ result = prime * result + ((_target == null) ? 0 : _target.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ReferenceModel other = (ReferenceModel) obj;
+ if (_beanClass == null) {
+ if (other._beanClass != null)
+ return false;
+ } else if (!_beanClass.equals(other._beanClass))
+ return false;
+ if (_cardinality != other._cardinality)
+ return false;
+ if (_name == null) {
+ if (other._name != null)
+ return false;
+ } else if (!_name.equals(other._name))
+ return false;
+ if (_option != other._option)
+ return false;
+ if (_policy != other._policy)
+ return false;
+ if (_scope != other._scope)
+ return false;
+ if (_service == null) {
+ if (other._service != null)
+ return false;
+ } else if (!_service.equals(other._service))
+ return false;
+ if (_target == null) {
+ if (other._target != null)
+ return false;
+ } else if (!_target.equals(other._target))
+ return false;
+ return true;
+ }
+
+ public boolean found() {
+ return _found.get();
+ }
+
+ public void found(boolean found) {
+ _found.set(found);
+ }
+
+ public Class<?> getBeanClass() {
+ return _beanClass;
+ }
+
+ public ReferenceCardinality getCardinality() {
+ return _cardinality;
+ }
+
+ public CollectionType getCollectionType() {
+ return _collectionType;
+ }
+
+ public Type getInjectionPointType() {
+ return _injectionPointType;
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public ReferencePolicy getPolicy() {
+ return _policy;
+ }
+
+ public ReferencePolicyOption getPolicyOption() {
+ return _option;
+ }
+
+ public Set<Annotation> getQualifiers() {
+ return _qualifiers;
+ }
+
+ public ReferenceScope getScope() {
+ return _scope;
+ }
+
+ public Class<?> getServiceClass() {
+ return _service;
+ }
+
+ public String getTarget() {
+ return _target;
+ }
+
+ public Set<Type> getTypes() {
+ return _types;
+ }
+
+ public void setQualifiers(Set<Annotation> qualifiers) {
+ _qualifiers.clear();
+ _qualifiers.addAll(qualifiers);
+ }
+
+ @Override
+ public String toString() {
+ if (_string == null) {
+ _string = String.format("reference[name='%s', service='%s', scope='%s', target='%s']", _name, _service, _scope, _target);
+ }
+ return _string;
+ }
+
+ public static String buildFilter(
+ Class<?> serviceType,
+ String target,
+ ReferenceScope scope,
+ Set<Annotation> qualifiers)
+ throws InvalidSyntaxException {
+
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("(&(");
+ sb.append(Constants.OBJECTCLASS);
+ sb.append("=");
+ sb.append(serviceType.getName());
+ sb.append(")");
+
+ if (scope == ReferenceScope.PROTOTYPE) {
+ sb.append("(");
+ sb.append(Constants.SERVICE_SCOPE);
+ sb.append("=");
+ sb.append(Constants.SCOPE_PROTOTYPE);
+ sb.append(")");
+ }
+ else if (scope == ReferenceScope.SINGLETON) {
+ sb.append("(");
+ sb.append(Constants.SERVICE_SCOPE);
+ sb.append("=");
+ sb.append(Constants.SCOPE_SINGLETON);
+ sb.append(")");
+ }
+ else if (scope == ReferenceScope.BUNDLE) {
+ sb.append("(");
+ sb.append(Constants.SERVICE_SCOPE);
+ sb.append("=");
+ sb.append(Constants.SCOPE_BUNDLE);
+ sb.append(")");
+ }
+
+ String targetFilter = target == null ? "" : target;
+
+ int targetFilterLength = targetFilter.length();
+
+ if (targetFilterLength > 0) {
+ FrameworkUtil.createFilter(targetFilter);
+
+ sb.append(targetFilter);
+ }
+
+ if (qualifiers != null) {
+ for (Annotation qualifier : qualifiers) {
+ Class<? extends Annotation> annotationType = qualifier.annotationType();
+
+ if (annotationType.equals(Reference.class)) {
+ continue;
+ }
+
+ Map<String, String> map = Conversions.convert(qualifier).sourceAs(qualifier.annotationType()).to(_mapType);
+
+ Maps.appendFilter(sb, map);
+ }
+ }
+
+ sb.append(")");
+
+ return sb.toString();
+ }
+
+ private static Class<?> calculateBeanClass(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType)type;
+
+ type = pType.getRawType();
+ }
+ else if (type instanceof WildcardType) {
+ throw new IllegalArgumentException(
+ "Cannot use a wildcard as the bean: " + type);
+ }
+
+ return cast(type);
+ }
+
+ private static CollectionType calculateCollectionType(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = cast(type);
+
+ Type rawType = parameterizedType.getRawType();
+
+ if ((List.class == cast(rawType)) ||
+ Collection.class.isAssignableFrom(cast(rawType))) {
+
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+
+ return calculateCollectionType(actualTypeArguments[0]);
+ }
+ else if (Map.class == cast(rawType)) {
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+
+ Type first = actualTypeArguments[0];
+ Type second = actualTypeArguments[1];
+
+ if (!(first instanceof ParameterizedType) &&
+ String.class.isAssignableFrom(cast(first))) {
+
+ if ((!(second instanceof ParameterizedType) && (second == Object.class)) ||
+ (second instanceof WildcardType)) {
+
+ return CollectionType.PROPERTIES;
+ }
+ }
+ }
+ else if (Map.Entry.class == cast(rawType)) {
+ return CollectionType.TUPLE;
+ }
+ else if (ServiceObjects.class == cast(rawType)) {
+ return CollectionType.SERVICEOBJECTS;
+ }
+ else if (ServiceReference.class == cast(rawType)) {
+ return CollectionType.REFERENCE;
+ }
+ }
+ else if (Map.Entry.class == cast(type)) {
+ return CollectionType.TUPLE;
+ }
+ else if (ServiceObjects.class == cast(type)) {
+ return CollectionType.SERVICEOBJECTS;
+ }
+ else if (ServiceReference.class == cast(type)) {
+ return CollectionType.REFERENCE;
+ }
+
+ return CollectionType.SERVICE;
+ }
+
+ private static ReferenceCardinality calculateCardinality(
+ ReferenceCardinality cardinality, Multiplicity multiplicity, Type type) {
+
+ if ((multiplicity == Multiplicity.UNARY) &&
+ ((cardinality == ReferenceCardinality.AT_LEAST_ONE) || (cardinality == ReferenceCardinality.MULTIPLE))) {
+
+ throw new IllegalArgumentException(
+ format(
+ "Unary injection point type %s cannot be defined by multiple cardinality %s",
+ type, cardinality));
+ }
+ else if ((multiplicity == Multiplicity.MULTIPLE) &&
+ ((cardinality == ReferenceCardinality.OPTIONAL) || (cardinality == ReferenceCardinality.MANDATORY))) {
+
+ throw new IllegalArgumentException(
+ format(
+ "Multiple injection point type %s cannot be defined by unary cardinality %s",
+ type, cardinality));
+ }
+
+ if ((cardinality == null) || (cardinality == ReferenceCardinality.DEFAULT)) {
+ switch(multiplicity) {
+ case MULTIPLE:
+ return ReferenceCardinality.MULTIPLE;
+ case UNARY:
+ return ReferenceCardinality.MANDATORY;
+ }
+ }
+
+ return cardinality;
+ }
+
+ private static Multiplicity calculateMultiplicity(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = cast(type);
+
+ Type rawType = parameterizedType.getRawType();
+
+ if ((Instance.class == cast(rawType)) ||
+ Collection.class.isAssignableFrom(cast(rawType)) ||
+ ServiceEvent.class == cast(rawType)) {
+
+ return Multiplicity.MULTIPLE;
+ }
+ }
+
+ return Multiplicity.UNARY;
+ }
+
+ public static String calculateName(String name, Class<?> service, Annotated annotated) {
+ if ((name != null) && (name.length() > 0)) {
+ return name;
+ }
+
+ if (annotated != null) {
+ if (annotated instanceof AnnotatedParameter) {
+ AnnotatedParameter<?> annotatedParameter = (AnnotatedParameter<?>)annotated;
+
+ return Types.getName(service) + annotatedParameter.getPosition();
+ }
+ if (annotated instanceof AnnotatedField) {
+ AnnotatedField<?> annotatedField = (AnnotatedField<?>)annotated;
+
+ return annotatedField.getJavaMember().getName();
+ }
+ }
+
+ return Types.getName(service);
+ }
+
+ private static ReferencePolicy calculatePolicy(ReferencePolicy policy) {
+ if ((policy == null) || (policy == ReferencePolicy.DEFAULT)) {
+ return ReferencePolicy.STATIC;
+ }
+
+ return policy;
+ }
+
+ private static ReferencePolicyOption calculatePolicyOption(ReferencePolicyOption option) {
+ if ((option == null) || (option == ReferencePolicyOption.DEFAULT)) {
+ return ReferencePolicyOption.RELUCTANT;
+ }
+
+ return option;
+ }
+
+ private static ReferenceScope calculateScope(ReferenceScope scope) {
+ if ((scope == null) || (scope == ReferenceScope.DEFAULT)) {
+ return ReferenceScope.DEFAULT;
+ }
+
+ return scope;
+ }
+
+ private static Class<?> calculateServiceClass(Type injectionPointType) {
+ Type type = injectionPointType;
+
+ if (!(type instanceof ParameterizedType)) {
+ return cast(type);
+ }
+
+ ParameterizedType parameterizedType = cast(type);
+
+ Type rawType = parameterizedType.getRawType();
+
+ if ((List.class == cast(rawType)) ||
+ Collection.class.isAssignableFrom(cast(rawType))) {
+
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+
+ type = actualTypeArguments[0];
+
+ if (type instanceof ParameterizedType) {
+ parameterizedType = (ParameterizedType)type;
+
+ rawType = parameterizedType.getRawType();
+ }
+ else if ((type instanceof WildcardType) ||
+ Map.Entry.class.isAssignableFrom(cast(type))) {
+
+ return null;
+ }
+ else {
+ rawType = type;
+ }
+ }
+
+ if (!Map.Entry.class.isAssignableFrom(cast(rawType)) &&
+ !ServiceObjects.class.isAssignableFrom(cast(rawType)) &&
+ !ServiceReference.class.isAssignableFrom(cast(rawType))) {
+
+ return cast(rawType);
+ }
+
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+
+ Type argument = actualTypeArguments[0];
+
+ if (Map.Entry.class.isAssignableFrom(cast(rawType))) {
+ if (!checkKey(argument)) {
+ throw new IllegalArgumentException(
+ "Tuples must have a key of type Map<String, [? or Object]>: " + argument);
+ }
+
+ argument = actualTypeArguments[1];
+ }
+
+ if (argument instanceof ParameterizedType) {
+ ParameterizedType parameterizedType1 = cast(argument);
+
+ return cast(parameterizedType1.getRawType());
+ }
+ else if (argument instanceof WildcardType) {
+ WildcardType wildcardType = (WildcardType)argument;
+
+ if ((wildcardType.getUpperBounds().length == 1)) {
+ argument = wildcardType.getUpperBounds()[0];
+
+ if (Object.class.equals(argument)) {
+ return null;
+ }
+ else if (argument instanceof Class) {
+ return cast(argument);
+ }
+ }
+
+ throw new IllegalArgumentException(
+ "@Reference cannot use nested parameterized types or multiple upper bounds: " + injectionPointType);
+ }
+
+ return cast(argument);
+ }
+
+ private static Class<?> calculateServiceClass(
+ Class<?> service, ReferenceCardinality cardinality, CollectionType collectionType, Type injectionPointType, Annotated annotated) {
+
+ Class<?> calculatedServiceClass = calculateServiceClass(injectionPointType);
+
+ if ((service == null) || (service == Object.class)) {
+ if (calculatedServiceClass == null) {
+ throw new IllegalArgumentException(
+ "Could not determine the service type from @Reference on annotated " +
+ annotated);
+ }
+
+ switch(collectionType) {
+ case PROPERTIES:
+ if (calculatedServiceClass == Map.class) {
+ throw new IllegalArgumentException(
+ "A @Reference cannot bind service properties to a Map<String, Object> without " +
+ "specifying the @Reference.service property: " + annotated);
+ }
+ break;
+ case REFERENCE:
+ if (calculatedServiceClass == ServiceReference.class) {
+ throw new IllegalArgumentException(
+ "A @Reference cannot bind a ServiceReference without specifying either the " +
+ "@Reference.service property or a generic type argument (e.g. ServiceReference<Foo>: " +
+ annotated);
+ }
+ break;
+ case SERVICEOBJECTS:
+ if (calculatedServiceClass == ServiceObjects.class) {
+ throw new IllegalArgumentException(
+ "A @Reference cannot bind a ServiceObjects without specifying either the " +
+ "@Reference.service property or a generic type argument (e.g. ServiceObjects<Foo>: " +
+ annotated);
+ }
+ break;
+ case TUPLE:
+ if (calculatedServiceClass == Map.Entry.class) {
+ throw new IllegalArgumentException(
+ "A @Reference cannot bind a Map.Entry without specifying either the " +
+ "@Reference.service property or a generic type argument (e.g. Map.Entry<Map<String, Object>, Foo>: " +
+ annotated);
+ }
+ break;
+ default:
+ }
+
+ return calculatedServiceClass;
+ }
+
+ switch(collectionType) {
+ case PROPERTIES:
+ if (Map.class.isAssignableFrom(calculatedServiceClass)) {
+ return service;
+ }
+ break;
+ case REFERENCE:
+ if ((calculatedServiceClass == null) ||
+ ServiceReference.class.isAssignableFrom(calculatedServiceClass)) {
+ return service;
+ }
+ break;
+ case SERVICEOBJECTS:
+ if ((calculatedServiceClass == null) ||
+ ServiceObjects.class.isAssignableFrom(calculatedServiceClass)) {
+ return service;
+ }
+ break;
+ case TUPLE:
+ if ((calculatedServiceClass != null) &&
+ Map.Entry.class.isAssignableFrom(calculatedServiceClass)) {
+
+ if (!checkKey(calculatedServiceClass)) {
+ throw new IllegalArgumentException(
+ "Tuples must have a key of type Map<String, [? or Object]>: " + calculatedServiceClass);
+ }
+
+ return service;
+ }
+ else if ((calculatedServiceClass == null) ||
+ calculatedServiceClass.isAssignableFrom(service)) {
+
+ return service;
+ }
+ break;
+ case SERVICE:
+ if (((calculatedServiceClass == null) &&
+ ((cardinality == ReferenceCardinality.MULTIPLE) ||
+ (cardinality == ReferenceCardinality.AT_LEAST_ONE))) ||
+ ((calculatedServiceClass != null) &&
+ calculatedServiceClass.isAssignableFrom(service))) {
+ return service;
+ }
+ }
+
+ throw new IllegalArgumentException(
+ "@Reference.service " + service + " is not compatible with annotated " + annotated);
+ }
+
+ // check the key type to make sure it complies with Map<String, ?> OR Map<String, Object>
+ private static boolean checkKey(Type mapEntryType) {
+ if (!(mapEntryType instanceof ParameterizedType)) {
+ return false;
+ }
+
+ ParameterizedType parameterizedKeyType = (ParameterizedType)mapEntryType;
+
+ if ((!Map.class.isAssignableFrom(cast(parameterizedKeyType.getRawType()))) ||
+ (!parameterizedKeyType.getActualTypeArguments()[0].equals(String.class))) {
+
+ return false;
+ }
+
+ Type valueType = parameterizedKeyType.getActualTypeArguments()[1];
+
+ if ((!valueType.equals(Object.class) &&
+ (
+ (!(valueType instanceof WildcardType)) ||
+ (((WildcardType)valueType).getUpperBounds().length != 1) ||
+ (!((WildcardType)valueType).getUpperBounds()[0].equals(Object.class))))) {
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private static ReferenceCardinality _cardinality(Attributes attributes) {
+ return ReferenceCardinality.get(
+ getValue(CDI10_URI, CARDINALITY_ATTRIBUTE, attributes, ReferenceCardinality.DEFAULT.toString()));
+ }
+
+ private static String _name(Attributes attributes) {
+ return getValue(CDI10_URI, NAME_ATTRIBUTE, attributes);
+ }
+
+ private static ReferencePolicyOption _option(Attributes attributes) {
+ return ReferencePolicyOption.get(
+ getValue(CDI10_URI, POLICY_OPTION_ATTRIBUTE, attributes, ReferencePolicyOption.DEFAULT.toString()));
+ }
+
+ private static ReferencePolicy _policy(Attributes attributes) {
+ return ReferencePolicy.get(
+ getValue(CDI10_URI, POLICY_ATTRIBUTE, attributes, ReferencePolicy.DEFAULT.toString()));
+ }
+
+ private static ReferenceScope _scope(Attributes attributes) {
+ return ReferenceScope.get(getValue(
+ CDI10_URI, SCOPE_ATTRIBUTE, attributes, ReferenceScope.DEFAULT.toString()));
+ }
+
+ private static String _target(Attributes attributes) {
+ return getValue(CDI10_URI, TARGET_ATTRIBUTE, attributes);
+ }
+
+ private static Type upwrapCDITypes(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType)type;
+
+ Type rawType = pType.getRawType();
+
+ if (Instance.class == cast(rawType) ||
+ ServiceEvent.class == cast(rawType)) {
+
+ type = pType.getActualTypeArguments()[0];
+ }
+ }
+
+ return type;
+ }
+
+ private static final TypeReference<Map<String, String>> _mapType = new TypeReference<Map<String, String>>(){};
+
+ private final Class<?> _beanClass;
+ private final ReferenceCardinality _cardinality;
+ private final CollectionType _collectionType;
+ private final AtomicBoolean _found = new AtomicBoolean();
+ private final Type _injectionPointType;
+ private final String _name;
+ private final ReferencePolicyOption _option;
+ private final ReferencePolicy _policy;
+ private final Set<Annotation> _qualifiers;
+ private final ReferenceScope _scope;
+ private final Class<?> _service;
+ private String _string;
+ private final String _target;
+ private final Set<Type> _types;
+
+ private static class ReferenceAnnotated implements Annotated {
+
+ public ReferenceAnnotated(Class<?> service) {
+ _service = service;
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+ return null;
+ }
+
+ @Override
+ public Set<Annotation> getAnnotations() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Type getBaseType() {
+ return _service;
+ }
+
+ @Override
+ public Set<Type> getTypeClosure() {
+ return Sets.hashSet(_service);
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ return false;
+ }
+
+ private final Class<?> _service;
+
+ }
+
+}
Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/service/ServiceDeclaration.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/service/ServiceDeclaration.java?rev=1807424&view=auto
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/service/ServiceDeclaration.java (added)
+++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/service/ServiceDeclaration.java Tue Sep 5 22:01:11 2017
@@ -0,0 +1,173 @@
+/**
+ * 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.service;
+
+import static org.apache.aries.cdi.container.internal.util.Reflection.cast;
+
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.stream.Collectors;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+
+import org.apache.aries.cdi.container.internal.component.ComponentModel;
+import org.apache.aries.cdi.container.internal.component.ComponentProperties;
+import org.apache.aries.cdi.container.internal.container.ContainerState;
+import org.apache.aries.cdi.container.internal.util.Types;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.PrototypeServiceFactory;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cdi.annotations.ServiceScope;
+
+public class ServiceDeclaration {
+
+ public ServiceDeclaration(
+ ContainerState containerState,
+ ComponentModel componentModel,
+ Bean<?> bean,
+ CreationalContext<?> creationalContext) {
+
+ _containerState = containerState;
+ _bean = bean;
+ _creationalContext = creationalContext;
+
+ _componentModel = componentModel;
+
+ Object instance = null;
+
+ if (_componentModel.getServiceScope() == ServiceScope.SINGLETON) {
+ instance = new SingletonScopeWrapper();
+ }
+ else if (_componentModel.getServiceScope() == ServiceScope.BUNDLE) {
+ instance = new BundleScopeWrapper();
+ }
+ else if (_componentModel.getServiceScope() == ServiceScope.PROTOTYPE) {
+ instance = new PrototypeScopeWrapper();
+ }
+
+ _instance = instance;
+ }
+
+ public String[] getClassNames() {
+ return Arrays.stream(
+ Types.types(_componentModel, _componentModel.getBeanClass(), _containerState.classLoader())
+ ).map(
+ c -> c.getName()
+ ).collect(
+ Collectors.toList()
+ ).toArray(
+ new String[0]
+ );
+ }
+
+ public String getName() {
+ return _componentModel.getName();
+ }
+
+ public ServiceScope getScope() {
+ return _componentModel.getServiceScope();
+ }
+
+ public Object getServiceInstance() {
+ return _instance;
+ }
+
+ public Dictionary<String, ?> getServiceProperties() {
+ return new ComponentProperties().bean(
+ _bean
+ ).componentModel(
+ _componentModel
+ ).containerState(
+ _containerState
+ ).build();
+ }
+
+ private final Bean<?> _bean;
+ private final ComponentModel _componentModel;
+ private final ContainerState _containerState;
+ private final CreationalContext<?> _creationalContext;
+ private final Object _instance;
+
+ @SuppressWarnings({"rawtypes"})
+ private class BundleScopeWrapper implements ServiceFactory {
+
+ @Override
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ return _bean.create(cast(_creationalContext));
+ }
+
+ @Override
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ _bean.destroy(cast(service), cast(_creationalContext));
+ }
+
+ }
+
+ @SuppressWarnings({"rawtypes"})
+ private class PrototypeScopeWrapper implements PrototypeServiceFactory {
+
+ @Override
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ return _bean.create(cast(_creationalContext));
+ }
+
+ @Override
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ _bean.destroy(cast(service), cast(_creationalContext));
+ }
+
+ }
+
+ @SuppressWarnings({"rawtypes"})
+ private class SingletonScopeWrapper implements ServiceFactory {
+
+ @Override
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ if (_instance == null) {
+ _instance = _bean.create(cast(_creationalContext));
+ }
+ return _instance;
+ }
+
+ @Override
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ }
+
+ private Object _instance;
+
+ }
+
+// private class ManagedServiceFactoryWrapper implements ManagedServiceFactory {
+//
+// @Override
+// public String getName() {
+// return _component.name();
+// }
+//
+// @Override
+// public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException {
+// }
+//
+// @Override
+// public void deleted(String pid) {
+// }
+//
+// private final Map<String, Object> _instances = new ConcurrentHashMap<>();
+//
+// }
+
+}
Modified: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Conversions.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Conversions.java?rev=1807424&r1=1807423&r2=1807424&view=diff
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Conversions.java (original)
+++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Conversions.java Tue Sep 5 22:01:11 2017
@@ -18,6 +18,7 @@ import java.util.Arrays;
import org.osgi.util.converter.Converter;
import org.osgi.util.converter.ConverterBuilder;
+import org.osgi.util.converter.Converting;
import org.osgi.util.converter.StandardConverter;
import org.osgi.util.converter.TypeRule;
@@ -27,8 +28,8 @@ public class Conversions {
return INSTANCE._converter.convert(object).defaultValue("").to(String.class);
}
- public static Converter c() {
- return INSTANCE._converter;
+ public static Converting convert(Object object) {
+ return INSTANCE._converter.convert(object);
}
private Conversions() {
Modified: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Maps.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Maps.java?rev=1807424&r1=1807423&r2=1807424&view=diff
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Maps.java (original)
+++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Maps.java Tue Sep 5 22:01:11 2017
@@ -70,20 +70,21 @@ public class Maps {
map(map, key, type, value);
}
+ @SuppressWarnings("unchecked")
static void map(Map<String, Object> map, String key, String type, String value) {
PropertyType propertyType = PropertyType.find(type);
Object object = map.get(key);
if (object == null) {
- Object valueObject = Conversions.c().convert(value).to(propertyType.getType());
+ Object valueObject = Conversions.convert(value).to(propertyType.getType());
map.put(key, valueObject);
return;
}
- Object valueObject = Conversions.c().convert(value).to(propertyType.componentType());
+ Object valueObject = Conversions.convert(value).to(propertyType.componentType());
if (propertyType.isRaw()) {
if (!object.getClass().isArray()) {
@@ -101,10 +102,12 @@ public class Maps {
}
}
else if (propertyType.isList()) {
+ @SuppressWarnings("rawtypes")
List list = Collections.checkedList((List)object, propertyType.componentType());
list.add(valueObject);
}
else if (propertyType.isSet()) {
+ @SuppressWarnings("rawtypes")
Set set = Collections.checkedSet((Set)object, propertyType.componentType());
set.add(valueObject);
}
Modified: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Strings.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Strings.java?rev=1807424&r1=1807423&r2=1807424&view=diff
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Strings.java (original)
+++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Strings.java Tue Sep 5 22:01:11 2017
@@ -19,6 +19,8 @@ import java.util.regex.Pattern;
public class Strings {
+ public static final String[] EMPTY_ARRAY = new String[0];
+
private Strings() {
// no instances
}
Added: aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Types.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Types.java?rev=1807424&view=auto
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Types.java (added)
+++ aries/trunk/cdi/cdi-extender/src/main/java/org/apache/aries/cdi/container/internal/util/Types.java Tue Sep 5 22:01:11 2017
@@ -0,0 +1,134 @@
+/**
+ * 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.util;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.apache.aries.cdi.container.internal.component.ComponentModel;
+import org.osgi.service.cdi.annotations.ServiceScope;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Types {
+
+ public static String getName(InjectionPoint injectionPoint) {
+ return getName(injectionPoint.getType());
+ }
+
+ public static String getName(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType)type;
+
+ Type rawType = pt.getRawType();
+
+ if (rawType instanceof Class) {
+ Class<?> clazz = (Class<?>)rawType;
+
+ return clazz.getSimpleName();
+ }
+ else {
+ return rawType.getTypeName();
+ }
+ }
+ else if (type instanceof GenericArrayType) {
+ GenericArrayType gat = (GenericArrayType)type;
+
+ Type genericComponentType = gat.getGenericComponentType();
+
+ if (genericComponentType instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType)genericComponentType;
+
+ Type rawType = pt.getRawType();
+
+ if (rawType instanceof Class) {
+ Class<?> clazz = (Class<?>)rawType;
+
+ return clazz.getSimpleName();
+ }
+ else {
+ return rawType.getTypeName();
+ }
+ }
+ else if (genericComponentType instanceof Class) {
+ Class<?> clazz = (Class<?>)genericComponentType;
+
+ return clazz.getSimpleName();
+ }
+ else {
+ return genericComponentType.getTypeName();
+ }
+ }
+ else if (type instanceof Class) {
+ Class<?> clazz = (Class<?>)type;
+
+ String simpleName = clazz.getSimpleName();
+
+ char lowerCase = Character.toLowerCase(simpleName.charAt(0));
+
+ return lowerCase + simpleName.substring(1, simpleName.length());
+ }
+
+ return type.getTypeName();
+ }
+
+ public static Class<?>[] types(
+ ComponentModel componentModel, Class<?> beanClass, ClassLoader classLoader) {
+
+ List<Class<?>> classes = new ArrayList<>();
+
+ if ((componentModel.getServiceScope() == ServiceScope.DEFAULT) ||
+ (componentModel.getServiceScope() == ServiceScope.NONE)) {
+
+ return new Class<?>[0];
+ }
+ else if (!componentModel.getProvides().isEmpty()) {
+ for (String provide : componentModel.getProvides()) {
+ try {
+ classes.add(classLoader.loadClass(provide));
+ }
+ catch (ReflectiveOperationException roe) {
+ if (_log.isWarnEnabled()) {
+ _log.warn(
+ "CDIe - component {} cannot load provided type {}. Skipping!",
+ componentModel.getBeanClass(), provide, roe);
+ }
+ }
+ }
+ }
+ else {
+ Class<?>[] interfaces = beanClass.getInterfaces();
+
+ if (interfaces.length > 0) {
+ for (Class<?> iface : interfaces) {
+ classes.add(iface);
+ }
+ }
+ else {
+ classes.add(beanClass);
+ }
+ }
+
+ return classes.toArray(new Class[0]);
+ }
+
+ public static final Logger _log = LoggerFactory.getLogger(Types.class);
+
+}
\ No newline at end of file
Modified: aries/trunk/cdi/cdi-extender/src/main/resources/META-INF/cdi.xsd
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/main/resources/META-INF/cdi.xsd?rev=1807424&r1=1807423&r2=1807424&view=diff
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/main/resources/META-INF/cdi.xsd (original)
+++ aries/trunk/cdi/cdi-extender/src/main/resources/META-INF/cdi.xsd Tue Sep 5 22:01:11 2017
@@ -29,46 +29,82 @@
the OSGi CDI Extender. OSGi Bean description documents
may be embedded in other XML documents. The OSGi CDI Extender
will process all XML documents listed in the osgi.beans
- attribute of the CDI extender requirement. XML documents containing
- OSGi Bean descriptions may contain one or more bean, configuration,
- and/or reference elements embedded in a larger document. Use of
- the namespace for bean descriptions is mandatory. The attributes
- and subelements of bean, configuration, and/or reference elements
- are always unqualified.
+ attribute of the CDI extender requirement. CDI Beans named by the
+ descriptor are described as components. XML documents containing
+ OSGi Bean descriptions may contain one or more component elements.
+ Use of the namespace for bean descriptions is mandatory. The
+ attributes and subelements of component elements are always
+ unqualified.
</documentation>
</annotation>
- <element name="bean" type="cdi:Tbean" />
- <complexType name="Tbean">
+ <element name="component" type="cdi:Tcomponent" />
+ <complexType name="Tcomponent">
<sequence>
- <element name="service" maxOccurs="1" minOccurs="0"
- type="cdi:Tservice" />
- <any namespace="##other" minOccurs="0" maxOccurs="unbounded"
- processContents="lax" />
+ <annotation>
+ <documentation xml:lang="en">
+ Implementations of CDI Support must not require component
+ descriptions to specify the sub-elements of the component
+ element in the order as required by the schema. CDI Support
+ implementations must allow other orderings since
+ arbitrary orderings do not affect the meaning of the
+ component description. Only the relative ordering of
+ property elements have meaning.
+ </documentation>
+ </annotation>
+ <element name="configuration" maxOccurs="unbounded" minOccurs="0" type="cdi:Tconfiguration" />
+ <element name="property" maxOccurs="unbounded" minOccurs="0" type="cdi:Tproperty" />
+ <element name="provide" maxOccurs="unbounded" minOccurs="0" type="cdi:Tprovide" />
+ <element name="reference" maxOccurs="unbounded" minOccurs="0" type="cdi:Treference" />
+ <any namespace="##other" maxOccurs="unbounded" minOccurs="0" processContents="lax" />
</sequence>
<attribute name="class" type="token" use="required" />
+ <attribute name="name" type="token" use="optional">
+ <annotation>
+ <documentation xml:lang="en">
+ The default value of this attribute is the value of
+ the class attribute. If multiple component elements use the same
+ value for the class attribute, then using the default value
+ for this attribute will result in duplicate names.
+ In this case, this attribute must be specified with
+ a unique value.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="service-scope" default="none" type="cdi:Tservice_scope" use="optional" />
<anyAttribute processContents="lax" />
</complexType>
- <element name="configuration" type="cdi:Tconfiguration" />
<complexType name="Tconfiguration">
<sequence>
- <any namespace="##other" minOccurs="0" maxOccurs="unbounded"
- processContents="lax" />
+ <any namespace="##any" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded" />
</sequence>
- <attribute name="beanClass" type="token" use="required" />
- <attribute name="pid" type="token" use="required" />
- <attribute name="required" type="boolean" default="true" use="optional" />
+ <attribute name="configuration-policy" default="optional" type="cdi:Tconfiguration-policy" use="optional" />
+ <attribute name="configuration-pid" use="optional">
+ <annotation>
+ <documentation xml:lang="en">
+ The default value is the name attribute of the component.
+ </documentation>
+ </annotation>
+ <simpleType>
+ <restriction>
+ <simpleType>
+ <list itemType="token" />
+ </simpleType>
+ <minLength value="1" />
+ </restriction>
+ </simpleType>
+ </attribute>
+ <attribute name="type" type="token" use="required" />
<anyAttribute processContents="lax" />
</complexType>
- <element name="reference" type="cdi:Treference" />
- <complexType name="Treference">
+ <complexType name="Tmulti-value">
<sequence>
- <any namespace="##any" processContents="lax"
- minOccurs="0" maxOccurs="unbounded" />
+ <element name="value" minOccurs="0" maxOccurs="unbounded" type="cdi:Tvalue"/>
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
</sequence>
- <attribute name="beanClass" type="token" use="required" />
- <attribute name="target" type="token" use="required" />
<anyAttribute processContents="lax" />
</complexType>
@@ -79,52 +115,92 @@
<element name="list" type="cdi:Tmulti-value"/>
<element name="set" type="cdi:Tmulti-value"/>
</choice>
- <any namespace="##other" minOccurs="0" maxOccurs="unbounded"
- processContents="lax" />
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
</sequence>
<attribute name="name" type="string" use="required" />
<attribute name="value" type="string" use="optional" />
- <attribute name="value-type" type="cdi:Tvalue-types" default="String" use="optional" />
+ <attribute name="value-type" default="String" type="cdi:Tvalue-types" use="optional" />
<anyAttribute processContents="lax" />
</complexType>
- <complexType name="Tmulti-value">
+ <complexType name="Tprovide">
<sequence>
- <element name="value" minOccurs="0" maxOccurs="unbounded" type="cdi:Tvalue"/>
- <any namespace="##other" minOccurs="0" maxOccurs="unbounded"
- processContents="lax" />
+ <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
</sequence>
+ <attribute name="interface" type="token" use="required" />
<anyAttribute processContents="lax" />
</complexType>
- <complexType name="Tvalue" mixed="true">
+ <complexType name="Treference">
<sequence>
- <any namespace="##other" minOccurs="0" maxOccurs="unbounded"
- processContents="lax" />
+ <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
</sequence>
+ <attribute name="cardinality" default="1..1" type="cdi:Tcardinality" use="optional" />
+ <attribute name="name" type="token" use="optional" />
+ <attribute name="policy" default="static" type="cdi:Tpolicy" use="optional" />
+ <attribute name="policy-option" default="reluctant" type="cdi:Tpolicy-option" use="optional" />
+ <attribute name="scope" default="bundle" type="cdi:Treference_scope" use="optional" />
+ <attribute name="service" type="token" use="required" />
+ <attribute name="target" type="string" use="optional" />
<anyAttribute processContents="lax" />
</complexType>
- <complexType name="Tprovide">
+ <complexType name="Tvalue" mixed="true">
<sequence>
- <any namespace="##any" processContents="lax"
- minOccurs="0" maxOccurs="unbounded" />
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
</sequence>
- <attribute name="interface" type="token" use="required" />
<anyAttribute processContents="lax" />
</complexType>
- <complexType name="Tservice">
- <sequence>
- <element name="property" type="cdi:Tproperty"
- maxOccurs="unbounded" minOccurs="0" />
- <element name="provide" type="cdi:Tprovide"
- minOccurs="1" maxOccurs="unbounded" />
- <any namespace="##other" processContents="lax"
- minOccurs="0" maxOccurs="unbounded" />
- </sequence>
- <anyAttribute processContents="lax" />
- </complexType>
+ <simpleType name="Tcardinality">
+ <restriction base="string">
+ <enumeration value="0..1" />
+ <enumeration value="0..n" />
+ <enumeration value="1..1" />
+ <enumeration value="1..n" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Tconfiguration-policy">
+ <restriction base="string">
+ <enumeration value="factory" />
+ <enumeration value="ignore" />
+ <enumeration value="optional" />
+ <enumeration value="require" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Tpolicy">
+ <restriction base="string">
+ <enumeration value="dynamic" />
+ <enumeration value="static" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Tpolicy-option">
+ <restriction base="string">
+ <enumeration value="greedy" />
+ <enumeration value="reluctant" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Treference_scope">
+ <restriction base="string">
+ <enumeration value="bundle" />
+ <enumeration value="prototype" />
+ <enumeration value="prototype_required" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Tservice_scope">
+ <restriction base="string">
+ <enumeration value="bundle" />
+ <enumeration value="none" />
+ <enumeration value="prototype" />
+ <enumeration value="singleton" />
+ </restriction>
+ </simpleType>
<!-- Specifies the data type of a property or of the elements in a multi-value
property. Numerical and boolean values are trimmed before they are processed.
@@ -133,23 +209,23 @@
type of property it will automatically be boxed. -->
<simpleType name="Tvalue-types">
<restriction base="string">
- <enumeration value="String" />
- <enumeration value="long" />
- <enumeration value="Long" />
+ <enumeration value="boolean" />
+ <enumeration value="Boolean" />
+ <enumeration value="byte" />
+ <enumeration value="Byte" />
+ <enumeration value="char" />
+ <enumeration value="Character" />
<enumeration value="double" />
<enumeration value="Double" />
<enumeration value="float" />
<enumeration value="Float" />
<enumeration value="int" />
<enumeration value="Integer" />
- <enumeration value="byte" />
- <enumeration value="Byte" />
- <enumeration value="char" />
- <enumeration value="Character" />
- <enumeration value="boolean" />
- <enumeration value="Boolean" />
+ <enumeration value="long" />
+ <enumeration value="Long" />
<enumeration value="short" />
<enumeration value="Short" />
+ <enumeration value="String" />
</restriction>
</simpleType>
Added: aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/component/ComponentExtension_Ctor_static_reluctant_Test.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/component/ComponentExtension_Ctor_static_reluctant_Test.java?rev=1807424&view=auto
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/component/ComponentExtension_Ctor_static_reluctant_Test.java (added)
+++ aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/component/ComponentExtension_Ctor_static_reluctant_Test.java Tue Sep 5 22:01:11 2017
@@ -0,0 +1,318 @@
+/**
+ * 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.component;
+
+import static org.apache.aries.cdi.container.test.TestUtil.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.aries.cdi.container.internal.model.BeansModel;
+import org.apache.aries.cdi.container.internal.reference.ReferenceModel;
+import org.apache.aries.cdi.container.test.MockCdiContainer;
+import org.apache.aries.cdi.container.test.MockCdiContainerAndComponents;
+import org.apache.aries.cdi.container.test.beans.Bar;
+import org.apache.aries.cdi.container.test.beans.CtorArrayListFoo;
+import org.apache.aries.cdi.container.test.beans.CtorFoo;
+import org.apache.aries.cdi.container.test.beans.CtorFooBar;
+import org.apache.aries.cdi.container.test.beans.CtorFooFoo;
+import org.apache.aries.cdi.container.test.beans.CtorFooFooNamed;
+import org.apache.aries.cdi.container.test.beans.CtorFooOptional;
+import org.apache.aries.cdi.container.test.beans.CtorListFoo;
+import org.apache.aries.cdi.container.test.beans.Foo;
+import org.apache.aries.cdi.container.test.beans.CtorCollectionFoo;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.osgi.service.cdi.annotations.ReferenceCardinality;
+import org.osgi.service.cdi.annotations.ReferencePolicy;
+import org.osgi.service.cdi.annotations.ReferencePolicyOption;
+
+public class ComponentExtension_Ctor_static_reluctant_Test {
+
+ @Test
+ public void test_CtorArrayListFoo() throws Exception {
+ try (MockCdiContainerAndComponents container =
+ new MockCdiContainerAndComponents(
+ "test", CtorArrayListFoo.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// List<ReferenceModel> references = container.getTrackedReferences();
+//
+// Assert.assertEquals(1, references.size());
+//
+// ReferenceModel referenceModel = references.get(0);
+//
+// Assert.assertEquals(ArrayList.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MULTIPLE, referenceModel.getCardinality());
+// Assert.assertEquals("Foo0", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+ @Test
+ public void test_CtorCollectionFoo() throws Exception {
+ try (MockCdiContainerAndComponents container = new MockCdiContainerAndComponents(
+ "test", CtorCollectionFoo.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// List<ReferenceModel> references = container.getTrackedReferences();
+//
+// Assert.assertEquals(1, references.size());
+//
+// ReferenceModel referenceModel = references.get(0);
+//
+// Assert.assertEquals(Collection.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MULTIPLE, referenceModel.getCardinality());
+// Assert.assertEquals("Foo0", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+ @Test
+ public void test_CtorFooFoo() throws Exception {
+ try (MockCdiContainerAndComponents container = new MockCdiContainerAndComponents(
+ "test", CtorFooFoo.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// List<ReferenceModel> references = container.getTrackedReferences();
+//
+// Assert.assertEquals(2, references.size());
+//
+// ReferenceModel referenceModel = references.get(0);
+//
+// Assert.assertEquals(Foo.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MANDATORY, referenceModel.getCardinality());
+// Assert.assertEquals("Foo0", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+ @Test
+ public void test_CtorFoo() throws Exception {
+ try (MockCdiContainerAndComponents container = new MockCdiContainerAndComponents(
+ "test", CtorFoo.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// List<ReferenceModel> references = container.getTrackedReferences();
+//
+// Assert.assertEquals(1, references.size());
+//
+// ReferenceModel referenceModel = references.get(0);
+//
+// Assert.assertEquals(Foo.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MANDATORY, referenceModel.getCardinality());
+// Assert.assertEquals("Foo0", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+ @Test
+ public void test_CtorListFoo() throws Exception {
+ try (MockCdiContainerAndComponents container = new MockCdiContainerAndComponents(
+ "test", CtorListFoo.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// List<ReferenceModel> references = container.getTrackedReferences();
+//
+// Assert.assertEquals(1, references.size());
+//
+// ReferenceModel referenceModel = references.get(0);
+//
+// Assert.assertEquals(List.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MULTIPLE, referenceModel.getCardinality());
+// Assert.assertEquals("Foo0", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+ @Test
+ public void test_CtorFooBar() throws Exception {
+ try (MockCdiContainerAndComponents container = new MockCdiContainerAndComponents(
+ "test", CtorFooBar.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// List<ReferenceModel> references = container.getTrackedReferences();
+//
+// Assert.assertEquals(2, references.size());
+//
+// ReferenceModel referenceModel = references.get(0);
+//
+// Assert.assertEquals(Foo.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MANDATORY, referenceModel.getCardinality());
+// Assert.assertEquals("Foo0", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+
+// referenceModel = references.get(1);
+//
+// Assert.assertEquals(Bar.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MANDATORY, referenceModel.getCardinality());
+// Assert.assertEquals("Bar1", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Bar.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+ @Test
+ public void test_CtorFooFooNamed() throws Exception {
+ try (MockCdiContainerAndComponents container = new MockCdiContainerAndComponents(
+ "test", CtorFooFooNamed.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// Collection<ReferenceModel> references = sort(container.getTrackedReferences(), (c1, c2) -> c1.toString().compareTo(c2.toString()));
+//
+// Assert.assertEquals(2, references.size());
+//
+// Iterator<ReferenceModel> referenceIterator = references.iterator();
+//
+// ReferenceModel referenceModel = referenceIterator.next();
+//
+// Assert.assertEquals(Foo.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MANDATORY, referenceModel.getCardinality());
+// Assert.assertEquals("foo_a", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+//
+// referenceModel = referenceIterator.next();
+//
+// Assert.assertEquals(Foo.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.MANDATORY, referenceModel.getCardinality());
+// Assert.assertEquals("foo_b", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+ @Test
+ public void test_CtorFooOptional() throws Exception {
+ try (MockCdiContainerAndComponents container = new MockCdiContainerAndComponents(
+ "test", CtorFooOptional.class.getName())) {
+
+ BeansModel beansModel = container.containerState().beansModel();
+
+ Collection<ComponentModel> models = sort(beansModel.getComponentModels());
+
+ Assert.assertEquals(1, models.size());
+
+// Collection<ReferenceModel> references = container.getTrackedReferences();
+//
+// Assert.assertEquals(1, references.size());
+//
+// Iterator<ReferenceModel> referenceIterator = references.iterator();
+//
+// ReferenceModel referenceModel = referenceIterator.next();
+//
+// Assert.assertEquals(Foo.class, referenceModel.getBeanClass());
+// Assert.assertEquals(
+// ReferenceCardinality.OPTIONAL, referenceModel.getCardinality());
+// Assert.assertEquals("Foo0", referenceModel.getName());
+// Assert.assertEquals(ReferencePolicy.STATIC, referenceModel.getPolicy());
+// Assert.assertEquals(
+// ReferencePolicyOption.RELUCTANT, referenceModel.getPolicyOption());
+// Assert.assertNull(referenceModel.getScope());
+// Assert.assertEquals(Foo.class, referenceModel.getServiceClass());
+// Assert.assertEquals("", referenceModel.getTarget());
+ }
+ }
+
+}
\ No newline at end of file
Added: aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Ignore.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Ignore.java?rev=1807424&view=auto
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Ignore.java (added)
+++ aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Ignore.java Tue Sep 5 22:01:11 2017
@@ -0,0 +1,355 @@
+/**
+ * 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.configuration;
+
+import static org.osgi.framework.Constants.SERVICE_PID;
+import static org.apache.aries.cdi.container.test.TestUtil.*;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.service.cdi.annotations.ConfigurationPolicy;
+
+public class ConfigurationCallbackTest_Ignore {
+
+ @Test
+ public void test_emptyAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+
+ callback.added(properties);
+ }
+
+ @Test
+ public void test_emptyUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+
+ callback.updated(properties);
+ }
+
+ @Test
+ public void test_nullAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.added(null);
+ }
+
+ @Test
+ public void test_nullUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.updated(null);
+ }
+
+ @Test
+ public void test_addAfterAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.added(properties);
+ }
+
+ @Test
+ public void test_addAfterRemove() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+ }
+
+ @Test
+ public void test_addAfterUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.added(properties);
+ }
+
+ @Test
+ public void test_removeAfterAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+ }
+
+ @Test
+ public void test_removeAfterRemove() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+ }
+
+ @Test
+ public void test_removeAfterUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fum");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+ }
+
+ @Test
+ public void test_removeBeforeAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+ }
+
+ @Test
+ public void test_updateAfterAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fum");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+ }
+
+ @Test
+ public void test_updateAfterRemove() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.updated(properties);
+ }
+
+ @Test
+ public void test_updateAfterUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fum");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fee");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+ }
+
+ @Test
+ public void test_updateBeforeAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.updated(properties);
+ }
+
+ private ConfigurationPolicy POLICY = ConfigurationPolicy.IGNORE;
+
+}
Added: aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Optional.java
URL: http://svn.apache.org/viewvc/aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Optional.java?rev=1807424&view=auto
==============================================================================
--- aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Optional.java (added)
+++ aries/trunk/cdi/cdi-extender/src/test/java/org/apache/aries/cdi/container/internal/configuration/ConfigurationCallbackTest_Optional.java Tue Sep 5 22:01:11 2017
@@ -0,0 +1,362 @@
+/**
+ * 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.configuration;
+
+import static org.osgi.framework.Constants.SERVICE_PID;
+import static org.apache.aries.cdi.container.test.TestUtil.*;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.service.cdi.annotations.ConfigurationPolicy;
+
+public class ConfigurationCallbackTest_Optional {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void test_emptyAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+
+ callback.added(properties);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void test_emptyUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+
+ callback.updated(properties);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void test_nullAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.added(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void test_nullUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.updated(null);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_addAfterAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+
+ callback.added(properties);
+ }
+
+ @Test
+ public void test_addAfterRemove() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_addAfterUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+
+ callback.added(properties);
+ }
+
+ @Test
+ public void test_removeAfterAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_removeAfterRemove() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+ }
+
+ @Test
+ public void test_removeAfterUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ Assert.assertEquals("foo", callback.properties().get(SERVICE_PID));
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fum");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ Assert.assertEquals("fum", callback.properties().get(SERVICE_PID));
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_removeBeforeAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.removed();
+ }
+
+ @Test
+ public void test_updateAfterAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ Assert.assertEquals("foo", callback.properties().get(SERVICE_PID));
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fum");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ Assert.assertEquals("fum", callback.properties().get(SERVICE_PID));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_updateAfterRemove() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+
+ callback.removed();
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ callback.updated(properties);
+ }
+
+ @Test
+ public void test_updateAfterUpdate() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.added(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ Assert.assertEquals("foo", callback.properties().get(SERVICE_PID));
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fum");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ Assert.assertEquals("fum", callback.properties().get(SERVICE_PID));
+
+ properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "fee");
+
+ callback.updated(properties);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertFalse(callback.properties().isEmpty());
+ Assert.assertEquals("fee", callback.properties().get(SERVICE_PID));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_updateBeforeAdd() throws Exception {
+ ConfigurationCallback callback = getCallback(POLICY);
+
+ Assert.assertTrue(callback.resolved());
+ Assert.assertNotNull(callback.properties());
+ Assert.assertTrue(callback.properties().isEmpty());
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(SERVICE_PID, "foo");
+
+ callback.updated(properties);
+ }
+
+ private ConfigurationPolicy POLICY = ConfigurationPolicy.OPTIONAL;
+
+}