This is an automated email from the ASF dual-hosted git repository.
arne pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwebbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 4885d0a OWB-1349: Use annotated type to check qualifier validation
rules
4885d0a is described below
commit 4885d0a52b03e5a4c099c102036ff556ab8fa4bc
Author: arne <[email protected]>
AuthorDate: Fri Sep 11 21:16:14 2020 +0200
OWB-1349: Use annotated type to check qualifier validation rules
---
.../webbeans/annotation/AnnotationManager.java | 48 ++++-
.../component/creation/BeanAttributesBuilder.java | 18 +-
.../apache/webbeans/container/BeanManagerImpl.java | 6 +-
.../org/apache/webbeans/util/AnnotationUtil.java | 5 +
.../qualifier/CacheUsesQualifierOverridesTest.java | 205 ++++++++++++++++++++-
5 files changed, 254 insertions(+), 28 deletions(-)
diff --git
a/webbeans-impl/src/main/java/org/apache/webbeans/annotation/AnnotationManager.java
b/webbeans-impl/src/main/java/org/apache/webbeans/annotation/AnnotationManager.java
index b5442c4..b934ea9 100644
---
a/webbeans-impl/src/main/java/org/apache/webbeans/annotation/AnnotationManager.java
+++
b/webbeans-impl/src/main/java/org/apache/webbeans/annotation/AnnotationManager.java
@@ -28,6 +28,7 @@ import
org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.util.AnnotationUtil;
import org.apache.webbeans.util.ArrayUtil;
import org.apache.webbeans.util.Asserts;
+import org.apache.webbeans.util.ClassUtil;
import javax.enterprise.context.NormalScope;
import javax.enterprise.inject.Any;
@@ -57,6 +58,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -459,7 +461,7 @@ public final class AnnotationManager
}
}
- private void checkQualifierConditions(Annotation ann)
+ public void checkQualifierConditions(Annotation ann)
{
if (ann == DefaultLiteral.INSTANCE || ann == AnyLiteral.INSTANCE ||
ann.annotationType().equals(Default.class) ||
ann.annotationType().equals(Any.class) ||
@@ -469,17 +471,49 @@ public final class AnnotationManager
return;
}
- Method[] methods =
webBeansContext.getSecurityService().doPrivilegedGetDeclaredMethods(ann.annotationType());
+ AnnotatedType annotatedType =
webBeansContext.getBeanManagerImpl().getAdditionalAnnotatedTypeQualifiers().get(ann.annotationType());
+ if (annotatedType == null)
+ {
+ Iterator<AnnotatedType> annotatedTypes =
(Iterator)webBeansContext.getBeanManagerImpl().getAnnotatedTypes(ann.annotationType()).iterator();
+ if (annotatedTypes.hasNext())
+ {
+ annotatedType = annotatedTypes.next();
+ // TODO what to do here, if we have more than one?
+ }
+ }
+ if (annotatedType != null)
+ {
+ Set<AnnotatedMethod> methods = annotatedType.getMethods();
- for (Method method : methods)
+ for (AnnotatedMethod method : methods)
+ {
+ Type baseType = method.getBaseType();
+ Class<?> clazz = ClassUtil.getClass(baseType);
+ if (clazz.isArray() || clazz.isAnnotation())
+ {
+ if (!AnnotationUtil.hasAnnotation(method.getAnnotations(),
Nonbinding.class))
+ {
+ throw new WebBeansConfigurationException("WebBeans
definition class : " + method.getJavaMember().getDeclaringClass().getName() + "
@Qualifier : "
+ +
ann.annotationType().getName()
+ + " must have
@NonBinding valued members for its array-valued and annotation valued members");
+ }
+ }
+ }
+ }
+ else
{
- Class<?> clazz = method.getReturnType();
- if (clazz.isArray() || clazz.isAnnotation())
+ Method[] methods =
webBeansContext.getSecurityService().doPrivilegedGetDeclaredMethods(ann.annotationType());
+
+ for (Method method : methods)
{
- if
(!AnnotationUtil.hasAnnotation(method.getDeclaredAnnotations(),
Nonbinding.class))
+ Class<?> clazz = method.getReturnType();
+ if (clazz.isArray() || clazz.isAnnotation())
{
- throw new WebBeansConfigurationException("@Qualifier : " +
ann.annotationType().getName()
+ if
(!AnnotationUtil.hasAnnotation(method.getDeclaredAnnotations(),
Nonbinding.class))
+ {
+ throw new WebBeansConfigurationException("@Qualifier :
" + ann.annotationType().getName()
+ " must have
@NonBinding valued members for its array-valued and annotation valued members");
+ }
}
}
}
diff --git
a/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BeanAttributesBuilder.java
b/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BeanAttributesBuilder.java
index db00d22..eb6693f 100644
---
a/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BeanAttributesBuilder.java
+++
b/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BeanAttributesBuilder.java
@@ -20,7 +20,6 @@ package org.apache.webbeans.component.creation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collections;
@@ -42,7 +41,6 @@ import javax.enterprise.inject.spi.AnnotatedMember;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
-import javax.enterprise.util.Nonbinding;
import javax.inject.Named;
import javax.inject.Scope;
import javax.interceptor.Interceptor;
@@ -217,21 +215,7 @@ public abstract class BeanAttributesBuilder<T, A extends
Annotated>
if (annotationManager.isQualifierAnnotation(type))
{
- Method[] methods =
webBeansContext.getSecurityService().doPrivilegedGetDeclaredMethods(type);
-
- for (Method method : methods)
- {
- Class<?> clazz = method.getReturnType();
- if (clazz.isArray() || clazz.isAnnotation())
- {
- if
(!AnnotationUtil.hasAnnotation(method.getDeclaredAnnotations(),
Nonbinding.class))
- {
- throw new WebBeansConfigurationException("WebBeans
definition class : " + method.getDeclaringClass().getName() + " @Qualifier : "
- +
annotation.annotationType().getName()
- + " must
have @NonBinding valued members for its array-valued and annotation valued
members");
- }
- }
- }
+ annotationManager.checkQualifierConditions(annotation);
if (qualifiedTypes.contains(annotation.annotationType()) &&
!isRepetable(annotated, annotation))
{
diff --git
a/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java
b/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java
index 082409b..4091b57 100644
---
a/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java
+++
b/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java
@@ -1442,7 +1442,11 @@ public class BeanManagerImpl implements BeanManager,
Referenceable
public <T> Iterable<AnnotatedType<T>> getAnnotatedTypes(Class<T> type)
{
final Collection<AnnotatedType<T>> types = new ArrayList<>(2);
- types.add(annotatedElementFactory.getAnnotatedType(type));
+ AnnotatedType<T> annotatedType =
annotatedElementFactory.getAnnotatedType(type);
+ if (annotatedType != null)
+ {
+ types.add(annotatedType);
+ }
final Collection<AnnotatedType<T>> userAnnotatedTypes =
getUserAnnotatedTypes(type);
if (userAnnotatedTypes != null)
{
diff --git
a/webbeans-impl/src/main/java/org/apache/webbeans/util/AnnotationUtil.java
b/webbeans-impl/src/main/java/org/apache/webbeans/util/AnnotationUtil.java
index 589344b..fba8093 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/util/AnnotationUtil.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/util/AnnotationUtil.java
@@ -479,6 +479,11 @@ public final class AnnotationUtil
return getAnnotation(anns, annotation) != null;
}
+ public static boolean hasAnnotation(Set<Annotation> anns, Class<? extends
Annotation> annotation)
+ {
+ return getAnnotation(anns, annotation) != null;
+ }
+
/**
* get the annotation of the given type from the array.
* @param anns
diff --git
a/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
b/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
index c26ec46..5710794 100644
---
a/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
+++
b/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
@@ -24,12 +24,25 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.function.Supplier;
import javax.enterprise.context.Dependent;
import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedParameter;
+import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.util.AnnotationLiteral;
@@ -38,15 +51,18 @@ import javax.inject.Qualifier;
import org.apache.webbeans.config.OwbParametrizedTypeImpl;
import org.apache.webbeans.test.AbstractUnitTest;
+import org.apache.webbeans.util.GenericsUtil;
import org.junit.Test;
public class CacheUsesQualifierOverridesTest extends AbstractUnitTest
{
@Test
- public void run()
+ public void configureExistingQualifier()
{
- addExtension(new Extension() {
- void changeQualifier(@Observes final BeforeBeanDiscovery
beforeBeanDiscovery) {
+ addExtension(new Extension()
+ {
+ void changeQualifier(@Observes final BeforeBeanDiscovery
beforeBeanDiscovery)
+ {
beforeBeanDiscovery.configureQualifier(TheQualifier.class)
.methods().forEach(m -> m.remove(it ->
it.annotationType() == Nonbinding.class));
}
@@ -61,8 +77,42 @@ public class CacheUsesQualifierOverridesTest extends
AbstractUnitTest
assertNotEquals(uno.getClass(), due.getClass());
}
+ @Test
+ public void addQualifierWithNonBinding()
+ {
+ addExtension(new Extension()
+ {
+ void changeQualifier(@Observes final BeforeBeanDiscovery
beforeBeanDiscovery)
+ {
+
beforeBeanDiscovery.configureQualifier(QualifierWithoutMarker.class)
+ .methods().forEach(m -> m.add(new
Nonbinding.Literal()));
+ }
+ });
+ startContainer(Impl1.class, Impl2.class);
+ final OwbParametrizedTypeImpl type = new OwbParametrizedTypeImpl(null,
Supplier.class, String.class);
+ final Supplier<String> uno = getInstance(type, new
QualifierWithoutMarker.Literal("non-binding attribute"));
+ assertEquals("1", uno.get());
+ }
+
+ @Test
+ public void addQualifier()
+ {
+ addExtension(new Extension()
+ {
+ void addQualifier(@Observes final BeforeBeanDiscovery
beforeBeanDiscovery)
+ {
+ beforeBeanDiscovery.addQualifier(new
QualifierWithArrayAttributeType());
+ }
+ });
+ startContainer(Impl1.class, Impl2.class);
+ final OwbParametrizedTypeImpl type = new OwbParametrizedTypeImpl(null,
Supplier.class, String.class);
+ final Supplier<String> uno = getInstance(type, new
QualifierWithoutMarker.Literal("non-binding attribute"));
+ assertEquals("1", uno.get());
+ }
+
@Dependent
@TheQualifier("uno")
+ @QualifierWithoutMarker
public static class Impl1 implements Supplier<String>
{
@Override
@@ -107,4 +157,153 @@ public class CacheUsesQualifierOverridesTest extends
AbstractUnitTest
}
}
}
+
+ @Target({FIELD, TYPE})
+ @Retention(RUNTIME)
+ public @interface QualifierWithoutMarker
+ {
+ String[] value() default {};
+
+ class Literal extends AnnotationLiteral<QualifierWithoutMarker>
implements QualifierWithoutMarker
+ {
+ private final String[] value;
+
+ public Literal(final String... value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public String[] value()
+ {
+ return value;
+ }
+ }
+ }
+
+ class QualifierWithArrayAttributeType implements
AnnotatedType<QualifierWithoutMarker>
+ {
+
+ @Override
+ public Type getBaseType()
+ {
+ return QualifierWithoutMarker.class;
+ }
+
+ @Override
+ public Set<Type> getTypeClosure()
+ {
+ return GenericsUtil.getTypeClosure(QualifierWithoutMarker.class);
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationType)
+ {
+ return QualifierWithoutMarker.class.getAnnotation(annotationType);
+ }
+
+ @Override
+ public Set<Annotation> getAnnotations()
+ {
+ return new
HashSet<>(Arrays.asList(QualifierWithoutMarker.class.getAnnotations()));
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class<? extends Annotation>
annotationType)
+ {
+ return
QualifierWithoutMarker.class.isAnnotationPresent(annotationType);
+ }
+
+ @Override
+ public Class<QualifierWithoutMarker> getJavaClass()
+ {
+ return QualifierWithoutMarker.class;
+ }
+
+ @Override
+ public Set<AnnotatedConstructor<QualifierWithoutMarker>>
getConstructors()
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<AnnotatedMethod<? super QualifierWithoutMarker>>
getMethods()
+ {
+ AnnotatedType<QualifierWithoutMarker> declaringType = this;
+ return Collections.singleton(new
AnnotatedMethod<QualifierWithoutMarker>()
+ {
+
+ @Override
+ public List<AnnotatedParameter<QualifierWithoutMarker>>
getParameters()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isStatic()
+ {
+ return false;
+ }
+
+ @Override
+ public AnnotatedType<QualifierWithoutMarker> getDeclaringType()
+ {
+ return declaringType;
+ }
+
+ @Override
+ public Type getBaseType()
+ {
+ return String[].class;
+ }
+
+ @Override
+ public Set<Type> getTypeClosure()
+ {
+ return GenericsUtil.getTypeClosure(String[].class);
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T>
annotationType)
+ {
+ if (Nonbinding.class.equals(annotationType))
+ {
+ return (T)new Nonbinding.Literal();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public Set<Annotation> getAnnotations()
+ {
+ return Collections.singleton(new Nonbinding.Literal());
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class<? extends Annotation>
annotationType)
+ {
+ return Nonbinding.class.equals(annotationType);
+ }
+
+ @Override
+ public Method getJavaMember() {
+ try {
+ return QualifierWithoutMarker.class.getMethod("value");
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ });
+ }
+
+ @Override
+ public Set<AnnotatedField<? super QualifierWithoutMarker>> getFields()
{
+ return Collections.emptySet();
+ }
+
+ }
}