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/22 17:40:02 UTC

[logging-log4j2] 02/06: Add variable withers

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 41b8043f16f09321b7c00325cc517710431f67f2
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Sat Mar 21 17:00:08 2020 -0500

    Add variable withers
    
    Signed-off-by: Matt Sicker <bo...@gmail.com>
---
 .../log4j/plugins/defaults/bean/AbstractBean.java  | 19 +++++-
 .../plugins/defaults/bean/DefaultBeanManager.java  | 69 +++++++++++-----------
 .../log4j/plugins/defaults/bean/SystemBean.java    | 19 +++++-
 .../defaults/model/DefaultElementManager.java      |  2 +-
 .../plugins/defaults/model/DefaultVariable.java    | 28 ++++++---
 .../logging/log4j/plugins/spi/model/Variable.java  |  6 ++
 6 files changed, 95 insertions(+), 48 deletions(-)

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 c9110bf..5987ff3 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
@@ -42,13 +42,23 @@ abstract class AbstractBean<T> implements Bean<T> {
     }
 
     @Override
+    public Collection<Type> getTypes() {
+        return variable.getTypes();
+    }
+
+    @Override
+    public Variable withTypes(final Collection<Type> types) {
+        return variable.withTypes(types);
+    }
+
+    @Override
     public Qualifiers getQualifiers() {
         return variable.getQualifiers();
     }
 
     @Override
