openwebbeans-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject svn commit: r1829748 - in /openwebbeans/trunk/webbeans-impl/src: main/java/org/apache/webbeans/container/ test/java/org/apache/webbeans/test/annotation/binding/ test/java/org/apache/webbeans/test/qualifier/
Date Sat, 21 Apr 2018 20:59:25 GMT
Author: rmannibucau
Date: Sat Apr 21 20:59:25 2018
New Revision: 1829748

URL: http://svn.apache.org/viewvc?rev=1829748&view=rev
Log:
OWB-1241 ensure to not rely on reflection to compare qualifiers of beans

Added:
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
Modified:
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
    openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java?rev=1829748&r1=1829747&r2=1829748&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java
Sat Apr 21 20:59:25 2018
@@ -21,6 +21,7 @@ package org.apache.webbeans.container;
 import org.apache.webbeans.annotation.EmptyAnnotationLiteral;
 import org.apache.webbeans.util.AnnotationUtil;
 
+import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.util.Nonbinding;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
@@ -28,22 +29,30 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.function.Function;
+import java.util.stream.Stream;
 
 public final class BeanCacheKey
 {
+    private static final Comparator<Annotation> ANNOTATION_COMPARATOR = new AnnotationComparator();
+
     private final boolean isDelegate;
     private final Type type;
     private final String path;
     private final Annotation qualifier;
     private final Annotation qualifiers[];
     private final int hashCode;
-    private static final Comparator<Annotation> ANNOTATION_COMPARATOR = new AnnotationComparator();
+    private volatile LazyAnnotatedTypes lazyAnnotatedTypes; // only needed for the "main"
key
+    private final Function<Class<?>, AnnotatedType<?>> lazyAtLoader;
 
-    public BeanCacheKey(boolean isDelegate, Type type, String path, Annotation... qualifiers)
+    public BeanCacheKey(boolean isDelegate, Type type, String path,
+                        Function<Class<?>, AnnotatedType<?>> lazyAtLoader,
+                        Annotation... qualifiers)
     {
         this.isDelegate = isDelegate;
         this.type = type;
         this.path = path;
+        this.lazyAtLoader = lazyAtLoader;
         int length = qualifiers != null ? qualifiers.length : 0;
         if (length == 0)
         {
@@ -90,20 +99,43 @@ public final class BeanCacheKey
         {
             return false;
         }
-        if (qualifier != null && cacheKey.qualifier != null ? !qualifierEquals(qualifier,
cacheKey.qualifier) : false)
+        if (qualifier != null && cacheKey.qualifier != null)
         {
-            return false;
+            ensureQualifierAtAreLoaded();
+            if (!qualifierEquals(lazyAnnotatedTypes.qualifierAt, qualifier, cacheKey.qualifier))
+            {
+                return false;
+            }
         }
         if (!qualifierArrayEquals(qualifiers, cacheKey.qualifiers))
         {
             return false;
         }
-        if (path != null ? !path.equals(cacheKey.path) : cacheKey.path != null)
+        return path != null ? path.equals(cacheKey.path) : cacheKey.path == null;
+    }
+
+    private void ensureQualifierAtAreLoaded()
+    {
+        if (lazyAnnotatedTypes == null)
         {
-            return false;
+            synchronized (this)
+            {
+                if (lazyAnnotatedTypes == null)
+                {
+                    if (qualifier != null)
+                    {
+                        lazyAnnotatedTypes = new LazyAnnotatedTypes(lazyAtLoader.apply(qualifier.annotationType()),
null);
+                    }
+                    else
+                    {
+                        lazyAnnotatedTypes = new LazyAnnotatedTypes(null, Stream.of(qualifiers)
+                                .map(Annotation::annotationType)
+                                .map(lazyAtLoader)
+                                .toArray(AnnotatedType[]::new));
+                    }
+                }
+            }
         }
-
-        return true;
     }
 
     private boolean qualifierArrayEquals(Annotation[] qualifiers1, Annotation[] qualifiers2)
@@ -120,11 +152,12 @@ public final class BeanCacheKey
         {
             return false;
         }
+        ensureQualifierAtAreLoaded();
         for (int i = 0; i < qualifiers1.length; i++)
         {
             Annotation a1 = qualifiers1[i];
             Annotation a2 = qualifiers2[i];
-            if (a1 == null ? a2 != null : !qualifierEquals(a1, a2))
+            if (a1 == null ? a2 != null : !qualifierEquals(lazyAnnotatedTypes.qualifierAts[i],
a1, a2))
             {
                 return false;
             }
@@ -193,9 +226,13 @@ public final class BeanCacheKey
     /**
      * Implements the equals() method for qualifiers, which ignores {@link Nonbinding} members.
      */
-    private boolean qualifierEquals(Annotation qualifier1, Annotation qualifier2)
+    private boolean qualifierEquals(AnnotatedType<?> at, Annotation qualifier1, Annotation
qualifier2)
     {
-        return ANNOTATION_COMPARATOR.compare(qualifier1, qualifier2) == 0;
+        if (at == null)
+        {
+            return AnnotationUtil.isCdiAnnotationEqual(qualifier1, qualifier2);
+        }
+        return AnnotationUtil.isCdiAnnotationEqual(at, qualifier1, qualifier2);
     }
 
 
@@ -350,4 +387,17 @@ public final class BeanCacheKey
             }
         }
     }
