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;
+    }
 }