-    public Collection<Type> getTypes() {
-        return variable.getTypes();
+    public Variable withQualifiers(final Qualifiers qualifiers) {
+        return variable.withQualifiers(qualifiers);
     }
 
     @Override
@@ -57,6 +67,11 @@ abstract class AbstractBean<T> implements Bean<T> {
     }
 
     @Override
+    public Variable withScopeType(final Class<? extends Annotation> scopeType) {
+        return variable.withScopeType(scopeType);
+    }
+
+    @Override
     public boolean equals(final Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
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 592a279..5c98bf1 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
@@ -23,7 +23,6 @@ import org.apache.logging.log4j.plugins.api.Produces;
 import org.apache.logging.log4j.plugins.api.Provider;
 import org.apache.logging.log4j.plugins.api.Singleton;
 import org.apache.logging.log4j.plugins.defaults.model.DefaultElementManager;
-import org.apache.logging.log4j.plugins.defaults.model.DefaultVariable;
 import org.apache.logging.log4j.plugins.spi.AmbiguousBeanException;
 import org.apache.logging.log4j.plugins.spi.DefinitionException;
 import org.apache.logging.log4j.plugins.spi.InjectionException;
@@ -232,7 +231,7 @@ public class DefaultBeanManager implements BeanManager {
         }
     }
 
-    private <T> void validateInjectionPoint(final InjectionPoint point) {
+    private void validateInjectionPoint(final InjectionPoint point) {
         final MetaElement element = point.getElement();
         if (element.isAnnotationPresent(Produces.class)) {
             throw new DefinitionException("Cannot inject into a @Produces element: " + element);
@@ -257,7 +256,7 @@ public class DefaultBeanManager implements BeanManager {
                 validateBeanInjectionPoint(point, ((ProducerBean<?>) bean).getType());
             }
         }
-        final Optional<Bean<T>> bean = getInjectionPointBean(point);
+        final Optional<Bean<?>> bean = getBeanForInjectionPoint(point);
         if (!bean.isPresent() && !rawType.equals(Optional.class)) {
             throw new UnsatisfiedBeanException(point);
         }
@@ -282,54 +281,49 @@ public class DefaultBeanManager implements BeanManager {
         }
     }
 
-    private <T> Optional<Bean<T>> getInjectionPointBean(final InjectionPoint point) {
+    private Optional<Bean<?>> getBeanForInjectionPoint(final InjectionPoint point) {
         // TODO: this will need to allow for TypeConverter usage somehow
         // first, look for an existing bean
         final Type type = point.getType();
         final Qualifiers qualifiers = point.getQualifiers();
-        final Variable variable = elementManager.createVariable(point);
-        final Optional<Bean<T>> existingBean = getExistingOrProvidedBean(type, qualifiers, () -> variable);
+        final Optional<Bean<?>> existingBean = getExistingOrProvidedBean(type, qualifiers,
+                () -> elementManager.createVariable(point));
         if (existingBean.isPresent()) {
             return existingBean;
         }
         if (type instanceof ParameterizedType) {
             final Class<?> rawType = TypeUtil.getRawType(type);
-            final Type actualType = ((ParameterizedType) type).getActualTypeArguments()[0];
-            if (rawType.equals(Provider.class)) {
+            if (rawType == Provider.class) {
+                final Type actualType = ((ParameterizedType) type).getActualTypeArguments()[0];
                 // if a Provider<T> is requested, we can convert an existing Bean<T> into a Bean<Provider<T>>
-                return this.<T>getBean(actualType, qualifiers)
-                        .map(bean -> new ProviderBean<>(variable, context -> getValue(bean, context)))
-                        .map(this::addBean)
-                        .map(TypeUtil::cast);
-            } else if (rawType.equals(Optional.class)) {
-                final Optional<Bean<T>> actualExistingBean = getExistingOrProvidedBean(actualType, qualifiers,
-                        // FIXME: remove need for DefaultVariable to be public
-                        () -> DefaultVariable.newVariable(
-                                TypeUtil.getTypeClosure(actualType), qualifiers, variable.getScopeType()));
-                final Bean<Optional<T>> optionalBean = addBean(new OptionalBean<>(variable,
-                        context -> actualExistingBean.map(bean -> getValue(bean, context))));
-                return Optional.of(TypeUtil.cast(optionalBean));
+                return getExistingBean(actualType, qualifiers)
+                        .map(bean -> new ProviderBean<>(
+                                elementManager.createVariable(point), context -> getValue(bean, context)))
+                        .map(this::addBean);
+            } else if (rawType == Optional.class) {
+                final Type actualType = ((ParameterizedType) type).getActualTypeArguments()[0];
+                final Variable variable = elementManager.createVariable(point);
+                return Optional.of(createOptionalBean(actualType, qualifiers, variable));
             }
         }
         return Optional.empty();
     }
 
-    private <T> Optional<Bean<T>> getExistingOrProvidedBean(final Type type, final Qualifiers qualifiers,
-                                                            final Supplier<Variable> variableSupplier) {
-        final Optional<Bean<T>> existingBean = getBean(type, qualifiers);
+    private Optional<Bean<?>> getExistingOrProvidedBean(final Type type, final Qualifiers qualifiers,
+                                                        final Supplier<Variable> variableSupplier) {
+        final Optional<Bean<?>> existingBean = getExistingBean(type, qualifiers);
         if (existingBean.isPresent()) {
             return existingBean;
         }
-        final Variable variable = variableSupplier.get();
         final Type providerType = new ParameterizedTypeImpl(null, Provider.class, type);
-        final Optional<Bean<Provider<T>>> providerBean = getBean(providerType, qualifiers);
-        return providerBean.map(bean -> new ProvidedBean<>(variable, context -> getValue(bean, context).get()))
+        return getExistingBean(providerType, qualifiers)
+                .<Bean<Provider<?>>>map(TypeUtil::cast)
+                .map(bean -> new ProvidedBean<>(variableSupplier.get(), context -> getValue(bean, context).get()))
                 .map(this::addBean);
     }
 
-    // FIXME: this needs to consider scopes
-    private <T> Optional<Bean<T>> getBean(final Type type, final Qualifiers qualifiers) {
-        final Set<Bean<T>> beans = this.<T>streamBeansMatchingType(type)
+    private Optional<Bean<?>> getExistingBean(final Type type, final Qualifiers qualifiers) {
+        final Set<Bean<?>> beans = beansWithType(type)
                 .filter(bean -> qualifiers.equals(bean.getQualifiers()))
                 .collect(Collectors.toSet());
         if (beans.size() > 1) {
@@ -338,19 +332,26 @@ public class DefaultBeanManager implements BeanManager {
         return beans.isEmpty() ? Optional.empty() : Optional.of(beans.iterator().next());
     }
 
-    private <T> Stream<Bean<T>> streamBeansMatchingType(final Type requiredType) {
+    private Stream<Bean<?>> beansWithType(final Type requiredType) {
         if (beansByType.containsKey(requiredType)) {
-            return beansByType.get(requiredType).stream().map(TypeUtil::cast);
+            return beansByType.get(requiredType).stream();
         }
         if (requiredType instanceof ParameterizedType) {
             return beansByType.getOrDefault(((ParameterizedType) requiredType).getRawType(), Collections.emptySet())
                     .stream()
-                    .filter(bean -> bean.hasMatchingType(requiredType))
-                    .map(TypeUtil::cast);
+                    .filter(bean -> bean.hasMatchingType(requiredType));
         }
         return Stream.empty();
     }
 
+    private Bean<?> createOptionalBean(final Type actualType, final Qualifiers qualifiers, final Variable variable) {
+        final Supplier<Variable> variableSupplier = () -> variable.withTypes(TypeUtil.getTypeClosure(actualType));
+        final Bean<?> optionalBean = new OptionalBean<>(variable, context ->
+                getExistingOrProvidedBean(actualType, qualifiers, variableSupplier)
+                        .map(bean -> getValue(bean, context)));
+        return addBean(optionalBean);
+    }
+
     @Override
     public <T> InitializationContext<T> createInitializationContext(final Bean<T> bean) {
         return new DefaultInitializationContext<>(bean);
@@ -374,7 +375,7 @@ public class DefaultBeanManager implements BeanManager {
 
     @Override
     public <T> Optional<T> getInjectableValue(final InjectionPoint point, final InitializationContext<?> parentContext) {
-        final Optional<Bean<T>> optionalResolvedBean = getInjectionPointBean(point);
+        final Optional<Bean<T>> optionalResolvedBean = getBeanForInjectionPoint(point).map(TypeUtil::cast);
         final Bean<T> resolvedBean = optionalResolvedBean.orElseThrow(() -> new UnsatisfiedBeanException(point));
         final Optional<T> existingValue = point.getBean()
                 .filter(bean -> !bean.equals(resolvedBean))
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 97cfb94..ed7810e 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
@@ -37,13 +37,23 @@ abstract class SystemBean<T> implements Bean<T> {
     }
 
     @Override
+    public Collection<Type> getTypes() {
+        return variable.getTypes();
+    }
+
+    @Override
+    public Variable withTypes(final Collection<Type> types) {
+        return variable.withTypes(types);
+    }
+
+    @Override
     public Qualifiers getQualifiers() {
         return variable.getQualifiers();
     }
 
     @Override
-    public Collection<Type> getTypes() {
-        return variable.getTypes();
+    public Variable withQualifiers(final Qualifiers qualifiers) {
+        return variable.withQualifiers(qualifiers);
     }
 
     @Override
@@ -52,6 +62,11 @@ abstract class SystemBean<T> implements Bean<T> {
     }
 
     @Override
+    public Variable withScopeType(final Class<? extends Annotation> scopeType) {
+        return variable.withScopeType(scopeType);
+    }
+
+    @Override
     public Collection<InjectionPoint> getInjectionPoints() {
         return Collections.emptySet();
     }
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 b1a4066..b690d59 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
@@ -193,7 +193,7 @@ public class DefaultElementManager implements ElementManager {
     private Variable createVariable(final MetaElement element, final Qualifiers qualifiers) {
         final Collection<Type> types = element.getTypeClosure();
         final Class<? extends Annotation> scopeType = getScopeType(element);
-        return DefaultVariable.newVariable(types, qualifiers, scopeType);
+        return new DefaultVariable(types, qualifiers, scopeType);
     }
 
     @Override
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 f06d8b4..cdf7928 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
@@ -23,21 +23,16 @@ import org.apache.logging.log4j.plugins.spi.model.Variable;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Objects;
 
 public class DefaultVariable implements Variable {
-
-    public static DefaultVariable 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 Qualifiers qualifiers;
     private final Class<? extends Annotation> scopeType;
 
-    private DefaultVariable(final Collection<Type> types, final Qualifiers qualifiers,
-                            final Class<? extends Annotation> scopeType) {
+    DefaultVariable(final Collection<Type> types, final Qualifiers qualifiers,
+                    final Class<? extends Annotation> scopeType) {
         this.types = Objects.requireNonNull(types);
         this.qualifiers = Objects.requireNonNull(qualifiers);
         this.scopeType = Objects.requireNonNull(scopeType);
@@ -45,7 +40,12 @@ public class DefaultVariable implements Variable {
 
     @Override
     public Collection<Type> getTypes() {
-        return types;
+        return Collections.unmodifiableCollection(types);
+    }
+
+    @Override
+    public Variable withTypes(final Collection<Type> types) {
+        return new DefaultVariable(types, getQualifiers(), getScopeType());
     }
 
     @Override
@@ -54,11 +54,21 @@ public class DefaultVariable implements Variable {
     }
 
     @Override
+    public Variable withQualifiers(final Qualifiers qualifiers) {
+        return new DefaultVariable(getTypes(), qualifiers, getScopeType());
+    }
+
+    @Override
     public Class<? extends Annotation> getScopeType() {
         return scopeType;
     }
 
     @Override
+    public Variable withScopeType(final Class<? extends Annotation> scopeType) {
+        return new DefaultVariable(getTypes(), getQualifiers(), scopeType);
+    }
+
+    @Override
     public boolean equals(final Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
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 dc8eeb2..0d9c035 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
@@ -27,6 +27,8 @@ import java.util.Collection;
 public interface Variable {
     Collection<Type> getTypes();
 
+    Variable withTypes(final Collection<Type> types);
+
     default boolean hasMatchingType(final Type requiredType) {
         for (final Type type : getTypes()) {
             if (TypeUtil.typesMatch(requiredType, type)) {
@@ -38,8 +40,12 @@ public interface Variable {
 
     Qualifiers getQualifiers();
 
+    Variable withQualifiers(final Qualifiers qualifiers);
+
     Class<? extends Annotation> getScopeType();
 
+    Variable withScopeType(final Class<? extends Annotation> scopeType);
+
     default boolean isDependentScoped() {
         return getScopeType() == Dependent.class;
     }