You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2020/03/07 20:35:52 UTC

[logging-log4j2] branch mean-bean-machine updated (1ed2584 -> a827c77)

This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a change to branch mean-bean-machine
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git.


    from 1ed2584  Add missing class
     new 6dc0812  Use weak cache for type closure lookup
     new cb9c012  Refactor cache API
     new a827c77  Refactor Collection<Qualifier> into own class

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/logging/log4j/plugins/api/Default.java  |  25 -----
 .../log4j/plugins/defaults/bean/AbstractBean.java  |   4 +-
 .../plugins/defaults/bean/DefaultBeanManager.java  |  19 ++--
 .../log4j/plugins/defaults/bean/SystemBean.java    |   4 +-
 .../defaults/model/DefaultElementManager.java      |  64 +++++-------
 .../defaults/model/DefaultInjectionPoint.java      |  11 +-
 .../plugins/defaults/model/DefaultMetaClass.java   |   5 +-
 .../plugins/defaults/model/DefaultVariable.java    |  10 +-
 .../log4j/plugins/spi/model/ElementManager.java    |   2 +-
 .../log4j/plugins/spi/model/InjectionPoint.java    |   3 +-
 .../spi/model/{Qualifier.java => Qualifiers.java}  | 111 ++++++++++++---------
 .../logging/log4j/plugins/spi/model/Variable.java  |   2 +-
 .../logging/log4j/plugins/util/TypeUtil.java       |   6 +-
 .../logging/log4j/plugins/util/WeakCache.java      |   8 ++
 .../logging/log4j/plugins/util/WeakLazyValue.java  |   2 +-
 .../log4j/plugins/spi/model/QualifiersTest.java    |  79 +++++++++++++++
 16 files changed, 210 insertions(+), 145 deletions(-)
 rename log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/{Qualifier.java => Qualifiers.java} (53%)
 create mode 100644 log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/spi/model/QualifiersTest.java


[logging-log4j2] 03/03: Refactor Collection into own class

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch mean-bean-machine
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit a827c7726955ddbfdeb7b9819d38f73980010bda
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Sat Mar 7 13:35:46 2020 -0600

    Refactor Collection<Qualifier> into own class
    
    This simplifies the model representation of qualifiers a bit.
    
    Signed-off-by: Matt Sicker <bo...@gmail.com>
---
 .../apache/logging/log4j/plugins/api/Default.java  |  25 -----
 .../log4j/plugins/defaults/bean/AbstractBean.java  |   4 +-
 .../plugins/defaults/bean/DefaultBeanManager.java  |  19 ++--
 .../log4j/plugins/defaults/bean/SystemBean.java    |   4 +-
 .../defaults/model/DefaultElementManager.java      |  20 ++--
 .../defaults/model/DefaultInjectionPoint.java      |  11 +-
 .../plugins/defaults/model/DefaultVariable.java    |  10 +-
 .../log4j/plugins/spi/model/ElementManager.java    |   2 +-
 .../log4j/plugins/spi/model/InjectionPoint.java    |   3 +-
 .../spi/model/{Qualifier.java => Qualifiers.java}  | 111 ++++++++++++---------
 .../logging/log4j/plugins/spi/model/Variable.java  |   2 +-
 .../log4j/plugins/spi/model/QualifiersTest.java    |  79 +++++++++++++++
 12 files changed, 175 insertions(+), 115 deletions(-)

diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/api/Default.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/api/Default.java
index 4ec2398..6578f65 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/api/Default.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/api/Default.java
@@ -17,7 +17,6 @@
 
 package org.apache.logging.log4j.plugins.api;
 
-import java.lang.annotation.Annotation;
 import java.lang.annotation.Documented;
 import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
@@ -29,28 +28,4 @@ import java.lang.annotation.RetentionPolicy;
 @Inherited
 // default qualifier unless qualifier besides @Named is present
 public @interface Default {
-    @SuppressWarnings("ClassExplicitlyAnnotation")
-    class Literal implements Default, Annotation {
-        @Override
-        public Class<? extends Annotation> annotationType() {
-            return Default.class;
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            return this == o || o instanceof Default;
-        }
-
-        @Override
-        public int hashCode() {
-            return Default.class.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return "@Default";
-        }
-    }
-
-    Default INSTANCE = new Literal();
 }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/AbstractBean.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/AbstractBean.java
