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 2022/07/23 23:40:39 UTC
[logging-log4j2] 02/02: Move reflection utils from DefaultInjector to ReflectionAccessor
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit f120775e53f01f627eafa96ed42df4f49338058a
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sat Jul 23 18:40:21 2022 -0500
Move reflection utils from DefaultInjector to ReflectionAccessor
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../logging/log4j/plugins/di/DefaultInjector.java | 96 +++-------------------
.../log4j/plugins/di/ReflectionAccessor.java | 61 ++++++++++++++
2 files changed, 71 insertions(+), 86 deletions(-)
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index cfb5d19964..578e9ae41e 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -46,13 +46,10 @@ import org.apache.logging.log4j.util.StringBuilders;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandles;
-import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
@@ -226,13 +223,6 @@ class DefaultInjector implements Injector {
this.accessor = accessor;
}
- private <M extends AccessibleObject & Member> void makeAccessible(final M member, final Object instance) {
- final boolean isStatic = Modifier.isStatic(member.getModifiers());
- if (!member.canAccess(isStatic ? null : instance)) {
- accessor.makeAccessible(member);
- }
- }
-
private <T> Supplier<T> getFactory(
final InjectionPoint<T> point, final Node node, final Set<Key<?>> chain, final StringBuilder debugLog) {
final AnnotatedElement element = point.getElement();
@@ -394,10 +384,9 @@ class DefaultInjector implements Injector {
final Class<?> rawType = key.getRawType();
validate(rawType, key.getName(), rawType);
final Constructor<?> constructor = getInjectableConstructor(key, chain);
- makeAccessible(constructor, null);
final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(constructor);
final var args = getArguments(key, node, points, chain, debugLog);
- return newInstance(constructor, args);
+ return accessor.newInstance(constructor, args);
}
private void validate(final AnnotatedElement element, final String name, final Object value) {
@@ -504,16 +493,15 @@ class DefaultInjector implements Injector {
}
private <T> void injectField(final Field field, final Node node, final Object instance, final StringBuilder debugLog) {
- makeAccessible(field, instance);
final InjectionPoint<T> point = InjectionPoint.forField(field);
final Supplier<T> factory = getFactory(point, node, Set.of(), debugLog);
final Key<T> key = point.getKey();
final Object value = key.getRawType() == Supplier.class ? factory : factory.get();
if (value != null) {
- setField(field, instance, value);
+ accessor.setFieldValue(field, instance, value);
}
if (AnnotationUtil.isMetaAnnotationPresent(field, Constraint.class)) {
- final Object fieldValue = getField(field, instance);
+ final Object fieldValue = accessor.getFieldValue(field, instance);
validate(field, key.getName(), fieldValue);
}
}
@@ -525,18 +513,18 @@ class DefaultInjector implements Injector {
for (Class<?> clazz = rawType; clazz != Object.class; clazz = clazz.getSuperclass()) {
for (final Method method : clazz.getDeclaredMethods()) {
if (isInjectable(method)) {
- makeAccessible(method, instance);
+ accessor.makeAccessible(method, instance);
if (method.getParameterCount() == 0) {
injectMethodsWithNoArgs.add(method);
} else {
final List<InjectionPoint<?>> injectionPoints = InjectionPoint.fromExecutable(method);
final var args = getArguments(key, node, injectionPoints, chain, debugLog);
- invokeMethod(method, instance, args);
+ accessor.invokeMethod(method, instance, args);
}
}
}
}
- injectMethodsWithNoArgs.forEach(method -> invokeMethod(method, instance));
+ injectMethodsWithNoArgs.forEach(method -> accessor.invokeMethod(method, instance));
}
private void inject(final Node node) {
@@ -608,9 +596,9 @@ class DefaultInjector implements Injector {
}
final var args = getArguments(key, node, points, Set.of(), debugLog);
if (factory instanceof Method) {
- return invokeMethod((Method) factory, null, args);
+ return accessor.invokeMethod((Method) factory, null, args);
} else {
- return newInstance((Constructor<?>) factory, args);
+ return accessor.newInstance((Constructor<?>) factory, args);
}
}
@@ -634,7 +622,7 @@ class DefaultInjector implements Injector {
}
private <T> List<Binding<T>> createMethodBindings(final Object instance, final Method method) {
- makeAccessible(method, instance);
+ accessor.makeAccessible(method, instance);
final Key<T> primaryKey = Key.forMethod(method);
LOGGER.debug("Checking {} on {} for conditions", primaryKey, method);
final Conditional conditional = AnnotationUtil.getLogicalAnnotation(method, Conditional.class);
@@ -657,7 +645,7 @@ class DefaultInjector implements Injector {
return value;
})
.toArray();
- return rethrow(() -> TypeUtil.cast(invokeMethod(method, instance, args)));
+ return TypeUtil.cast(accessor.invokeMethod(method, instance, args));
};
final Supplier<T> factory = getScopeForMethod(method).get(primaryKey, unscoped);
final Collection<String> aliases = Keys.getAliases(method);
@@ -834,70 +822,6 @@ class DefaultInjector implements Injector {
parameter -> AnnotationUtil.isMetaAnnotationPresent(parameter, QualifierType.class));
}
- private static Object getField(final Field field, final Object instance) {
- try {
- return field.get(instance);
- } catch (final IllegalAccessException e) {
- throw errorFrom(e);
- }
- }
-
- private static void setField(final Field field, final Object instance, final Object value) {
- try {
- field.set(instance, value);
- } catch (final IllegalAccessException e) {
- throw errorFrom(e);
- }
- }
-
- private static Object invokeMethod(final Method method, final Object instance, final Object... args) {
- try {
- return method.invoke(instance, args);
- } catch (final InvocationTargetException e) {
- throw new InjectException(e.getMessage(), e.getCause());
- } catch (final IllegalAccessException e) {
- throw errorFrom(e);
- }
- }
-
- private static <T> T newInstance(final Constructor<T> constructor, final Object[] args) {
- try {
- return constructor.newInstance(args);
- } catch (final InvocationTargetException e) {
- throw new InjectException(e.getMessage(), e.getCause());
- } catch (final IllegalAccessException e) {
- throw errorFrom(e);
- } catch (final InstantiationException e) {
- throw new InjectException(e.getMessage(), e);
- }
- }
-
- private static IllegalAccessError errorFrom(final IllegalAccessException e) {
- final IllegalAccessError error = new IllegalAccessError(e.getMessage());
- error.initCause(e);
- return error;
- }
-
- private static <T> T rethrow(final CheckedSupplier<T> supplier) {
- try {
- return supplier.get();
- } catch (final Throwable e) {
- rethrow(e);
- throw new IllegalStateException("unreachable", e);
- }
- }
-
- // type inference and erasure ensures that checked exceptions can be thrown here without being checked anymore
- @SuppressWarnings("unchecked")
- private static <T extends Throwable> void rethrow(final Throwable t) throws T {
- throw (T) t;
- }
-
- @FunctionalInterface
- private interface CheckedSupplier<T> {
- T get() throws Throwable;
- }
-
private static class SingletonScope implements Scope {
private final Map<Key<?>, Supplier<?>> singletonProviders = new ConcurrentHashMap<>();
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java
index 22508ce806..3755ccea58 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java
@@ -18,8 +18,69 @@
package org.apache.logging.log4j.plugins.di;
import java.lang.reflect.AccessibleObject;
+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.lang.reflect.Modifier;
@FunctionalInterface
public interface ReflectionAccessor {
void makeAccessible(final AccessibleObject object);
+
+ default <M extends AccessibleObject & Member> void makeAccessible(final M member, final Object instance) {
+ final boolean isStatic = Modifier.isStatic(member.getModifiers());
+ if (!member.canAccess(isStatic ? null : instance)) {
+ makeAccessible(member);
+ }
+ }
+
+ default Object getFieldValue(final Field field, final Object instance) {
+ makeAccessible(field, instance);
+ try {
+ return field.get(instance);
+ } catch (final IllegalAccessException e) {
+ throw errorFrom(e);
+ }
+ }
+
+ default void setFieldValue(final Field field, final Object instance, final Object value) {
+ makeAccessible(field, instance);
+ try {
+ field.set(instance, value);
+ } catch (final IllegalAccessException e) {
+ throw errorFrom(e);
+ }
+ }
+
+ default Object invokeMethod(final Method method, final Object instance, final Object... args) {
+ makeAccessible(method, instance);
+ try {
+ return method.invoke(instance, args);
+ } catch (final InvocationTargetException e) {
+ throw new InjectException(e.getMessage(), e.getCause());
+ } catch (final IllegalAccessException e) {
+ throw errorFrom(e);
+ }
+ }
+
+ default <T> T newInstance(final Constructor<T> constructor, final Object[] args) {
+ makeAccessible(constructor, null);
+ try {
+ return constructor.newInstance(args);
+ } catch (final InvocationTargetException e) {
+ throw new InjectException(e.getMessage(), e.getCause());
+ } catch (final IllegalAccessException e) {
+ throw errorFrom(e);
+ } catch (final InstantiationException e) {
+ throw new InjectException(e.getMessage(), e);
+ }
+ }
+
+ private static IllegalAccessError errorFrom(final IllegalAccessException e) {
+ final IllegalAccessError error = new IllegalAccessError(e.getMessage());
+ error.initCause(e);
+ return error;
+ }
}