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/03/23 03:43:31 UTC
[logging-log4j2] 02/02: Revert MethodHandle usage back to reflection
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 fdd78e9a50b7566c6a4e1b70be1e62708dd517ad
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Tue Mar 22 22:42:47 2022 -0500
Revert MethodHandle usage back to reflection
The access rules seem a bit too difficult to work around in Java 17.
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../log4j/core/config/LoggersPluginTest.java | 2 +-
.../logging/log4j/core/impl/DefaultCallback.java | 3 +-
.../log4j/plugin/processor/PluginProcessor.java | 9 -
.../logging/log4j/plugins/di/InjectorTest.java | 3 +-
.../logging/log4j/plugins/di/DefaultInjector.java | 189 +++++++++++----------
.../logging/log4j/plugins/di/InjectException.java | 30 ++++
.../apache/logging/log4j/plugins/di/Injector.java | 11 +-
.../log4j/plugins/di/ReflectionAccessor.java | 25 +++
.../log4j/plugins/processor/PluginService.java | 5 +-
.../logging/log4j/plugins/util/PluginRegistry.java | 3 +-
.../logging/log4j/plugins/util/PluginType.java | 27 +--
11 files changed, 164 insertions(+), 143 deletions(-)
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java
index 4a2df35..5108210 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java
@@ -43,6 +43,6 @@ public class LoggersPluginTest {
//System.out.println(data.getFormattedStatus());
assertThat(data.getLevel()).isEqualTo(Level.ERROR);
- assertThat(data.getMessage().getFormattedMessage()).contains("multiple root loggers");
+ assertThat(data.getMessage().getFormattedMessage()).startsWith("Could not configure plugin element Loggers");
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
index 5940303..1233ab9 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
@@ -45,7 +45,6 @@ import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.PropertiesUtil;
-import java.lang.invoke.MethodHandles;
import java.util.Map;
import java.util.function.Supplier;
@@ -81,7 +80,7 @@ public class DefaultCallback implements InjectorCallback {
public void configure(final Injector injector) {
final PropertiesUtil properties = PropertiesUtil.getProperties();
final var loader = new PropertyLoader(injector, properties, Loader.getClassLoader());
- injector.setLookup(MethodHandles.lookup());
+ injector.setReflectionAccessor(object -> object.setAccessible(true));
injector.registerBindingIfAbsent(ContextSelector.KEY,
() -> loader.getInstance(Constants.LOG4J_CONTEXT_SELECTOR, ContextSelector.class,
() -> ClassLoaderContextSelector.class))
diff --git a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
index f0e1911..cf6a7a6 100644
--- a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
+++ b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
@@ -156,18 +156,11 @@ public class PluginProcessor extends AbstractProcessor {
try (final PrintWriter writer = createSourceFile(fqcn)) {
writer.println("package " + pkg + ".plugins;");
writer.println("");
- writer.println("import org.apache.logging.log4j.plugins.di.LookupSelector;");
writer.println("import org.apache.logging.log4j.plugins.processor.PluginEntry;");
writer.println("import org.apache.logging.log4j.plugins.processor.PluginService;");
writer.println("");
- writer.println("import java.lang.invoke.MethodHandles.Lookup;");
- writer.println("");
- writer.println("import static java.lang.invoke.MethodHandles.lookup;");
- writer.println("import static java.lang.invoke.MethodHandles.privateLookupIn;");
- writer.println("");
writer.println("public class Log4jPlugins extends PluginService {");
writer.println("");
- writer.println(" private static final Lookup LOOKUP = lookup();");
writer.println(" private static final PluginEntry[] ENTRIES = new PluginEntry[] {");
StringBuilder sb = new StringBuilder();
int max = list.size() - 1;
@@ -189,8 +182,6 @@ public class PluginProcessor extends AbstractProcessor {
writer.println(" };");
writer.println(" @Override");
writer.println(" public PluginEntry[] getEntries() { return ENTRIES; }");
- writer.println(" @Override");
- writer.println(" protected LookupSelector getLookupSelector() { return clazz -> privateLookupIn(clazz, LOOKUP); }");
writer.println("}");
}
}
diff --git a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java
index 654439b..8f93480 100644
--- a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java
+++ b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java
@@ -41,7 +41,6 @@ import org.junit.jupiter.api.parallel.Resources;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -589,7 +588,7 @@ class InjectorTest {
final Plugin plugin = clazz.getAnnotation(Plugin.class);
final PluginEntry entry = new PluginEntry(plugin.name().toLowerCase(Locale.ROOT), clazz.getName(), plugin.name(),
plugin.printObject(), plugin.deferChildren(), plugin.category());
- return new PluginType<>(entry, clazz, MethodHandles.lookup().in(clazz), plugin.elementType());
+ return new PluginType<>(entry, clazz, plugin.elementType());
}
@Test
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 51bf172..d7050d2 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
@@ -22,7 +22,6 @@ import org.apache.logging.log4j.plugins.FactoryType;
import org.apache.logging.log4j.plugins.Inject;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.PluginException;
import org.apache.logging.log4j.plugins.QualifierType;
import org.apache.logging.log4j.plugins.ScopeType;
import org.apache.logging.log4j.plugins.Singleton;
@@ -42,14 +41,13 @@ import org.apache.logging.log4j.util.ServiceRegistry;
import org.apache.logging.log4j.util.StringBuilders;
import java.lang.annotation.Annotation;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.VarHandle;
+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;
@@ -75,7 +73,7 @@ class DefaultInjector implements Injector {
private final BindingMap bindingMap;
private final Map<Class<? extends Annotation>, Scope> scopes = new ConcurrentHashMap<>();
- private Lookup lookup = MethodHandles.lookup();
+ private ReflectionAccessor accessor = object -> object.setAccessible(true);
DefaultInjector() {
bindingMap = new BindingMap();
@@ -86,7 +84,7 @@ class DefaultInjector implements Injector {
DefaultInjector(final DefaultInjector original) {
bindingMap = new BindingMap(original.bindingMap);
scopes.putAll(original.scopes);
- lookup = original.lookup;
+ accessor = original.accessor;
}
@Override
@@ -170,8 +168,15 @@ class DefaultInjector implements Injector {
}
@Override
- public void setLookup(final Lookup lookup) {
- this.lookup = lookup;
+ public void setReflectionAccessor(final ReflectionAccessor accessor) {
+ 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(
@@ -219,10 +224,10 @@ 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 MethodHandle handle = getConstructorHandle(constructor, lookup);
final var args = getArguments(key, node, points, chain, debugLog);
- return rethrow(() -> handle.invokeWithArguments(args));
+ return newInstance(constructor, args);
}
private void validate(final AnnotatedElement element, final String name, final Object value) {
@@ -260,17 +265,16 @@ class DefaultInjector implements Injector {
}
private <T> void injectField(final Field field, final Node node, final Object instance, final StringBuilder debugLog) {
- final Lookup fieldLookup = node != null ? node.getType().getPluginLookup() : lookup.in(instance.getClass());
- final VarHandle handle = getFieldHandle(field, fieldLookup);
+ 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) {
- handle.set(instance, value);
+ setField(field, instance, value);
}
if (AnnotationUtil.isMetaAnnotationPresent(field, Constraint.class)) {
- final Object fieldValue = handle.get(instance);
+ final Object fieldValue = getField(field, instance);
validate(field, key.getName(), fieldValue);
}
}
@@ -278,23 +282,22 @@ class DefaultInjector implements Injector {
private void injectMethods(
final Key<?> key, final Node node, final Object instance, final Set<Key<?>> chain, final StringBuilder debugLog) {
final Class<?> rawType = key.getRawType();
- final Lookup methodLookup = node != null ? node.getType().getPluginLookup() : lookup.in(instance.getClass());
- final List<MethodHandle> injectMethodsWithNoArgs = new ArrayList<>();
+ final List<Method> injectMethodsWithNoArgs = new ArrayList<>();
for (Class<?> clazz = rawType; clazz != Object.class; clazz = clazz.getSuperclass()) {
for (final Method method : clazz.getDeclaredMethods()) {
if (isInjectable(method)) {
- final MethodHandle handle = getMethodHandle(method, methodLookup).bindTo(instance);
+ makeAccessible(method, instance);
if (method.getParameterCount() == 0) {
- injectMethodsWithNoArgs.add(handle);
+ injectMethodsWithNoArgs.add(method);
} else {
final List<InjectionPoint<?>> injectionPoints = InjectionPoint.fromExecutable(method);
- final List<?> args = getArguments(key, node, injectionPoints, chain, debugLog);
- rethrow(() -> handle.invokeWithArguments(args));
+ final var args = getArguments(key, node, injectionPoints, chain, debugLog);
+ invokeMethod(method, instance, args);
}
}
}
}
- injectMethodsWithNoArgs.forEach(handle -> rethrow(handle::invoke));
+ injectMethodsWithNoArgs.forEach(method -> invokeMethod(method, instance));
}
private void inject(final Node node) {
@@ -354,15 +357,15 @@ class DefaultInjector implements Injector {
.map(Executable.class::cast)
.orElseGet(() -> getInjectableConstructor(key, Set.of()));
final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(factory);
- final Lookup pluginLookup = type.getPluginLookup();
- final MethodHandle handle;
+ if (!factory.canAccess(null)) {
+ accessor.makeAccessible(factory);
+ }
+ final var args = getArguments(key, node, points, Set.of(), debugLog);
if (factory instanceof Method) {
- handle = getMethodHandle((Method) factory, pluginLookup);
+ return invokeMethod((Method) factory, null, args);
} else {
- handle = getConstructorHandle((Constructor<?>) factory, pluginLookup);
+ return newInstance((Constructor<?>) factory, args);
}
- final var args = getArguments(key, node, points, Set.of(), debugLog);
- return rethrow(() -> handle.invokeWithArguments(args));
}
private void registerModuleInstance(final Object module) {
@@ -379,7 +382,7 @@ class DefaultInjector implements Injector {
createMethodBindings(module, method).forEach(binding -> {
final var key = binding.getKey();
if (!bindingMap.putIfAbsent(key, binding.getSupplier())) {
- throw new PluginException(String.format(
+ throw new InjectException(String.format(
"Duplicate @Factory method (%s: %s) found for %s", moduleClass, method, key));
}
});
@@ -388,20 +391,22 @@ class DefaultInjector implements Injector {
}
private <T> List<Binding<T>> createMethodBindings(final Object instance, final Method method) {
+ makeAccessible(method, instance);
final Key<T> primaryKey = Key.forMethod(method);
final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(method);
- final MethodHandle handle = getMethodHandle(method, lookup);
- final MethodHandle boundHandle = Modifier.isStatic(method.getModifiers()) ? handle : handle.bindTo(instance);
final var argumentFactories = getArgumentFactories(primaryKey, null, points, Set.of(primaryKey), null);
final Supplier<T> unscoped = () -> {
- final List<Object> args = argumentFactories.entrySet()
+ final var args = argumentFactories.entrySet()
.stream()
- .flatMap(e -> {
+ .map(e -> {
+ final Parameter parameter = e.getKey();
+ final String name = AnnotatedElementNameProvider.getName(parameter);
final Object value = e.getValue().get();
- return e.getKey().isVarArgs() ? Stream.of((Object[]) value) : Stream.of(value);
+ validate(parameter, name, value);
+ return value;
})
- .collect(Collectors.toList());
- return TypeUtil.cast(rethrow(() -> boundHandle.invokeWithArguments(args)));
+ .toArray();
+ return rethrow(() -> TypeUtil.cast(invokeMethod(method, instance, args)));
};
final Supplier<T> factory = getScopeForMethod(method).get(primaryKey, unscoped);
final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(method);
@@ -413,20 +418,20 @@ class DefaultInjector implements Injector {
return bindings;
}
- private List<Object> getArguments(
+ private Object[] getArguments(
final Key<?> key, final Node node, final List<InjectionPoint<?>> points, final Set<Key<?>> chain,
final StringBuilder debugLog) {
return getArgumentFactories(key, node, points, chain, debugLog)
.entrySet()
.stream()
- .flatMap(e -> {
+ .map(e -> {
final Parameter parameter = e.getKey();
final String name = AnnotatedElementNameProvider.getName(parameter);
final Object value = e.getValue().get();
validate(parameter, name, value);
- return parameter.isVarArgs() ? Stream.of((Object[]) value) : Stream.of(value);
+ return value;
})
- .collect(Collectors.toList());
+ .toArray();
}
private Map<Parameter, Supplier<?>> getArgumentFactories(
@@ -446,7 +451,7 @@ class DefaultInjector implements Injector {
sb.append(chainKey).append(" -> ");
}
sb.append(parameterKey);
- throw new PluginException(sb.toString());
+ throw new InjectException(sb.toString());
}
argFactories.put(parameter, () -> getFactory(point, node, newChain, debugLog).get());
}
@@ -464,7 +469,8 @@ class DefaultInjector implements Injector {
return scope != null ? scopes.get(scope.annotationType()) : DefaultScope.INSTANCE;
}
- private static boolean isCompatibleValidator(final Constraint constraint, final Class<? extends Annotation> annotationType) {
+ private static boolean isCompatibleValidator(
+ final Constraint constraint, final Class<? extends Annotation> annotationType) {
for (final Type type : constraint.value().getGenericInterfaces()) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
@@ -478,7 +484,8 @@ class DefaultInjector implements Injector {
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- private static void initializeConstraintValidator(final ConstraintValidator<? extends Annotation> validator, final Annotation annotation) {
+ private static void initializeConstraintValidator(
+ final ConstraintValidator<? extends Annotation> validator, final Annotation annotation) {
// runtime type checking ensures this raw type usage is correct
((ConstraintValidator) validator).initialize(annotation);
}
@@ -525,61 +532,13 @@ class DefaultInjector implements Injector {
return newChain;
}
- private static VarHandle getFieldHandle(final Field field, final Lookup lookup) {
- final Class<?> declaringClass = field.getDeclaringClass();
- try {
- return lookup.unreflectVarHandle(field);
- } catch (final IllegalAccessException outer) {
- try {
- return MethodHandles.privateLookupIn(declaringClass, lookup).unreflectVarHandle(field);
- } catch (final IllegalAccessException inner) {
- final var error = new IllegalAccessError("Cannot access field " + field);
- error.addSuppressed(inner);
- error.addSuppressed(outer);
- throw error;
- }
- }
- }
-
- private static MethodHandle getMethodHandle(final Method method, final Lookup lookup) {
- final Class<?> declaringClass = method.getDeclaringClass();
- try {
- return lookup.unreflect(method);
- } catch (final IllegalAccessException outer) {
- try {
- return MethodHandles.privateLookupIn(declaringClass, lookup).unreflect(method);
- } catch (final IllegalAccessException inner) {
- final var error = new IllegalAccessError("Cannot access method " + method);
- error.addSuppressed(inner);
- error.addSuppressed(outer);
- throw error;
- }
- }
- }
-
- private static MethodHandle getConstructorHandle(final Constructor<?> constructor, final Lookup lookup) {
- final Class<?> declaringClass = constructor.getDeclaringClass();
- try {
- return lookup.unreflectConstructor(constructor);
- } catch (final IllegalAccessException outer) {
- try {
- return MethodHandles.privateLookupIn(declaringClass, lookup).unreflectConstructor(constructor);
- } catch (final IllegalAccessException inner) {
- final var error = new IllegalAccessError("Cannot access constructor " + constructor);
- error.addSuppressed(inner);
- error.addSuppressed(outer);
- throw error;
- }
- }
- }
-
private static <T> Constructor<T> getInjectableConstructor(final Key<T> key, final Set<Key<?>> chain) {
final Class<T> rawType = key.getRawType();
final List<Constructor<?>> injectConstructors = Stream.of(rawType.getDeclaredConstructors())
.filter(constructor -> constructor.isAnnotationPresent(Inject.class))
.collect(Collectors.toList());
if (injectConstructors.size() > 1) {
- throw new PluginException("Multiple @Inject constructors found in " + rawType);
+ throw new InjectException("Multiple @Inject constructors found in " + rawType);
}
if (injectConstructors.size() == 1) {
return TypeUtil.cast(injectConstructors.get(0));
@@ -597,7 +556,7 @@ class DefaultInjector implements Injector {
final String prefix = chain.isEmpty() ? "" : "chain ";
final String keysToString =
prefix + keys.stream().map(Key::toString).collect(Collectors.joining(" -> "));
- throw new PluginException(
+ throw new InjectException(
"No @Inject constructors or no-arg constructor found for " + keysToString);
}
@@ -612,6 +571,50 @@ 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();
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/InjectException.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/InjectException.java
new file mode 100644
index 0000000..7913745
--- /dev/null
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/InjectException.java
@@ -0,0 +1,30 @@
+/*
+ * 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 org.apache.logging.log4j.plugins.PluginException;
+
+public class InjectException extends PluginException {
+ public InjectException(final String message) {
+ super(message);
+ }
+
+ public InjectException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
index e5ad184..8420c92 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
@@ -21,7 +21,6 @@ import org.apache.logging.log4j.plugins.FactoryType;
import org.apache.logging.log4j.plugins.Node;
import java.lang.annotation.Annotation;
-import java.lang.invoke.MethodHandles.Lookup;
import java.util.function.Supplier;
/**
@@ -149,12 +148,12 @@ public interface Injector {
*/
<T> Injector registerBindingIfAbsent(final Key<T> key, final Supplier<? extends T> factory);
-
/**
- * Sets the {@link Lookup} used for obtaining MethodHandle and VarHandle instances. A custom caller class
- * can invoke {@code setLookup(MethodHandles.lookup())} as a typical use case.
+ * Sets the {@link ReflectionAccessor} used for invoking {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)}
+ * from an appropriate caller class. Customizing this allows for changing the base module that other modules should
+ * open themselves to.
*
- * @param lookup handle lookup object for access checks
+ * @param accessor accessor to use
*/
- void setLookup(final Lookup lookup);
+ void setReflectionAccessor(final ReflectionAccessor accessor);
}
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
new file mode 100644
index 0000000..22508ce
--- /dev/null
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java
@@ -0,0 +1,25 @@
+/*
+ * 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.reflect.AccessibleObject;
+
+@FunctionalInterface
+public interface ReflectionAccessor {
+ void makeAccessible(final AccessibleObject object);
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
index aa1392d..00d8a7c 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
@@ -16,7 +16,6 @@
*/
package org.apache.logging.log4j.plugins.processor;
-import org.apache.logging.log4j.plugins.di.LookupSelector;
import org.apache.logging.log4j.plugins.util.PluginType;
import java.util.ArrayList;
@@ -41,15 +40,13 @@ public abstract class PluginService {
for (PluginEntry entry : entries) {
String category = entry.getCategory().toLowerCase();
List<PluginType<?>> list = categories.computeIfAbsent(category, ignored -> new ArrayList<>());
- PluginType<?> type = new PluginType<>(entry, classLoader, getLookupSelector());
+ PluginType<?> type = new PluginType<>(entry, classLoader);
list.add(type);
}
}
public abstract PluginEntry[] getEntries();
- protected abstract LookupSelector getLookupSelector();
-
public Map<String, List<PluginType<?>>> getCategories() {
return Collections.unmodifiableMap(categories);
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
index dd3a4ce..413f9e1 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
@@ -253,8 +253,7 @@ public class PluginRegistry {
newPluginsByCategory.put(categoryLowerCase, types);
for (final Map.Entry<String, PluginEntry> inner : outer.getValue().entrySet()) {
final PluginEntry entry = inner.getValue();
- final PluginType<?> type = new PluginType<>(entry, context.getClassLoader(),
- clazz -> MethodHandles.privateLookupIn(clazz, context.getLookup()));
+ final PluginType<?> type = new PluginType<>(entry, context.getClassLoader());
types.add(type);
++pluginCount;
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
index 55adbc5..f1ab067 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
@@ -16,12 +16,9 @@
*/
package org.apache.logging.log4j.plugins.util;
-import org.apache.logging.log4j.plugins.di.LookupSelector;
import org.apache.logging.log4j.plugins.processor.PluginEntry;
import org.apache.logging.log4j.util.LazyValue;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
import java.util.function.Supplier;
/**
@@ -34,7 +31,6 @@ public class PluginType<T> {
private final PluginEntry pluginEntry;
private final Supplier<Class<T>> pluginClass;
- private final Supplier<Lookup> pluginLookup;
private final String elementName;
/**
@@ -44,15 +40,10 @@ public class PluginType<T> {
* @param elementName The name of the element.
* @since 2.1
*/
- public PluginType(final PluginEntry pluginEntry, final Class<T> pluginClass, final String elementName) {
- this(pluginEntry, pluginClass, MethodHandles.lookup().in(pluginClass), elementName);
- }
-
public PluginType(
- final PluginEntry pluginEntry, final Class<T> pluginClass, final Lookup pluginLookup, final String elementName) {
+ final PluginEntry pluginEntry, final Class<T> pluginClass, final String elementName) {
this.pluginEntry = pluginEntry;
this.pluginClass = () -> pluginClass;
- this.pluginLookup = () -> pluginLookup;
this.elementName = elementName;
}
@@ -61,9 +52,9 @@ public class PluginType<T> {
* @since 3.0
* @param pluginEntry The PluginEntry.
*/
- public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader, final LookupSelector lookupSelector) {
+ public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader) {
this.pluginEntry = pluginEntry;
- final LazyValue<Class<T>> pluginClass = new LazyValue<>(() -> {
+ this.pluginClass = new LazyValue<>(() -> {
try {
return TypeUtil.cast(classLoader.loadClass(pluginEntry.getClassName()));
} catch (final ClassNotFoundException e) {
@@ -71,14 +62,6 @@ public class PluginType<T> {
" located for element " + pluginEntry.getName(), e);
}
});
- this.pluginClass = pluginClass;
- this.pluginLookup = pluginClass.map(clazz -> {
- try {
- return lookupSelector.in(clazz);
- } catch (final IllegalAccessException e) {
- throw new IllegalAccessError(e.getMessage());
- }
- });
this.elementName = pluginEntry.getName();
}
@@ -91,10 +74,6 @@ public class PluginType<T> {
return pluginClass.get();
}
- public Lookup getPluginLookup() {
- return pluginLookup.get();
- }
-
public String getElementName() {
return this.elementName;
}