index aeaf77b..524e849 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/AbstractBean.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/AbstractBean.java
@@ -19,7 +19,7 @@ package org.apache.logging.log4j.plugins.defaults.bean;
 
 import org.apache.logging.log4j.plugins.spi.bean.Bean;
 import org.apache.logging.log4j.plugins.spi.model.MetaClass;
-import org.apache.logging.log4j.plugins.spi.model.Qualifier;
+import org.apache.logging.log4j.plugins.spi.model.Qualifiers;
 import org.apache.logging.log4j.plugins.spi.model.Variable;
 
 import java.lang.annotation.Annotation;
@@ -42,7 +42,7 @@ abstract class AbstractBean<D, T> implements Bean<T> {
     }
 
     @Override
-    public Collection<Qualifier> getQualifiers() {
+    public Qualifiers getQualifiers() {
         return variable.getQualifiers();
     }
 
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/DefaultBeanManager.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/DefaultBeanManager.java
index f431939..ec4ba8b 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/DefaultBeanManager.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/DefaultBeanManager.java
@@ -44,7 +44,7 @@ import org.apache.logging.log4j.plugins.spi.model.MetaField;
 import org.apache.logging.log4j.plugins.spi.model.MetaMember;
 import org.apache.logging.log4j.plugins.spi.model.MetaMethod;
 import org.apache.logging.log4j.plugins.spi.model.MetaParameter;
-import org.apache.logging.log4j.plugins.spi.model.Qualifier;
+import org.apache.logging.log4j.plugins.spi.model.Qualifiers;
 import org.apache.logging.log4j.plugins.spi.model.Variable;
 import org.apache.logging.log4j.plugins.spi.scope.InitializationContext;
 import org.apache.logging.log4j.plugins.spi.scope.ScopeContext;
@@ -88,6 +88,7 @@ public class DefaultBeanManager implements BeanManager {
 
     public DefaultBeanManager(final ElementManager elementManager) {
         this.elementManager = elementManager;
+        // TODO: need a better way to register scope contexts
         scopes.put(PrototypeScoped.class, new PrototypeScopeContext());
         scopes.put(SingletonScoped.class, new DefaultScopeContext(SingletonScoped.class));
     }
@@ -276,7 +277,7 @@ public class DefaultBeanManager implements BeanManager {
             throw new InjectionException("Expected one type parameter argument for " + point + " but got " +
                     Arrays.toString(typeArguments));
         }
-        if (point.getQualifiers().contains(Qualifier.DEFAULT_QUALIFIER)) {
+        if (point.getQualifiers().hasDefaultQualifier()) {
             final Type typeArgument = typeArguments[0];
             if (!typeArgument.equals(expectedType)) {
                 throw new InjectionException("Expected type " + expectedType + " but got " + typeArgument + " in " + point);
@@ -288,7 +289,7 @@ public class DefaultBeanManager implements BeanManager {
         // TODO: this will need to allow for TypeConverter usage somehow
         // first, look for an existing bean
         final Type type = point.getType();
-        final Collection<Qualifier> qualifiers = point.getQualifiers();
+        final Qualifiers qualifiers = point.getQualifiers();
         final Optional<Bean<T>> existingBean = getExistingOrProvidedBean(type, qualifiers,
                 () -> elementManager.createVariable(point));
         if (existingBean.isPresent()) {
@@ -321,7 +322,7 @@ public class DefaultBeanManager implements BeanManager {
         return Optional.empty();
     }
 
-    private <T> Optional<Bean<T>> getExistingOrProvidedBean(final Type type, final Collection<Qualifier> qualifiers,
+    private <T> Optional<Bean<T>> getExistingOrProvidedBean(final Type type, final Qualifiers qualifiers,
                                                             final Supplier<Variable<T>> variableSupplier) {
         final Optional<Bean<T>> existingBean = getBean(type, qualifiers);
         if (existingBean.isPresent()) {
@@ -334,9 +335,9 @@ public class DefaultBeanManager implements BeanManager {
                 .map(this::addBean);
     }
 
-    private <T> Optional<Bean<T>> getBean(final Type type, final Collection<Qualifier> qualifiers) {
+    private <T> Optional<Bean<T>> getBean(final Type type, final Qualifiers qualifiers) {
         final Set<Bean<T>> beans = this.<T>streamBeansMatchingType(type)
-                .filter(bean -> areCollectionsIsomorphic(qualifiers, bean.getQualifiers()))
+                .filter(bean -> qualifiers.equals(bean.getQualifiers()))
                 .collect(Collectors.toSet());
         if (beans.size() > 1) {
             throw new AmbiguousBeanException(beans, "type " + type + " and qualifiers " + qualifiers);
@@ -440,11 +441,11 @@ public class DefaultBeanManager implements BeanManager {
 
     private static class DisposesMethod<D> {
         private final Collection<Type> types;
-        private final Collection<Qualifier> qualifiers;
+        private final Qualifiers qualifiers;
         private final Bean<D> declaringBean;
         private final MetaMethod<D, ?> disposesMethod;
 
-        private DisposesMethod(final Collection<Type> types, final Collection<Qualifier> qualifiers,
+        private DisposesMethod(final Collection<Type> types, final Qualifiers qualifiers,
                                final Bean<D> declaringBean, final MetaMethod<D, ?> disposesMethod) {
             this.types = types;
             this.qualifiers = qualifiers;
@@ -455,7 +456,7 @@ public class DefaultBeanManager implements BeanManager {
         boolean matches(final Variable<?> variable, final Bean<?> declaringBean) {
             return Objects.equals(declaringBean, this.declaringBean) &&
                     areCollectionsIsomorphic(types, variable.getTypes()) &&
-                    areCollectionsIsomorphic(qualifiers, variable.getQualifiers());
+                    qualifiers.equals(variable.getQualifiers());
         }
     }
 
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/SystemBean.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/SystemBean.java
index 91205b0..66d8230 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/SystemBean.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/bean/SystemBean.java
@@ -18,8 +18,8 @@
 package org.apache.logging.log4j.plugins.defaults.bean;
 
 import org.apache.logging.log4j.plugins.spi.model.MetaClass;
-import org.apache.logging.log4j.plugins.spi.model.Qualifier;
 import org.apache.logging.log4j.plugins.spi.bean.Bean;
+import org.apache.logging.log4j.plugins.spi.model.Qualifiers;
 import org.apache.logging.log4j.plugins.spi.model.Variable;
 import org.apache.logging.log4j.plugins.spi.model.InjectionPoint;
 import org.apache.logging.log4j.plugins.spi.scope.InitializationContext;
@@ -37,7 +37,7 @@ abstract class SystemBean<T> implements Bean<T> {
     }
 
     @Override
-    public Collection<Qualifier> getQualifiers() {
+    public Qualifiers getQualifiers() {
         return variable.getQualifiers();
     }
 
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java
index ca038da..882c124 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java
@@ -18,8 +18,6 @@
 package org.apache.logging.log4j.plugins.defaults.model;
 
 import org.apache.logging.log4j.plugins.api.AliasFor;
-import org.apache.logging.log4j.plugins.api.Default;
-import org.apache.logging.log4j.plugins.api.Named;
 import org.apache.logging.log4j.plugins.api.PrototypeScoped;
 import org.apache.logging.log4j.plugins.api.QualifierType;
 import org.apache.logging.log4j.plugins.api.ScopeType;
@@ -32,7 +30,7 @@ import org.apache.logging.log4j.plugins.spi.model.MetaElement;
 import org.apache.logging.log4j.plugins.spi.model.MetaExecutable;
 import org.apache.logging.log4j.plugins.spi.model.MetaField;
 import org.apache.logging.log4j.plugins.spi.model.MetaParameter;
-import org.apache.logging.log4j.plugins.spi.model.Qualifier;
+import org.apache.logging.log4j.plugins.spi.model.Qualifiers;
 import org.apache.logging.log4j.plugins.spi.model.Variable;
 import org.apache.logging.log4j.plugins.util.Cache;
 import org.apache.logging.log4j.plugins.util.WeakCache;
@@ -41,10 +39,8 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Objects;
-import java.util.stream.Collectors;
 
 public class DefaultElementManager implements ElementManager {
 
@@ -84,12 +80,8 @@ public class DefaultElementManager implements ElementManager {
     }
 
     @Override
-    public Collection<Qualifier> getQualifiers(final MetaElement<?> element) {
-        final Collection<Annotation> qualifiers = filterQualifiers(element.getAnnotations());
-        if (qualifiers.stream().noneMatch(annotation -> annotation.annotationType() != Named.class)) {
-            qualifiers.add(Default.INSTANCE);
-        }
-        return qualifiers.stream().map(Qualifier::fromAnnotation).collect(Collectors.toCollection(HashSet::new));
+    public Qualifiers getQualifiers(final MetaElement<?> element) {
+        return Qualifiers.fromQualifierAnnotations(filterQualifiers(element.getAnnotations()));
     }
 
     private Collection<Annotation> filterQualifiers(final Collection<Annotation> annotations) {
@@ -160,7 +152,7 @@ public class DefaultElementManager implements ElementManager {
     @Override
     public <D, T> InjectionPoint<T> createFieldInjectionPoint(final MetaField<D, T> field, final Bean<D> owner) {
         Objects.requireNonNull(field);
-        final Collection<Qualifier> qualifiers = getQualifiers(field);
+        final Qualifiers qualifiers = getQualifiers(field);
         return new DefaultInjectionPoint<>(field.getBaseType(), qualifiers, owner, field, field);
     }
 
@@ -170,7 +162,7 @@ public class DefaultElementManager implements ElementManager {
                                                                   final Bean<D> owner) {
         Objects.requireNonNull(executable);
         Objects.requireNonNull(parameter);
-        final Collection<Qualifier> qualifiers = getQualifiers(parameter);
+        final Qualifiers qualifiers = getQualifiers(parameter);
         return new DefaultInjectionPoint<>(parameter.getBaseType(), qualifiers, owner, executable, parameter);
     }
 
@@ -186,7 +178,7 @@ public class DefaultElementManager implements ElementManager {
         return createVariable(point.getElement(), point.getQualifiers());
     }
 
-    private <T> Variable<T> createVariable(final MetaElement<T> element, final Collection<Qualifier> qualifiers) {
+    private <T> Variable<T> createVariable(final MetaElement<T> element, final Qualifiers qualifiers) {
         final Collection<Type> types = element.getTypeClosure();
         final Class<? extends Annotation> scopeType = getScopeType(element);
         return DefaultVariable.newVariable(types, qualifiers, scopeType);
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultInjectionPoint.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultInjectionPoint.java
index 0ccccdf..80bc723 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultInjectionPoint.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultInjectionPoint.java
@@ -18,24 +18,23 @@
 package org.apache.logging.log4j.plugins.defaults.model;
 
 import org.apache.logging.log4j.plugins.spi.bean.Bean;
-import org.apache.logging.log4j.plugins.spi.model.MetaElement;
 import org.apache.logging.log4j.plugins.spi.model.InjectionPoint;
+import org.apache.logging.log4j.plugins.spi.model.MetaElement;
 import org.apache.logging.log4j.plugins.spi.model.MetaMember;
-import org.apache.logging.log4j.plugins.spi.model.Qualifier;
+import org.apache.logging.log4j.plugins.spi.model.Qualifiers;
 
 import java.lang.reflect.Type;
-import java.util.Collection;
 import java.util.Objects;
 import java.util.Optional;
 
 class DefaultInjectionPoint<T> implements InjectionPoint<T> {
     private final Type type;
-    private final Collection<Qualifier> qualifiers;
+    private final Qualifiers qualifiers;
     private final Bean<?> bean;
     private final MetaMember<?, ?> member;
     private final MetaElement<T> element;
 
-    DefaultInjectionPoint(final Type type, final Collection<Qualifier> qualifiers, final Bean<?> bean,
+    DefaultInjectionPoint(final Type type, final Qualifiers qualifiers, final Bean<?> bean,
                           final MetaMember<?, ?> member, final MetaElement<T> element) {
         this.type = type;
         this.qualifiers = qualifiers;
@@ -50,7 +49,7 @@ class DefaultInjectionPoint<T> implements InjectionPoint<T> {
     }
 
     @Override
-    public Collection<Qualifier> getQualifiers() {
+    public Qualifiers getQualifiers() {
         return qualifiers;
     }
 
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultVariable.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultVariable.java
index db5f6a5..f756908 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultVariable.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultVariable.java
@@ -17,7 +17,7 @@
 
 package org.apache.logging.log4j.plugins.defaults.model;
 
-import org.apache.logging.log4j.plugins.spi.model.Qualifier;
+import org.apache.logging.log4j.plugins.spi.model.Qualifiers;
 import org.apache.logging.log4j.plugins.spi.model.Variable;
 
 import java.lang.annotation.Annotation;
@@ -27,16 +27,16 @@ import java.util.Objects;
 
 public class DefaultVariable<T> implements Variable<T> {
 
-    public static <T> DefaultVariable<T> newVariable(final Collection<Type> types, final Collection<Qualifier> qualifiers,
+    public static <T> DefaultVariable<T> newVariable(final Collection<Type> types, final Qualifiers qualifiers,
                                                      final Class<? extends Annotation> scopeType) {
         return new DefaultVariable<>(types, qualifiers, scopeType);
     }
 
     private final Collection<Type> types;
-    private final Collection<Qualifier> qualifiers;
+    private final Qualifiers qualifiers;
     private final Class<? extends Annotation> scopeType;
 
-    private DefaultVariable(final Collection<Type> types, final Collection<Qualifier> qualifiers,
+    private DefaultVariable(final Collection<Type> types, final Qualifiers qualifiers,
                             final Class<? extends Annotation> scopeType) {
         this.types = Objects.requireNonNull(types);
         this.qualifiers = Objects.requireNonNull(qualifiers);
@@ -49,7 +49,7 @@ public class DefaultVariable<T> implements Variable<T> {
     }
 
     @Override
-    public Collection<Qualifier> getQualifiers() {
+    public Qualifiers getQualifiers() {
         return qualifiers;
     }
 
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/ElementManager.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/ElementManager.java
index cd9dea1..00aa67d 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/ElementManager.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/ElementManager.java
@@ -53,7 +53,7 @@ public interface ElementManager extends AutoCloseable {
      * @param element program element to extract qualifiers from
      * @return qualifiers present on the element
      */
-    Collection<Qualifier> getQualifiers(MetaElement<?> element);
+    Qualifiers getQualifiers(MetaElement<?> element);
 
     /**
      * Checks if a class has exactly one injectable constructor. A constructor is <i>injectable</i> if:
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/InjectionPoint.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/InjectionPoint.java
index f4e1de9..6e47521 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/InjectionPoint.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/InjectionPoint.java
@@ -20,7 +20,6 @@ package org.apache.logging.log4j.plugins.spi.model;
 import org.apache.logging.log4j.plugins.spi.bean.Bean;
 
 import java.lang.reflect.Type;
-import java.util.Collection;
 import java.util.Optional;
 
 /**
@@ -39,7 +38,7 @@ public interface InjectionPoint<T> {
      * Gets the qualifiers of this point. If no qualifiers other than {@link org.apache.logging.log4j.plugins.api.Named}
      * are present, then these qualifiers will also include {@link org.apache.logging.log4j.plugins.api.Default}.
      */
-    Collection<Qualifier> getQualifiers();
+    Qualifiers getQualifiers();
 
     /**
      * Gets the bean where this injection point is defined or empty for static methods and fields.
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Qualifier.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Qualifiers.java
similarity index 53%
rename from log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Qualifier.java
rename to log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Qualifiers.java
index fba378c..74c8d0c 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Qualifier.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Qualifiers.java
@@ -20,22 +20,80 @@ package org.apache.logging.log4j.plugins.spi.model;
 import org.apache.logging.log4j.plugins.api.AliasFor;
 import org.apache.logging.log4j.plugins.api.Default;
 import org.apache.logging.log4j.plugins.api.Ignore;
+import org.apache.logging.log4j.plugins.api.Named;
 import org.apache.logging.log4j.plugins.spi.InjectionException;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 
-// TODO: consider a composite class for qualifier collections or other potential ways to model this
-public final class Qualifier {
+/**
+ * Represents a normalized set of {@linkplain org.apache.logging.log4j.plugins.api.QualifierType qualifier annotations}.
+ */
+public final class Qualifiers {
+    private final Map<Class<? extends Annotation>, Map<String, Object>> qualifiers;
+
+    private Qualifiers(final Map<Class<? extends Annotation>, Map<String, Object>> qualifiers) {
+        this.qualifiers = qualifiers;
+    }
 
-    public static final Qualifier DEFAULT_QUALIFIER = new Qualifier(Default.class, Collections.emptyMap());
+    public boolean hasDefaultQualifier() {
+        return qualifiers.containsKey(Default.class);
+    }
 
-    public static Qualifier fromAnnotation(final Annotation annotation) {
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        final Qualifiers that = (Qualifiers) o;
+        return qualifiers.equals(that.qualifiers);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(qualifiers);
+    }
+
+    @Override
+    public String toString() {
+        return qualifiers.toString();
+    }
+
+    /**
+     * Creates a normalized Qualifiers instance from a collection of qualifier annotation instances.
+     */
+    public static Qualifiers fromQualifierAnnotations(final Collection<Annotation> annotations) {
+        final Map<Class<? extends Annotation>, Map<String, Object>> qualifiers = new HashMap<>(annotations.size());
+        for (final Annotation annotation : annotations) {
+            final Class<? extends Annotation> annotationType = annotation.annotationType();
+            final AliasFor alias = annotationType.getAnnotation(AliasFor.class);
+            final Class<? extends Annotation> qualifierType = alias != null ? alias.value() : annotationType;
+            qualifiers.put(qualifierType, getQualifierAttributes(annotation));
+        }
+        if (needsDefaultQualifier(qualifiers.keySet())) {
+            qualifiers.put(Default.class, Collections.emptyMap());
+        }
+        return new Qualifiers(Collections.unmodifiableMap(qualifiers));
+    }
+
+    private static boolean needsDefaultQualifier(final Collection<Class<? extends Annotation>> qualifierTypes) {
+        if (qualifierTypes.contains(Default.class)) {
+            return false;
+        }
+        for (final Class<? extends Annotation> qualifierType : qualifierTypes) {
+            if (qualifierType != Named.class) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static Map<String, Object> getQualifierAttributes(final Annotation annotation) {
         final Class<? extends Annotation> annotationType = annotation.annotationType();
         final Method[] elements = annotationType.getDeclaredMethods();
         final Map<String, Object> attributes = new HashMap<>(elements.length);
@@ -44,10 +102,7 @@ public final class Qualifier {
                 attributes.put(element.getName(), getAnnotationElement(annotation, element));
             }
         }
-        // FIXME: support default name for @Named when value is blank
-        final AliasFor alias = annotationType.getAnnotation(AliasFor.class);
-        final Class<? extends Annotation> qualifierType = alias != null ? alias.value() : annotationType;
-        return new Qualifier(qualifierType, Collections.unmodifiableMap(attributes));
+        return Collections.unmodifiableMap(attributes);
     }
 
     private static Object getAnnotationElement(final Annotation annotation, final Method element) {
@@ -60,44 +115,4 @@ public final class Qualifier {
                     e.getCause());
         }
     }
-
-    private final Class<? extends Annotation> qualifierType;
-    private final Map<String, Object> attributes;
-
-    private Qualifier(final Class<? extends Annotation> qualifierType, final Map<String, Object> attributes) {
-        this.qualifierType = qualifierType;
-        this.attributes = attributes;
-    }
-
-    public Class<? extends Annotation> getQualifierType() {
-        return qualifierType;
-    }
-
-    public Map<String, Object> getAttributes() {
-        return attributes;
-    }
-
-    @Override
-    public boolean equals(final Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        final Qualifier that = (Qualifier) o;
-        return qualifierType.equals(that.qualifierType) &&
-                attributes.equals(that.attributes);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(qualifierType, attributes);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append('@').append(qualifierType.getSimpleName());
-        if (!attributes.isEmpty()) {
-            sb.append(attributes);
-        }
-        return sb.toString();
-    }
 }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Variable.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Variable.java
index fa7e02e..bb8db73 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Variable.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/spi/model/Variable.java
@@ -35,7 +35,7 @@ public interface Variable<T> {
         return false;
     }
 
-    Collection<Qualifier> getQualifiers();
+    Qualifiers getQualifiers();
 
     Class<? extends Annotation> getScopeType();
 }
diff --git a/log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/spi/model/QualifiersTest.java b/log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/spi/model/QualifiersTest.java
new file mode 100644
index 0000000..739ec6b
--- /dev/null
+++ b/log4j-plugins/src/test/java/org/apache/logging/log4j/plugins/spi/model/QualifiersTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.logging.log4j.plugins.spi.model;
+
+import org.apache.logging.log4j.plugins.api.AliasFor;
+import org.apache.logging.log4j.plugins.api.Named;
+import org.apache.logging.log4j.plugins.api.QualifierType;
+import org.junit.Test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.*;
+
+public class QualifiersTest {
+    @Test
+    public void emptyQualifiersShouldContainDefaultQualifier() {
+        final Qualifiers qualifiers = Qualifiers.fromQualifierAnnotations(Collections.emptyList());
+        assertTrue(qualifiers.hasDefaultQualifier());
+    }
+
+    @Test
+    public void qualifiersWithNamedOnlyShouldContainDefaultQualifier() {
+        @Named
+        class Foo {
+        }
+        final Qualifiers qualifiers = Qualifiers.fromQualifierAnnotations(Arrays.asList(Foo.class.getAnnotations()));
+        assertTrue(qualifiers.hasDefaultQualifier());
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @QualifierType
+    public @interface Bar {
+    }
+
+    @Test
+    public void qualifiersWithNonDefaultQualifiersShouldNotContainDefaultQualifier() {
+        @Bar
+        class Foo {
+        }
+        final Qualifiers qualifiers = Qualifiers.fromQualifierAnnotations(Arrays.asList(Foo.class.getAnnotations()));
+        assertFalse(qualifiers.hasDefaultQualifier());
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @AliasFor(Bar.class)
+    public @interface BarAlias {
+    }
+
+    @Test
+    public void qualifiersShouldAccountForAliases() {
+        @Bar
+        class Foo {
+        }
+        @BarAlias
+        class FooAlias {
+        }
+        final Qualifiers foo = Qualifiers.fromQualifierAnnotations(Arrays.asList(Foo.class.getAnnotations()));
+        final Qualifiers fooAlias = Qualifiers.fromQualifierAnnotations(Arrays.asList(FooAlias.class.getAnnotations()));
+        assertEquals(foo, fooAlias);
+    }
+}
\ No newline at end of file


[logging-log4j2] 02/03: Refactor cache API

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch mean-bean-machine
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit cb9c012c0672688221859a6b8e30675ca2cc4a0a
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Sat Mar 7 11:46:58 2020 -0600

    Refactor cache API
    
    Signed-off-by: Matt Sicker <bo...@gmail.com>
---
 .../defaults/model/DefaultElementManager.java      | 44 ++++++++++------------
 .../plugins/defaults/model/DefaultMetaClass.java   |  5 +--
 .../logging/log4j/plugins/util/TypeUtil.java       |  4 +-
 .../logging/log4j/plugins/util/WeakCache.java      |  8 ++++
 4 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java
index 58d8b28..ca038da 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultElementManager.java
@@ -35,9 +35,7 @@ import org.apache.logging.log4j.plugins.spi.model.MetaParameter;
 import org.apache.logging.log4j.plugins.spi.model.Qualifier;
 import org.apache.logging.log4j.plugins.spi.model.Variable;
 import org.apache.logging.log4j.plugins.util.Cache;
-import org.apache.logging.log4j.plugins.util.LazyValue;
 import org.apache.logging.log4j.plugins.util.WeakCache;
-import org.apache.logging.log4j.plugins.util.WeakLazyValue;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
@@ -54,28 +52,26 @@ public class DefaultElementManager implements ElementManager {
         QUALIFIER, SCOPE, STEREOTYPE, UNKNOWN
     }
 
-    private final Cache<Class<?>, MetaClass<?>> classCache = new WeakCache<>(clazz ->
-            WeakLazyValue.forSupplier(DefaultMetaClass.newMetaClassSupplier(clazz)));
-
-    private final Cache<Class<? extends Annotation>, AnnotationType> annotationTypeCache = new WeakCache<>(clazz ->
-            LazyValue.forSupplier(() -> {
-                for (final Annotation annotation : clazz.getAnnotations()) {
-                    Class<? extends Annotation> type = annotation.annotationType();
-                    if (type == AliasFor.class) {
-                        type = ((AliasFor) annotation).value();
-                    }
-                    if (type == QualifierType.class) {
-                        return AnnotationType.QUALIFIER;
-                    }
-                    if (type == ScopeType.class) {
-                        return AnnotationType.SCOPE;
-                    }
-                    if (type == Stereotype.class) {
-                        return AnnotationType.STEREOTYPE;
-                    }
-                }
-                return AnnotationType.UNKNOWN;
-            }));
+    private final Cache<Class<?>, MetaClass<?>> classCache = WeakCache.newWeakRefCache(DefaultMetaClass::newMetaClass);
+
+    private final Cache<Class<? extends Annotation>, AnnotationType> annotationTypeCache = WeakCache.newCache(clazz -> {
+        for (final Annotation annotation : clazz.getAnnotations()) {
+            Class<? extends Annotation> type = annotation.annotationType();
+            if (type == AliasFor.class) {
+                type = ((AliasFor) annotation).value();
+            }
+            if (type == QualifierType.class) {
+                return AnnotationType.QUALIFIER;
+            }
+            if (type == ScopeType.class) {
+                return AnnotationType.SCOPE;
+            }
+            if (type == Stereotype.class) {
+                return AnnotationType.STEREOTYPE;
+            }
+        }
+        return AnnotationType.UNKNOWN;
+    });
 
     @Override
     public <T> MetaClass<T> getMetaClass(final Class<T> clazz) {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultMetaClass.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultMetaClass.java
index feb915e..8f4d26e 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultMetaClass.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/defaults/model/DefaultMetaClass.java
@@ -33,13 +33,12 @@ import java.lang.reflect.Type;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Optional;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 class DefaultMetaClass<T> implements MetaClass<T> {
 
-    static <T> Supplier<MetaClass<T>> newMetaClassSupplier(final Class<T> javaClass) {
-        return () -> newMetaClass(javaClass, javaClass, javaClass.getAnnotations());
+    static <T> MetaClass<T> newMetaClass(final Class<T> javaClass) {
+        return newMetaClass(javaClass, javaClass, javaClass.getAnnotations());
     }
 
     static <T> MetaClass<T> newMetaClass(final Type baseType, final Class<T> javaClass, final Annotation... annotations) {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java
index 9415b84..bd125dc 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java
@@ -405,8 +405,8 @@ public final class TypeUtil {
         return TYPE_CLOSURE_CACHE.get(type);
     }
 
-    private static final Cache<Type, Collection<Type>> TYPE_CLOSURE_CACHE = new WeakCache<>(
-            type -> WeakLazyValue.forSupplier(() -> new TypeResolver(type).types.values()));
+    private static final Cache<Type, Collection<Type>> TYPE_CLOSURE_CACHE =
+            WeakCache.newWeakRefCache(type -> new TypeResolver(type).types.values());
 
     private static class TypeResolver {
         private final Map<TypeVariable<?>, Type> resolvedTypeVariables = new HashMap<>();
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakCache.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakCache.java
index d44c14f..d8137df 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakCache.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakCache.java
@@ -23,6 +23,14 @@ import java.util.function.Function;
 
 public class WeakCache<K, V> implements Cache<K, V> {
 
+    public static <K, V> WeakCache<K, V> newCache(final Function<K, V> function) {
+        return new WeakCache<>(key -> LazyValue.forSupplier(() -> function.apply(key)));
+    }
+
+    public static <K, V> WeakCache<K, V> newWeakRefCache(final Function<K, V> function) {
+        return new WeakCache<>(key -> WeakLazyValue.forSupplier(() -> function.apply(key)));
+    }
+
     private final long maxSize;
     private final Function<K, Value<? extends V>> valueFunction;
     private final Map<K, Value<? extends V>> map = new WeakHashMap<>();


[logging-log4j2] 01/03: Use weak cache for type closure lookup

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch mean-bean-machine
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 6dc081251276c082cc9c02bae43f58e050d13ef5
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Sat Mar 7 11:31:14 2020 -0600

    Use weak cache for type closure lookup
    
    Signed-off-by: Matt Sicker <bo...@gmail.com>
---
 .../main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java   | 6 ++++--
 .../java/org/apache/logging/log4j/plugins/util/WeakLazyValue.java   | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java
index f27a86f..9415b84 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/TypeUtil.java
@@ -402,10 +402,12 @@ public final class TypeUtil {
      * Returns the type closure of a generic type.
      */
     public static Collection<Type> getTypeClosure(final Type type) {
-        // TODO: weak cache?
-        return new TypeResolver(type).types.values();
+        return TYPE_CLOSURE_CACHE.get(type);
     }
 
+    private static final Cache<Type, Collection<Type>> TYPE_CLOSURE_CACHE = new WeakCache<>(
+            type -> WeakLazyValue.forSupplier(() -> new TypeResolver(type).types.values()));
+
     private static class TypeResolver {
         private final Map<TypeVariable<?>, Type> resolvedTypeVariables = new HashMap<>();
         private final Map<Class<?>, Type> types = new LinkedHashMap<>();
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakLazyValue.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakLazyValue.java
index 6f6cd07..b90a3a7 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakLazyValue.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/WeakLazyValue.java
@@ -23,7 +23,7 @@ import java.util.function.Supplier;
 public class WeakLazyValue<T> implements Value<T> {
 
     public static <T> WeakLazyValue<T> forSupplier(final Supplier<T> valueSupplier) {
-        return new WeakLazyValue<T>(valueSupplier);
+        return new WeakLazyValue<>(valueSupplier);
     }
 
     private final Supplier<T> valueSupplier;