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 2021/06/20 00:17:24 UTC
[logging-log4j2] 03/04: Simplify reflection model and qualifiers
matching
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 f7ea16edb33d6a6752575c2070574e011d8a8aee
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Sat Jun 19 19:08:01 2021 -0500
Simplify reflection model and qualifiers matching
This refactors a few things in the LOG4J2-2854 APIs:
* Rearranged some packages
* Removed the MetaElement and ElementManager API to rely directly on native reflection APIs
* Ported tests from JUnit 4 to JUnit 5
* Added NamedAliases and alias providers
* Removed Variable and collapsed it into the plain Bean interface
* Replaced qualifiers with names and aliases
* Replaced default qualifier with an empty string name (empty string name cannot be directly used as a name as that indicates to derive the name from the program element usually)
---
.../core/config/di/AmbiguousBeanException.java | 2 -
.../log4j/core/config/di/{api/bean => }/Bean.java | 32 +-
.../logging/log4j/core/config/di/BeanManager.java | 237 ++++++++++
.../di/{api/bean => }/InitializationContext.java | 2 +-
.../config/di/{api/model => }/InjectionPoint.java | 19 +-
.../config/di/{api/bean => }/InjectionTarget.java | 2 +-
.../di/{api/bean => }/InjectionTargetFactory.java | 2 +-
.../core/config/di/{api/bean => }/Injector.java | 20 +-
.../core/config/di/{api/bean => }/Producer.java | 3 +-
.../config/di/{api/bean => }/ProducerFactory.java | 2 +-
.../config/di/{api/bean => }/ProviderFactory.java | 2 +-
.../config/di/{api/bean => }/ScopeContext.java | 2 +-
.../core/config/di/UnsatisfiedBeanException.java | 2 -
.../log4j/core/config/di/ValidationException.java | 17 +-
.../log4j/core/config/di/api/bean/BeanManager.java | 113 -----
.../core/config/di/api/model/ElementManager.java | 152 -------
.../config/di/api/model/MetaAnnotationElement.java | 24 --
.../log4j/core/config/di/api/model/MetaClass.java | 42 --
.../core/config/di/api/model/MetaConstructor.java | 22 -
.../core/config/di/api/model/MetaElement.java | 56 ---
.../log4j/core/config/di/api/model/MetaField.java | 24 --
.../log4j/core/config/di/api/model/MetaMember.java | 24 --
.../log4j/core/config/di/api/model/MetaMethod.java | 22 -
.../core/config/di/api/model/MetaParameter.java | 21 -
.../log4j/core/config/di/api/model/Qualifiers.java | 87 ----
.../config/di/impl/{bean => }/AbstractBean.java | 36 +-
.../di/impl/{bean => }/AbstractProducer.java | 23 +-
.../impl/{bean => }/AbstractProducerFactory.java | 23 +-
.../di/impl/{bean => }/DefaultBeanManager.java | 257 ++++++-----
.../{bean => }/DefaultInitializationContext.java | 6 +-
.../core/config/di/impl/DefaultInjectionPoint.java | 121 ++++++
.../di/impl/{bean => }/DefaultInjectionTarget.java | 72 ++--
.../di/impl/DefaultInjectionTargetFactory.java | 125 ++++++
.../log4j/core/config/di/impl/DefaultInjector.java | 118 +++++
.../di/impl/{bean => }/DefaultScopeContext.java | 8 +-
.../di/impl/{bean => }/DependentScopeContext.java | 8 +-
.../config/di/impl/{bean => }/FieldProducer.java | 34 +-
.../di/impl/{bean => }/FieldProducerFactory.java | 23 +-
.../di/impl/{bean => }/InjectionTargetBean.java | 22 +-
.../config/di/impl/{bean => }/MethodProducer.java | 25 +-
.../di/impl/{bean => }/MethodProducerFactory.java | 22 +-
.../config/di/impl/{bean => }/OptionalBean.java | 28 +-
.../config/di/impl/{bean => }/ProducerBean.java | 22 +-
.../{bean/SystemBean.java => ProvidedBean.java} | 56 +--
.../log4j/core/config/di/impl/ProviderBean.java | 76 ++++
.../impl/bean/DefaultInjectionTargetFactory.java | 111 -----
.../core/config/di/impl/bean/DefaultInjector.java | 84 ----
.../core/config/di/impl/bean/ProvidedBean.java | 36 --
.../core/config/di/impl/bean/ProviderBean.java | 37 --
.../di/impl/model/AbstractMetaExecutable.java | 44 --
.../config/di/impl/model/AbstractMetaMember.java | 74 ----
.../di/impl/model/DefaultElementManager.java | 197 ---------
.../di/impl/model/DefaultInjectionPoint.java | 98 -----
.../di/impl/model/DefaultMetaAnnotation.java | 112 -----
.../impl/model/DefaultMetaAnnotationElement.java | 76 ----
.../config/di/impl/model/DefaultMetaClass.java | 143 ------
.../di/impl/model/DefaultMetaConstructor.java | 50 ---
.../config/di/impl/model/DefaultMetaField.java | 57 ---
.../config/di/impl/model/DefaultMetaMethod.java | 51 ---
.../config/di/impl/model/DefaultMetaParameter.java | 64 ---
.../core/config/di/impl/model/DefaultVariable.java | 79 ----
.../log4j/core/config/plugins/PluginAliases.java | 10 +-
.../log4j/core/config/plugins/PluginAttribute.java | 3 +
.../config/plugins/PluginBuilderAttribute.java | 3 +
.../log4j/core/config/plugins/PluginElement.java | 3 +
.../log4j/core/config/plugins/PluginValue.java | 3 +
.../util/PluginAliasesProvider.java} | 13 +-
.../util/PluginAttributeNameProvider.java} | 15 +-
.../util/PluginBuilderAttributeNameProvider.java | 22 +-
.../util/PluginElementNameProvider.java} | 15 +-
.../util/PluginValueNameProvider.java} | 19 +-
log4j-core/src/main/java9/module-info.java | 5 +-
.../log4j/core/test/junit/BeanJUnit4Runner.java | 133 ------
.../logging/log4j/core/test/junit/WithBeans.java | 36 --
.../log4j/core/config/di/BeanManagerTest.java | 479 +++++++++++++++++++++
.../log4j/core/config/di/InjectionPointTest.java | 136 ++++++
.../log4j/core/config/di/InjectionTargetTest.java | 109 +++++
.../di/impl/bean/DefaultBeanManagerTest.java | 352 ---------------
log4j-core/src/test/java9/module-info.java | 3 +-
.../logging/log4j/plugins/PluginAliases.java | 4 +
.../logging/log4j/plugins/di/AnnotationAlias.java | 6 +-
.../apache/logging/log4j/plugins/di/Default.java | 33 --
.../apache/logging/log4j/plugins/di/Inject.java | 2 +-
.../org/apache/logging/log4j/plugins/di/Named.java | 4 +-
.../plugins/di/{Ignore.java => NamedAliases.java} | 14 +-
.../inject/AbstractConfigurationInjector.java | 8 +-
.../AliasesProvider.java} | 11 +-
.../name/AnnotatedElementAliasesProvider.java | 46 ++
.../plugins/name/AnnotatedElementNameProvider.java | 56 ++-
.../log4j/plugins/name/NamedAliasesProvider.java | 54 +++
.../log4j/plugins/name/PluginAliasesProvider.java | 15 +-
.../logging/log4j/plugins/util/AnnotationUtil.java | 28 +-
.../log4j/plugins/util/ParameterizedTypeImpl.java | 2 +-
.../logging/log4j/plugins/util/TypeUtil.java | 24 +-
94 files changed, 2101 insertions(+), 2914 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java
index 55cab85..919a6e6 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java
@@ -17,8 +17,6 @@
package org.apache.logging.log4j.core.config.di;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-
import java.util.Collection;
public class AmbiguousBeanException extends ResolutionException {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Bean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Bean.java
similarity index 69%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Bean.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Bean.java
index b942e1c..4b718ca 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Bean.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Bean.java
@@ -15,15 +15,16 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
+import org.apache.logging.log4j.plugins.di.DependentScoped;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
import java.util.Collection;
-public interface Bean<T> extends Variable {
+public interface Bean<T> {
/**
* Creates a new instance of this bean. The given {@link InitializationContext} should be used by implementations
* to track dependent objects.
@@ -46,5 +47,24 @@ public interface Bean<T> extends Variable {
// for a managed bean: that class
// for a producer field or producer method: the declaring class
- MetaClass<?> getDeclaringClass();
+ Class<?> getDeclaringClass();
+
+ Collection<Type> getTypes();
+
+ default boolean hasMatchingType(final Type requiredType) {
+ for (final Type type : getTypes()) {
+ if (TypeUtil.typesMatch(requiredType, type)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ String getName();
+
+ Class<? extends Annotation> getScopeType();
+
+ default boolean isDependentScoped() {
+ return getScopeType() == DependentScoped.class;
+ }
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/BeanManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/BeanManager.java
new file mode 100644
index 0000000..967cc1f
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/BeanManager.java
@@ -0,0 +1,237 @@
+/*
+ * 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.core.config.di;
+
+import org.apache.logging.log4j.plugins.di.Inject;
+import org.apache.logging.log4j.plugins.di.Produces;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
+import org.apache.logging.log4j.plugins.name.NameProvider;
+import org.apache.logging.log4j.plugins.util.AnnotationUtil;
+import org.apache.logging.log4j.util.Strings;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Central SPI for injecting and managing beans and their instances.
+ */
+public interface BeanManager extends AutoCloseable {
+
+ /**
+ * Loads beans from the given classes. This looks for injectable classes and producers in the provided classes,
+ * loads them into this manager, and returns the loaded beans.
+ *
+ * @param beanClasses classes to load beans from
+ * @return beans loaded from the given classes
+ */
+ Collection<Bean<?>> loadBeans(final Collection<Class<?>> beanClasses);
+
+ /**
+ * Loads beans from the given classes. This looks for injectable classes and producers, registers them in this
+ * manager, validates them, then returns the validated beans.
+ *
+ * @param beanClasses classes to load beans from
+ * @throws ValidationException if any beans have validation errors
+ */
+ default void loadAndValidateBeans(final Class<?>... beanClasses) {
+ final Collection<Bean<?>> beans = loadBeans(List.of(beanClasses));
+ validateBeans(beans);
+ }
+
+ /**
+ * Validates beans and throws a {@link ValidationException} if there are any errors.
+ *
+ * @param beans beans to check for validation errors
+ * @throws ValidationException if any beans have validation errors
+ */
+ void validateBeans(final Iterable<Bean<?>> beans);
+
+ /**
+ * Validates the given injection point.
+ *
+ * @param point injection point to validate
+ * @throws DefinitionException if the injection point is improperly defined
+ * @throws UnsatisfiedBeanException if no beans can satisfy the injection point
+ */
+ void validateInjectionPoint(InjectionPoint point);
+
+ /**
+ * Checks if a class has exactly one injectable constructor. A constructor is <i>injectable</i> if:
+ * <ol>
+ * <li>it is annotated with {@link Inject}; or</li>
+ * <li>it has as least one parameter annotated with {@link Inject} or a {@linkplain NameProvider name provider annotation}; or</li>
+ * <li>it is the lone no-arg constructor.</li>
+ * </ol>
+ *
+ * @param type class to find an injectable constructor in
+ * @return true if the class has exactly one injectable constructor or false otherwise
+ */
+ default boolean isInjectable(final Class<?> type) {
+ int injectConstructors = 0;
+ final Constructor<?>[] constructors = type.getDeclaredConstructors();
+ for (final Constructor<?> constructor : constructors) {
+ if (AnnotationUtil.isAnnotationPresent(constructor, Inject.class)) {
+ injectConstructors++;
+ }
+ }
+ if (injectConstructors > 1) {
+ return false;
+ }
+ if (injectConstructors == 1) {
+ return true;
+ }
+
+ int implicitConstructors = 0;
+ for (final Constructor<?> constructor : constructors) {
+ for (final Parameter parameter : constructor.getParameters()) {
+ if (isInjectable(parameter)) {
+ implicitConstructors++;
+ break;
+ }
+ }
+ }
+ if (implicitConstructors > 1) {
+ return false;
+ }
+ if (implicitConstructors == 1) {
+ return true;
+ }
+
+ try {
+ type.getDeclaredConstructor();
+ return true;
+ } catch (final NoSuchMethodException ignored) {
+ return false;
+ }
+ }
+
+ /**
+ * Checks if an element is injectable. An element is <i>injectable</i> if:
+ * <ol>
+ * <li>it is annotated with {@link Inject}; or</li>
+ * <li>it is annotated with a {@linkplain NameProvider name provider annotation} and is not annotated
+ * with {@link Produces}.</li>
+ * </ol>
+ *
+ * @param element field, method, or parameter to check
+ * @return true if the element is injectable or false otherwise
+ */
+ default boolean isInjectable(final AnnotatedElement element) {
+ if (AnnotationUtil.isAnnotationPresent(element, Inject.class)) {
+ return true;
+ }
+ if (AnnotationUtil.isAnnotationPresent(element, Produces.class)) {
+ return false;
+ }
+ return AnnotatedElementNameProvider.hasName(element);
+ }
+
+ default <T> Optional<Bean<T>> getDefaultBean(final Class<T> beanType) {
+ return getNamedBean(beanType, Strings.EMPTY);
+ }
+
+ default <T> Optional<Bean<T>> getNamedBean(final Class<T> beanType, final String name) {
+ return getBean(beanType, name, List.of());
+ }
+
+ <T> Optional<Bean<T>> getBean(Type type, final String name, Collection<String> aliases);
+
+ /**
+ * Creates an injection point for a field with an optional owning bean.
+ *
+ * @param field field where injection will take place
+ * @param owner bean where field is located or null for static fields
+ * @return an injection point describing the field
+ */
+ InjectionPoint createFieldInjectionPoint(final Field field, final Bean<?> owner);
+
+ /**
+ * Creates an injection point for a method or constructor parameter with an optional owning bean.
+ *
+ * @param executable method or constructor where injection will take place
+ * @param parameter which parameter of that executable to create a point at
+ * @param owner bean where executable is located or null for static methods
+ * @return an injection point describing the parameter
+ */
+ InjectionPoint createParameterInjectionPoint(final Executable executable, final Parameter parameter, final Bean<?> owner);
+
+ /**
+ * Creates a collection of injection points for all the parameters of a method or constructor with an optional
+ * owning bean.
+ *
+ * @param executable method or constructor where injection will take place
+ * @param owner bean where executable is located or null for static methods
+ * @return collection of injection points describing the executable parameters
+ */
+ default Collection<InjectionPoint> createExecutableInjectionPoints(final Executable executable, final Bean<?> owner) {
+ final Parameter[] parameters = executable.getParameters();
+ final Collection<InjectionPoint> points = new ArrayList<>(parameters.length);
+ for (final Parameter parameter : parameters) {
+ points.add(createParameterInjectionPoint(executable, parameter, owner));
+ }
+ return points;
+ }
+
+ /**
+ * Creates an InitializationContext for a given Bean instance for use in dependency injection SPIs.
+ *
+ * @param bean bean to create an initialization context for (may be null to bootstrap a dependency graph)
+ * @param <T> type of object created by bean
+ * @return new InitializationContext for the given Bean
+ */
+ <T> InitializationContext<T> createInitializationContext(final Bean<T> bean);
+
+ /**
+ * Gets or creates the value for a given bean inside a given InitializationContext.
+ *
+ * @param bean bean to get or create value for
+ * @param parentContext which context this bean is being used in
+ * @param <T> type of value
+ * @return value of the bean in the given context
+ */
+ <T> T getValue(final Bean<T> bean, final InitializationContext<?> parentContext);
+
+ /**
+ * Gets the value to use for injecting into a given InjectionPoint in a given InitializationContext.
+ *
+ * @param point location where injectable value would be injected
+ * @param parentContext which context this value is being injected under
+ * @param <T> type of injectable value
+ * @return value to inject if defined or empty otherwise
+ */
+ <T> Optional<T> getInjectableValue(final InjectionPoint point, final InitializationContext<?> parentContext);
+
+ /**
+ * Destroys all the beans managed by this instance.
+ */
+ @Override
+ void close();
+
+ // TODO: integrate with constraint validators
+ // TODO: integrate with TypeConverters
+ // TODO: need some sort of default value strategy to bridge over @PluginAttribute and optional injected values
+ // TODO: add support for injecting collections and arrays
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InitializationContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InitializationContext.java
similarity index 97%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InitializationContext.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InitializationContext.java
index d1bc90e..a2dded6 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InitializationContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InitializationContext.java
@@ -15,7 +15,7 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
import java.util.Optional;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/InjectionPoint.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionPoint.java
similarity index 75%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/InjectionPoint.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionPoint.java
index 7fd6856..c76390c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/InjectionPoint.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionPoint.java
@@ -15,11 +15,12 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.model;
-
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
+package org.apache.logging.log4j.core.config.di;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Member;
import java.lang.reflect.Type;
+import java.util.Collection;
import java.util.Optional;
/**
@@ -32,11 +33,9 @@ public interface InjectionPoint {
*/
Type getType();
- /**
- * Gets the qualifiers of this point. If no qualifiers other than {@link org.apache.logging.log4j.plugins.di.Named}
- * are present, then these qualifiers will also include {@link org.apache.logging.log4j.plugins.di.Default}.
- */
- Qualifiers getQualifiers();
+ String getName();
+
+ Collection<String> getAliases();
/**
* Gets the bean where this injection point is defined or empty for static methods and fields.
@@ -46,11 +45,11 @@ public interface InjectionPoint {
/**
* Gets the field, method, or constructor where injection takes place.
*/
- MetaMember<?> getMember();
+ Member getMember();
/**
* Gets the program element corresponding to this injection point.
*/
- MetaElement getElement();
+ AnnotatedElement getElement();
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InjectionTarget.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionTarget.java
similarity index 97%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InjectionTarget.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionTarget.java
index 837e99e..ec4463a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InjectionTarget.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionTarget.java
@@ -15,7 +15,7 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
import org.apache.logging.log4j.plugins.di.Inject;
import org.apache.logging.log4j.plugins.di.PostConstruct;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InjectionTargetFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionTargetFactory.java
similarity index 94%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InjectionTargetFactory.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionTargetFactory.java
index 512773a..3b3d809 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/InjectionTargetFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/InjectionTargetFactory.java
@@ -15,7 +15,7 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
public interface InjectionTargetFactory<T> {
InjectionTarget<T> createInjectionTarget(final Bean<T> bean);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Injector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Injector.java
similarity index 61%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Injector.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Injector.java
index c56eb68..52d74f0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Injector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Injector.java
@@ -15,29 +15,27 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
-
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaConstructor;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
+package org.apache.logging.log4j.core.config.di;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.Collection;
public interface Injector {
- <T> T construct(final MetaConstructor<T> constructor, final Collection<InjectionPoint> points,
+ <T> T construct(final Constructor<T> constructor, final Collection<InjectionPoint> points,
final InitializationContext<T> context);
- <D, T> T produce(final D producerInstance, final MetaMethod<D, T> producerMethod,
+ <D, T> T produce(final D producerInstance, final Method producerMethod,
final Collection<InjectionPoint> points, final InitializationContext<D> context);
- <T> void dispose(final T disposerInstance, final MetaMethod<T, ?> disposerMethod,
+ <T> void dispose(final T disposerInstance, final Method disposerMethod,
final Collection<InjectionPoint> points, final Object instance,
final InitializationContext<T> context);
- <T> void invoke(final T instance, final MetaMethod<T, ?> method, final Collection<InjectionPoint> points,
+ <T> void invoke(final T instance, final Method method, final Collection<InjectionPoint> points,
final InitializationContext<T> context);
- <D, T> void set(final D instance, final MetaField<D, T> field, final InjectionPoint point,
+ <D, T> void set(final D instance, final Field field, final InjectionPoint point,
final InitializationContext<D> context);
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Producer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Producer.java
similarity index 95%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Producer.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Producer.java
index 3665e64..a65cc90 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/Producer.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/Producer.java
@@ -15,9 +15,8 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
import org.apache.logging.log4j.plugins.di.Disposes;
import org.apache.logging.log4j.plugins.di.Inject;
import org.apache.logging.log4j.plugins.di.Produces;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ProducerFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProducerFactory.java
similarity index 94%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ProducerFactory.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProducerFactory.java
index 2051102..2fe22a9 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ProducerFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProducerFactory.java
@@ -15,7 +15,7 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
public interface ProducerFactory {
// only time bean is null is static @Produces potentially?
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ProviderFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProviderFactory.java
similarity index 94%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ProviderFactory.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProviderFactory.java
index a557ed1..8981cbf 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ProviderFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ProviderFactory.java
@@ -15,7 +15,7 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
import org.apache.logging.log4j.plugins.di.Provider;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ScopeContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ScopeContext.java
similarity index 97%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ScopeContext.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ScopeContext.java
index 2670d04..b56353f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/ScopeContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ScopeContext.java
@@ -15,7 +15,7 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.bean;
+package org.apache.logging.log4j.core.config.di;
import org.apache.logging.log4j.plugins.di.ScopeType;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/UnsatisfiedBeanException.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/UnsatisfiedBeanException.java
index 12f6ab3..e792e3d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/UnsatisfiedBeanException.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/UnsatisfiedBeanException.java
@@ -17,8 +17,6 @@
package org.apache.logging.log4j.core.config.di;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-
import java.lang.reflect.Type;
public class UnsatisfiedBeanException extends ResolutionException {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ValidationException.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ValidationException.java
index d0fe1a0..74bdb6c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ValidationException.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/ValidationException.java
@@ -17,11 +17,20 @@
package org.apache.logging.log4j.core.config.di;
-import java.util.List;
+import java.util.Collection;
public class ValidationException extends InjectionException {
- public ValidationException(final List<Throwable> validationErrors) {
- super("Found " + validationErrors.size() + " error(s) in bean deployment. See suppressed exceptions for details.");
- validationErrors.forEach(this::addSuppressed);
+ public static ValidationException fromValidationErrors(final Collection<Throwable> validationErrors) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Found ").append(validationErrors.size()).append(" error(s) in bean deployment. Errors:");
+ validationErrors.forEach(error -> sb.append("\n • ").append(error.getMessage()));
+ final String message = sb.toString();
+ final ValidationException exception = new ValidationException(message);
+ validationErrors.forEach(exception::addSuppressed);
+ return exception;
+ }
+
+ private ValidationException(final String message) {
+ super(message);
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/BeanManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/BeanManager.java
deleted file mode 100644
index c448a1d..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/bean/BeanManager.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.core.config.di.api.bean;
-
-import org.apache.logging.log4j.core.config.di.DefinitionException;
-import org.apache.logging.log4j.core.config.di.UnsatisfiedBeanException;
-import org.apache.logging.log4j.core.config.di.ValidationException;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Optional;
-
-/**
- * Central SPI for injecting and managing beans and their instances.
- */
-public interface BeanManager extends AutoCloseable {
-
- /**
- * Loads beans from the given classes. This looks for injectable classes and producers in the provided classes,
- * loads them into this manager, and returns the loaded beans.
- *
- * @param beanClasses classes to load beans from
- * @return beans loaded from the given classes
- */
- Collection<Bean<?>> loadBeans(final Collection<Class<?>> beanClasses);
-
- /**
- * Loads beans from the given classes. This looks for injectable classes and producers, registers them in this
- * manager, validates them, then returns the validated beans.
- *
- * @param beanClasses classes to load beans from
- * @throws ValidationException if any beans have validation errors
- */
- default void loadAndValidateBeans(final Class<?>... beanClasses) {
- final Collection<Bean<?>> beans = loadBeans(Arrays.asList(beanClasses));
- validateBeans(beans);
- }
-
- /**
- * Validates beans and throws a {@link ValidationException} if there are any errors.
- *
- * @param beans beans to check for validation errors
- * @throws ValidationException if any beans have validation errors
- */
- void validateBeans(final Iterable<Bean<?>> beans);
-
- /**
- * Validates the given injection point.
- *
- * @param point injection point to validate
- * @throws DefinitionException if the injection point is improperly defined
- * @throws UnsatisfiedBeanException if no beans can satisfy the injection point
- */
- void validateInjectionPoint(InjectionPoint point);
-
- <T> Optional<Bean<T>> getBean(final Type type, final Qualifiers qualifiers);
-
- /**
- * Creates an InitializationContext for a given Bean instance for use in dependency injection SPIs.
- *
- * @param bean bean to create an initialization context for
- * @param <T> type of object created by bean
- * @return new InitializationContext for the given Bean
- */
- <T> InitializationContext<T> createInitializationContext(final Bean<T> bean);
-
- /**
- * Gets or creates the value for a given bean inside a given InitializationContext.
- *
- * @param bean bean to get or create value for
- * @param parentContext which context this bean is being used in
- * @param <T> type of value
- * @return value of the bean in the given context
- */
- <T> T getValue(final Bean<T> bean, final InitializationContext<?> parentContext);
-
- /**
- * Gets the value to use for injecting into a given InjectionPoint in a given InitializationContext.
- *
- * @param point location where injectable value would be injected
- * @param parentContext which context this value is being injected under
- * @param <T> type of injectable value
- * @return value to inject if defined or empty otherwise
- */
- <T> Optional<T> getInjectableValue(final InjectionPoint point, final InitializationContext<?> parentContext);
-
- @Override
- void close();
-
- // TODO: integrate with constraint validators
- // TODO: integrate with TypeConverters
- // TODO: need some sort of default value strategy to bridge over @PluginAttribute and optional injected values
- // TODO: need to support @PluginAliases still
- // TODO: add support for injecting collections and arrays
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/ElementManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/ElementManager.java
deleted file mode 100644
index bab1036..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/ElementManager.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-import org.apache.logging.log4j.plugins.di.Default;
-import org.apache.logging.log4j.plugins.di.Inject;
-import org.apache.logging.log4j.plugins.di.Named;
-import org.apache.logging.log4j.plugins.di.Produces;
-import org.apache.logging.log4j.plugins.di.QualifierType;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-
-import java.lang.annotation.Annotation;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Manages model metadata of program elements.
- */
-public interface ElementManager extends AutoCloseable {
-
- /**
- * Gets metadata about a class.
- */
- <T> MetaClass<T> getMetaClass(final Class<T> clazz);
-
- /**
- * Indicates if an annotation type is considered a {@linkplain QualifierType qualifier}.
- */
- boolean isQualifierType(Class<? extends Annotation> annotationType);
-
- /**
- * Extracts the collection of {@linkplain QualifierType qualifiers} from the annotations on an element.
- * If no qualifiers other than {@link Named} are present, then the {@link Default} qualifier is also returned in
- * the collection.
- *
- * @param element program element to extract qualifiers from
- * @return qualifiers present on the element
- */
- Qualifiers getQualifiers(MetaElement element);
-
- /**
- * Checks if a class has exactly one injectable constructor. A constructor is <i>injectable</i> if:
- * <ol>
- * <li>it is annotated with {@link Inject}; or</li>
- * <li>it has as least one parameter annotated with {@link Inject} or a {@linkplain QualifierType qualifier annotation}; or</li>
- * <li>it is the lone no-arg constructor.</li>
- * </ol>
- *
- * @param type class to find an injectable constructor in
- * @return true if the class has exactly one injectable constructor or false otherwise
- */
- default boolean isInjectable(final MetaClass<?> type) {
- final List<MetaConstructor<?>> injectConstructors = type.getConstructors().stream()
- .filter(constructor -> constructor.isAnnotationPresent(Inject.class))
- .collect(Collectors.toList());
- if (injectConstructors.size() > 1) {
- return false;
- }
- if (injectConstructors.size() == 1) {
- return true;
- }
- final List<MetaConstructor<?>> implicitConstructors = type.getConstructors().stream()
- .filter(constructor -> constructor.getParameters().stream().anyMatch(this::isInjectable))
- .collect(Collectors.toList());
- if (implicitConstructors.size() > 1) {
- return false;
- }
- if (implicitConstructors.size() == 1) {
- return true;
- }
- return type.getDefaultConstructor().isPresent();
- }
-
- /**
- * Checks if an element is injectable. An element is <i>injectable</i> if:
- * <ol>
- * <li>it is annotated with {@link Inject}; or</li>
- * <li>it is annotated with a {@linkplain QualifierType qualifier annotation} and is not annotated with {@link Produces}.</li>
- * </ol>
- *
- * @param element field, method, or parameter to check
- * @return true if the element is injectable or false otherwise
- */
- default boolean isInjectable(final MetaElement element) {
- return element.isAnnotationPresent(Inject.class) ||
- (element.getAnnotations().stream().map(MetaAnnotation::getAnnotationType).anyMatch(this::isQualifierType) &&
- !element.isAnnotationPresent(Produces.class));
- }
-
- /**
- * Creates an injection point for a field with an optional owning bean.
- *
- * @param field field where injection will take place
- * @param owner bean where field is located or null for static fields
- * @param <D> bean type
- * @return an injection point describing the field
- */
- <D> InjectionPoint createFieldInjectionPoint(final MetaField<D, ?> field, final Bean<D> owner);
-
- /**
- * Creates an injection point for a method or constructor parameter with an optional owning bean.
- *
- * @param executable method or constructor where injection will take place
- * @param parameter which parameter of that executable to create a point at
- * @param owner bean where executable is located or null for static methods
- * @param <D> bean type
- * @return an injection point describing the parameter
- */
- <D> InjectionPoint createParameterInjectionPoint(final MetaExecutable<D> executable,
- final MetaParameter parameter, final Bean<D> owner);
-
- /**
- * Creates a collection of injection points for all the parameters of a method or constructor with an optional
- * owning bean.
- *
- * @param executable method or constructor where injection will take place
- * @param owner bean where executable is located or null for static methods
- * @param <D> bean type
- * @return collection of injection points describing the executable parameters
- */
- default <D> Collection<InjectionPoint> createExecutableInjectionPoints(final MetaExecutable<D> executable, final Bean<D> owner) {
- Objects.requireNonNull(executable);
- return executable.getParameters().stream()
- .map(parameter -> createParameterInjectionPoint(executable, parameter, owner))
- .collect(Collectors.toList());
- }
-
- /**
- * Creates a variable for an element.
- */
- Variable createVariable(final MetaElement element);
-
- @Override
- void close();
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaAnnotationElement.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaAnnotationElement.java
deleted file mode 100644
index 7d7af1e..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaAnnotationElement.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-public interface MetaAnnotationElement<T> extends MetaElement {
- T getValue();
-
- MetaAnnotationElement<T> withNewValue(final T value);
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaClass.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaClass.java
deleted file mode 100644
index 0ed3261..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaClass.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.Optional;
-
-public interface MetaClass<T> extends MetaElement {
- Class<T> getJavaClass();
-
- Collection<MetaConstructor<T>> getConstructors();
-
- MetaConstructor<T> getMetaConstructor(final Constructor<T> constructor);
-
- Optional<MetaConstructor<T>> getDefaultConstructor();
-
- Collection<MetaMethod<T, ?>> getMethods();
-
- <U> MetaMethod<T, U> getMetaMethod(final Method method);
-
- Collection<MetaField<T, ?>> getFields();
-
- <U> MetaField<T, U> getMetaField(final Field field);
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaConstructor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaConstructor.java
deleted file mode 100644
index f49ef3e..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaConstructor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-public interface MetaConstructor<T> extends MetaExecutable<T> {
- T construct(final Object... args);
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaElement.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaElement.java
deleted file mode 100644
index 7962c6e..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaElement.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-import org.apache.logging.log4j.plugins.di.AnnotationAlias;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.Collection;
-
-public interface MetaElement {
-
- /**
- * Returns the source code name of this element.
- */
- String getName();
-
- Type getType();
-
- default Collection<Type> getTypeClosure() {
- return TypeUtil.getTypeClosure(getType());
- }
-
- /**
- * Returns all the annotations present on this element.
- */
- Collection<MetaAnnotation> getAnnotations();
-
- /**
- * Indicates whether or not an annotation is present on this element taking into account
- * {@linkplain AnnotationAlias annotation aliasing}.
- *
- * @param annotationType type of annotation to look for
- * @return whether or not the annotation is directly or indirectly present on this element
- */
- default boolean isAnnotationPresent(final Class<? extends Annotation> annotationType) {
- return getAnnotations().stream().anyMatch(annotation -> annotationType == annotation.getAnnotationType());
- }
-
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaField.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaField.java
deleted file mode 100644
index 905d34a..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaField.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-public interface MetaField<D, T> extends MetaMember<D> {
- T get(final D target);
-
- void set(final D target, final T value);
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaMember.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaMember.java
deleted file mode 100644
index 2170c81..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaMember.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-public interface MetaMember<D> extends MetaElement {
- MetaClass<D> getDeclaringClass();
-
- boolean isStatic();
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaMethod.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaMethod.java
deleted file mode 100644
index c0c3c88..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaMethod.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-public interface MetaMethod<D, T> extends MetaExecutable<D> {
- T invoke(final D target, final Object... args);
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaParameter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaParameter.java
deleted file mode 100644
index 7ad8223..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaParameter.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-public interface MetaParameter extends MetaElement {
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/Qualifiers.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/Qualifiers.java
deleted file mode 100644
index f80ce68..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/Qualifiers.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.core.config.di.api.model;
-
-import org.apache.logging.log4j.plugins.di.Default;
-import org.apache.logging.log4j.util.StringBuilders;
-
-import java.lang.annotation.Annotation;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents a normalized set of {@linkplain org.apache.logging.log4j.plugins.di.QualifierType qualifier annotations}.
- */
-public final class Qualifiers {
-
- public static final Qualifiers DEFAULT = new Qualifiers(Collections.singletonMap(Default.class, Collections.emptyMap()));
-
- public static Qualifiers fromAnnotations(final Set<MetaAnnotation> qualifiers) {
- return new Qualifiers(qualifiers.stream()
- .collect(Collectors.toMap(MetaAnnotation::getAnnotationType,
- ann -> ann.getAnnotationElements().stream()
- .collect(Collectors.toMap(MetaElement::getName, MetaAnnotationElement::getValue)))));
- }
-
- 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 boolean hasDefaultQualifier() {
- return qualifiers.containsKey(Default.class);
- }
-
- @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() {
- if (qualifiers.isEmpty()) {
- return "[]";
- }
- StringBuilder sb = new StringBuilder().append('[');
- for (final Map.Entry<Class<? extends Annotation>, Map<String, Object>> qualifier : qualifiers.entrySet()) {
- sb.append('@').append(qualifier.getKey().getSimpleName());
- final Map<String, Object> elements = qualifier.getValue();
- if (!elements.isEmpty()) {
- sb.append('(');
- for (final Map.Entry<String, Object> element : elements.entrySet()) {
- StringBuilders.appendKeyDqValue(sb, element.getKey(), element.getValue()).append(", ");
- }
- sb.delete(sb.length() - 2, sb.length()).append(')');
- }
- sb.append(", ");
- }
- return sb.delete(sb.length() - 2, sb.length()).append(']').toString();
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractBean.java
similarity index 63%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractBean.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractBean.java
index 57554ed..87e496d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractBean.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractBean.java
@@ -15,12 +15,9 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
+import org.apache.logging.log4j.core.config.di.Bean;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
@@ -28,32 +25,37 @@ import java.util.Collection;
import java.util.Objects;
abstract class AbstractBean<T> implements Bean<T> {
- private final Variable variable;
- private final MetaClass<?> declaringClass;
+ private final Collection<Type> types;
+ private final String name;
+ private final Class<? extends Annotation> scopeType;
+ private final Class<?> declaringClass;
- AbstractBean(final Variable variable, final MetaClass<?> declaringClass) {
- this.variable = Objects.requireNonNull(variable);
+ AbstractBean(final Collection<Type> types, final String name, final Class<? extends Annotation> scopeType,
+ final Class<?> declaringClass) {
+ this.types = types;
+ this.name = name;
+ this.scopeType = scopeType;
this.declaringClass = declaringClass;
}
@Override
- public MetaClass<?> getDeclaringClass() {
+ public Class<?> getDeclaringClass() {
return declaringClass;
}
@Override
public Collection<Type> getTypes() {
- return variable.getTypes();
+ return types;
}
@Override
- public Qualifiers getQualifiers() {
- return variable.getQualifiers();
+ public String getName() {
+ return name;
}
@Override
public Class<? extends Annotation> getScopeType() {
- return variable.getScopeType();
+ return scopeType;
}
@Override
@@ -61,13 +63,13 @@ abstract class AbstractBean<T> implements Bean<T> {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final AbstractBean<?> that = (AbstractBean<?>) o;
- return variable.equals(that.variable) &&
- Objects.equals(declaringClass, that.declaringClass);
+ return types.equals(that.types) && name.equals(that.name) && scopeType.equals(that.scopeType) &&
+ declaringClass.equals(that.declaringClass);
}
@Override
public int hashCode() {
- return Objects.hash(variable, declaringClass);
+ return Objects.hash(types, name, scopeType, declaringClass);
}
abstract boolean isTrackingDependencies();
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractProducer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducer.java
similarity index 77%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractProducer.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducer.java
index 03fe913..710a396 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractProducer.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducer.java
@@ -15,16 +15,17 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.Injector;
-import org.apache.logging.log4j.core.config.di.api.bean.Producer;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.BeanManager;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.Injector;
+import org.apache.logging.log4j.core.config.di.Producer;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Objects;
@@ -32,11 +33,11 @@ import java.util.Objects;
abstract class AbstractProducer<P, T> implements Producer<T> {
private final BeanManager beanManager;
private final Bean<P> producerBean;
- private final MetaMethod<P, ?> disposerMethod;
+ private final Method disposerMethod;
private final Collection<InjectionPoint> disposerInjectionPoints;
final Injector injector;
- AbstractProducer(final BeanManager beanManager, final Bean<P> producerBean, final MetaMethod<P, ?> disposerMethod,
+ AbstractProducer(final BeanManager beanManager, final Bean<P> producerBean, final Method disposerMethod,
final Collection<InjectionPoint> disposerInjectionPoints) {
this.beanManager = beanManager;
this.producerBean = producerBean;
@@ -66,7 +67,7 @@ abstract class AbstractProducer<P, T> implements Producer<T> {
if (hasDisposerMethod()) {
// as producer and disposer bean is unrelated to this bean, we need to recreate it on demand
try (final InitializationContext<P> context = createContext()) {
- final P declaringInstance = disposerMethod.isStatic() ? null : getProducerInstance(context);
+ final P declaringInstance = Modifier.isStatic(disposerMethod.getModifiers()) ? null : getProducerInstance(context);
injector.dispose(declaringInstance, disposerMethod, disposerInjectionPoints, instance, context);
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractProducerFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducerFactory.java
similarity index 62%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractProducerFactory.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducerFactory.java
index f993c42..6d0afa9 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/AbstractProducerFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/AbstractProducerFactory.java
@@ -15,25 +15,24 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.ProducerFactory;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMember;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.ProducerFactory;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Objects;
-abstract class AbstractProducerFactory<D> implements ProducerFactory {
- final Bean<D> declaringBean;
- final MetaMember<D> producerMember;
- final MetaMethod<D, ?> disposerMethod;
+abstract class AbstractProducerFactory implements ProducerFactory {
+ final Bean<?> declaringBean;
+ final Member producerMember;
+ final Method disposerMethod;
final Collection<InjectionPoint> disposerInjectionPoints;
- AbstractProducerFactory(final Bean<D> declaringBean, final MetaMember<D> producerMember,
- final MetaMethod<D, ?> disposerMethod,
+ AbstractProducerFactory(final Bean<?> declaringBean, final Member producerMember, final Method disposerMethod,
final Collection<InjectionPoint> disposerInjectionPoints) {
this.declaringBean = declaringBean;
this.producerMember = Objects.requireNonNull(producerMember);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultBeanManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultBeanManager.java
similarity index 58%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultBeanManager.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultBeanManager.java
index f9e3e43..75e4698 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultBeanManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultBeanManager.java
@@ -15,41 +15,40 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
import org.apache.logging.log4j.core.config.di.AmbiguousBeanException;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.BeanManager;
import org.apache.logging.log4j.core.config.di.DefinitionException;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
import org.apache.logging.log4j.core.config.di.InjectionException;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.InjectionTargetFactory;
+import org.apache.logging.log4j.core.config.di.Injector;
+import org.apache.logging.log4j.core.config.di.ProducerFactory;
import org.apache.logging.log4j.core.config.di.ResolutionException;
+import org.apache.logging.log4j.core.config.di.ScopeContext;
import org.apache.logging.log4j.core.config.di.UnsatisfiedBeanException;
import org.apache.logging.log4j.core.config.di.ValidationException;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.InjectionTargetFactory;
-import org.apache.logging.log4j.core.config.di.api.bean.Injector;
-import org.apache.logging.log4j.core.config.di.api.bean.ProducerFactory;
-import org.apache.logging.log4j.core.config.di.api.bean.ScopeContext;
-import org.apache.logging.log4j.core.config.di.api.model.ElementManager;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaElement;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMember;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-import org.apache.logging.log4j.core.config.di.api.model.MetaParameter;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
-import org.apache.logging.log4j.core.config.di.impl.model.DefaultElementManager;
import org.apache.logging.log4j.plugins.di.DependentScoped;
import org.apache.logging.log4j.plugins.di.Disposes;
import org.apache.logging.log4j.plugins.di.Produces;
import org.apache.logging.log4j.plugins.di.Provider;
+import org.apache.logging.log4j.plugins.di.ScopeType;
import org.apache.logging.log4j.plugins.di.SingletonScoped;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
+import org.apache.logging.log4j.plugins.util.AnnotationUtil;
import org.apache.logging.log4j.plugins.util.LazyValue;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
@@ -69,20 +68,14 @@ import java.util.stream.Stream;
public class DefaultBeanManager implements BeanManager {
- private final ElementManager elementManager;
private final Injector injector = new DefaultInjector(this);
private final Collection<Bean<?>> enabledBeans = ConcurrentHashMap.newKeySet();
private final Map<Type, Collection<Bean<?>>> beansByType = new ConcurrentHashMap<>();
- private final Collection<DisposesMethod<?>> disposesMethods = Collections.synchronizedCollection(new ArrayList<>());
+ private final Collection<DisposesMethod> disposesMethods = Collections.synchronizedCollection(new ArrayList<>());
private final Map<Class<? extends Annotation>, ScopeContext> scopes = new ConcurrentHashMap<>();
public DefaultBeanManager() {
- this(new DefaultElementManager());
- }
-
- public DefaultBeanManager(final ElementManager elementManager) {
- this.elementManager = elementManager;
// TODO: need a better way to register scope contexts
scopes.put(DependentScoped.class, new DependentScopeContext());
scopes.put(SingletonScoped.class, new DefaultScopeContext(SingletonScoped.class));
@@ -91,23 +84,24 @@ public class DefaultBeanManager implements BeanManager {
@Override
public Collection<Bean<?>> loadBeans(final Collection<Class<?>> beanClasses) {
return beanClasses.stream()
- .map(elementManager::getMetaClass)
- .flatMap(metaClass -> loadBeans(metaClass).stream())
+ .flatMap(beanClass -> loadBeans(beanClass).stream())
.collect(Collectors.toSet());
}
- private <T> Collection<Bean<?>> loadBeans(final MetaClass<T> metaClass) {
+ private <T> Collection<Bean<?>> loadBeans(final Class<T> beanClass) {
final Bean<T> created;
- if (elementManager.isInjectable(metaClass)) {
- final Variable variable = elementManager.createVariable(metaClass);
+ if (isInjectable(beanClass)) {
+ final Collection<Type> types = TypeUtil.getTypeClosure(beanClass);
+ final String name = AnnotatedElementNameProvider.getName(beanClass);
+ final Class<? extends Annotation> scopeType = getScopeType(beanClass);
final InjectionTargetFactory<T> factory =
- new DefaultInjectionTargetFactory<>(elementManager, injector, metaClass);
- created = addBean(new InjectionTargetBean<>(variable, metaClass, factory));
+ new DefaultInjectionTargetFactory<>(this, injector, beanClass);
+ created = addBean(new InjectionTargetBean<>(types, name, scopeType, beanClass, factory));
} else {
created = null;
}
- loadDisposerMethods(metaClass, created);
- final Collection<Bean<?>> beans = loadProducerBeans(metaClass, created);
+ loadDisposerMethods(beanClass, created);
+ final Collection<Bean<?>> beans = loadProducerBeans(beanClass, created);
if (created != null) {
beans.add(created);
}
@@ -140,67 +134,71 @@ public class DefaultBeanManager implements BeanManager {
beansByType.computeIfAbsent(type, ignored -> ConcurrentHashMap.newKeySet()).add(bean);
}
- private <T> void loadDisposerMethods(final MetaClass<T> metaClass, final Bean<T> bean) {
- for (final MetaMethod<T, ?> method : metaClass.getMethods()) {
- for (final MetaParameter parameter : method.getParameters()) {
- if (parameter.isAnnotationPresent(Disposes.class)) {
- disposesMethods.add(new DisposesMethod<>(
- parameter.getType(), elementManager.getQualifiers(parameter), bean, method));
+ private void loadDisposerMethods(final Class<?> metaClass, final Bean<?> bean) {
+ for (final Method method : metaClass.getDeclaredMethods()) {
+ for (final Parameter parameter : method.getParameters()) {
+ if (AnnotationUtil.isAnnotationPresent(parameter, Disposes.class)) {
+ final String name = AnnotatedElementNameProvider.getName(parameter);
+ final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(parameter);
+ method.setAccessible(true);
+ disposesMethods.add(new DisposesMethod(parameter.getParameterizedType(), name, aliases, bean, method));
}
}
}
}
- private <P> Collection<Bean<?>> loadProducerBeans(final MetaClass<P> producingClass, final Bean<P> producingBean) {
+ private <P> Collection<Bean<?>> loadProducerBeans(final Class<P> producingClass, final Bean<P> producingBean) {
final Collection<Bean<?>> beans = new HashSet<>();
- for (final MetaMethod<P, ?> method : producingClass.getMethods()) {
- if (method.isAnnotationPresent(Produces.class)) {
+ for (final Method method : producingClass.getDeclaredMethods()) {
+ if (AnnotationUtil.isAnnotationPresent(method, Produces.class)) {
+ method.setAccessible(true);
beans.add(loadProducerBean(method, producingBean));
}
}
- for (final MetaField<P, ?> field : producingClass.getFields()) {
- if (field.isAnnotationPresent(Produces.class)) {
+ for (final Field field : producingClass.getDeclaredFields()) {
+ if (AnnotationUtil.isAnnotationPresent(field, Produces.class)) {
+ field.setAccessible(true);
beans.add(loadProducerBean(field, producingBean));
}
}
return beans;
}
- private <P> Bean<?> loadProducerBean(final MetaMember<P> member, final Bean<P> producingBean) {
- final Variable variable = elementManager.createVariable(member);
- final MetaClass<P> declaringType = member.getDeclaringClass();
- final ProducerFactory factory = getProducerFactory(member, producingBean);
- return addBean(new ProducerBean<>(variable, declaringType, factory));
+ private Bean<?> loadProducerBean(final Method method, final Bean<?> producingBean) {
+ final Collection<Type> types = TypeUtil.getTypeClosure(method.getGenericReturnType());
+ final String name = AnnotatedElementNameProvider.getName(method);
+ final Method disposerMethod = resolveDisposerMethod(types, name, producingBean);
+ final Collection<InjectionPoint> disposerIPs = disposerMethod == null ? Collections.emptySet() :
+ createExecutableInjectionPoints(disposerMethod, producingBean);
+ final Collection<InjectionPoint> producerIPs = createExecutableInjectionPoints(method, producingBean);
+ final ProducerFactory factory = new MethodProducerFactory(
+ this, producingBean, method, producerIPs, disposerMethod, disposerIPs);
+ return addBean(new ProducerBean<>(types, name, getScopeType(method), method.getDeclaringClass(), factory));
}
- private <P> ProducerFactory getProducerFactory(final MetaMember<P> member, final Bean<P> producingBean) {
- final Variable variable = elementManager.createVariable(member);
- final MetaMethod<P, ?> disposerMethod = resolveDisposerMethod(variable, producingBean);
+ private Bean<?> loadProducerBean(final Field field, final Bean<?> producingBean) {
+ final Collection<Type> types = TypeUtil.getTypeClosure(field.getGenericType());
+ final String name = AnnotatedElementNameProvider.getName(field);
+ final Method disposerMethod = resolveDisposerMethod(types, name, producingBean);
final Collection<InjectionPoint> disposerIPs = disposerMethod == null ? Collections.emptySet() :
- elementManager.createExecutableInjectionPoints(disposerMethod, producingBean);
- if (member instanceof MetaField<?, ?>) {
- final MetaField<P, ?> field = (MetaField<P, ?>) member;
- return new FieldProducerFactory<>(this, producingBean, field, disposerMethod, disposerIPs);
- } else {
- final MetaMethod<P, ?> method = (MetaMethod<P, ?>) member;
- final Collection<InjectionPoint> producerIPs =
- elementManager.createExecutableInjectionPoints(method, producingBean);
- return new MethodProducerFactory<>(this, producingBean, method, producerIPs, disposerMethod, disposerIPs);
- }
+ createExecutableInjectionPoints(disposerMethod, producingBean);
+ final ProducerFactory factory = new FieldProducerFactory(
+ this, producingBean, field, disposerMethod, disposerIPs);
+ return addBean(new ProducerBean<>(types, name, getScopeType(field), field.getDeclaringClass(), factory));
}
- private <D> MetaMethod<D, ?> resolveDisposerMethod(final Variable variable, final Bean<D> disposingBean) {
- final List<MetaMethod<?, ?>> methods = disposesMethods.stream()
- .filter(method -> method.matches(variable, disposingBean))
+ private Method resolveDisposerMethod(final Collection<Type> types, final String name, final Bean<?> disposingBean) {
+ final List<Method> methods = disposesMethods.stream()
+ .filter(method -> method.matches(types, name, disposingBean))
.map(method -> method.disposesMethod)
.collect(Collectors.toList());
if (methods.isEmpty()) {
return null;
}
if (methods.size() == 1) {
- return TypeUtil.cast(methods.get(0));
+ return methods.get(0);
}
- throw new ResolutionException("Ambiguous @Disposes methods for " + variable + ": " + methods);
+ throw new ResolutionException("Ambiguous @Disposes methods for matching types " + types + " and name '" + name + "': " + methods);
}
@Override
@@ -216,14 +214,14 @@ public class DefaultBeanManager implements BeanManager {
}
}
if (!errors.isEmpty()) {
- throw new ValidationException(errors);
+ throw ValidationException.fromValidationErrors(errors);
}
}
@Override
public void validateInjectionPoint(final InjectionPoint point) {
- final MetaElement element = point.getElement();
- if (element.isAnnotationPresent(Produces.class)) {
+ final AnnotatedElement element = point.getElement();
+ if (AnnotationUtil.isAnnotationPresent(element, Produces.class)) {
throw new DefinitionException("Cannot inject into a @Produces element: " + element);
}
final Type type = point.getType();
@@ -241,13 +239,13 @@ public class DefaultBeanManager implements BeanManager {
if (rawType.equals(Bean.class)) {
final Bean<?> bean = point.getBean().orElseThrow(() -> new UnsatisfiedBeanException(point));
if (bean instanceof InjectionTargetBean<?>) {
- validateBeanInjectionPoint(point, bean.getDeclaringClass().getType());
+ validateBeanInjectionPoint(point, bean.getDeclaringClass());
} else if (bean instanceof ProducerBean<?>) {
validateBeanInjectionPoint(point, ((ProducerBean<?>) bean).getType());
}
}
- final Optional<Bean<Object>> bean = getBean(point.getType(), point.getQualifiers());
- if (!bean.isPresent() && !rawType.equals(Optional.class)) {
+ final Optional<Bean<Object>> bean = getBean(point.getType(), point.getName(), point.getAliases());
+ if (bean.isEmpty() && !rawType.equals(Optional.class)) {
throw new UnsatisfiedBeanException(point);
}
}
@@ -263,19 +261,17 @@ public class DefaultBeanManager implements BeanManager {
throw new DefinitionException("Expected one type parameter argument for " + point + " but got " +
Arrays.toString(typeArguments));
}
- if (point.getQualifiers().hasDefaultQualifier()) {
- final Type typeArgument = typeArguments[0];
- if (!typeArgument.equals(expectedType)) {
- throw new DefinitionException("Expected type " + expectedType + " but got " + typeArgument + " in " + point);
- }
+ final Type typeArgument = typeArguments[0];
+ if (!typeArgument.equals(expectedType)) {
+ throw new DefinitionException("Expected type " + expectedType + " but got " + typeArgument + " in " + point);
}
}
@Override
- public <T> Optional<Bean<T>> getBean(final Type type, final Qualifiers qualifiers) {
+ public <T> Optional<Bean<T>> getBean(final Type type, final String name, final Collection<String> aliases) {
// TODO: this will need to allow for TypeConverter usage somehow
// first, look for an existing bean
- final Optional<Bean<T>> existingBean = getExistingOrProvidedBean(type, qualifiers);
+ final Optional<Bean<T>> existingBean = getExistingOrProvidedBean(type, name, aliases);
if (existingBean.isPresent()) {
return existingBean;
}
@@ -284,43 +280,47 @@ public class DefaultBeanManager implements BeanManager {
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>>
- final Optional<Bean<T>> actualExistingBean = getExistingBean(actualType, qualifiers);
- return actualExistingBean.map(bean -> new ProviderBean<>(bean, context -> () -> getValue(bean, context)))
+ final Optional<Bean<T>> actualExistingBean = getExistingBean(actualType, name, aliases);
+ return actualExistingBean.map(bean -> new ProviderBean<>(type, bean, context -> () -> getValue(bean, context)))
.map(this::addBean)
.map(TypeUtil::cast);
} else if (rawType == Optional.class) {
final Type actualType = ((ParameterizedType) type).getActualTypeArguments()[0];
// fake T like in Provider above
- final Bean<Optional<T>> optionalBean = createOptionalBean(type, actualType, qualifiers);
+ final Bean<Optional<T>> optionalBean = addBean(new OptionalBean<>(type, name,
+ LazyValue.forSupplier(() -> getExistingOrProvidedBean(actualType, name, aliases)),
+ this::getValue));
return Optional.of(optionalBean).map(TypeUtil::cast);
}
}
return Optional.empty();
}
- private <T> Optional<Bean<T>> getExistingOrProvidedBean(final Type type, final Qualifiers qualifiers) {
- final Optional<Bean<T>> existingBean = getExistingBean(type, qualifiers);
+ private <T> Optional<Bean<T>> getExistingOrProvidedBean(final Type type, final String name, final Collection<String> aliases) {
+ final Optional<Bean<T>> existingBean = getExistingBean(type, name, aliases);
if (existingBean.isPresent()) {
return existingBean;
}
- return getProvidedBean(type, qualifiers);
+ return getProvidedBean(type, name, aliases);
}
- private <T> Optional<Bean<T>> getExistingBean(final Type type, final Qualifiers qualifiers) {
+ private <T> Optional<Bean<T>> getExistingBean(final Type type, final String name, final Collection<String> aliases) {
final Set<Bean<T>> beans = this.<T>beansWithType(type)
- .filter(bean -> qualifiers.equals(bean.getQualifiers()))
+ .filter(bean -> name.equalsIgnoreCase(bean.getName()) || aliases.stream().anyMatch(bean.getName()::equalsIgnoreCase))
.collect(Collectors.toSet());
if (beans.size() > 1) {
- throw new AmbiguousBeanException(beans, "type " + type + " and qualifiers " + qualifiers);
+ throw new AmbiguousBeanException(beans, "type " + type + ", name '" + name + "', and aliases " + aliases);
}
return beans.isEmpty() ? Optional.empty() : Optional.of(beans.iterator().next());
}
- private <T> Optional<Bean<T>> getProvidedBean(final Type providedType, final Qualifiers qualifiers) {
- return getExistingBean(TypeUtil.getParameterizedType(Provider.class, providedType), qualifiers)
- .<Bean<Provider<T>>>map(TypeUtil::cast)
- .map(bean -> new ProvidedBean<>(bean, context -> getValue(bean, context)))
- .map(this::addBean);
+ private <T> Optional<Bean<T>> getProvidedBean(final Type providedType, final String name, final Collection<String> aliases) {
+ // TODO: need a way to get @Plugin(name) for builder class (potential alias?)
+ final Optional<Bean<Provider<T>>> existingBean =
+ getExistingBean(TypeUtil.getParameterizedType(Provider.class, providedType), name, aliases);
+ final Optional<Bean<T>> providedBean = existingBean.map(bean ->
+ new ProvidedBean<>(providedType, bean, context -> getValue(bean, context)));
+ return providedBean.map(this::addBean);
}
private <T> Stream<Bean<T>> beansWithType(final Type requiredType) {
@@ -336,10 +336,27 @@ public class DefaultBeanManager implements BeanManager {
return Stream.empty();
}
- private <T> Bean<Optional<T>> createOptionalBean(final Type type, final Type typeArgument, final Qualifiers qualifiers) {
- return addBean(new OptionalBean<>(type, qualifiers,
- LazyValue.forSupplier(() -> getExistingOrProvidedBean(typeArgument, qualifiers)),
- this::getValue));
+ @Override
+ public InjectionPoint createFieldInjectionPoint(final Field field, final Bean<?> owner) {
+ Objects.requireNonNull(field);
+ return DefaultInjectionPoint.forField(field, owner);
+ }
+
+ @Override
+ public InjectionPoint createParameterInjectionPoint(final Executable executable, final Parameter parameter, final Bean<?> owner) {
+ Objects.requireNonNull(executable);
+ Objects.requireNonNull(parameter);
+ return DefaultInjectionPoint.forParameter(executable, parameter, owner);
+ }
+
+ private Class<? extends Annotation> getScopeType(final AnnotatedElement element) {
+ for (final Annotation annotation : element.getAnnotations()) {
+ final Class<? extends Annotation> annotationType = annotation.annotationType();
+ if (annotationType.isAnnotationPresent(ScopeType.class)) {
+ return annotationType;
+ }
+ }
+ return DependentScoped.class;
}
@Override
@@ -365,7 +382,7 @@ public class DefaultBeanManager implements BeanManager {
@Override
public <T> Optional<T> getInjectableValue(final InjectionPoint point, final InitializationContext<?> parentContext) {
- final Bean<T> resolvedBean = this.<T>getBean(point.getType(), point.getQualifiers())
+ final Bean<T> resolvedBean = this.<T>getBean(point.getType(), point.getName(), point.getAliases())
.orElseThrow(() -> new UnsatisfiedBeanException(point));
final Optional<T> existingValue = point.getBean()
.filter(bean -> !bean.equals(resolvedBean))
@@ -396,28 +413,42 @@ public class DefaultBeanManager implements BeanManager {
beansByType.clear();
enabledBeans.clear();
disposesMethods.clear();
- scopes.values().forEach(ScopeContext::close);
+ // TODO: better scope closing after more scopes are supported
+ scopes.get(SingletonScoped.class).close();
scopes.clear();
}
- private static class DisposesMethod<D> {
+ private static class DisposesMethod {
private final Type type;
- private final Qualifiers qualifiers;
- private final Bean<D> declaringBean;
- private final MetaMethod<D, ?> disposesMethod;
+ private final String name;
+ private final Collection<String> aliases;
+ private final Bean<?> declaringBean;
+ private final Method disposesMethod;
- private DisposesMethod(final Type type, final Qualifiers qualifiers,
- final Bean<D> declaringBean, final MetaMethod<D, ?> disposesMethod) {
+ private DisposesMethod(final Type type, final String name, final Collection<String> aliases,
+ final Bean<?> declaringBean, final Method disposesMethod) {
this.type = type;
- this.qualifiers = qualifiers;
+ this.name = name;
+ this.aliases = aliases;
this.declaringBean = declaringBean;
this.disposesMethod = disposesMethod;
}
- boolean matches(final Variable variable, final Bean<?> declaringBean) {
- return Objects.equals(declaringBean, this.declaringBean) &&
- variable.hasMatchingType(type) &&
- qualifiers.equals(variable.getQualifiers());
+ boolean matches(final Collection<Type> types, final String name, final Bean<?> declaringBean) {
+ return Objects.equals(declaringBean, this.declaringBean) && matchesName(name) && matchesType(types);
+ }
+
+ private boolean matchesType(final Collection<Type> types) {
+ for (final Type t : types) {
+ if (TypeUtil.typesMatch(type, t)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean matchesName(final String name) {
+ return this.name.equalsIgnoreCase(name) || aliases.stream().anyMatch(name::equalsIgnoreCase);
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInitializationContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInitializationContext.java
similarity index 96%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInitializationContext.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInitializationContext.java
index 61200f3..3d61bea 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInitializationContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInitializationContext.java
@@ -15,10 +15,10 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.plugins.util.Value;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionPoint.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionPoint.java
new file mode 100644
index 0000000..3404e29
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionPoint.java
@@ -0,0 +1,121 @@
+/*
+ * 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.core.config.di.impl;
+
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Objects;
+import java.util.Optional;
+
+class DefaultInjectionPoint implements InjectionPoint {
+ static DefaultInjectionPoint forField(final Field field, final Bean<?> owner) {
+ return new DefaultInjectionPoint(field.getGenericType(),
+ AnnotatedElementNameProvider.getName(field),
+ AnnotatedElementAliasesProvider.getAliases(field),
+ owner, field, field);
+ }
+
+ static DefaultInjectionPoint forParameter(final Executable executable, final Parameter parameter, final Bean<?> owner) {
+ return new DefaultInjectionPoint(parameter.getParameterizedType(),
+ AnnotatedElementNameProvider.getName(parameter),
+ AnnotatedElementAliasesProvider.getAliases(parameter),
+ owner, executable, parameter);
+ }
+
+ private final Type type;
+ private final String name;
+ private final Collection<String> aliases;
+ private final Bean<?> bean;
+ private final Member member;
+ private final AnnotatedElement element;
+
+ private DefaultInjectionPoint(final Type type, final String name, final Collection<String> aliases,
+ final Bean<?> bean, final Member member, final AnnotatedElement element) {
+ this.type = type;
+ this.name = name;
+ this.aliases = aliases;
+ this.bean = bean;
+ this.member = member;
+ this.element = element;
+ }
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Collection<String> getAliases() {
+ return aliases;
+ }
+
+ @Override
+ public Optional<Bean<?>> getBean() {
+ return Optional.ofNullable(bean);
+ }
+
+ @Override
+ public Member getMember() {
+ return member;
+ }
+
+ @Override
+ public AnnotatedElement getElement() {
+ return element;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final DefaultInjectionPoint that = (DefaultInjectionPoint) o;
+ return Objects.equals(bean, that.bean) && member.equals(that.member) && element.equals(that.element);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bean, member, element);
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultInjectionPoint{" +
+ "type=" + type +
+ ", name='" + name + '\'' +
+ ", aliases=" + aliases +
+ ", bean=" + bean +
+ ", member=" + member +
+ ", element=" + element +
+ '}';
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjectionTarget.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTarget.java
similarity index 60%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjectionTarget.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTarget.java
index 38cbea2..7807599 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjectionTarget.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTarget.java
@@ -15,22 +15,25 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InitializationException;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.InjectionTarget;
+import org.apache.logging.log4j.core.config.di.Injector;
import org.apache.logging.log4j.plugins.di.Disposes;
import org.apache.logging.log4j.plugins.di.Inject;
import org.apache.logging.log4j.plugins.di.Produces;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.InjectionTarget;
-import org.apache.logging.log4j.core.config.di.api.bean.Injector;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaConstructor;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMember;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
+import org.apache.logging.log4j.plugins.util.AnnotationUtil;
import org.apache.logging.log4j.plugins.util.TypeUtil;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -41,15 +44,15 @@ import java.util.stream.Collectors;
class DefaultInjectionTarget<T> implements InjectionTarget<T> {
private final Injector injector;
- private final MetaClass<T> metaClass;
+ private final Class<T> metaClass;
private final Collection<InjectionPoint> injectionPoints;
- private final MetaConstructor<T> constructor;
- private final List<MetaMethod<T, ?>> postConstructMethods;
- private final List<MetaMethod<T, ?>> preDestroyMethods;
+ private final Constructor<T> constructor;
+ private final List<Method> postConstructMethods;
+ private final List<Method> preDestroyMethods;
- DefaultInjectionTarget(final Injector injector, final MetaClass<T> metaClass,
- final Collection<InjectionPoint> injectionPoints, final MetaConstructor<T> constructor,
- final List<MetaMethod<T, ?>> postConstructMethods, final List<MetaMethod<T, ?>> preDestroyMethods) {
+ DefaultInjectionTarget(final Injector injector, final Class<T> metaClass,
+ final Collection<InjectionPoint> injectionPoints, final Constructor<T> constructor,
+ final List<Method> postConstructMethods, final List<Method> preDestroyMethods) {
this.injector = injector;
this.metaClass = metaClass;
this.injectionPoints = Objects.requireNonNull(injectionPoints);
@@ -74,18 +77,19 @@ class DefaultInjectionTarget<T> implements InjectionTarget<T> {
private void injectFields(final T instance, final InitializationContext<T> context) {
injectionPoints.stream()
- .filter(point -> point.getElement() instanceof MetaField<?, ?>)
+ .filter(point -> point.getElement() instanceof Field)
.forEachOrdered(point -> injector.set(instance, TypeUtil.cast(point.getElement()), point, context));
}
private void injectMethods(final T instance, final InitializationContext<T> context) {
- final Set<MetaMember<?>> injectedMethods = new HashSet<>();
+ final Set<Method> injectedMethods = new HashSet<>();
for (final InjectionPoint point : injectionPoints) {
- if (point.getMember() instanceof MetaMethod<?, ?> &&
- !injectedMethods.contains(point.getMember()) &&
- !point.getElement().isAnnotationPresent(Produces.class) &&
- !point.getElement().isAnnotationPresent(Disposes.class)) {
- final MetaMethod<T, ?> method = TypeUtil.cast(point.getMember());
+ final Member member = point.getMember();
+ final AnnotatedElement element = point.getElement();
+ if (member instanceof Method && !injectedMethods.contains(member) &&
+ !AnnotationUtil.isAnnotationPresent(element, Produces.class) &&
+ !AnnotationUtil.isAnnotationPresent(element, Disposes.class)) {
+ final Method method = TypeUtil.cast(member);
final Set<InjectionPoint> methodInjectionPoints = injectionPoints.stream()
.filter(p -> method.equals(p.getMember()))
.collect(Collectors.toSet());
@@ -93,8 +97,8 @@ class DefaultInjectionTarget<T> implements InjectionTarget<T> {
injectedMethods.add(method);
}
}
- for (final MetaMethod<T, ?> method : metaClass.getMethods()) {
- if (method.isAnnotationPresent(Inject.class) && method.getParameters().isEmpty()) {
+ for (final Method method : metaClass.getMethods()) {
+ if (method.isAnnotationPresent(Inject.class) && method.getParameterCount() == 0) {
injector.invoke(instance, method, Collections.emptySet(), context);
}
}
@@ -102,15 +106,23 @@ class DefaultInjectionTarget<T> implements InjectionTarget<T> {
@Override
public void postConstruct(final T instance) {
- for (final MetaMethod<T, ?> method : postConstructMethods) {
- method.invoke(instance);
+ for (final Method method : postConstructMethods) {
+ try {
+ method.invoke(instance);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new InitializationException("Error invoking post construct method " + method.getName(), e);
+ }
}
}
@Override
public void preDestroy(final T instance) {
- for (final MetaMethod<T, ?> method : preDestroyMethods) {
- method.invoke(instance);
+ for (final Method method : preDestroyMethods) {
+ try {
+ method.invoke(instance);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new InitializationException("Error invoking pre destroy method " + method.getName(), e);
+ }
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTargetFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTargetFactory.java
new file mode 100644
index 0000000..3193c36
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjectionTargetFactory.java
@@ -0,0 +1,125 @@
+/*
+ * 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.core.config.di.impl;
+
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.BeanManager;
+import org.apache.logging.log4j.core.config.di.DefinitionException;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.InjectionTarget;
+import org.apache.logging.log4j.core.config.di.InjectionTargetFactory;
+import org.apache.logging.log4j.core.config.di.Injector;
+import org.apache.logging.log4j.plugins.di.Inject;
+import org.apache.logging.log4j.plugins.di.PostConstruct;
+import org.apache.logging.log4j.plugins.di.PreDestroy;
+import org.apache.logging.log4j.plugins.util.AnnotationUtil;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
+class DefaultInjectionTargetFactory<T> implements InjectionTargetFactory<T> {
+ private final BeanManager beanManager;
+ private final Injector injector;
+ private final Class<T> type;
+
+ DefaultInjectionTargetFactory(final BeanManager beanManager, final Injector injector, final Class<T> type) {
+ this.beanManager = beanManager;
+ this.injector = injector;
+ this.type = type;
+ }
+
+ @Override
+ public InjectionTarget<T> createInjectionTarget(final Bean<T> bean) {
+ final Constructor<T> constructor = getInjectableConstructor();
+ final Collection<InjectionPoint> injectionPoints =
+ new HashSet<>(beanManager.createExecutableInjectionPoints(constructor, bean));
+ for (final Field field : type.getDeclaredFields()) {
+ if (beanManager.isInjectable(field)) {
+ // TODO: if field is static, validate it's using an appropriate scope (singleton?)
+ field.setAccessible(true);
+ injectionPoints.add(beanManager.createFieldInjectionPoint(field, bean));
+ }
+ }
+ final List<Method> methods = new ArrayList<>();
+ for (final Method method : type.getDeclaredMethods()) {
+ methods.add(0, method);
+ if (!Modifier.isStatic(method.getModifiers()) && beanManager.isInjectable(method)) {
+ method.setAccessible(true);
+ injectionPoints.addAll(beanManager.createExecutableInjectionPoints(method, bean));
+ }
+ }
+ // FIXME: verify these methods are ordered properly
+ final List<Method> postConstructMethods = methods.stream()
+ .filter(method -> AnnotationUtil.isAnnotationPresent(method, PostConstruct.class))
+ .peek(method -> method.setAccessible(true))
+ .collect(Collectors.toList());
+ final List<Method> preDestroyMethods = methods.stream()
+ .filter(method -> AnnotationUtil.isAnnotationPresent(method, PreDestroy.class))
+ .peek(method -> method.setAccessible(true))
+ .collect(Collectors.toList());
+ return new DefaultInjectionTarget<>(injector, type, injectionPoints, constructor,
+ postConstructMethods, preDestroyMethods);
+ }
+
+ private Constructor<T> getInjectableConstructor() {
+ final Constructor<?>[] allConstructors = type.getDeclaredConstructors();
+ final List<Constructor<?>> injectConstructors = Arrays.stream(allConstructors)
+ .filter(constructor -> AnnotationUtil.isAnnotationPresent(constructor, Inject.class))
+ .collect(Collectors.toList());
+ if (injectConstructors.size() > 1) {
+ throw new DefinitionException("Found more than one constructor with @Inject for " + type);
+ }
+ if (injectConstructors.size() == 1) {
+ final Constructor<?> constructor = injectConstructors.get(0);
+ constructor.setAccessible(true);
+ return TypeUtil.cast(constructor);
+ }
+ final List<Constructor<?>> injectParameterConstructors = Arrays.stream(allConstructors)
+ .filter(constructor -> Arrays.stream(constructor.getParameters()).anyMatch(beanManager::isInjectable))
+ .collect(Collectors.toList());
+ if (injectParameterConstructors.size() > 1) {
+ throw new DefinitionException("No @Inject constructors found and remaining constructors ambiguous for " + type);
+ }
+ if (injectParameterConstructors.size() == 1) {
+ final Constructor<?> constructor = injectParameterConstructors.get(0);
+ constructor.setAccessible(true);
+ return TypeUtil.cast(constructor);
+ }
+ if (allConstructors.length == 1) {
+ final Constructor<?> constructor = allConstructors[0];
+ if (constructor.getParameterCount() == 0) {
+ constructor.setAccessible(true);
+ return TypeUtil.cast(constructor);
+ }
+ }
+ try {
+ return type.getDeclaredConstructor();
+ } catch (final NoSuchMethodException ignored) {
+ throw new DefinitionException("No candidate constructors found for " + type);
+ }
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjector.java
new file mode 100644
index 0000000..3e9bb94
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultInjector.java
@@ -0,0 +1,118 @@
+/*
+ * 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.core.config.di.impl;
+
+import org.apache.logging.log4j.core.config.di.BeanManager;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InitializationException;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.Injector;
+import org.apache.logging.log4j.plugins.di.Disposes;
+import org.apache.logging.log4j.plugins.util.AnnotationUtil;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.Collection;
+import java.util.Optional;
+
+public class DefaultInjector implements Injector {
+ private final BeanManager beanManager;
+
+ public DefaultInjector(final BeanManager beanManager) {
+ this.beanManager = beanManager;
+ }
+
+ @Override
+ public <T> T construct(final Constructor<T> constructor, final Collection<InjectionPoint> points, final InitializationContext<T> context) {
+ try {
+ return constructor.newInstance(createArguments(constructor.getParameters(), points, context, null));
+ } catch (final IllegalAccessException | InstantiationException e) {
+ throw new InitializationException("Error invoking constructor " + constructor, e);
+ } catch (final InvocationTargetException e) {
+ throw new InitializationException("Error invoking constructor " + constructor, e.getCause());
+ }
+ }
+
+ @Override
+ public <D, T> T produce(final D producerInstance, final Method producerMethod, final Collection<InjectionPoint> points, final InitializationContext<D> context) {
+ try {
+ return TypeUtil.cast(producerMethod.invoke(producerInstance, createArguments(producerMethod.getParameters(), points, context, null)));
+ } catch (IllegalAccessException e) {
+ throw new InitializationException("Error producing instance via " + producerMethod.getName(), e);
+ } catch (InvocationTargetException e) {
+ throw new InitializationException("Error producing instance via " + producerMethod.getName(), e.getCause());
+ }
+ }
+
+ @Override
+ public <T> void dispose(final T disposerInstance, final Method disposerMethod, final Collection<InjectionPoint> points, final Object instance, final InitializationContext<T> context) {
+ try {
+ disposerMethod.invoke(disposerInstance, createArguments(disposerMethod.getParameters(), points, context, instance));
+ } catch (IllegalAccessException e) {
+ throw new InitializationException("Error disposing instance via " + disposerMethod.getName(), e);
+ } catch (InvocationTargetException e) {
+ throw new InitializationException("Error disposing instance via " + disposerMethod.getName(), e.getCause());
+ }
+ }
+
+ @Override
+ public <T> void invoke(final T instance, final Method method, final Collection<InjectionPoint> points, final InitializationContext<T> context) {
+ try {
+ method.invoke(instance, createArguments(method.getParameters(), points, context, null));
+ } catch (IllegalAccessException e) {
+ throw new InitializationException("Error invoking injection method " + method.getName(), e);
+ } catch (InvocationTargetException e) {
+ throw new InitializationException("Error invoking injection method " + method.getName(), e.getCause());
+ }
+ }
+
+ @Override
+ public <D, T> void set(final D instance, final Field field, final InjectionPoint point, final InitializationContext<D> context) {
+ final Optional<T> optionalValue = beanManager.getInjectableValue(point, context);
+ optionalValue.ifPresent(value -> {
+ try {
+ field.set(instance, value);
+ } catch (IllegalAccessException e) {
+ throw new InitializationException("Error injecting value to field " + field.getName(), e);
+ }
+ });
+ }
+
+ private Object[] createArguments(final Parameter[] parameters, final Collection<InjectionPoint> injectionPoints,
+ final InitializationContext<?> context, final Object producedInstance) {
+ final Object[] arguments = new Object[parameters.length];
+ for (int i = 0; i < parameters.length; i++) {
+ final Parameter parameter = parameters[i];
+ if (AnnotationUtil.isAnnotationPresent(parameter, Disposes.class)) {
+ arguments[i] = producedInstance;
+ } else {
+ final InjectionPoint injectionPoint = injectionPoints.stream()
+ .filter(point -> parameter.equals(point.getElement()))
+ .findAny()
+ .orElseThrow();
+ arguments[i] = beanManager.getInjectableValue(injectionPoint, context)
+ .orElseThrow(() -> new UnsupportedOperationException("TODO: primitives and defaults"));
+ }
+ }
+ return arguments;
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultScopeContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultScopeContext.java
similarity index 90%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultScopeContext.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultScopeContext.java
index b0904ae..f8ca9e6 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultScopeContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DefaultScopeContext.java
@@ -15,11 +15,11 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.ScopeContext;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.ScopeContext;
import org.apache.logging.log4j.plugins.util.LazyValue;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.plugins.util.Value;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DependentScopeContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DependentScopeContext.java
similarity index 86%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DependentScopeContext.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DependentScopeContext.java
index c0394bc..c125c9c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DependentScopeContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/DependentScopeContext.java
@@ -15,12 +15,12 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.ScopeContext;
import org.apache.logging.log4j.plugins.di.DependentScoped;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.ScopeContext;
import java.lang.annotation.Annotation;
import java.util.Optional;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/FieldProducer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/FieldProducer.java
similarity index 59%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/FieldProducer.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/FieldProducer.java
index 9f094e2..40fda2c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/FieldProducer.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/FieldProducer.java
@@ -15,24 +15,26 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.BeanManager;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
class FieldProducer<P, T> extends AbstractProducer<P, T> {
- private final MetaField<P, T> field;
+ private final Field field;
- FieldProducer(final BeanManager beanManager, final Bean<P> producerBean, final MetaField<P, T> field,
- final MetaMethod<P, ?> disposerMethod, final Collection<InjectionPoint> disposerInjectionPoints) {
+ FieldProducer(final BeanManager beanManager, final Bean<P> producerBean, final Field field,
+ final Method disposerMethod, final Collection<InjectionPoint> disposerInjectionPoints) {
super(beanManager, producerBean, disposerMethod, disposerInjectionPoints);
this.field = field;
}
@@ -44,11 +46,17 @@ class FieldProducer<P, T> extends AbstractProducer<P, T> {
@Override
public T produce(final InitializationContext<T> context) {
- if (field.isStatic()) {
- return field.get(null);
+ if (Modifier.isStatic(field.getModifiers())) {
+ try {
+ return TypeUtil.cast(field.get(null));
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
}
try (final InitializationContext<P> parentContext = createContext()) {
- return field.get(getProducerInstance(parentContext));
+ return TypeUtil.cast(field.get(getProducerInstance(parentContext)));
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/FieldProducerFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/FieldProducerFactory.java
similarity index 63%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/FieldProducerFactory.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/FieldProducerFactory.java
index 7c28286..06abe54 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/FieldProducerFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/FieldProducerFactory.java
@@ -15,23 +15,22 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.Producer;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.BeanManager;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.Producer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.Collection;
-class FieldProducerFactory<D> extends AbstractProducerFactory<D> {
+class FieldProducerFactory extends AbstractProducerFactory {
private final BeanManager beanManager;
- FieldProducerFactory(final BeanManager beanManager, final Bean<D> declaringBean,
- final MetaField<D, ?> producerField, final MetaMethod<D, ?> disposerMethod,
+ FieldProducerFactory(final BeanManager beanManager, final Bean<?> declaringBean,
+ final Field producerField, final Method disposerMethod,
final Collection<InjectionPoint> disposerInjectionPoints) {
super(declaringBean, producerField, disposerMethod, disposerInjectionPoints);
this.beanManager = beanManager;
@@ -39,7 +38,7 @@ class FieldProducerFactory<D> extends AbstractProducerFactory<D> {
@Override
public <T> Producer<T> createProducer(final Bean<T> bean) {
- final MetaField<D, T> field = TypeUtil.cast(producerMember);
+ final Field field = (Field) producerMember;
return new FieldProducer<>(beanManager, declaringBean, field, disposerMethod, disposerInjectionPoints);
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/InjectionTargetBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/InjectionTargetBean.java
similarity index 77%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/InjectionTargetBean.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/InjectionTargetBean.java
index 301bcb2..0a7a63c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/InjectionTargetBean.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/InjectionTargetBean.java
@@ -15,25 +15,25 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
import org.apache.logging.log4j.core.config.di.IllegalProductException;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.InjectionTarget;
-import org.apache.logging.log4j.core.config.di.api.bean.InjectionTargetFactory;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.InjectionTarget;
+import org.apache.logging.log4j.core.config.di.InjectionTargetFactory;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Objects;
class InjectionTargetBean<T> extends AbstractBean<T> {
private final InjectionTarget<T> injectionTarget;
- InjectionTargetBean(final Variable variable, final MetaClass<T> declaringClass,
- final InjectionTargetFactory<T> factory) {
- super(variable, declaringClass);
+ InjectionTargetBean(final Collection<Type> types, final String name, final Class<? extends Annotation> scopeType,
+ final Class<T> declaringClass, final InjectionTargetFactory<T> factory) {
+ super(types, name, scopeType, declaringClass);
Objects.requireNonNull(factory);
injectionTarget = factory.createInjectionTarget(this);
}
@@ -73,7 +73,7 @@ class InjectionTargetBean<T> extends AbstractBean<T> {
return "InjectionTargetBean{" +
"types=" + getTypes() +
", scope=@" + getScopeType().getSimpleName() +
- ", qualifiers=" + getQualifiers() +
+ ", name=" + getName() +
", declaringClass=" + getDeclaringClass() +
'}';
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/MethodProducer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/MethodProducer.java
similarity index 67%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/MethodProducer.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/MethodProducer.java
index cfc37b2..676e50e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/MethodProducer.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/MethodProducer.java
@@ -15,27 +15,28 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.BeanManager;
import org.apache.logging.log4j.core.config.di.DefinitionException;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collection;
class MethodProducer<P, T> extends AbstractProducer<P, T> {
- private final MetaMethod<P, T> producerMethod;
+ private final Method producerMethod;
private final Collection<InjectionPoint> producerInjectionPoints;
MethodProducer(final BeanManager beanManager, final Bean<P> producerBean,
- final MetaMethod<P, T> producerMethod, final Collection<InjectionPoint> producerInjectionPoints,
- final MetaMethod<P, ?> disposerMethod, final Collection<InjectionPoint> disposerInjectionPoints) {
+ final Method producerMethod, final Collection<InjectionPoint> producerInjectionPoints,
+ final Method disposerMethod, final Collection<InjectionPoint> disposerInjectionPoints) {
super(beanManager, producerBean, disposerMethod, disposerInjectionPoints);
- if (!producerMethod.isStatic() && producerBean == null) {
+ if (!Modifier.isStatic(producerMethod.getModifiers()) && producerBean == null) {
throw new DefinitionException("Producer instance method must be in a bean");
}
this.producerMethod = producerMethod;
@@ -44,13 +45,13 @@ class MethodProducer<P, T> extends AbstractProducer<P, T> {
@Override
Type getType() {
- return producerMethod.getType();
+ return producerMethod.getGenericReturnType();
}
@Override
public T produce(final InitializationContext<T> context) {
try (final InitializationContext<P> parentContext = createContext()) {
- final P declaringInstance = producerMethod.isStatic() ? null : getProducerInstance(parentContext);
+ final P declaringInstance = Modifier.isStatic(producerMethod.getModifiers()) ? null : getProducerInstance(parentContext);
return injector.produce(declaringInstance, producerMethod, producerInjectionPoints, parentContext);
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/MethodProducerFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/MethodProducerFactory.java
similarity index 65%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/MethodProducerFactory.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/MethodProducerFactory.java
index c1cbf43..4556b3c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/MethodProducerFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/MethodProducerFactory.java
@@ -15,24 +15,24 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.Producer;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.BeanManager;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.Producer;
import org.apache.logging.log4j.plugins.util.TypeUtil;
+import java.lang.reflect.Method;
import java.util.Collection;
-class MethodProducerFactory<D> extends AbstractProducerFactory<D> {
+class MethodProducerFactory extends AbstractProducerFactory {
private final BeanManager beanManager;
private final Collection<InjectionPoint> producerInjectionPoints;
- MethodProducerFactory(final BeanManager beanManager, final Bean<D> declaringBean,
- final MetaMethod<D, ?> producerMethod, final Collection<InjectionPoint> producerInjectionPoints,
- final MetaMethod<D, ?> disposerMethod, final Collection<InjectionPoint> disposerInjectionPoints) {
+ MethodProducerFactory(final BeanManager beanManager, final Bean<?> declaringBean,
+ final Method producerMethod, final Collection<InjectionPoint> producerInjectionPoints,
+ final Method disposerMethod, final Collection<InjectionPoint> disposerInjectionPoints) {
super(declaringBean, producerMethod, disposerMethod, disposerInjectionPoints);
this.producerInjectionPoints = producerInjectionPoints;
this.beanManager = beanManager;
@@ -40,7 +40,7 @@ class MethodProducerFactory<D> extends AbstractProducerFactory<D> {
@Override
public <T> Producer<T> createProducer(final Bean<T> bean) {
- final MetaMethod<D, T> producerMethod = TypeUtil.cast(producerMember);
+ final Method producerMethod = TypeUtil.cast(producerMember);
return new MethodProducer<>(beanManager, declaringBean, producerMethod, producerInjectionPoints,
disposerMethod, disposerInjectionPoints);
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/OptionalBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/OptionalBean.java
similarity index 75%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/OptionalBean.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/OptionalBean.java
index aa73480..c161e7c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/OptionalBean.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/OptionalBean.java
@@ -15,14 +15,12 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
import org.apache.logging.log4j.plugins.di.DependentScoped;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.plugins.util.Value;
@@ -34,27 +32,27 @@ import java.util.Optional;
import java.util.function.BiFunction;
class OptionalBean<T> implements Bean<Optional<T>> {
- private final Type type;
- private final Qualifiers qualifiers;
+ private final Collection<Type> types;
+ private final String name;
private final Value<Optional<Bean<T>>> optionalBean;
private final BiFunction<Bean<T>, InitializationContext<?>, T> getBeanValue;
- OptionalBean(final Type type, final Qualifiers qualifiers, final Value<Optional<Bean<T>>> optionalBean,
+ OptionalBean(final Type type, final String name, final Value<Optional<Bean<T>>> optionalBean,
final BiFunction<Bean<T>, InitializationContext<?>, T> getBeanValue) {
- this.type = type;
- this.qualifiers = qualifiers;
+ this.types = TypeUtil.getTypeClosure(type);
+ this.name = name;
this.optionalBean = optionalBean;
this.getBeanValue = getBeanValue;
}
@Override
public Collection<Type> getTypes() {
- return TypeUtil.getTypeClosure(type);
+ return types;
}
@Override
- public Qualifiers getQualifiers() {
- return qualifiers;
+ public String getName() {
+ return name;
}
@Override
@@ -79,7 +77,7 @@ class OptionalBean<T> implements Bean<Optional<T>> {
}
@Override
- public MetaClass<?> getDeclaringClass() {
+ public Class<?> getDeclaringClass() {
return optionalBean.get().map(Bean::getDeclaringClass).orElse(null);
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProducerBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProducerBean.java
similarity index 78%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProducerBean.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProducerBean.java
index 11b5608..2e19977 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProducerBean.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProducerBean.java
@@ -15,16 +15,15 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
import org.apache.logging.log4j.core.config.di.IllegalProductException;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.Producer;
-import org.apache.logging.log4j.core.config.di.api.bean.ProducerFactory;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.Producer;
+import org.apache.logging.log4j.core.config.di.ProducerFactory;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Objects;
@@ -33,14 +32,15 @@ class ProducerBean<T> extends AbstractBean<T> {
private final Producer<T> producer;
private final Type type;
- ProducerBean(final Variable variable, final MetaClass<?> declaringClass, final ProducerFactory factory) {
- super(variable, declaringClass);
+ ProducerBean(final Collection<Type> types, final String name, final Class<? extends Annotation> scopeType,
+ final Class<?> declaringClass, final ProducerFactory factory) {
+ super(types, name, scopeType, declaringClass);
Objects.requireNonNull(factory);
producer = factory.createProducer(this);
if (producer instanceof AbstractProducer<?, ?>) {
type = ((AbstractProducer<?, ?>) producer).getType();
} else {
- type = variable.getTypes().iterator().next();
+ type = types.iterator().next();
}
}
@@ -82,7 +82,7 @@ class ProducerBean<T> extends AbstractBean<T> {
return "ProducerBean{" +
"types=" + getTypes() +
", scope=@" + getScopeType().getSimpleName() +
- ", qualifiers=" + getQualifiers() +
+ ", name=" + getName() +
", declaringClass=" + getDeclaringClass() +
'}';
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/SystemBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProvidedBean.java
similarity index 50%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/SystemBean.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProvidedBean.java
index 5906f0c..655b8c0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/SystemBean.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProvidedBean.java
@@ -15,54 +15,62 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.impl.bean;
+package org.apache.logging.log4j.core.config.di.impl;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.ProviderFactory;
+import org.apache.logging.log4j.plugins.di.Provider;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
-import java.util.Collections;
-abstract class SystemBean<T> implements Bean<T> {
- private final Variable variable;
+class ProvidedBean<T> implements Bean<T> {
+ private final Collection<Type> types;
+ private final Bean<Provider<T>> providerBean;
+ private final ProviderFactory<T> providerFactory;
- SystemBean(final Variable variable) {
- this.variable = variable;
+ ProvidedBean(final Type type, final Bean<Provider<T>> providerBean, final ProviderFactory<T> providerFactory) {
+ this.types = TypeUtil.getTypeClosure(type);
+ this.providerBean = providerBean;
+ this.providerFactory = providerFactory;
}
@Override
- public Collection<Type> getTypes() {
- return variable.getTypes();
+ public T create(final InitializationContext<T> context) {
+ return providerFactory.getProvider(context).get();
}
@Override
- public Qualifiers getQualifiers() {
- return variable.getQualifiers();
+ public void destroy(final T instance, final InitializationContext<T> context) {
+ context.close();
}
@Override
- public Class<? extends Annotation> getScopeType() {
- return variable.getScopeType();
+ public Collection<InjectionPoint> getInjectionPoints() {
+ return providerBean.getInjectionPoints();
}
@Override
- public Collection<InjectionPoint> getInjectionPoints() {
- return Collections.emptySet();
+ public Class<?> getDeclaringClass() {
+ return providerBean.getDeclaringClass();
}
@Override
- public MetaClass<T> getDeclaringClass() {
- throw new UnsupportedOperationException("TODO");
+ public Collection<Type> getTypes() {
+ return types;
}
@Override
- public void destroy(final T instance, final InitializationContext<T> context) {
- context.close();
+ public String getName() {
+ return providerBean.getName();
+ }
+
+ @Override
+ public Class<? extends Annotation> getScopeType() {
+ return providerBean.getScopeType();
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProviderBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProviderBean.java
new file mode 100644
index 0000000..5b00f50
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/ProviderBean.java
@@ -0,0 +1,76 @@
+/*
+ * 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.core.config.di.impl;
+
+import org.apache.logging.log4j.core.config.di.Bean;
+import org.apache.logging.log4j.core.config.di.InitializationContext;
+import org.apache.logging.log4j.core.config.di.InjectionPoint;
+import org.apache.logging.log4j.core.config.di.ProviderFactory;
+import org.apache.logging.log4j.plugins.di.Provider;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+class ProviderBean<T> implements Bean<Provider<T>> {
+ private final Collection<Type> types;
+ private final Bean<T> bean;
+ private final ProviderFactory<T> factory;
+
+ ProviderBean(final Type providerType, final Bean<T> bean, final ProviderFactory<T> factory) {
+ this.types = TypeUtil.getTypeClosure(providerType);
+ this.bean = bean;
+ this.factory = factory;
+ }
+
+ @Override
+ public Provider<T> create(final InitializationContext<Provider<T>> context) {
+ return factory.getProvider(context);
+ }
+
+ @Override
+ public void destroy(final Provider<T> instance, final InitializationContext<Provider<T>> context) {
+ context.close();
+ }
+
+ @Override
+ public Collection<InjectionPoint> getInjectionPoints() {
+ return bean.getInjectionPoints();
+ }
+
+ @Override
+ public Class<?> getDeclaringClass() {
+ return bean.getDeclaringClass();
+ }
+
+ @Override
+ public Collection<Type> getTypes() {
+ return types;
+ }
+
+ @Override
+ public String getName() {
+ return bean.getName();
+ }
+
+ @Override
+ public Class<? extends Annotation> getScopeType() {
+ return bean.getScopeType();
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjectionTargetFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjectionTargetFactory.java
deleted file mode 100644
index a0de95b..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjectionTargetFactory.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.core.config.di.impl.bean;
-
-import org.apache.logging.log4j.plugins.di.Inject;
-import org.apache.logging.log4j.plugins.di.PostConstruct;
-import org.apache.logging.log4j.plugins.di.PreDestroy;
-import org.apache.logging.log4j.core.config.di.DefinitionException;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.InjectionTarget;
-import org.apache.logging.log4j.core.config.di.api.bean.InjectionTargetFactory;
-import org.apache.logging.log4j.core.config.di.api.bean.Injector;
-import org.apache.logging.log4j.core.config.di.api.model.ElementManager;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaConstructor;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.stream.Collectors;
-
-class DefaultInjectionTargetFactory<T> implements InjectionTargetFactory<T> {
- private final ElementManager elementManager;
- private final Injector injector;
- private final MetaClass<T> type;
-
- DefaultInjectionTargetFactory(final ElementManager elementManager, final Injector injector,
- final MetaClass<T> type) {
- this.elementManager = elementManager;
- this.injector = injector;
- this.type = type;
- }
-
- @Override
- public InjectionTarget<T> createInjectionTarget(final Bean<T> bean) {
- final MetaConstructor<T> constructor = getInjectableConstructor();
- final Collection<InjectionPoint> injectionPoints =
- new HashSet<>(elementManager.createExecutableInjectionPoints(constructor, bean));
- for (final MetaField<T, ?> field : type.getFields()) {
- if (elementManager.isInjectable(field)) {
- // TODO: if field is static, validate it's using an appropriate scope (singleton?)
- injectionPoints.add(elementManager.createFieldInjectionPoint(field, bean));
- }
- }
- final List<MetaMethod<T, ?>> methods = new ArrayList<>();
- for (final MetaMethod<T, ?> method : type.getMethods()) {
- methods.add(0, method);
- if (!method.isStatic() && elementManager.isInjectable(method)) {
- injectionPoints.addAll(elementManager.createExecutableInjectionPoints(method, bean));
- }
- }
- // FIXME: verify these methods are ordered properly
- final List<MetaMethod<T, ?>> postConstructMethods = methods.stream()
- .filter(method -> method.isAnnotationPresent(PostConstruct.class))
- .collect(Collectors.toList());
- final List<MetaMethod<T, ?>> preDestroyMethods = methods.stream()
- .filter(method -> method.isAnnotationPresent(PreDestroy.class))
- .collect(Collectors.toList());
- return new DefaultInjectionTarget<>(injector, type, injectionPoints, constructor,
- postConstructMethods, preDestroyMethods);
- }
-
- private MetaConstructor<T> getInjectableConstructor() {
- final Collection<MetaConstructor<T>> allConstructors = type.getConstructors();
- final List<MetaConstructor<T>> injectConstructors = allConstructors.stream()
- .filter(constructor -> constructor.isAnnotationPresent(Inject.class))
- .collect(Collectors.toList());
- if (injectConstructors.size() > 1) {
- throw new DefinitionException("Found more than one constructor with @Inject for " + type);
- }
- if (injectConstructors.size() == 1) {
- return injectConstructors.get(0);
- }
- final List<MetaConstructor<T>> injectParameterConstructors = allConstructors.stream()
- .filter(constructor -> constructor.getParameters().stream().anyMatch(elementManager::isInjectable))
- .collect(Collectors.toList());
- if (injectParameterConstructors.size() > 1) {
- throw new DefinitionException("No @Inject constructors found and remaining constructors ambiguous for " + type);
- }
- if (injectParameterConstructors.size() == 1) {
- return injectParameterConstructors.get(0);
- }
- if (allConstructors.size() == 1) {
- final MetaConstructor<T> constructor = allConstructors.iterator().next();
- if (constructor.getParameters().size() == 0) {
- return constructor;
- }
- }
- return type.getDefaultConstructor()
- .orElseThrow(() -> new DefinitionException("No candidate constructors found for " + type));
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjector.java
deleted file mode 100644
index fde8c96..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultInjector.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.core.config.di.impl.bean;
-
-import org.apache.logging.log4j.plugins.di.Disposes;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.Injector;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaConstructor;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-import org.apache.logging.log4j.core.config.di.api.model.MetaParameter;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-
-public class DefaultInjector implements Injector {
- private final BeanManager beanManager;
-
- public DefaultInjector(final BeanManager beanManager) {
- this.beanManager = beanManager;
- }
-
- private Object[] createArguments(final List<MetaParameter> parameters,
- final Collection<InjectionPoint> injectionPoints,
- final InitializationContext<?> context, final Object producedInstance) {
- return parameters.stream().map(parameter ->
- parameter.isAnnotationPresent(Disposes.class) ? producedInstance : injectionPoints.stream()
- .filter(point -> parameter.equals(point.getElement()))
- .findAny()
- .flatMap(point -> beanManager.getInjectableValue(point, context))
- .orElseThrow(() -> new UnsupportedOperationException("TODO: primitives and defaults")))
- .toArray();
- }
-
- @Override
- public <T> T construct(final MetaConstructor<T> constructor, final Collection<InjectionPoint> points,
- final InitializationContext<T> context) {
- return constructor.construct(createArguments(constructor.getParameters(), points, context, null));
- }
-
- @Override
- public <D, T> T produce(final D producerInstance, final MetaMethod<D, T> producerMethod,
- final Collection<InjectionPoint> points, final InitializationContext<D> context) {
- return producerMethod.invoke(producerInstance, createArguments(producerMethod.getParameters(), points, context, null));
- }
-
- @Override
- public <T> void dispose(final T disposerInstance, final MetaMethod<T, ?> disposerMethod,
- final Collection<InjectionPoint> points, final Object instance,
- final InitializationContext<T> context) {
- disposerMethod.invoke(disposerInstance, createArguments(disposerMethod.getParameters(), points, context, instance));
- }
-
- @Override
- public <T> void invoke(final T instance, final MetaMethod<T, ?> method, final Collection<InjectionPoint> points,
- final InitializationContext<T> context) {
- method.invoke(instance, createArguments(method.getParameters(), points, context, null));
- }
-
- @Override
- public <D, T> void set(final D instance, final MetaField<D, T> field, final InjectionPoint point,
- final InitializationContext<D> context) {
- final Optional<T> optionalValue = beanManager.getInjectableValue(point, context);
- optionalValue.ifPresent(value -> field.set(instance, value));
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProvidedBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProvidedBean.java
deleted file mode 100644
index 6a8b388..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProvidedBean.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.core.config.di.impl.bean;
-
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.ProviderFactory;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
-
-class ProvidedBean<T> extends SystemBean<T> {
- private final ProviderFactory<T> providerFactory;
-
- ProvidedBean(final Variable variable, final ProviderFactory<T> providerFactory) {
- super(variable);
- this.providerFactory = providerFactory;
- }
-
- @Override
- public T create(final InitializationContext<T> context) {
- return providerFactory.getProvider(context).get();
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProviderBean.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProviderBean.java
deleted file mode 100644
index 80c519b..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/bean/ProviderBean.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.core.config.di.impl.bean;
-
-import org.apache.logging.log4j.plugins.di.Provider;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.ProviderFactory;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
-
-class ProviderBean<T> extends SystemBean<Provider<T>> {
- private final ProviderFactory<T> providerFactory;
-
- ProviderBean(final Variable variable, final ProviderFactory<T> providerFactory) {
- super(variable);
- this.providerFactory = providerFactory;
- }
-
- @Override
- public Provider<T> create(final InitializationContext<Provider<T>> context) {
- return providerFactory.getProvider(context);
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/AbstractMetaExecutable.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/AbstractMetaExecutable.java
deleted file mode 100644
index 4060dec..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/AbstractMetaExecutable.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaExecutable;
-import org.apache.logging.log4j.core.config.di.api.model.MetaParameter;
-
-import java.lang.reflect.Executable;
-import java.lang.reflect.Parameter;
-import java.util.ArrayList;
-import java.util.List;
-
-abstract class AbstractMetaExecutable<D, T> extends AbstractMetaMember<D, T> implements MetaExecutable<D> {
- private final List<MetaParameter> parameters;
-
- AbstractMetaExecutable(final MetaClass<D> declaringClass, final Executable executable, final MetaClass<T> type) {
- super(declaringClass, executable, type);
- parameters = new ArrayList<>(executable.getParameterCount());
- for (final Parameter parameter : executable.getParameters()) {
- parameters.add(new DefaultMetaParameter(parameter));
- }
- }
-
- @Override
- public List<MetaParameter> getParameters() {
- return parameters;
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/AbstractMetaMember.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/AbstractMetaMember.java
deleted file mode 100644
index 4a5d72b..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/AbstractMetaMember.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotation;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMember;
-
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Member;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
-import java.util.Collection;
-
-abstract class AbstractMetaMember<D, T> implements MetaMember<D> {
- private final String name;
- private final Collection<MetaAnnotation> annotations;
- private final MetaClass<D> declaringClass;
- private final MetaClass<T> type;
- private final boolean isStatic;
-
- AbstractMetaMember(final MetaClass<D> declaringClass, final Member member, final MetaClass<T> type) {
- this.name = member.getName();
- this.annotations = DefaultMetaAnnotation.fromAnnotations(((AnnotatedElement) member).getAnnotations());
- this.declaringClass = declaringClass;
- this.type = type;
- this.isStatic = Modifier.isStatic(member.getModifiers());
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public Collection<MetaAnnotation> getAnnotations() {
- return annotations;
- }
-
- @Override
- public Type getType() {
- return type.getType();
- }
-
- @Override
- public Collection<Type> getTypeClosure() {
- return type.getTypeClosure();
- }
-
- @Override
- public MetaClass<D> getDeclaringClass() {
- return declaringClass;
- }
-
- @Override
- public boolean isStatic() {
- return isStatic;
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultElementManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultElementManager.java
deleted file mode 100644
index ed8da5c..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultElementManager.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.plugins.di.AnnotationAlias;
-import org.apache.logging.log4j.plugins.di.Default;
-import org.apache.logging.log4j.plugins.di.DependentScoped;
-import org.apache.logging.log4j.plugins.di.Ignore;
-import org.apache.logging.log4j.plugins.di.Named;
-import org.apache.logging.log4j.plugins.di.QualifierType;
-import org.apache.logging.log4j.plugins.di.ScopeType;
-import org.apache.logging.log4j.plugins.internal.util.BeanUtils;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.model.ElementManager;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotation;
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotationElement;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaElement;
-import org.apache.logging.log4j.core.config.di.api.model.MetaExecutable;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-import org.apache.logging.log4j.core.config.di.api.model.MetaParameter;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-import org.apache.logging.log4j.core.config.di.api.model.Variable;
-import org.apache.logging.log4j.plugins.util.Cache;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-import org.apache.logging.log4j.plugins.util.WeakCache;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Objects;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-public class DefaultElementManager implements ElementManager {
-
- private static final Pattern BEAN_METHOD = Pattern.compile("^(is|get|set)([A-Z].*)$");
-
- private enum AnnotationType {
- QUALIFIER, SCOPE, 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 == AnnotationAlias.class) {
- type = ((AnnotationAlias) annotation).value();
- }
- if (type == QualifierType.class) {
- return AnnotationType.QUALIFIER;
- }
- if (type == ScopeType.class) {
- return AnnotationType.SCOPE;
- }
- }
- return AnnotationType.UNKNOWN;
- });
-
- @Override
- public <T> MetaClass<T> getMetaClass(final Class<T> clazz) {
- return classCache.get(clazz);
- }
-
- @Override
- public boolean isQualifierType(final Class<? extends Annotation> annotationType) {
- return getAnnotationType(annotationType) == AnnotationType.QUALIFIER;
- }
-
- @Override
- public Qualifiers getQualifiers(final MetaElement element) {
- final String elementName = element.getName();
- final String defaultNamedValue;
- if (element instanceof MetaMethod<?, ?>) {
- final Matcher matcher = BEAN_METHOD.matcher(elementName);
- if (matcher.matches()) {
- defaultNamedValue = BeanUtils.decapitalize(matcher.group(2));
- } else {
- defaultNamedValue = elementName;
- }
- } else if (element instanceof MetaClass<?>) {
- defaultNamedValue = BeanUtils.decapitalize(((MetaClass<?>) element).getJavaClass().getSimpleName());
- } else {
- defaultNamedValue = elementName;
- }
- final Set<MetaAnnotation> qualifiers = element.getAnnotations().stream()
- .filter(annotation -> isQualifierType(annotation.getAnnotationType()))
- .map(annotation -> transformQualifier(annotation, defaultNamedValue))
- .collect(Collectors.toCollection(LinkedHashSet::new));
- if (qualifiers.stream().map(MetaAnnotation::getAnnotationType).noneMatch(type -> type != Named.class)) {
- qualifiers.add(new DefaultMetaAnnotation(Default.class, Collections.emptySet()));
- }
- return Qualifiers.fromAnnotations(qualifiers);
- }
-
- private static MetaAnnotation transformQualifier(final MetaAnnotation annotation, final String defaultNamedValue) {
- final Class<? extends Annotation> annotationType = annotation.getAnnotationType();
- final Set<MetaAnnotationElement<?>> elements = annotation.getAnnotationElements().stream()
- .filter(element -> !element.isAnnotationPresent(Ignore.class))
- .map(element -> {
- if (annotationType == Named.class && element.getName().equals("value")) {
- final MetaAnnotationElement<String> namedValue = TypeUtil.cast(element);
- final String value = namedValue.getValue();
- if (value.isEmpty()) {
- return namedValue.withNewValue(defaultNamedValue);
- } else {
- return namedValue;
- }
- } else {
- return element;
- }
- })
- .collect(Collectors.toCollection(LinkedHashSet::new));
- return new DefaultMetaAnnotation(annotationType, elements);
- }
-
- private Class<? extends Annotation> getScopeType(final MetaElement element) {
- final Collection<Class<? extends Annotation>> scopeTypes = filterScopeTypes(element.getAnnotations());
- return scopeTypes.isEmpty() ? DependentScoped.class : scopeTypes.iterator().next();
- }
-
- private Collection<Class<? extends Annotation>> filterScopeTypes(final Collection<MetaAnnotation> annotations) {
- // only expect at most one scope
- final Collection<Class<? extends Annotation>> scopeTypes = new LinkedHashSet<>(1);
- for (final MetaAnnotation annotation : annotations) {
- final Class<? extends Annotation> annotationType = annotation.getAnnotationType();
- if (isScopeType(annotationType)) {
- scopeTypes.add(annotationType);
- }
- }
- return Collections.unmodifiableCollection(scopeTypes);
- }
-
- private boolean isScopeType(final Class<? extends Annotation> annotationType) {
- return getAnnotationType(annotationType) == AnnotationType.SCOPE;
- }
-
- private AnnotationType getAnnotationType(final Class<? extends Annotation> annotationType) {
- return annotationTypeCache.get(annotationType);
- }
-
- @Override
- public <D> InjectionPoint createFieldInjectionPoint(final MetaField<D, ?> field, final Bean<D> owner) {
- Objects.requireNonNull(field);
- final Qualifiers qualifiers = getQualifiers(field);
- return new DefaultInjectionPoint(field.getType(), qualifiers, owner, field, field);
- }
-
- @Override
- public <D> InjectionPoint createParameterInjectionPoint(final MetaExecutable<D> executable,
- final MetaParameter parameter,
- final Bean<D> owner) {
- Objects.requireNonNull(executable);
- Objects.requireNonNull(parameter);
- final Qualifiers qualifiers = getQualifiers(parameter);
- return new DefaultInjectionPoint(parameter.getType(), qualifiers, owner, executable, parameter);
- }
-
- @Override
- public Variable createVariable(final MetaElement element) {
- Objects.requireNonNull(element);
- return createVariable(element, getQualifiers(element));
- }
-
- private Variable createVariable(final MetaElement element, final Qualifiers qualifiers) {
- final Collection<Type> types = element.getTypeClosure();
- final Class<? extends Annotation> scopeType = getScopeType(element);
- return new DefaultVariable(types, qualifiers, scopeType);
- }
-
- @Override
- public void close() {
- classCache.close();
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultInjectionPoint.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultInjectionPoint.java
deleted file mode 100644
index 0ecefe8..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultInjectionPoint.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaElement;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMember;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-
-import java.lang.reflect.Type;
-import java.util.Objects;
-import java.util.Optional;
-
-class DefaultInjectionPoint implements InjectionPoint {
- private final Type type;
- private final Qualifiers qualifiers;
- private final Bean<?> bean;
- private final MetaMember<?> member;
- private final MetaElement element;
-
- DefaultInjectionPoint(final Type type, final Qualifiers qualifiers, final Bean<?> bean,
- final MetaMember<?> member, final MetaElement element) {
- this.type = type;
- this.qualifiers = qualifiers;
- this.bean = bean;
- this.member = member;
- this.element = element;
- }
-
- @Override
- public Type getType() {
- return type;
- }
-
- @Override
- public Qualifiers getQualifiers() {
- return qualifiers;
- }
-
- @Override
- public Optional<Bean<?>> getBean() {
- return Optional.ofNullable(bean);
- }
-
- @Override
- public MetaMember<?> getMember() {
- return member;
- }
-
- @Override
- public MetaElement getElement() {
- return element;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- final DefaultInjectionPoint that = (DefaultInjectionPoint) o;
- return qualifiers.equals(that.qualifiers) &&
- Objects.equals(bean, that.bean) &&
- member.equals(that.member) &&
- element.equals(that.element) &&
- type.equals(that.type);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(qualifiers, bean, member, element, type);
- }
-
- @Override
- public String toString() {
- return "DefaultInjectionPoint{" +
- "type=" + type.getTypeName() +
- ", qualifiers=" + qualifiers +
- ", bean=" + bean +
- ", member=" + member +
- ", element=" + element +
- '}';
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaAnnotation.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaAnnotation.java
deleted file mode 100644
index 62d8636..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaAnnotation.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.plugins.di.AnnotationAlias;
-import org.apache.logging.log4j.plugins.di.Named;
-import org.apache.logging.log4j.core.config.di.InitializationException;
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotation;
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotationElement;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-class DefaultMetaAnnotation implements MetaAnnotation {
-
- static List<MetaAnnotation> fromAnnotations(final Annotation... annotations) {
- if (annotations.length == 0) {
- return Collections.emptyList();
- }
- final List<MetaAnnotation> metaAnnotations = new ArrayList<>(annotations.length);
- for (final Annotation annotation : annotations) {
- metaAnnotations.add(fromAnnotation(annotation));
- }
- return Collections.unmodifiableList(metaAnnotations);
- }
-
- private static DefaultMetaAnnotation fromAnnotation(final Annotation annotation) {
- final Class<? extends Annotation> originalType = annotation.annotationType();
- final Method[] annotationElements = originalType.getDeclaredMethods();
- final Set<MetaAnnotationElement<?>> elements = new LinkedHashSet<>(annotationElements.length);
- for (final Method element : annotationElements) {
- final String name;
- final Named named = element.getAnnotation(Named.class);
- if (named != null && !named.value().isEmpty()) {
- name = named.value();
- } else {
- name = element.getName();
- }
- final Object value = getAnnotationElementValue(annotation, element);
- elements.add(new DefaultMetaAnnotationElement<>(name, value, fromAnnotations(element.getAnnotations())));
- }
- final AnnotationAlias alias = originalType.getAnnotation(AnnotationAlias.class);
- final Class<? extends Annotation> annotationType = alias != null ? alias.value() : originalType;
- return new DefaultMetaAnnotation(annotationType, elements);
- }
-
- private static Object getAnnotationElementValue(final Annotation annotation, final Method element) {
- try {
- return element.invoke(annotation);
- } catch (final IllegalAccessException e) {
- throw new InitializationException("Cannot access element " + element.getName() + " of annotation " + annotation, e);
- } catch (final InvocationTargetException e) {
- throw new InitializationException("Cannot access element " + element.getName() + " of annotation " + annotation,
- e.getCause());
- }
- }
-
- private final Class<? extends Annotation> annotationType;
- private final Set<MetaAnnotationElement<?>> elements;
-
- DefaultMetaAnnotation(final Class<? extends Annotation> annotationType, final Set<MetaAnnotationElement<?>> elements) {
- this.annotationType = annotationType;
- this.elements = Collections.unmodifiableSet(elements);
- }
-
- @Override
- public Class<? extends Annotation> getAnnotationType() {
- return annotationType;
- }
-
- @Override
- public Collection<MetaAnnotationElement<?>> getAnnotationElements() {
- return elements;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- final DefaultMetaAnnotation that = (DefaultMetaAnnotation) o;
- return annotationType.equals(that.annotationType) &&
- elements.equals(that.elements);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(annotationType, elements);
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaAnnotationElement.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaAnnotationElement.java
deleted file mode 100644
index 266be71..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaAnnotationElement.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotation;
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotationElement;
-
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Objects;
-
-class DefaultMetaAnnotationElement<T> implements MetaAnnotationElement<T> {
- private final String name;
- private final T value;
- private final Collection<MetaAnnotation> annotations;
-
- DefaultMetaAnnotationElement(final String name, final T value, final Collection<MetaAnnotation> annotations) {
- this.name = name;
- this.value = value;
- this.annotations = Collections.unmodifiableCollection(annotations);
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public Type getType() {
- return value.getClass();
- }
-
- @Override
- public Collection<MetaAnnotation> getAnnotations() {
- return annotations;
- }
-
- @Override
- public T getValue() {
- return value;
- }
-
- @Override
- public MetaAnnotationElement<T> withNewValue(final T value) {
- return new DefaultMetaAnnotationElement<>(name, value, annotations);
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- final DefaultMetaAnnotationElement<?> that = (DefaultMetaAnnotationElement<?>) o;
- return name.equals(that.name) && value.equals(that.value);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(name, value);
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaClass.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaClass.java
deleted file mode 100644
index 3f956cc..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaClass.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotation;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaConstructor;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-import org.apache.logging.log4j.plugins.util.LazyValue;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-import org.apache.logging.log4j.plugins.util.Value;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-class DefaultMetaClass<T> implements MetaClass<T> {
-
- 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) {
- return new DefaultMetaClass<>(baseType, javaClass, TypeUtil.getTypeClosure(baseType), DefaultMetaAnnotation.fromAnnotations(annotations));
- }
-
- private final Type baseType;
- private final Class<T> javaClass;
- private final Collection<Type> typeClosure;
- private final Collection<MetaAnnotation> annotations;
- private final Value<Collection<MetaConstructor<T>>> constructors;
- private final Value<Collection<MetaMethod<T, ?>>> methods;
- private final Value<Collection<MetaField<T, ?>>> fields;
-
- private DefaultMetaClass(final Type baseType, final Class<T> javaClass, final Collection<Type> typeClosure,
- final Collection<MetaAnnotation> annotations) {
- this.baseType = baseType;
- this.javaClass = javaClass;
- this.typeClosure = typeClosure;
- this.annotations = annotations;
- constructors = LazyValue.forSupplier(() -> Arrays.stream(javaClass.getConstructors())
- .<Constructor<T>>map(TypeUtil::cast)
- .map(this::getMetaConstructor)
- .collect(Collectors.toList()));
- methods = LazyValue.forSupplier(() -> Arrays.stream(javaClass.getMethods())
- .map(this::getMetaMethod)
- .collect(Collectors.toList()));
- fields = LazyValue.forSupplier(() -> TypeUtil.getAllDeclaredFields(javaClass).stream()
- .map(this::getMetaField)
- .collect(Collectors.toList()));
- }
-
- @Override
- public String getName() {
- return baseType.getTypeName();
- }
-
- @Override
- public Collection<MetaAnnotation> getAnnotations() {
- return annotations;
- }
-
- @Override
- public Type getType() {
- return baseType;
- }
-
- @Override
- public Collection<Type> getTypeClosure() {
- return typeClosure;
- }
-
- @Override
- public Class<T> getJavaClass() {
- return javaClass;
- }
-
- @Override
- public Collection<MetaConstructor<T>> getConstructors() {
- return constructors.get();
- }
-
- @Override
- public MetaConstructor<T> getMetaConstructor(final Constructor<T> constructor) {
- return new DefaultMetaConstructor<>(this, constructor);
- }
-
- @Override
- public Optional<MetaConstructor<T>> getDefaultConstructor() {
- try {
- return Optional.of(new DefaultMetaConstructor<>(this, javaClass.getConstructor()));
- } catch (final NoSuchMethodException ignored) {
- return Optional.empty();
- }
- }
-
- @Override
- public Collection<MetaMethod<T, ?>> getMethods() {
- return methods.get();
- }
-
- @Override
- public <U> MetaMethod<T, U> getMetaMethod(final Method method) {
- return new DefaultMetaMethod<>(this, method);
- }
-
- @Override
- public Collection<MetaField<T, ?>> getFields() {
- return fields.get();
- }
-
- @Override
- public <U> MetaField<T, U> getMetaField(final Field field) {
- return new DefaultMetaField<>(this, field);
- }
-
- @Override
- public String toString() {
- return baseType.getTypeName();
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaConstructor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaConstructor.java
deleted file mode 100644
index b118b52..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaConstructor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.InitializationException;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaConstructor;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-class DefaultMetaConstructor<T> extends AbstractMetaExecutable<T, T> implements MetaConstructor<T> {
- private final Constructor<T> constructor;
-
- DefaultMetaConstructor(final MetaClass<T> metaClass, final Constructor<T> constructor) {
- super(metaClass, constructor, metaClass);
- this.constructor = constructor;
- }
-
- @Override
- public T construct(final Object... args) {
- try {
- return constructor.newInstance(args);
- } catch (final IllegalAccessException | InstantiationException e) {
- throw new InitializationException("Error invoking constructor " + constructor, e);
- } catch (final InvocationTargetException e) {
- throw new InitializationException("Error invoking constructor " + constructor, e.getCause());
- }
- }
-
- @Override
- public String toString() {
- return constructor.toGenericString();
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaField.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaField.java
deleted file mode 100644
index 5031219..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaField.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.InitializationException;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaField;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-
-import java.lang.reflect.Field;
-
-public class DefaultMetaField<D, T> extends AbstractMetaMember<D, T> implements MetaField<D, T> {
- private final Field field;
-
- DefaultMetaField(final MetaClass<D> declaringClass, final Field field) {
- super(declaringClass, field, DefaultMetaClass.newMetaClass(field.getGenericType(), TypeUtil.cast(field.getType())));
- this.field = field;
- }
-
- @Override
- public T get(final D target) {
- try {
- return TypeUtil.cast(field.get(target));
- } catch (final IllegalAccessException e) {
- throw new InitializationException("Error getting field value of " + field + " from target " + target, e);
- }
- }
-
- @Override
- public void set(final D target, final T value) {
- try {
- field.set(target, value);
- } catch (final IllegalAccessException e) {
- throw new InitializationException("Error setting field value of " + field + " on target " + target, e);
- }
- }
-
- @Override
- public String toString() {
- return field.toGenericString();
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaMethod.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaMethod.java
deleted file mode 100644
index dbe7b35..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaMethod.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.InitializationException;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-class DefaultMetaMethod<D, T> extends AbstractMetaExecutable<D, T> implements MetaMethod<D, T> {
- private final Method method;
-
- DefaultMetaMethod(final MetaClass<D> declaringClass, final Method method) {
- super(declaringClass, method, DefaultMetaClass.newMetaClass(method.getGenericReturnType(), TypeUtil.cast(method.getReturnType())));
- this.method = method;
- }
-
- @Override
- public T invoke(final D target, final Object... args) {
- try {
- return TypeUtil.cast(method.invoke(target, args));
- } catch (final IllegalAccessException e) {
- throw new InitializationException("Error invoking method: " + method + " on target " + target, e);
- } catch (final InvocationTargetException e) {
- throw new InitializationException("Error invoking method: " + method + " on target " + target, e.getCause());
- }
- }
-
- @Override
- public String toString() {
- return method.toGenericString();
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaParameter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaParameter.java
deleted file mode 100644
index b85f41f..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultMetaParameter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.api.model.MetaAnnotation;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaParameter;
-
-import java.lang.reflect.Parameter;
-import java.lang.reflect.Type;
-import java.util.Collection;
-
-class DefaultMetaParameter implements MetaParameter {
- private final String name;
- private final MetaClass<?> parameterClass;
- private final String toString;
-
- DefaultMetaParameter(final Parameter parameter) {
- name = parameter.getName();
- parameterClass = DefaultMetaClass.newMetaClass(
- parameter.getParameterizedType(), parameter.getType(), parameter.getAnnotations());
- toString = parameter.toString();
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public Collection<MetaAnnotation> getAnnotations() {
- return parameterClass.getAnnotations();
- }
-
- @Override
- public Type getType() {
- return parameterClass.getType();
- }
-
- @Override
- public Collection<Type> getTypeClosure() {
- return parameterClass.getTypeClosure();
- }
-
- @Override
- public String toString() {
- return toString;
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultVariable.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultVariable.java
deleted file mode 100644
index f527f09..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/impl/model/DefaultVariable.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.core.config.di.impl.model;
-
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-import org.apache.logging.log4j.core.config.di.api.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 {
- private final Collection<Type> types;
- private final Qualifiers qualifiers;
- private 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);
- }
-
- @Override
- public Collection<Type> getTypes() {
- return Collections.unmodifiableCollection(types);
- }
-
- @Override
- public Qualifiers getQualifiers() {
- return qualifiers;
- }
-
- @Override
- public Class<? extends Annotation> getScopeType() {
- return scopeType;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- final DefaultVariable that = (DefaultVariable) o;
- return types.equals(that.types) &&
- qualifiers.equals(that.qualifiers) &&
- scopeType.equals(that.scopeType);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(types, qualifiers, scopeType);
- }
-
- @Override
- public String toString() {
- return "DefaultVariable{" +
- "types=" + types +
- ", qualifiers=" + qualifiers +
- ", scope=" + scopeType +
- '}';
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAliases.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAliases.java
index 2b06df6..09cac10 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAliases.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAliases.java
@@ -16,7 +16,14 @@
*/
package org.apache.logging.log4j.core.config.plugins;
-import java.lang.annotation.*;
+import org.apache.logging.log4j.core.config.plugins.util.PluginAliasesProvider;
+import org.apache.logging.log4j.plugins.name.AliasesProvider;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
* Identifies a list of aliases for a Plugin, PluginAttribute, or PluginBuilderAttribute.
@@ -25,6 +32,7 @@ import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.TYPE, ElementType.FIELD})
+@AliasesProvider(PluginAliasesProvider.class)
public @interface PluginAliases {
String[] value();
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java
index e75de09..a4d62d3 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginAttribute.java
@@ -16,8 +16,10 @@
*/
package org.apache.logging.log4j.core.config.plugins;
+import org.apache.logging.log4j.core.config.plugins.util.PluginAttributeNameProvider;
import org.apache.logging.log4j.core.config.plugins.visitors.PluginAttributeVisitor;
import org.apache.logging.log4j.plugins.inject.InjectorStrategy;
+import org.apache.logging.log4j.plugins.name.NameProvider;
import org.apache.logging.log4j.util.Strings;
import java.lang.annotation.Documented;
@@ -38,6 +40,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@InjectorStrategy(PluginAttributeVisitor.class)
+@NameProvider(PluginAttributeNameProvider.class)
public @interface PluginAttribute {
/**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderAttribute.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderAttribute.java
index 17ad890..a7b4a8b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderAttribute.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginBuilderAttribute.java
@@ -17,8 +17,10 @@
package org.apache.logging.log4j.core.config.plugins;
+import org.apache.logging.log4j.core.config.plugins.util.PluginBuilderAttributeNameProvider;
import org.apache.logging.log4j.core.config.plugins.visitors.PluginBuilderAttributeVisitor;
import org.apache.logging.log4j.plugins.inject.InjectorStrategy;
+import org.apache.logging.log4j.plugins.name.NameProvider;
import org.apache.logging.log4j.util.Strings;
import java.lang.annotation.Documented;
@@ -35,6 +37,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@InjectorStrategy(PluginBuilderAttributeVisitor.class)
+@NameProvider(PluginBuilderAttributeNameProvider.class)
public @interface PluginBuilderAttribute {
/**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java
index 5c4f41e..b832da9 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginElement.java
@@ -16,8 +16,10 @@
*/
package org.apache.logging.log4j.core.config.plugins;
+import org.apache.logging.log4j.core.config.plugins.util.PluginElementNameProvider;
import org.apache.logging.log4j.core.config.plugins.visitors.PluginElementVisitor;
import org.apache.logging.log4j.plugins.inject.InjectorStrategy;
+import org.apache.logging.log4j.plugins.name.NameProvider;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
@@ -33,6 +35,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@InjectorStrategy(PluginElementVisitor.class)
+@NameProvider(PluginElementNameProvider.class)
public @interface PluginElement {
/**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java
index 9389aa9..bcbadc0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/PluginValue.java
@@ -16,8 +16,10 @@
*/
package org.apache.logging.log4j.core.config.plugins;
+import org.apache.logging.log4j.core.config.plugins.util.PluginValueNameProvider;
import org.apache.logging.log4j.core.config.plugins.visitors.PluginValueVisitor;
import org.apache.logging.log4j.plugins.inject.InjectorStrategy;
+import org.apache.logging.log4j.plugins.name.NameProvider;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
@@ -36,6 +38,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@InjectorStrategy(PluginValueVisitor.class)
+@NameProvider(PluginValueNameProvider.class)
public @interface PluginValue {
String value();
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaExecutable.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginAliasesProvider.java
similarity index 63%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaExecutable.java
rename to log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginAliasesProvider.java
index 650ffb6..6ca1276 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaExecutable.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginAliasesProvider.java
@@ -15,10 +15,17 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.model;
+package org.apache.logging.log4j.core.config.plugins.util;
+import org.apache.logging.log4j.core.config.plugins.PluginAliases;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
+
+import java.util.Collection;
import java.util.List;
-public interface MetaExecutable<T> extends MetaMember<T> {
- List<MetaParameter> getParameters();
+public class PluginAliasesProvider implements AnnotatedElementAliasesProvider<PluginAliases> {
+ @Override
+ public Collection<String> getAliases(final PluginAliases annotation) {
+ return List.of(annotation.value());
+ }
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginAttributeNameProvider.java
similarity index 60%
copy from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java
copy to log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginAttributeNameProvider.java
index 55cab85..33e3b89 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginAttributeNameProvider.java
@@ -15,14 +15,17 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di;
+package org.apache.logging.log4j.core.config.plugins.util;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
+import org.apache.logging.log4j.util.Strings;
-import java.util.Collection;
+import java.util.Optional;
-public class AmbiguousBeanException extends ResolutionException {
- public AmbiguousBeanException(final Collection<? extends Bean<?>> beans, final String target) {
- super("Found " + beans.size() + " ambiguous beans for " + target + ": " + beans);
+public class PluginAttributeNameProvider implements AnnotatedElementNameProvider<PluginAttribute> {
+ @Override
+ public Optional<String> getSpecifiedName(final PluginAttribute annotation) {
+ return Strings.trimToOptional(annotation.value());
}
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Named.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilderAttributeNameProvider.java
similarity index 60%
copy from log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Named.java
copy to log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilderAttributeNameProvider.java
index bff71ca..9c37232 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Named.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilderAttributeNameProvider.java
@@ -15,21 +15,17 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.plugins.di;
+package org.apache.logging.log4j.core.config.plugins.util;
-import org.apache.logging.log4j.plugins.name.NameProvider;
-import org.apache.logging.log4j.plugins.name.NamedQualifierNameProvider;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
import org.apache.logging.log4j.util.Strings;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import java.util.Optional;
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@QualifierType
-@NameProvider(NamedQualifierNameProvider.class)
-public @interface Named {
- // TODO: consider supporting String[] for listing aliases? (or see @Alternative?)
- String value() default Strings.EMPTY;
+public class PluginBuilderAttributeNameProvider implements AnnotatedElementNameProvider<PluginBuilderAttribute> {
+ @Override
+ public Optional<String> getSpecifiedName(final PluginBuilderAttribute annotation) {
+ return Strings.trimToOptional(annotation.value());
+ }
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginElementNameProvider.java
similarity index 60%
copy from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java
copy to log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginElementNameProvider.java
index 55cab85..e450895 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/AmbiguousBeanException.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginElementNameProvider.java
@@ -15,14 +15,17 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di;
+package org.apache.logging.log4j.core.config.plugins.util;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
+import org.apache.logging.log4j.util.Strings;
-import java.util.Collection;
+import java.util.Optional;
-public class AmbiguousBeanException extends ResolutionException {
- public AmbiguousBeanException(final Collection<? extends Bean<?>> beans, final String target) {
- super("Found " + beans.size() + " ambiguous beans for " + target + ": " + beans);
+public class PluginElementNameProvider implements AnnotatedElementNameProvider<PluginElement> {
+ @Override
+ public Optional<String> getSpecifiedName(final PluginElement annotation) {
+ return Strings.trimToOptional(annotation.value());
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/UnsatisfiedBeanException.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginValueNameProvider.java
similarity index 61%
copy from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/UnsatisfiedBeanException.java
copy to log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginValueNameProvider.java
index 12f6ab3..12dc26b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/UnsatisfiedBeanException.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginValueNameProvider.java
@@ -15,18 +15,17 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di;
+package org.apache.logging.log4j.core.config.plugins.util;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
+import org.apache.logging.log4j.core.config.plugins.PluginValue;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
+import org.apache.logging.log4j.util.Strings;
-import java.lang.reflect.Type;
+import java.util.Optional;
-public class UnsatisfiedBeanException extends ResolutionException {
- public UnsatisfiedBeanException(final InjectionPoint point) {
- super("No beans found for " + point);
- }
-
- public UnsatisfiedBeanException(final Type type) {
- super("No beans found for type " + type);
+public class PluginValueNameProvider implements AnnotatedElementNameProvider<PluginValue> {
+ @Override
+ public Optional<String> getSpecifiedName(final PluginValue annotation) {
+ return Strings.trimToOptional(annotation.value());
}
}
diff --git a/log4j-core/src/main/java9/module-info.java b/log4j-core/src/main/java9/module-info.java
index b78bddf..d4b3d93 100644
--- a/log4j-core/src/main/java9/module-info.java
+++ b/log4j-core/src/main/java9/module-info.java
@@ -30,10 +30,7 @@ module org.apache.logging.log4j.core {
exports org.apache.logging.log4j.core.config.builder.impl;
exports org.apache.logging.log4j.core.config.composite;
exports org.apache.logging.log4j.core.config.di;
- exports org.apache.logging.log4j.core.config.di.api.bean;
- exports org.apache.logging.log4j.core.config.di.api.model;
- exports org.apache.logging.log4j.core.config.di.impl.bean;
- exports org.apache.logging.log4j.core.config.di.impl.model;
+ exports org.apache.logging.log4j.core.config.di.impl;
exports org.apache.logging.log4j.core.config.json;
exports org.apache.logging.log4j.core.config.plugins;
exports org.apache.logging.log4j.core.config.plugins.convert;
diff --git a/log4j-core/src/test/java-test/org/apache/logging/log4j/core/test/junit/BeanJUnit4Runner.java b/log4j-core/src/test/java-test/org/apache/logging/log4j/core/test/junit/BeanJUnit4Runner.java
deleted file mode 100644
index 151ea3f..0000000
--- a/log4j-core/src/test/java-test/org/apache/logging/log4j/core/test/junit/BeanJUnit4Runner.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.core.test.junit;
-
-import org.apache.logging.log4j.core.config.di.DefinitionException;
-import org.apache.logging.log4j.core.config.di.UnsatisfiedBeanException;
-import org.apache.logging.log4j.core.config.di.api.bean.Bean;
-import org.apache.logging.log4j.core.config.di.api.bean.BeanManager;
-import org.apache.logging.log4j.core.config.di.api.bean.InitializationContext;
-import org.apache.logging.log4j.core.config.di.api.bean.Injector;
-import org.apache.logging.log4j.core.config.di.api.model.ElementManager;
-import org.apache.logging.log4j.core.config.di.api.model.InjectionPoint;
-import org.apache.logging.log4j.core.config.di.api.model.MetaClass;
-import org.apache.logging.log4j.core.config.di.api.model.MetaMethod;
-import org.apache.logging.log4j.core.config.di.api.model.Qualifiers;
-import org.apache.logging.log4j.core.config.di.impl.bean.DefaultBeanManager;
-import org.apache.logging.log4j.core.config.di.impl.bean.DefaultInjector;
-import org.apache.logging.log4j.core.config.di.impl.model.DefaultElementManager;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-import org.junit.Test;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.Statement;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * JUnit 4 test runner that integrates with {@link BeanManager} to create test instances and inject test parameters.
- * Beans to load can be specified with the {@link WithBeans} annotation on the class or method. The test class itself
- * must be a bean. Each test method creates a new BeanManager, loads beans annotated on the test class, creates a
- * test instance, loads beans annotated on the test method, then injects values into the test method parameters, invoking
- * that method.
- */
-public class BeanJUnit4Runner extends BlockJUnit4ClassRunner {
- private ElementManager elementManager;
- private MetaClass<?> testMetaClass;
-
- private BeanManager beanManager;
- private Injector injector;
- private Bean<?> testClassBean;
-
- public BeanJUnit4Runner(final Class<?> clazz) throws InitializationError {
- super(clazz);
- }
-
- @Override
- protected void collectInitializationErrors(final List<Throwable> errors) {
- // this must come before call to super to allow use in validateConstructor()
- elementManager = new DefaultElementManager();
- testMetaClass = elementManager.getMetaClass(getTestClass().getJavaClass());
- super.collectInitializationErrors(errors);
- }
-
- @Override
- protected void validateConstructor(final List<Throwable> errors) {
- if (!elementManager.isInjectable(testMetaClass)) {
- errors.add(new DefinitionException(testMetaClass + " does not have any injectable constructors"));
- }
- }
-
- @Override
- protected void validateTestMethods(final List<Throwable> errors) {
- for (final FrameworkMethod method : getTestClass().getAnnotatedMethods(Test.class)) {
- method.validatePublicVoid(false, errors);
- }
- }
-
- @Override
- protected Object createTest() throws Exception {
- return createTestInstance();
- }
-
- private <T> T createTestInstance() {
- beanManager = new DefaultBeanManager(elementManager);
- injector = new DefaultInjector(beanManager);
- final WithBeans testClassBeans = getTestClass().getAnnotation(WithBeans.class);
- if (testClassBeans != null) {
- beanManager.loadAndValidateBeans(testClassBeans.value());
- }
- final Class<T> testClass = TypeUtil.cast(getTestClass().getJavaClass());
- beanManager.loadAndValidateBeans(testClass);
- final Bean<T> testClassBean = beanManager.<T>getBean(testClass, Qualifiers.DEFAULT)
- .orElseThrow(() -> new UnsatisfiedBeanException(testClass));
- this.testClassBean = testClassBean;
- return beanManager.getValue(testClassBean, beanManager.createInitializationContext(null));
- }
-
- @Override
- protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
- return genericMethodInvoker(method, test);
- }
-
- private <T> Statement genericMethodInvoker(final FrameworkMethod method, final T testInstance) {
- final Bean<T> testClassBean = TypeUtil.cast(this.testClassBean);
- return new Statement() {
- @Override
- public void evaluate() throws Throwable {
- try (final InitializationContext<T> context = beanManager.createInitializationContext(testClassBean)) {
- final WithBeans methodBeans = method.getAnnotation(WithBeans.class);
- if (methodBeans != null) {
- beanManager.loadAndValidateBeans(methodBeans.value());
- }
- final Class<T> testClass = TypeUtil.cast(getTestClass().getJavaClass());
- final MetaClass<T> metaClass = elementManager.getMetaClass(testClass);
- final MetaMethod<T, Void> metaMethod = metaClass.getMetaMethod(method.getMethod());
- final Collection<InjectionPoint> points =
- elementManager.createExecutableInjectionPoints(metaMethod, testClassBean);
- injector.invoke(testInstance, metaMethod, points, context);
- } finally {
- beanManager.close();
- beanManager = null;
- }
- }
- };
- }
-}
diff --git a/log4j-core/src/test/java-test/org/apache/logging/log4j/core/test/junit/WithBeans.java b/log4j-core/src/test/java-test/org/apache/logging/log4j/core/test/junit/WithBeans.java
deleted file mode 100644
index 694ccc0..0000000
--- a/log4j-core/src/test/java-test/org/apache/logging/log4j/core/test/junit/WithBeans.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.core.test.junit;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Lists bean classes to load for a unit test.
- *
- * @see BeanJUnit4Runner
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Documented
-public @interface WithBeans {
- Class<?>[] value();
-}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/BeanManagerTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/BeanManagerTest.java
new file mode 100644
index 0000000..ec6364b
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/BeanManagerTest.java
@@ -0,0 +1,479 @@
+/*
+ * 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.core.config.di;
+
+import org.apache.logging.log4j.core.config.di.impl.DefaultBeanManager;
+import org.apache.logging.log4j.plugins.di.Inject;
+import org.apache.logging.log4j.plugins.di.Named;
+import org.apache.logging.log4j.plugins.di.PostConstruct;
+import org.apache.logging.log4j.plugins.di.PreDestroy;
+import org.apache.logging.log4j.plugins.di.Produces;
+import org.apache.logging.log4j.plugins.di.Provider;
+import org.apache.logging.log4j.plugins.di.SingletonScoped;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class BeanManagerTest {
+
+ final BeanManager beanManager = new DefaultBeanManager();
+
+ @AfterEach
+ void tearDown() {
+ beanManager.close();
+ }
+
+ @SingletonScoped
+ static class SingletonBean {
+ }
+
+ @Test
+ void defaultConstructorInjection() {
+ beanManager.loadAndValidateBeans(SingletonBean.class);
+ final Bean<SingletonBean> bean = beanManager.getDefaultBean(SingletonBean.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final SingletonBean value = beanManager.getValue(bean, context);
+ assertNotNull(value);
+ }
+ }
+
+ @Produces
+ @Named
+ @SingletonScoped
+ static SingletonBean getSingleton() {
+ return new SingletonBean();
+ }
+
+ static class ParameterInjectionBean {
+ final SingletonBean first;
+ SingletonBean second;
+ SingletonBean singletonBean;
+
+ @Inject
+ ParameterInjectionBean(@Named("singleton") final SingletonBean first) {
+ this.first = first;
+ }
+
+ @Inject
+ void parameterInjection(@Named("singleton") final SingletonBean second, final SingletonBean singletonBean) {
+ this.second = second;
+ this.singletonBean = singletonBean;
+ }
+ }
+
+ @Test
+ void parameterInjection() {
+ beanManager.loadAndValidateBeans(getClass(), SingletonBean.class, ParameterInjectionBean.class);
+ final Bean<ParameterInjectionBean> bean = beanManager.getDefaultBean(ParameterInjectionBean.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final ParameterInjectionBean value = beanManager.getValue(bean, context);
+ assertNotNull(value);
+ assertNotNull(value.first);
+ assertNotNull(value.second);
+ assertNotNull(value.singletonBean);
+ assertSame(value.first, value.second);
+ assertNotSame(value.first, value.singletonBean);
+ }
+ }
+
+ static class FieldInjectionBean {
+ @Inject
+ @Named("singleton")
+ private SingletonBean singletonBean;
+
+ @Inject
+ private SingletonBean singleton;
+
+ @Named("primary name")
+ @Named("first alias")
+ @Named("singleton")
+ @Named("one more alias")
+ private SingletonBean bean;
+ }
+
+ @Test
+ void fieldInjection() {
+ beanManager.loadAndValidateBeans(getClass(), SingletonBean.class, FieldInjectionBean.class);
+ final Bean<FieldInjectionBean> bean = beanManager.getDefaultBean(FieldInjectionBean.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final FieldInjectionBean value = beanManager.getValue(bean, context);
+ assertNotNull(value.singletonBean);
+ assertNotNull(value.singleton);
+ assertNotNull(value.bean);
+ assertNotSame(value.singletonBean, value.singleton);
+ assertSame(value.singletonBean, value.bean);
+ }
+ }
+
+ static class ImplicitConstructorBean {
+ private final SingletonBean singleton;
+
+ ImplicitConstructorBean(@Named final SingletonBean singleton) {
+ this.singleton = singleton;
+ }
+ }
+
+ @Test
+ void implicitConstructorInjection() {
+ beanManager.loadAndValidateBeans(getClass(), SingletonBean.class, ImplicitConstructorBean.class);
+ final Bean<ImplicitConstructorBean> bean = beanManager.getDefaultBean(ImplicitConstructorBean.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final ImplicitConstructorBean value = beanManager.getValue(bean, context);
+ assertNotNull(value.singleton);
+ }
+ }
+
+ static class ExplicitConstructorBean {
+ private final SingletonBean singleton;
+
+ @Inject
+ ExplicitConstructorBean(final SingletonBean singleton) {
+ this.singleton = singleton;
+ }
+ }
+
+ @Test
+ void explicitConstructorInjection() {
+ beanManager.loadAndValidateBeans(getClass(), SingletonBean.class, ExplicitConstructorBean.class);
+ final Bean<ExplicitConstructorBean> bean = beanManager.getDefaultBean(ExplicitConstructorBean.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final ExplicitConstructorBean value = beanManager.getValue(bean, context);
+ assertNotNull(value.singleton);
+ }
+ }
+
+ @Named("dep")
+ static class DependentBean {
+ }
+
+ static class ScopeTestingBean {
+ @Named("dep") DependentBean field;
+
+ DependentBean first;
+ DependentBean second;
+
+ ScopeTestingBean(@Named("dep") DependentBean first, @Named("dep") DependentBean second) {
+ this.first = first;
+ this.second = second;
+ }
+ }
+
+ @Test
+ void dependentScope() {
+ beanManager.loadAndValidateBeans(DependentBean.class, ScopeTestingBean.class);
+ final Bean<ScopeTestingBean> bean = beanManager.getDefaultBean(ScopeTestingBean.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final ScopeTestingBean value = beanManager.getValue(bean, context);
+ assertNotSame(value.field, value.first);
+ assertNotSame(value.field, value.second);
+ assertNotSame(value.first, value.second);
+ }
+ }
+
+ static class StaticMethodProducerBean {
+ final DependentBean first;
+ final DependentBean second;
+ final SingletonBean singletonBean;
+
+ private StaticMethodProducerBean(final DependentBean first, final DependentBean second, final SingletonBean singletonBean) {
+ this.first = first;
+ this.second = second;
+ this.singletonBean = singletonBean;
+ }
+
+ @Produces
+ @Named("static")
+ static StaticMethodProducerBean create(@Named("dep") final DependentBean first,
+ @Named("dep") final DependentBean second,
+ @Named final SingletonBean singleton) {
+ return new StaticMethodProducerBean(first, second, singleton);
+ }
+ }
+
+ @Test
+ void staticMethodProducer() {
+ beanManager.loadAndValidateBeans(getClass(), SingletonBean.class, DependentBean.class, StaticMethodProducerBean.class);
+ final Bean<StaticMethodProducerBean> bean = beanManager.getNamedBean(StaticMethodProducerBean.class, "static").orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final StaticMethodProducerBean value = beanManager.getValue(bean, context);
+ assertNotNull(value.first);
+ assertNotNull(value.second);
+ assertNotSame(value.first, value.second);
+ assertNotNull(value.singletonBean);
+ }
+ }
+
+ static class ProviderClassProducerBean {
+ final DependentBean first;
+ final DependentBean second;
+ final SingletonBean singletonBean;
+
+ private ProviderClassProducerBean(final DependentBean first, final DependentBean second, final SingletonBean singletonBean) {
+ this.first = first;
+ this.second = second;
+ this.singletonBean = singletonBean;
+ }
+
+ @Named("builder")
+ static class Builder implements Provider<ProviderClassProducerBean> {
+ private DependentBean dep;
+ private DependentBean bean;
+ private SingletonBean singleton;
+
+ @Inject
+ public Builder setDep(@Named final DependentBean dep) {
+ this.dep = dep;
+ return this;
+ }
+
+ @Inject
+ public Builder setBean(@Named("dep") final DependentBean bean) {
+ this.bean = bean;
+ return this;
+ }
+
+ @Inject
+ public Builder setSingleton(@Named final SingletonBean singleton) {
+ this.singleton = singleton;
+ return this;
+ }
+
+ @Override
+ public ProviderClassProducerBean get() {
+ return new ProviderClassProducerBean(dep, bean, singleton);
+ }
+ }
+ }
+
+ @Test
+ void providerClassProducer() {
+ beanManager.loadAndValidateBeans(getClass(), SingletonBean.class, DependentBean.class, ProviderClassProducerBean.Builder.class);
+ final Bean<ProviderClassProducerBean> bean = beanManager.getNamedBean(ProviderClassProducerBean.class, "builder").orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final ProviderClassProducerBean value = beanManager.getValue(bean, context);
+ assertNotNull(value.first);
+ assertNotNull(value.second);
+ assertNotSame(value.first, value.second);
+ assertNotNull(value.singletonBean);
+ }
+ }
+
+ static class ProviderParameterInjectionBean {
+ final DependentBean alpha;
+ final DependentBean beta;
+ final DependentBean gamma;
+
+ @Inject
+ ProviderParameterInjectionBean(@Named("dep") final Provider<DependentBean> beanProvider) {
+ alpha = beanProvider.get();
+ beta = beanProvider.get();
+ gamma = beanProvider.get();
+ }
+ }
+
+ @Test
+ void providerParameterInjection() {
+ beanManager.loadAndValidateBeans(DependentBean.class, ProviderParameterInjectionBean.class);
+ final Bean<ProviderParameterInjectionBean> bean = beanManager.getDefaultBean(ProviderParameterInjectionBean.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final ProviderParameterInjectionBean value = beanManager.getValue(bean, context);
+ assertNotSame(value.alpha, value.beta);
+ assertNotSame(value.beta, value.gamma);
+ assertNotSame(value.gamma, value.alpha);
+ }
+ }
+
+ static class SimpleBean {
+ }
+
+ static class OptionalInjection {
+ @Inject
+ private Optional<SimpleBean> field;
+ private final SimpleBean arg;
+ private SimpleBean methodArg;
+
+ @Inject
+ OptionalInjection(final Optional<SimpleBean> arg) {
+ this.arg = arg.orElse(null);
+ }
+
+ @Inject
+ void setMethodArg(final Optional<SimpleBean> methodArg) {
+ this.methodArg = methodArg.orElse(null);
+ }
+ }
+
+ @Test
+ void optionalInjectionWhenBeanIsAbsent() {
+ beanManager.loadAndValidateBeans(OptionalInjection.class);
+ final Bean<OptionalInjection> bean = beanManager.getDefaultBean(OptionalInjection.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final OptionalInjection value = beanManager.getValue(bean, context);
+ assertTrue(value.field.isEmpty());
+ assertNull(value.arg);
+ assertNull(value.methodArg);
+ }
+ }
+
+ @Test
+ void optionalInjectionWhenBeanIsPresent() {
+ beanManager.loadAndValidateBeans(SimpleBean.class, OptionalInjection.class);
+ final Bean<OptionalInjection> bean = beanManager.getDefaultBean(OptionalInjection.class).orElseThrow();
+ try (final var context = beanManager.createInitializationContext(null)) {
+ final OptionalInjection value = beanManager.getValue(bean, context);
+ assertTrue(value.field.isPresent());
+ assertNotNull(value.arg);
+ assertNotNull(value.methodArg);
+ }
+ }
+
+ @SingletonScoped
+ static class IdGenerator {
+ private final AtomicInteger current = new AtomicInteger();
+
+ @Produces
+ public int nextId() {
+ return current.incrementAndGet();
+ }
+
+ public int getCurrent() {
+ return current.get();
+ }
+ }
+
+ static class PostConstructInjection {
+ private int one;
+ private int two;
+ @Inject
+ private int three;
+ private int four;
+ private int five;
+ private int six;
+ @Inject
+ private IdGenerator idGenerator;
+
+ @Inject
+ public PostConstructInjection(final int a, final int b) {
+ one = a;
+ two = b;
+ }
+
+ @PostConstruct
+ public void init() {
+ six = idGenerator.nextId();
+ }
+
+ @Inject
+ public void setValue(final int value, final Integer otherValue) {
+ four = value;
+ five = otherValue;
+ }
+
+ @PreDestroy
+ public void destroy() {
+ idGenerator.nextId();
+ one = -1;
+ }
+ }
+
+ @Test
+ void postConstructPreDestroy() {
+ beanManager.loadAndValidateBeans(IdGenerator.class, PostConstructInjection.class);
+ final Bean<IdGenerator> idGeneratorBean = beanManager.getDefaultBean(IdGenerator.class).orElseThrow();
+ try (var context = beanManager.createInitializationContext(null)) {
+ final IdGenerator idGenerator = beanManager.getValue(idGeneratorBean, context);
+ assertEquals(0, idGenerator.getCurrent());
+ final Bean<PostConstructInjection> bean = beanManager.getDefaultBean(PostConstructInjection.class).orElseThrow();
+ final PostConstructInjection value = beanManager.getValue(bean, context);
+ assertEquals(1, value.one);
+ assertEquals(2, value.two);
+ assertEquals(3, value.three);
+ assertEquals(4, value.four);
+ assertEquals(5, value.five);
+ assertEquals(6, value.six);
+ bean.destroy(value, context.createDependentContext(bean));
+ assertEquals(7, idGenerator.getCurrent());
+ assertEquals(-1, value.one);
+ }
+ }
+
+ @SingletonScoped
+ static class DeferredSingleton {
+ private final int id;
+
+ @Inject
+ public DeferredSingleton(final int id) {
+ this.id = id;
+ }
+ }
+
+ static class DeferredDependent {
+ private final int id;
+
+ @Inject
+ public DeferredDependent(final int id) {
+ this.id = id;
+ }
+ }
+
+ static class DeferredProviderBean {
+ @Inject
+ IdGenerator generator;
+
+ @Inject
+ Provider<DeferredSingleton> singletonProvider;
+
+ @Inject
+ Provider<DeferredDependent> dependentProvider;
+ }
+
+ @Test
+ void testDeferredProviderNotInvokedUntilInitiallyProvided() {
+ beanManager.loadAndValidateBeans(IdGenerator.class, DeferredSingleton.class, DeferredDependent.class, DeferredProviderBean.class);
+ final Bean<DeferredProviderBean> bean = beanManager.getDefaultBean(DeferredProviderBean.class).orElseThrow();
+ try (var context = beanManager.createInitializationContext(null)) {
+ final DeferredProviderBean value = beanManager.getValue(bean, context);
+ final IdGenerator generator = value.generator;
+ final Provider<DeferredSingleton> singletonProvider = value.singletonProvider;
+ final Provider<DeferredDependent> dependentProvider = value.dependentProvider;
+ assertEquals(0, generator.getCurrent());
+ assertEquals(1, singletonProvider.get().id);
+ assertEquals(1, generator.getCurrent());
+ assertEquals(1, singletonProvider.get().id);
+ assertEquals(1, generator.getCurrent());
+ assertEquals(2, dependentProvider.get().id);
+ assertEquals(2, generator.getCurrent());
+ assertEquals(1, singletonProvider.get().id);
+ assertEquals(2, generator.getCurrent());
+ assertEquals(3, dependentProvider.get().id);
+ assertEquals(3, generator.getCurrent());
+ assertEquals(1, singletonProvider.get().id);
+ assertEquals(3, generator.getCurrent());
+ assertEquals(4, dependentProvider.get().id);
+ assertEquals(4, generator.getCurrent());
+ }
+ }
+
+ // TODO: add tests for other supported injection scenarios
+ // TODO: add tests for hierarchical scopes
+ // TODO: add tests for @Named alias annotations like @PluginAttribute == @Named
+}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/InjectionPointTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/InjectionPointTest.java
new file mode 100644
index 0000000..60e89e4
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/InjectionPointTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.core.config.di;
+
+import org.apache.logging.log4j.core.config.di.impl.DefaultBeanManager;
+import org.apache.logging.log4j.plugins.di.Inject;
+import org.apache.logging.log4j.plugins.di.Named;
+import org.apache.logging.log4j.plugins.di.SingletonScoped;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class InjectionPointTest {
+
+ @SingletonScoped
+ static class SingletonInstance {
+ }
+
+ static class FieldBean {
+ @Inject
+ static SingletonInstance instance;
+
+ @Inject
+ SingletonInstance singletonInstance;
+ }
+
+ static class GenericBean<T> {
+ @Inject
+ SingletonInstance instance;
+
+ @Inject
+ T value;
+ }
+
+ static class ConstructedBean {
+ private final String alpha;
+ private final String beta;
+ private final String gamma;
+
+ ConstructedBean(@Named final String alpha, @Named final String beta, @Named final String gamma) {
+ this.alpha = alpha;
+ this.beta = beta;
+ this.gamma = gamma;
+ }
+ }
+
+ static class MethodBean {
+ private SingletonInstance instance;
+
+ @Inject
+ public void setInstance(final SingletonInstance instance) {
+ this.instance = instance;
+ }
+ }
+
+ private final BeanManager beanManager = new DefaultBeanManager();
+
+ @AfterEach
+ void tearDown() {
+ beanManager.close();
+ }
+
+ @Test
+ void fieldInjectionPoints() throws Exception {
+ final Field staticField = FieldBean.class.getDeclaredField("instance");
+ final InjectionPoint staticInjectionPoint = beanManager.createFieldInjectionPoint(staticField, null);
+ final Field instanceField = FieldBean.class.getDeclaredField("singletonInstance");
+ final InjectionPoint instanceInjectionPoint = beanManager.createFieldInjectionPoint(instanceField, null);
+ assertAll(
+ () -> assertEquals(Strings.EMPTY, staticInjectionPoint.getName()),
+ () -> assertEquals(SingletonInstance.class, staticInjectionPoint.getType()),
+ () -> assertEquals(staticField, staticInjectionPoint.getElement()),
+ () -> assertEquals(staticField, staticInjectionPoint.getMember()),
+ () -> assertTrue(staticInjectionPoint.getBean().isEmpty()),
+ () -> assertEquals(Strings.EMPTY, instanceInjectionPoint.getName()),
+ () -> assertEquals(SingletonInstance.class, instanceInjectionPoint.getType()),
+ () -> assertEquals(instanceField, instanceInjectionPoint.getElement()),
+ () -> assertEquals(instanceField, instanceInjectionPoint.getMember()),
+ () -> assertTrue(instanceInjectionPoint.getBean().isEmpty())
+ );
+ }
+
+ @Test
+ void constructorInjectionPoints() throws Exception {
+ final Constructor<ConstructedBean> constructor = ConstructedBean.class.getDeclaredConstructor(String.class, String.class, String.class);
+ final Collection<InjectionPoint> injectionPoints = beanManager.createExecutableInjectionPoints(constructor, null);
+ final List<InjectionPoint> sorted = injectionPoints.stream()
+ .sorted(Comparator.comparing(InjectionPoint::getName))
+ .collect(Collectors.toList());
+ assertEquals(3, sorted.size());
+ final InjectionPoint alpha = sorted.get(0);
+ final InjectionPoint beta = sorted.get(1);
+ final InjectionPoint gamma = sorted.get(2);
+ assertAll(
+ () -> assertEquals("alpha", alpha.getName()),
+ () -> assertEquals("beta", beta.getName()),
+ () -> assertEquals("gamma", gamma.getName())
+ );
+ }
+
+ @Test
+ void methodInjectionPoints() throws Exception {
+ final Method method = MethodBean.class.getDeclaredMethod("setInstance", SingletonInstance.class);
+ final Collection<InjectionPoint> points = beanManager.createExecutableInjectionPoints(method, null);
+ assertEquals(1, points.size());
+ final InjectionPoint injectionPoint = points.iterator().next();
+ assertEquals(Strings.EMPTY, injectionPoint.getName());
+ }
+}
\ No newline at end of file
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/InjectionTargetTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/InjectionTargetTest.java
new file mode 100644
index 0000000..c06d2ad
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/InjectionTargetTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.core.config.di;
+
+import org.apache.logging.log4j.core.config.di.impl.DefaultBeanManager;
+import org.apache.logging.log4j.plugins.di.Inject;
+import org.apache.logging.log4j.plugins.di.Named;
+import org.apache.logging.log4j.plugins.di.Produces;
+import org.apache.logging.log4j.plugins.di.SingletonScoped;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class InjectionTargetTest {
+
+ @SingletonScoped
+ static class SingletonBean {
+ }
+
+ @Produces
+ @Named
+ @SingletonScoped
+ static SingletonBean foo() {
+ return new SingletonBean();
+ }
+
+ static class InjectedSingletonBeans {
+ private final SingletonBean foo;
+ private SingletonBean bar;
+ private SingletonBean bean;
+
+ @Inject
+ InjectedSingletonBeans(@Named final SingletonBean foo) {
+ this.foo = foo;
+ }
+
+ @Inject
+ void setBar(final SingletonBean bar) {
+ this.bar = bar;
+ }
+
+ @Inject
+ void setBean(@Named("foo") final SingletonBean bean) {
+ this.bean = bean;
+ }
+ }
+
+ @Test
+ void singletonBeans() {
+ final BeanManager beanManager = new DefaultBeanManager();
+ beanManager.loadAndValidateBeans(SingletonBean.class, getClass(), InjectedSingletonBeans.class);
+ final Optional<Bean<InjectedSingletonBeans>> bean = beanManager.getDefaultBean(InjectedSingletonBeans.class);
+ assertTrue(bean.isPresent());
+ try (InitializationContext<InjectedSingletonBeans> context = beanManager.createInitializationContext(null)) {
+ final InjectedSingletonBeans beans = beanManager.getValue(bean.orElseThrow(), context);
+ assertNotNull(beans);
+ assertNotNull(beans.foo);
+ assertNotNull(beans.bar);
+ assertNotSame(beans.foo, beans.bar);
+ assertSame(beans.foo, beans.bean);
+ }
+ }
+
+ @Named("empty")
+ static class EmptyBean {
+ }
+
+ static class DependentBeans {
+ private final EmptyBean first;
+ private final EmptyBean second;
+
+ DependentBeans(@Named("empty") final EmptyBean first, @Named("empty") final EmptyBean second) {
+ this.first = first;
+ this.second = second;
+ }
+ }
+
+ @Test
+ void dependentBeans() {
+ final BeanManager beanManager = new DefaultBeanManager();
+ beanManager.loadAndValidateBeans(DependentBeans.class, EmptyBean.class);
+ final Optional<Bean<DependentBeans>> bean = beanManager.getDefaultBean(DependentBeans.class);
+ try (InitializationContext<DependentBeans> context = beanManager.createInitializationContext(null)) {
+ final DependentBeans beans = beanManager.getValue(bean.orElseThrow(), context);
+ assertNotNull(beans);
+ assertNotSame(beans.first, beans.second);
+ }
+ }
+}
\ No newline at end of file
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultBeanManagerTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultBeanManagerTest.java
deleted file mode 100644
index 32a328f..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/di/impl/bean/DefaultBeanManagerTest.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * 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.core.config.di.impl.bean;
-
-import org.apache.logging.log4j.core.test.junit.BeanJUnit4Runner;
-import org.apache.logging.log4j.core.test.junit.WithBeans;
-import org.apache.logging.log4j.plugins.di.Default;
-import org.apache.logging.log4j.plugins.di.Inject;
-import org.apache.logging.log4j.plugins.di.Named;
-import org.apache.logging.log4j.plugins.di.PostConstruct;
-import org.apache.logging.log4j.plugins.di.Produces;
-import org.apache.logging.log4j.plugins.di.Provider;
-import org.apache.logging.log4j.plugins.di.QualifierType;
-import org.apache.logging.log4j.plugins.di.SingletonScoped;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.junit.Assert.*;
-
-@RunWith(BeanJUnit4Runner.class)
-public class DefaultBeanManagerTest {
-
- @Retention(RetentionPolicy.RUNTIME)
- @QualifierType
- public @interface Run {
- }
-
- @Produces
- @SingletonScoped
- public String globalString = "global string value";
-
- @Produces
- @SingletonScoped
- @Run
- public String testString() {
- return "test string value";
- }
-
- @Test
- public void testParameterInjection(final String unqualified, @Run final String qualified) {
- assertEquals(globalString, unqualified);
- assertEquals(testString(), qualified);
- }
-
- public static class FieldInjection {
- @Inject
- private String unqualified;
- @Run
- private String implicitQualified;
- @Default
- private String implicitDefault;
- }
-
- @WithBeans(FieldInjection.class)
- @Test
- public void testFieldInjection(final FieldInjection instance) {
- assertEquals(globalString, instance.unqualified);
- assertEquals(testString(), instance.implicitQualified);
- assertEquals(globalString, instance.implicitDefault);
- }
-
- public static class ExplicitConstructorInjection {
- private final String first;
- private final String second;
-
- @Inject
- public ExplicitConstructorInjection(@Default final String first, @Run final String second) {
- this.first = first;
- this.second = second;
- }
- }
-
- @WithBeans(ExplicitConstructorInjection.class)
- @Test
- public void testExplicitConstructorInjection(final ExplicitConstructorInjection instance) {
- assertEquals(globalString, instance.first);
- assertEquals(testString(), instance.second);
- }
-
- public static class ImplicitConstructorInjection {
- private final String first;
- private final String second;
-
- public ImplicitConstructorInjection(final String first, @Run final String second) {
- this.first = first;
- this.second = second;
- }
- }
-
- @WithBeans(ImplicitConstructorInjection.class)
- @Test
- public void testImplicitConstructorInjection(final ImplicitConstructorInjection instance) {
- assertEquals(globalString, instance.first);
- assertEquals(testString(), instance.second);
- }
-
- public static class DefaultConstructorInjection {
- }
-
- @WithBeans(DefaultConstructorInjection.class)
- @Test
- public void testNoArgsConstructorInjection(final DefaultConstructorInjection instance) {
- assertNotNull(instance);
- }
-
- @WithBeans(DefaultConstructorInjection.class)
- @Test
- public void testDependentScopeDifferentInstances(final DefaultConstructorInjection first,
- final DefaultConstructorInjection second) {
- assertNotSame(first, second);
- }
-
- @SingletonScoped
- public static class SingletonInjection {
- }
-
- @WithBeans(SingletonInjection.class)
- @Test
- public void testSingletonScopeSameInstances(final SingletonInjection first, final SingletonInjection second) {
- assertSame(first, second);
- }
-
- public static class StaticMethodProduction {
- private final String first;
- private final String second;
-
- private StaticMethodProduction(final String first, final String second) {
- this.first = first;
- this.second = second;
- }
-
- @Produces
- public static StaticMethodProduction produce(final String first, @Run final String second) {
- return new StaticMethodProduction(first, second);
- }
- }
-
- @WithBeans(StaticMethodProduction.class)
- @Test
- public void testStaticMethodProduction(final StaticMethodProduction instance) {
- assertEquals(globalString, instance.first);
- assertEquals(testString(), instance.second);
- }
-
- public static class ProviderProvidedProduction {
- private final String first;
- private final String second;
-
- private ProviderProvidedProduction(final String first, final String second) {
- this.first = first;
- this.second = second;
- }
-
- public static class Builder implements Provider<ProviderProvidedProduction> {
- private String first;
- private String second;
-
- @Inject
- public Builder withFirst(final String first) {
- this.first = first;
- return this;
- }
-
- @Inject
- public Builder withSecond(@Run final String second) {
- this.second = second;
- return this;
- }
-
- @Override
- public ProviderProvidedProduction get() {
- return new ProviderProvidedProduction(first, second);
- }
- }
- }
-
- @WithBeans(ProviderProvidedProduction.Builder.class)
- @Test
- public void testProviderProvidedProduction(final ProviderProvidedProduction instance) {
- assertEquals(globalString, instance.first);
- assertEquals(testString(), instance.second);
- }
-
- @Test
- public void testProviderInjection(final Provider<String> stringProvider) {
- assertEquals(globalString, stringProvider.get());
- }
-
- @Test
- public void testQualifiedProviderInjection(@Run final Provider<String> stringProvider) {
- assertEquals(testString(), stringProvider.get());
- }
-
- @Test
- public void testOptionalInjectionWhenNoBeanProvided(final Optional<DefaultConstructorInjection> instance) {
- assertFalse(instance.isPresent());
- }
-
- @WithBeans(DefaultConstructorInjection.class)
- @Test
- public void testOptionalInjectionWhenBeanProvided(final Optional<DefaultConstructorInjection> instance) {
- assertTrue(instance.isPresent());
- }
-
- @SingletonScoped
- public static class IdGenerator {
- private final AtomicInteger current = new AtomicInteger();
-
- @Produces
- public int nextId() {
- return current.incrementAndGet();
- }
-
- public int getCurrent() {
- return current.get();
- }
- }
-
- public static class PostConstructInjection {
- private int one;
- private int two;
- @Inject
- private int three;
- private int four;
- private int five;
- private int six;
- @Inject
- private IdGenerator idGenerator;
-
- @Inject
- public PostConstructInjection(final int a, final int b) {
- one = a;
- two = b;
- }
-
- @PostConstruct
- public void init() {
- six = idGenerator.nextId();
- }
-
- @Inject
- public void setValue(final int value, final Integer otherValue) {
- four = value;
- five = otherValue;
- }
- }
-
- @WithBeans({IdGenerator.class, PostConstructInjection.class})
- @Test
- public void testPostConstructInjection(final PostConstructInjection instance) {
- assertEquals(1, instance.one);
- assertEquals(2, instance.two);
- assertEquals(3, instance.three);
- assertEquals(4, instance.four);
- assertEquals(5, instance.five);
- assertEquals(6, instance.six);
- }
-
- public static class DefaultNamedQualifier {
- @Produces
- @Named
- public String methodProducer() {
- return "foobar";
- }
-
- @Produces
- @Named
- public short getAnswer() {
- return 42;
- }
- }
-
- @Named
- public static class FooBar {
- }
-
- @WithBeans({DefaultNamedQualifier.class, FooBar.class})
- @Test
- public void testDefaultNamedQualifier(@Named final String methodProducer,
- @Named("methodProducer") final String alternative,
- @Named final short answer, @Named final FooBar fooBar) {
- assertEquals("foobar", methodProducer);
- assertEquals(methodProducer, alternative);
- assertEquals(42, answer);
- assertNotNull(fooBar);
- }
-
- @SingletonScoped
- public static class DeferredSingleton {
- private final int id;
-
- @Inject
- public DeferredSingleton(final int id) {
- this.id = id;
- }
- }
-
- public static class DeferredDependent {
- private final int id;
-
- @Inject
- public DeferredDependent(final int id) {
- this.id = id;
- }
- }
-
- @WithBeans({IdGenerator.class, DeferredSingleton.class, DeferredDependent.class})
- @Test
- public void testDeferredProviderNotInvokedUntilInitiallyProvided(final IdGenerator generator,
- final Provider<DeferredSingleton> singletonProvider,
- final Provider<DeferredDependent> dependentProvider) {
- assertEquals(0, generator.getCurrent());
- assertEquals(1, singletonProvider.get().id);
- assertEquals(1, generator.getCurrent());
- assertEquals(1, singletonProvider.get().id);
- assertEquals(1, generator.getCurrent());
- assertEquals(2, dependentProvider.get().id);
- assertEquals(2, generator.getCurrent());
- assertEquals(1, singletonProvider.get().id);
- assertEquals(2, generator.getCurrent());
- assertEquals(3, dependentProvider.get().id);
- assertEquals(3, generator.getCurrent());
- assertEquals(1, singletonProvider.get().id);
- assertEquals(3, generator.getCurrent());
- assertEquals(4, dependentProvider.get().id);
- assertEquals(4, generator.getCurrent());
- }
-
- // TODO: add tests for other supported injection scenarios
- // TODO: add tests for hierarchical scopes
- // TODO: add tests for @Named alias annotations like @PluginAttribute == @Named
-}
\ No newline at end of file
diff --git a/log4j-core/src/test/java9/module-info.java b/log4j-core/src/test/java9/module-info.java
index b7d1787..773cd42 100644
--- a/log4j-core/src/test/java9/module-info.java
+++ b/log4j-core/src/test/java9/module-info.java
@@ -27,7 +27,8 @@ open module org.apache.logging.log4j.core {
exports org.apache.logging.log4j.core.config;
exports org.apache.logging.log4j.core.config.arbiters;
exports org.apache.logging.log4j.core.config.builder;
- exports org.apache.logging.log4j.core.config.di.impl.bean;
+ exports org.apache.logging.log4j.core.config.di;
+ exports org.apache.logging.log4j.core.config.di.impl;
exports org.apache.logging.log4j.core.config.plugins;
exports org.apache.logging.log4j.core.config.plugins.convert;
exports org.apache.logging.log4j.core.config.plugins.util;
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginAliases.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginAliases.java
index a194798..07acea7 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginAliases.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginAliases.java
@@ -16,6 +16,9 @@
*/
package org.apache.logging.log4j.plugins;
+import org.apache.logging.log4j.plugins.name.AliasesProvider;
+import org.apache.logging.log4j.plugins.name.PluginAliasesProvider;
+
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -29,6 +32,7 @@ import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
+@AliasesProvider(PluginAliasesProvider.class)
public @interface PluginAliases {
/**
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/AnnotationAlias.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/AnnotationAlias.java
index f522b3a..d570c3b 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/AnnotationAlias.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/AnnotationAlias.java
@@ -27,10 +27,8 @@ import java.lang.annotation.Target;
/**
* Meta annotation for making an annotation an alias for another annotation. Annotations with this annotation will be
* interpreted as if they were implemented by the given annotation type instead. This applies to
- * {@linkplain QualifierType qualifiers}, {@linkplain ScopeType scopes}, {@link Inject}, {@link Produces},
- * {@link Disposes}, {@link PostConstruct}, and {@link PreDestroy}. Individual annotation elements are aliased to the
- * same element names from the aliased annotation unless otherwise annotated with {@link Named} which should specify
- * the aliased annotation element name.
+ * {@linkplain ScopeType scopes}, {@link Inject}, {@link Produces}, {@link Disposes}, {@link PostConstruct}, and
+ * {@link PreDestroy}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Default.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Default.java
deleted file mode 100644
index 0087d5f..0000000
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Default.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.di;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Default {@linkplain QualifierType qualifier type} when no other qualifiers are present.
- */
-@QualifierType
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@Inherited
-public @interface Default {
-}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Inject.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Inject.java
index dbe62d8..6266b12 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Inject.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Inject.java
@@ -41,7 +41,7 @@ import java.lang.annotation.Target;
* declare any type parameters of their own, take zero or more dependencies as arguments, and may return a value which
* is ignored (e.g., for builder method chaining).
*
- * @see QualifierType
+ * @see Named
* @see Provider
*/
@Retention(RetentionPolicy.RUNTIME)
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Named.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Named.java
index bff71ca..0c7a542 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Named.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Named.java
@@ -22,14 +22,14 @@ import org.apache.logging.log4j.plugins.name.NamedQualifierNameProvider;
import org.apache.logging.log4j.util.Strings;
import java.lang.annotation.Documented;
+import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Documented
-@QualifierType
@NameProvider(NamedQualifierNameProvider.class)
+@Repeatable(NamedAliases.class)
public @interface Named {
- // TODO: consider supporting String[] for listing aliases? (or see @Alternative?)
String value() default Strings.EMPTY;
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Ignore.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/NamedAliases.java
similarity index 72%
rename from log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Ignore.java
rename to log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/NamedAliases.java
index f060fc3..6903d2b 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Ignore.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/NamedAliases.java
@@ -17,17 +17,21 @@
package org.apache.logging.log4j.plugins.di;
+import org.apache.logging.log4j.plugins.name.AliasesProvider;
+import org.apache.logging.log4j.plugins.name.NameProvider;
+import org.apache.logging.log4j.plugins.name.NamedAliasesProvider;
+
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-// TODO: documentation around where this can be applied
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+@Target({ElementType.PARAMETER, ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Documented
-@Inherited
-public @interface Ignore {
+@NameProvider(NamedAliasesProvider.class)
+@AliasesProvider(NamedAliasesProvider.class)
+public @interface NamedAliases {
+ Named[] value();
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/inject/AbstractConfigurationInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/inject/AbstractConfigurationInjector.java
index 86df282..05de95e 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/inject/AbstractConfigurationInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/inject/AbstractConfigurationInjector.java
@@ -19,8 +19,8 @@ package org.apache.logging.log4j.plugins.inject;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.PluginAliases;
import org.apache.logging.log4j.plugins.bind.ConfigurationBinder;
+import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
import org.apache.logging.log4j.status.StatusLogger;
@@ -60,9 +60,9 @@ public abstract class AbstractConfigurationInjector<Ann extends Annotation, Cfg>
public ConfigurationInjector<Ann, Cfg> withAnnotatedElement(final AnnotatedElement element) {
this.annotatedElement = Objects.requireNonNull(element);
withName(AnnotatedElementNameProvider.getName(element));
- final PluginAliases aliases = element.getAnnotation(PluginAliases.class);
- if (aliases != null) {
- withAliases(aliases.value());
+ final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(element);
+ if (!aliases.isEmpty()) {
+ withAliases(aliases.toArray(new String[0]));
}
return this;
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/QualifierType.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AliasesProvider.java
similarity index 84%
rename from log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/QualifierType.java
rename to log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AliasesProvider.java
index a5d0821..cf58304 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/QualifierType.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AliasesProvider.java
@@ -15,17 +15,18 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.plugins.di;
+package org.apache.logging.log4j.plugins.name;
+import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-@Target(ElementType.ANNOTATION_TYPE)
-@Retention(RetentionPolicy.RUNTIME)
@Documented
-public @interface QualifierType {
- // default is @Default
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface AliasesProvider {
+ Class<? extends AnnotatedElementAliasesProvider<? extends Annotation>> value();
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AnnotatedElementAliasesProvider.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AnnotatedElementAliasesProvider.java
new file mode 100644
index 0000000..573d02f
--- /dev/null
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AnnotatedElementAliasesProvider.java
@@ -0,0 +1,46 @@
+/*
+ * 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.name;
+
+import org.apache.logging.log4j.util.ReflectionUtil;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.util.Collection;
+import java.util.List;
+
+public interface AnnotatedElementAliasesProvider<A extends Annotation> {
+
+ static Collection<String> getAliases(final AnnotatedElement element) {
+ for (final Annotation annotation : element.getAnnotations()) {
+ if (annotation.annotationType().isAnnotationPresent(AliasesProvider.class)) {
+ return getAliasesForAnnotation(annotation);
+ }
+ }
+ return List.of();
+ }
+
+ private static <A extends Annotation> Collection<String> getAliasesForAnnotation(final A annotation) {
+ @SuppressWarnings("unchecked") final var providerType = (Class<AnnotatedElementAliasesProvider<A>>)
+ annotation.annotationType().getAnnotation(AliasesProvider.class).value();
+ final AnnotatedElementAliasesProvider<A> provider = ReflectionUtil.instantiate(providerType);
+ return provider.getAliases(annotation);
+ }
+
+ Collection<String> getAliases(final A annotation);
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AnnotatedElementNameProvider.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AnnotatedElementNameProvider.java
index 5c3a039..95e303a 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AnnotatedElementNameProvider.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/AnnotatedElementNameProvider.java
@@ -18,13 +18,17 @@
package org.apache.logging.log4j.plugins.name;
import org.apache.logging.log4j.plugins.internal.util.BeanUtils;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.util.ReflectionUtil;
+import org.apache.logging.log4j.util.Strings;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
+import java.lang.reflect.Type;
import java.util.Optional;
/**
@@ -35,13 +39,24 @@ import java.util.Optional;
*/
public interface AnnotatedElementNameProvider<A extends Annotation> {
- static String getName(final AnnotatedElement element) {
+ static boolean hasName(final AnnotatedElement element) {
for (final Annotation annotation : element.getAnnotations()) {
- final Optional<String> specifiedName = getSpecifiedNameForAnnotation(annotation);
- if (specifiedName.isPresent()) {
- return specifiedName.get();
+ if (annotation.annotationType().isAnnotationPresent(NameProvider.class)) {
+ return true;
}
}
+ return false;
+ }
+
+ // note: empty name is the equivalent to a default name
+ static String getName(final AnnotatedElement element) {
+ if (!hasName(element)) {
+ return Strings.EMPTY;
+ }
+ final Optional<String> specifiedName = getSpecifiedName(element);
+ if (specifiedName.isPresent()) {
+ return specifiedName.get();
+ }
if (element instanceof Field) {
return ((Field) element).getName();
@@ -50,7 +65,10 @@ public interface AnnotatedElementNameProvider<A extends Annotation> {
if (element instanceof Method) {
final Method method = (Method) element;
final String methodName = method.getName();
- if (methodName.startsWith("set")) {
+ if (methodName.startsWith("is")) {
+ return BeanUtils.decapitalize(methodName.substring(2));
+ }
+ if (methodName.startsWith("set") | methodName.startsWith("get")) {
return BeanUtils.decapitalize(methodName.substring(3));
}
if (methodName.startsWith("with")) {
@@ -63,17 +81,33 @@ public interface AnnotatedElementNameProvider<A extends Annotation> {
return ((Parameter) element).getName();
}
+ if (element instanceof Type) {
+ return ((Type) element).getTypeName();
+ }
+
+ if (element instanceof Constructor<?>) {
+ return ((Constructor<?>) element).getDeclaringClass().getName();
+ }
+
throw new IllegalArgumentException("Unknown element type for naming: " + element.getClass());
}
- static <A extends Annotation> Optional<String> getSpecifiedNameForAnnotation(final A annotation) {
+ private static Optional<String> getSpecifiedName(final AnnotatedElement element) {
+ for (final Annotation annotation : element.getAnnotations()) {
+ final Optional<String> name = getSpecifiedNameForAnnotation(annotation);
+ if (name.isPresent()) {
+ return name;
+ }
+ }
+ return Optional.empty();
+ }
+
+ private static <A extends Annotation> Optional<String> getSpecifiedNameForAnnotation(final A annotation) {
return Optional.ofNullable(annotation.annotationType().getAnnotation(NameProvider.class))
.map(NameProvider::value)
- .flatMap(clazz -> {
- @SuppressWarnings("unchecked") final AnnotatedElementNameProvider<A> factory =
- (AnnotatedElementNameProvider<A>) ReflectionUtil.instantiate(clazz);
- return factory.getSpecifiedName(annotation);
- });
+ .map(TypeUtil::<Class<? extends AnnotatedElementNameProvider<A>>>cast)
+ .map(ReflectionUtil::instantiate)
+ .flatMap(provider -> provider.getSpecifiedName(annotation));
}
/**
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/NamedAliasesProvider.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/NamedAliasesProvider.java
new file mode 100644
index 0000000..a3e12c1
--- /dev/null
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/NamedAliasesProvider.java
@@ -0,0 +1,54 @@
+/*
+ * 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.name;
+
+import org.apache.logging.log4j.plugins.di.Named;
+import org.apache.logging.log4j.plugins.di.NamedAliases;
+import org.apache.logging.log4j.util.Strings;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+public class NamedAliasesProvider implements AnnotatedElementNameProvider<NamedAliases>, AnnotatedElementAliasesProvider<NamedAliases> {
+ @Override
+ public Optional<String> getSpecifiedName(final NamedAliases annotation) {
+ final Named[] named = annotation.value();
+ if (named.length == 0) {
+ return Optional.empty();
+ }
+ return Strings.trimToOptional(named[0].value());
+ }
+
+ @Override
+ public Collection<String> getAliases(final NamedAliases annotation) {
+ // first @Named is the primary name
+ final Named[] named = annotation.value();
+ final int size = named.length - 1;
+ if (size <= 0) {
+ return Collections.emptyList();
+ }
+ final List<String> aliases = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ aliases.add(named[i + 1].value());
+ }
+ return aliases;
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaAnnotation.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/PluginAliasesProvider.java
similarity index 69%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaAnnotation.java
rename to log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/PluginAliasesProvider.java
index a2627ed..81a6ec5 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/MetaAnnotation.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/name/PluginAliasesProvider.java
@@ -15,13 +15,16 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.model;
+package org.apache.logging.log4j.plugins.name;
-import java.lang.annotation.Annotation;
-import java.util.Collection;
+import org.apache.logging.log4j.plugins.PluginAliases;
-public interface MetaAnnotation {
- Class<? extends Annotation> getAnnotationType();
+import java.util.Collection;
+import java.util.List;
- Collection<MetaAnnotationElement<?>> getAnnotationElements();
+public class PluginAliasesProvider implements AnnotatedElementAliasesProvider<PluginAliases> {
+ @Override
+ public Collection<String> getAliases(final PluginAliases annotation) {
+ return List.of(annotation.value());
+ }
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/Variable.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/AnnotationUtil.java
similarity index 57%
rename from log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/Variable.java
rename to log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/AnnotationUtil.java
index 0b43c30..7bfcc3f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/di/api/model/Variable.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/AnnotationUtil.java
@@ -15,32 +15,28 @@
* limitations under the license.
*/
-package org.apache.logging.log4j.core.config.di.api.model;
+package org.apache.logging.log4j.plugins.util;
-import org.apache.logging.log4j.plugins.di.DependentScoped;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
+import org.apache.logging.log4j.plugins.di.AnnotationAlias;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.Collection;
+import java.lang.reflect.AnnotatedElement;
-public interface Variable {
- Collection<Type> getTypes();
+public final class AnnotationUtil {
- default boolean hasMatchingType(final Type requiredType) {
- for (final Type type : getTypes()) {
- if (TypeUtil.typesMatch(requiredType, type)) {
+ public static boolean isAnnotationPresent(final AnnotatedElement element, final Class<? extends Annotation> annotationType) {
+ if (element.isAnnotationPresent(annotationType)) {
+ return true;
+ }
+ for (final Annotation annotation : element.getAnnotations()) {
+ final AnnotationAlias alias = annotation.annotationType().getAnnotation(AnnotationAlias.class);
+ if (alias != null && annotationType.equals(alias.value())) {
return true;
}
}
return false;
}
- Qualifiers getQualifiers();
-
- Class<? extends Annotation> getScopeType();
-
- default boolean isDependentScoped() {
- return getScopeType() == DependentScoped.class;
+ private AnnotationUtil() {
}
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/ParameterizedTypeImpl.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/ParameterizedTypeImpl.java
index b9a66e8..8117704 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/ParameterizedTypeImpl.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/ParameterizedTypeImpl.java
@@ -22,7 +22,7 @@ import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;
-public class ParameterizedTypeImpl implements ParameterizedType {
+class ParameterizedTypeImpl implements ParameterizedType {
private final Type ownerType;
private final Type rawType;
private final Type[] actualTypeArguments;
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 8f53575..2abcd19 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
@@ -27,7 +27,6 @@ import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -503,20 +502,15 @@ public final class TypeUtil {
}
- private static final Map<Class<?>, Class<?>> PRIMITIVE_BOXED_TYPES;
-
- static {
- final Map<Class<?>, Class<?>> map = new HashMap<>();
- map.put(boolean.class, Boolean.class);
- map.put(byte.class, Byte.class);
- map.put(char.class, Character.class);
- map.put(double.class, Double.class);
- map.put(float.class, Float.class);
- map.put(int.class, Integer.class);
- map.put(long.class, Long.class);
- map.put(short.class, Short.class);
- PRIMITIVE_BOXED_TYPES = Collections.unmodifiableMap(map);
- }
+ private static final Map<Class<?>, Class<?>> PRIMITIVE_BOXED_TYPES = Map.of(
+ boolean.class, Boolean.class,
+ byte.class, Byte.class,
+ char.class, Character.class,
+ double.class, Double.class,
+ float.class, Float.class,
+ int.class, Integer.class,
+ long.class, Long.class,
+ short.class, Short.class);
/**
* Returns the reference type for a class. For primitives, this is their boxed equivalent. For other types, this is