+
+    private static final class LazyAnnotatedTypes
+    {
+        private final AnnotatedType<?> qualifierAt;
+        private final AnnotatedType<?>[] qualifierAts;
+
+        private LazyAnnotatedTypes(final AnnotatedType<?> qualifierAt,
+                                   final AnnotatedType<?>[] qualifierAts)
+        {
+            this.qualifierAt = qualifierAt;
+            this.qualifierAts = qualifierAts;
+        }
+    }
 }

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java?rev=1829748&r1=1829747&r2=1829748&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
Sat Apr 21 20:59:25 2018
@@ -89,7 +89,8 @@ public class InjectionResolver
     /**
      * This Map contains all resolved beans via it's type and qualifiers.
      * If a bean have resolved as not existing, the entry will contain <code>null</code>
as value.
-     * The Long key is a hashCode, see {@link BeanCacheKey#BeanCacheKey(boolean, Type, String,
Annotation...)}
+     * The Long key is a hashCode, see
+     * {@link BeanCacheKey#BeanCacheKey(boolean, Type, String, java.util.function.Function,
Annotation...)}
      */
     private Map<BeanCacheKey, Set<Bean<?>>> resolvedBeansByType = new ConcurrentHashMap<>();
 
@@ -458,7 +459,7 @@ public class InjectionResolver
             currentQualifier = true;
         }
 
-        Set<Bean<?>> resolvedComponents = null;
+        Set<Bean<?>> resolvedComponents;
         BeanCacheKey cacheKey = null;
 
         if (!startup)
@@ -466,7 +467,7 @@ public class InjectionResolver
             // we only cache and validate once the set of Beans is final, otherwise we would
cache crap
             validateInjectionPointType(injectionPointType);
 
-            cacheKey = new BeanCacheKey(isDelegate, injectionPointType, bdaBeansXMLFilePath,
qualifiers);
+            cacheKey = new BeanCacheKey(isDelegate, injectionPointType, bdaBeansXMLFilePath,
this::findQualifierModel, qualifiers);
 
             resolvedComponents = resolvedBeansByType.get(cacheKey);
             if (resolvedComponents != null)
@@ -475,10 +476,7 @@ public class InjectionResolver
             }
         }
 
-        if (resolvedComponents  == null)
-        {
-            resolvedComponents = new HashSet<>();
-        }
+        resolvedComponents = new HashSet<>();
 
         boolean returnAll = injectionPointType.equals(Object.class) && currentQualifier;
 
@@ -809,7 +807,7 @@ public class InjectionResolver
                     Annotation qualifier = itQualifiers.next();
                     if (annot.annotationType().equals(qualifier.annotationType()))
                     {
-                        AnnotatedType<?> at = webBeansContext.getBeanManagerImpl().getAdditionalAnnotatedTypeQualifiers().get(qualifier.annotationType());
+                        AnnotatedType<?> at = findQualifierModel(qualifier.annotationType());
                         if (at == null)
                         {
                             if (AnnotationUtil.isCdiAnnotationEqual(qualifier, annot))
@@ -837,4 +835,9 @@ public class InjectionResolver
 
         return result;
     }
+
+    private AnnotatedType<? extends Annotation> findQualifierModel(final Class<?>
qualifier)
+    {
+        return webBeansContext.getBeanManagerImpl().getAdditionalAnnotatedTypeQualifiers().get(qualifier);
+    }
 }

Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java?rev=1829748&r1=1829747&r2=1829748&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java
(original)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java
Sat Apr 21 20:59:25 2018
@@ -127,8 +127,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testEmptyNull()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -145,8 +145,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testTypeUnequal()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null);
-        BeanCacheKey b = new BeanCacheKey(true, Integer.class, null);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null);
+        BeanCacheKey b = new BeanCacheKey(true, Integer.class, null, it -> null);
         Assert.assertFalse(a.equals(b));
         Assert.assertFalse(a.hashCode() == b.hashCode());
     }
@@ -154,8 +154,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testPath()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, "A");
-        BeanCacheKey b = new BeanCacheKey(true, String.class, "A");
+        BeanCacheKey a = new BeanCacheKey(true, String.class, "A", it -> null);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, "A", it -> null);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -163,8 +163,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testPathUnequal()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, "A");
-        BeanCacheKey b = new BeanCacheKey(true, String.class, "B");
+        BeanCacheKey a = new BeanCacheKey(true, String.class, "A", it -> null);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, "B", it -> null);
         Assert.assertFalse(a.equals(b));
         Assert.assertFalse(a.hashCode() == b.hashCode());
     }
