diff --git a/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java b/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java index 6148633fe5..30a44e88f5 100644 --- a/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java +++ b/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java @@ -192,6 +192,18 @@ public WeldInstance createInstance() { return delegate().createInstance(); } + @Override + public boolean isMatchingBean(Set beanTypes, Set beanQualifiers, Type requiredType, + Set requiredQualifiers) { + return delegate().isMatchingBean(beanTypes, beanQualifiers, requiredType, requiredQualifiers); + } + + @Override + public boolean isMatchingEvent(Type eventType, Set eventQualifiers, Type observedEventType, + Set observedEventQualifiers) { + return delegate().isMatchingEvent(eventType, eventQualifiers, observedEventType, observedEventQualifiers); + } + @Override public Bean getPassivationCapableBean(BeanIdentifier identifier) { return delegate().getPassivationCapableBean(identifier); diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java b/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java index bc8149b45d..ea890057f7 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java @@ -25,7 +25,6 @@ import java.util.Set; import jakarta.enterprise.context.Dependent; -import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.spi.BeanAttributes; import jakarta.enterprise.inject.spi.configurator.BeanAttributesConfigurator; @@ -222,7 +221,8 @@ public BeanAttributesConfigurator alternative(boolean alternative) { @Override public BeanAttributes complete() { - return new ImmutableBeanAttributes(ImmutableSet.copyOf(stereotypes), isAlternative, name, initQualifiers(qualifiers), + return new ImmutableBeanAttributes(ImmutableSet.copyOf(stereotypes), isAlternative, name, + Bindings.normalizeBeanQualifiers(qualifiers), ImmutableSet.copyOf(types), initScope()); } @@ -258,27 +258,4 @@ private Class initScope() { return Dependent.class; } - private Set initQualifiers(Set qualifiers) { - if (qualifiers.isEmpty()) { - return Bindings.DEFAULT_QUALIFIERS; - } - Set normalized = new HashSet(qualifiers); - normalized.remove(Any.Literal.INSTANCE); - normalized.remove(Default.Literal.INSTANCE); - if (normalized.isEmpty()) { - normalized = Bindings.DEFAULT_QUALIFIERS; - } else { - ImmutableSet.Builder builder = ImmutableSet.builder(); - if (normalized.size() == 1) { - if (normalized.iterator().next().annotationType().equals(Named.class)) { - builder.add(Default.Literal.INSTANCE); - } - } - builder.add(Any.Literal.INSTANCE); - builder.addAll(qualifiers); - normalized = builder.build(); - } - return normalized; - } - } diff --git a/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java b/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java index c21c50be87..bfbf1df8ee 100644 --- a/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java +++ b/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java @@ -128,4 +128,13 @@ public interface BeanManagerLogger extends WeldLogger { @Message(id = 1336, value = "InjectionTargetFactory.configure() may not be called after createInjectionTarget() invocation. AnnotatedType used: {0}", format = Format.MESSAGE_FORMAT) IllegalStateException unableToConfigureInjectionTargetFactory(Object param1); + @Message(id = 1337, value = "BeanContainer#{0} requires all parameters to be non-null.", format = Format.MESSAGE_FORMAT) + IllegalArgumentException assignabilityMethodIllegalArgs(Object param1); + + @Message(id = 1338, value = "All annotations passed into BeanContainer#{0} have to be CDI Qualifiers. Following annotation was not recognized as a qualifier: {1}", format = Format.MESSAGE_FORMAT) + IllegalArgumentException annotationNotAQualifier(Object param1, Object param2); + + @Message(id = 1339, value = "Provided event type {0} cannot contain unresolvable type parameter", format = Format.MESSAGE_FORMAT) + IllegalArgumentException eventTypeUnresolvableWildcard(Object param1); + } \ No newline at end of file diff --git a/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java b/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java index c7517058fd..d60b61cd37 100644 --- a/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java +++ b/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java @@ -53,6 +53,8 @@ import jakarta.enterprise.context.spi.Contextual; import jakarta.enterprise.context.spi.CreationalContext; import jakarta.enterprise.event.Event; +import jakarta.enterprise.inject.Any; +import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.Instance; import jakarta.enterprise.inject.spi.Annotated; import jakarta.enterprise.inject.spi.AnnotatedField; @@ -154,6 +156,7 @@ import org.jboss.weld.module.ObserverNotifierFactory; import org.jboss.weld.resolution.BeanTypeAssignabilityRules; import org.jboss.weld.resolution.DecoratorResolvableBuilder; +import org.jboss.weld.resolution.EventTypeAssignabilityRules; import org.jboss.weld.resolution.InterceptorResolvable; import org.jboss.weld.resolution.InterceptorResolvableBuilder; import org.jboss.weld.resolution.NameBasedResolver; @@ -177,9 +180,11 @@ import org.jboss.weld.util.LazyValueHolder; import org.jboss.weld.util.Observers; import org.jboss.weld.util.Preconditions; +import org.jboss.weld.util.Types; import org.jboss.weld.util.collections.ImmutableSet; import org.jboss.weld.util.collections.SetMultimap; import org.jboss.weld.util.collections.WeldCollections; +import org.jboss.weld.util.reflection.HierarchyDiscovery; import org.jboss.weld.util.reflection.Reflections; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -1563,6 +1568,72 @@ public WeldInstance createInstance() { return getInstance(createCreationalContext(null)); } + @Override + public boolean isMatchingBean(Set beanTypes, Set beanQualifiers, Type requiredType, + Set requiredQualifiers) { + String loggingMethodName = "isMatchingBean()"; + if (beanTypes == null || beanQualifiers == null || requiredType == null || requiredQualifiers == null) { + throw BeanManagerLogger.LOG.assignabilityMethodIllegalArgs(loggingMethodName); + } + validateQualifiers(beanQualifiers, loggingMethodName); + validateQualifiers(requiredQualifiers, loggingMethodName); + // always add Object as bean type; filter bean types to only contain legal bean types + Set legalBeanTypes = new HashSet<>(beanTypes); + legalBeanTypes.add(Object.class); + legalBeanTypes = Beans.getLegalBeanTypes(legalBeanTypes, beanTypes); + // type check first + if (BeanTypeAssignabilityRules.instance().matches(requiredType, legalBeanTypes)) { + // normalize qualifiers, adding built-ins where missing, then compare + Set normalizedBeanQualifiers = Bindings.normalizeBeanQualifiers(beanQualifiers); + Set normalizedRequiredQualifiers = requiredQualifiers.isEmpty() ? Set.of(Default.Literal.INSTANCE) + : requiredQualifiers; + MetaAnnotationStore metaAnnotationStore = services.get(MetaAnnotationStore.class); + if (Beans.containsAllQualifiers(QualifierInstance.of(normalizedRequiredQualifiers, metaAnnotationStore), + QualifierInstance.of(normalizedBeanQualifiers, metaAnnotationStore))) { + return true; + } + } + return false; + } + + @Override + public boolean isMatchingEvent(Type eventType, Set eventQualifiers, Type observedEventType, + Set observedEventQualifiers) { + String loggingMethodName = "isMatchingEvent()"; + if (eventType == null || eventQualifiers == null || observedEventType == null || observedEventQualifiers == null) { + throw BeanManagerLogger.LOG.assignabilityMethodIllegalArgs(loggingMethodName); + } + if (Types.containsTypeVariable(Types.getCanonicalType(eventType))) { + throw BeanManagerLogger.LOG.eventTypeUnresolvableWildcard(eventType); + } + validateQualifiers(eventQualifiers, loggingMethodName); + validateQualifiers(observedEventQualifiers, loggingMethodName); + // type check first + if (EventTypeAssignabilityRules.instance().matches(observedEventType, + HierarchyDiscovery.forNormalizedType(eventType).getTypeClosure())) { + // normalize qualifiers, adding built-ins where missing, then compare + Set normalizedEventQualifiers = new HashSet<>(eventQualifiers); + if (eventQualifiers.isEmpty()) { + normalizedEventQualifiers.add(Default.Literal.INSTANCE); + } + normalizedEventQualifiers.add(Any.Literal.INSTANCE); + MetaAnnotationStore metaAnnotationStore = services.get(MetaAnnotationStore.class); + if (Beans.containsAllQualifiers(QualifierInstance.of(observedEventQualifiers, metaAnnotationStore), + QualifierInstance.of(normalizedEventQualifiers, metaAnnotationStore))) { + return true; + } + } + return false; + } + + private void validateQualifiers(Set qualifiers, String methodName) { + for (Annotation qualifierCandidate : qualifiers) { + if (!isQualifier(qualifierCandidate.annotationType())) { + throw BeanManagerLogger.LOG.annotationNotAQualifier(methodName, qualifierCandidate.annotationType()); + } + } + } + private Bean findNormalScopedDependant(CreationalContextImpl weldCreationalContext) { CreationalContextImpl parent = weldCreationalContext.getParentCreationalContext(); if (parent != null) { diff --git a/impl/src/main/java/org/jboss/weld/util/Bindings.java b/impl/src/main/java/org/jboss/weld/util/Bindings.java index 7d03970808..fc8d95d598 100644 --- a/impl/src/main/java/org/jboss/weld/util/Bindings.java +++ b/impl/src/main/java/org/jboss/weld/util/Bindings.java @@ -17,11 +17,13 @@ package org.jboss.weld.util; import java.lang.annotation.Annotation; +import java.util.HashSet; import java.util.Set; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.inject.Named; import org.jboss.weld.logging.BeanManagerLogger; import org.jboss.weld.logging.MetadataLogger; @@ -102,4 +104,33 @@ private static void checkInterceptorBinding(Annotation qualifier, MetaAnnotation throw BeanManagerLogger.LOG.interceptorResolutionWithNonbindingType(qualifier); } } + + /** + * Normalize set of qualifiers for a bean - automatically adds {@code @Any} and {@code Default} if needed. + * + * @param qualifiers input set of qualifiers, possibly missing built-in qualifiers + * @return normalized set of bean qualifiers + */ + public static Set normalizeBeanQualifiers(Set qualifiers) { + if (qualifiers.isEmpty()) { + return DEFAULT_QUALIFIERS; + } + Set normalized = new HashSet(qualifiers); + normalized.remove(Any.Literal.INSTANCE); + normalized.remove(Default.Literal.INSTANCE); + if (normalized.isEmpty()) { + normalized = DEFAULT_QUALIFIERS; + } else { + ImmutableSet.Builder builder = ImmutableSet.builder(); + if (normalized.size() == 1) { + if (normalized.iterator().next().annotationType().equals(Named.class)) { + builder.add(Default.Literal.INSTANCE); + } + } + builder.add(Any.Literal.INSTANCE); + builder.addAll(qualifiers); + normalized = builder.build(); + } + return normalized; + } } diff --git a/pom.xml b/pom.xml index a0c3bbccaf..08e9c2b170 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ 1.2.0.Final 2.0.1 - 4.1.0-M1 + 4.1.0-SNAPSHOT @@ -88,8 +88,8 @@ 1.2.6 2.0.0 3.3.0 - 7.4.0 - 6.0.Alpha2 + 7.9.0 + 6.0-SNAPSHOT 1.0.3.Final 5.0.1.Final