@@ -172,16 +172,16 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testNonEqualsWithBindingMemberParameter()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a1);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a2);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a1);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a2);
         Assert.assertFalse(a.equals(b));
     }
 
     @Test
     public void testEqualsWithBindingMember()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a1);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a1);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a1);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a1);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -190,8 +190,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testEqualsWithNonBindingMember()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a3);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a3);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a3);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a3);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -199,8 +199,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testEquals2Annotations()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a12);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a12);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a12);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a12);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -208,8 +208,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testEquals2AnnotationsUnorderedName()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a13);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a31);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a13);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a31);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -217,8 +217,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testEquals2AnnotationsUnorderedParam()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a12);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a21);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a12);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a21);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -226,16 +226,16 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testDiffMembers()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a4);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a5);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a4);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a5);
         Assert.assertFalse(a.equals(b));
     }
 
     @Test
     public void testOnyDiffMembersInNonBinding()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a5);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a6);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a5);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a6);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -243,8 +243,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testAnnotationOrdering()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a56);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a65);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a56);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a65);
         Assert.assertEquals(a, b);
         Assert.assertEquals(a.hashCode(), b.hashCode());
     }
@@ -252,32 +252,32 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testMemberArraysInt()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a7);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, a8);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a7);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, a8);
         Assert.assertFalse(a.equals(b));
     }
 
     @Test
     public void testMemberArraysString()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a9);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, aa);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a9);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, aa);
         Assert.assertFalse(a.equals(b));
     }
 
     @Test
     public void testMemberArraysBoolean()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, ab);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, ac);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, ab);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, ac);
         Assert.assertFalse(a.equals(b));
     }
 
     @Test
     public void testDiffArrays()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, null, a9a);
-        BeanCacheKey b = new BeanCacheKey(true, String.class, null, abc);
+        BeanCacheKey a = new BeanCacheKey(true, String.class, null, it -> null, a9a);
+        BeanCacheKey b = new BeanCacheKey(true, String.class, null, it -> null, abc);
         Assert.assertFalse(a.equals(b));
         Assert.assertFalse(a.hashCode() == b.hashCode());
     }
@@ -286,8 +286,8 @@ public class BeanCacheKeyUnitTest
     @Test
     public void testDelegateUnequal()
     {
-        BeanCacheKey a = new BeanCacheKey(true, String.class, "A");
-        BeanCacheKey b = new BeanCacheKey(false, String.class, "A");
+        BeanCacheKey a = new BeanCacheKey(true, String.class, "A", it -> null);
+        BeanCacheKey b = new BeanCacheKey(false, String.class, "A", it -> null);
         Assert.assertFalse(a.equals(b));
         Assert.assertFalse(a.hashCode() == b.hashCode());
     }

Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java?rev=1829748&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
(added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/qualifier/CacheUsesQualifierOverridesTest.java
Sat Apr 21 20:59:25 2018
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.webbeans.test.qualifier;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.function.Supplier;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.enterprise.util.Nonbinding;
+import javax.inject.Qualifier;
+
+import org.apache.webbeans.config.OwbParametrizedTypeImpl;
+import org.apache.webbeans.test.AbstractUnitTest;
+import org.junit.Test;
+
+public class CacheUsesQualifierOverridesTest extends AbstractUnitTest
+{
+    @Test
+    public void run()
+    {
+        addExtension(new Extension() {
+            void changeQualifier(@Observes final BeforeBeanDiscovery beforeBeanDiscovery)
{
+                beforeBeanDiscovery.configureQualifier(TheQualifier.class)
+                        .methods().forEach(m -> m.remove(it -> it.annotationType()
== Nonbinding.class));
+            }
+        });
+        startContainer(Impl1.class, Impl2.class);
+        final OwbParametrizedTypeImpl type = new OwbParametrizedTypeImpl(null, Supplier.class,
String.class);
+        final Supplier<String> uno = getInstance(type, new TheQualifier.Literal("uno"));
+        final Supplier<String> due = getInstance(type, new TheQualifier.Literal("due"));
+        assertEquals("1", uno.get());
+        assertEquals("2", due.get());
+        // redundant but this is the real test here, previous are just nicer to read in the
output
+        assertNotEquals(uno.getClass(), due.getClass());
+    }
+
+    @Dependent
+    @TheQualifier("uno")
+    public static class Impl1 implements Supplier<String>
+    {
+        @Override
+        public String get()
+        {
+            return "1";
+        }
+    }
+
+    @Dependent
+    @TheQualifier("due")
+    public static class Impl2 implements Supplier<String>
+    {
+        @Override
+        public String get()
+        {
+            return "2";
+        }
+    }
+
+    @Qualifier
+    @Target({FIELD, TYPE})
+    @Retention(RUNTIME)
+    public @interface TheQualifier
+    {
+        @Nonbinding
+        String value();
+
+        class Literal extends AnnotationLiteral<TheQualifier> implements TheQualifier
+        {
+            private final String value;
+
+            public Literal(final String value)
+            {
+                this.value = value;
+            }
+
+            @Override
+            public String value()
+            {
+                return value;
+            }
+        }
+    }
+}



Mime
View raw message