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 2023/11/14 06:19:10 UTC
(logging-log4j2) 07/07: Remove ServiceRegistry in favor of utility function
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch the-great-deletion
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 3118f4799728d6b2b987a1858ac80b4c8579fc38
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Tue Nov 14 00:06:39 2023 -0600
Remove ServiceRegistry in favor of utility function
Without a need for tracking externally registered services, everywhere that was looking up services can do so more directly now.
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../logging/log4j/util/ServiceLoaderUtilTest.java | 27 ++--
.../logging/log4j/message/ThreadDumpMessage.java | 16 +--
.../apache/logging/log4j/spi/LoggingSystem.java | 9 +-
.../apache/logging/log4j/util/PropertiesUtil.java | 41 ++----
.../logging/log4j/util/ServiceLoaderUtil.java | 142 +++------------------
.../apache/logging/log4j/util/ServiceRegistry.java | 81 ------------
.../log4j/core/config/AbstractConfiguration.java | 11 +-
.../log4j/core/impl/ThreadContextDataInjector.java | 22 ++--
.../logging/log4j/core/util/WatchManager.java | 12 +-
.../org/apache/logging/log4j/plugins/di/DI.java | 8 +-
10 files changed, 76 insertions(+), 293 deletions(-)
diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java
index e6d9d704bd..b82fb953b2 100644
--- a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java
+++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java
@@ -16,10 +16,10 @@
*/
package org.apache.logging.log4j.util;
-import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
import java.util.stream.Collectors;
import org.apache.logging.log4j.Level;
@@ -32,29 +32,30 @@ import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertEquals;
public class ServiceLoaderUtilTest {
@Test
public void testServiceResolution() {
- final List<Object> services = new ArrayList<>();
- assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(BetterService.class, MethodHandles.lookup(), false)
- .forEach(services::add));
- assertThat(services).hasSize(1);
- services.clear();
- assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(PropertySource.class, MethodHandles.lookup(), false)
- .forEach(services::add));
- assertThat(services).hasSize(3);
- }
+ final List<Object> services = new ArrayList<>();
+ final ClassLoader classLoader = getClass().getClassLoader();
+ assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream(ServiceLoader.load(BetterService.class, classLoader))
+ .forEach(services::add));
+ assertThat(services).hasSize(1);
+ services.clear();
+ assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream(ServiceLoader.load(PropertySource.class, classLoader))
+ .forEach(services::add));
+ assertThat(services).hasSize(3);
+ }
@Test
@UsingStatusListener
public void testBrokenServiceFile(final ListStatusListener listener) {
final List<Service> services = new ArrayList<>();
- assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(Service.class, MethodHandles.lookup(), false)
+ final ClassLoader classLoader = getClass().getClassLoader();
+ assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream(ServiceLoader.load(Service.class, classLoader))
.forEach(services::add));
- assertEquals(2, services.size());
+ assertThat(services).hasSize(2);
// A warning for each broken service
final List<Throwable> errors = listener.findStatusData(Level.WARN).map(StatusData::getThrowable)
.collect(Collectors.toList());
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
index cbfa241b5b..585728251f 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
@@ -16,16 +16,15 @@
*/
package org.apache.logging.log4j.message;
-import java.lang.invoke.MethodHandles;
import java.util.HashMap;
import java.util.Map;
+import java.util.ServiceLoader;
import aQute.bnd.annotation.Cardinality;
-import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceConsumer;
import org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory;
import org.apache.logging.log4j.util.Lazy;
-import org.apache.logging.log4j.util.ServiceRegistry;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
import org.apache.logging.log4j.util.StringBuilderFormattable;
import org.apache.logging.log4j.util.Strings;
@@ -33,13 +32,12 @@ import org.apache.logging.log4j.util.Strings;
* Captures information about all running Threads.
*/
@AsynchronouslyFormattable
-@ServiceConsumer(value = ThreadInfoFactory.class, resolution = Resolution.OPTIONAL, cardinality = Cardinality.SINGLE)
+@ServiceConsumer(value = ThreadInfoFactory.class, cardinality = Cardinality.SINGLE)
public class ThreadDumpMessage implements Message, StringBuilderFormattable {
- private static final Lazy<ThreadInfoFactory> FACTORY = Lazy.lazy(() -> {
- final var services = ServiceRegistry.getInstance()
- .getServices(ThreadInfoFactory.class, MethodHandles.lookup(), null);
- return services.isEmpty() ? new BasicThreadInfoFactory() : services.get(0);
- });
+ private static final Lazy<ThreadInfoFactory> FACTORY = Lazy.lazy(() ->
+ ServiceLoaderUtil.safeStream(ServiceLoader.load(ThreadInfoFactory.class, ThreadInfoFactory.class.getClassLoader()))
+ .findFirst()
+ .orElseGet(BasicThreadInfoFactory::new));
private final Map<ThreadInformation, StackTraceElement[]> threads;
private final String title;
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java
index 4691a74c48..55dbf3ecc3 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java
@@ -18,13 +18,13 @@ package org.apache.logging.log4j.spi;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
+import java.util.ServiceLoader;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.function.Supplier;
@@ -45,7 +45,7 @@ import org.apache.logging.log4j.util.LoaderUtil;
import org.apache.logging.log4j.util.LowLevelLogUtil;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.PropertyEnvironment;
-import org.apache.logging.log4j.util.ServiceRegistry;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
import static org.apache.logging.log4j.spi.LoggingSystemProperty.LOGGER_FLOW_MESSAGE_FACTORY_CLASS;
import static org.apache.logging.log4j.spi.LoggingSystemProperty.LOGGER_MESSAGE_FACTORY_CLASS;
@@ -187,8 +187,9 @@ public class LoggingSystem {
}
private static List<Provider> loadDefaultProviders() {
- return ServiceRegistry.getInstance()
- .getServices(Provider.class, MethodHandles.lookup(), provider -> validVersion(provider.getVersions()));
+ return ServiceLoaderUtil.safeStream(ServiceLoader.load(Provider.class, Provider.class.getClassLoader()))
+ .filter(provider -> validVersion(provider.getVersions()))
+ .collect(Collectors.toList());
}
private static List<Provider> loadLegacyProviders() {
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
index d656f89b5d..86a7a34c7c 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
@@ -20,7 +20,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandles;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -38,9 +37,9 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
import aQute.bnd.annotation.Cardinality;
-import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceConsumer;
import org.apache.logging.log4j.internal.CopyOnWriteNavigableSet;
@@ -58,7 +57,7 @@ import org.apache.logging.log4j.internal.CopyOnWriteNavigableSet;
* @see PropertySource
*/
@InternalApi
-@ServiceConsumer(value = PropertySource.class, resolution = Resolution.OPTIONAL, cardinality = Cardinality.MULTIPLE)
+@ServiceConsumer(value = PropertySource.class, cardinality = Cardinality.MULTIPLE)
public class PropertiesUtil implements PropertyEnvironment {
private static final String LOG4J_NAMESPACE = "component";
@@ -66,6 +65,9 @@ public class PropertiesUtil implements PropertyEnvironment {
private static final String DELIMITER = ".";
private static final String META_INF = "META-INF/";
private static final String LOG4J_SYSTEM_PROPERTIES_FILE_NAME = "log4j2.system.properties";
+ private static final Lazy<List<PropertySource>> SERVICE_PROPERTY_SOURCES = Lazy.lazy(() ->
+ ServiceLoaderUtil.safeStream(ServiceLoader.load(PropertySource.class, PropertiesUtil.class.getClassLoader()))
+ .collect(Collectors.toList()));
private static final Lazy<PropertiesUtil> COMPONENT_PROPERTIES = Lazy.lazy(PropertiesUtil::new);
private static final ThreadLocal<PropertiesUtil> environments = new InheritableThreadLocal<>();
@@ -234,21 +236,6 @@ public class PropertiesUtil implements PropertyEnvironment {
return environment.getStringProperty(name);
}
- /**
- * Return the system properties or an empty Properties object if an error occurs.
- *
- * @return The system properties.
- */
- public static Properties getSystemProperties() {
- try {
- return new Properties(System.getProperties());
- } catch (final SecurityException ex) {
- LowLevelLogUtil.logException("Unable to access system properties.", ex);
- // Sandboxed - can't read System Properties
- return new Properties();
- }
- }
-
/**
* Reloads all properties. This is primarily useful for unit tests.
*
@@ -438,20 +425,14 @@ public class PropertiesUtil implements PropertyEnvironment {
private final String contextName;
private Environment(final String contextName, final List<PropertySource> propertySources) {
- try {
- final Properties sysProps = PropertyFilePropertySource.loadPropertiesFile(LOG4J_SYSTEM_PROPERTIES_FILE_NAME);
- for (String key : sysProps.stringPropertyNames()) {
- if (System.getProperty(key) == null) {
- System.setProperty(key, sysProps.getProperty(key));
- }
- };
- } catch (final SecurityException ex) {
- // Access to System Properties is restricted so just skip it.
+ final Properties sysProps = PropertyFilePropertySource.loadPropertiesFile(LOG4J_SYSTEM_PROPERTIES_FILE_NAME);
+ for (String key : sysProps.stringPropertyNames()) {
+ if (System.getProperty(key) == null) {
+ System.setProperty(key, sysProps.getProperty(key));
+ }
}
sources.addAll(propertySources);
- final ServiceRegistry registry = ServiceRegistry.getInstance();
- // Does not log errors using StatusLogger, which depends on PropertiesUtil being initialized.
- sources.addAll(registry.getServices(PropertySource.class, MethodHandles.lookup(), null, /*verbose=*/false));
+ sources.addAll(SERVICE_PROPERTY_SOURCES.get());
this.contextName = contextName;
reload();
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
index 95c9f3cef8..084555f36d 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
@@ -16,29 +16,18 @@
*/
package org.apache.logging.log4j.util;
-import java.lang.invoke.CallSite;
-import java.lang.invoke.LambdaMetafactory;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.Set;
-import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.status.StatusLogger;
-
/**
- * This class should be considered internal.
+ * Handles {@link ServiceLoader} lookups with better error handling.
*/
@InternalApi
public final class ServiceLoaderUtil {
@@ -48,102 +37,21 @@ public final class ServiceLoaderUtil {
private ServiceLoaderUtil() {
}
- /**
- * Retrieves the available services from the caller's classloader.
- *
- * Broken services will be ignored.
- *
- * @param <T> The service type.
- * @param serviceType The class of the service.
- * @param lookup The calling class data.
- * @return A stream of service instances.
- */
- public static <T> Stream<T> loadServices(final Class<T> serviceType, final Lookup lookup) {
- return loadServices(serviceType, lookup, false);
- }
-
- /**
- * Retrieves the available services from the caller's classloader and possibly
- * the thread context classloader.
- *
- * Broken services will be ignored.
- *
- * @param <T> The service type.
- * @param serviceType The class of the service.
- * @param lookup The calling class data.
- * @param useTccl If true the thread context classloader will also be used.
- * @return A stream of service instances.
- */
- public static <T> Stream<T> loadServices(final Class<T> serviceType, final Lookup lookup, final boolean useTccl) {
- return loadServices(serviceType, lookup, useTccl, true);
- }
-
- static <T> Stream<T> loadServices(final Class<T> serviceType, final Lookup lookup, final boolean useTccl,
- final boolean verbose) {
- final ClassLoader classLoader = lookup.lookupClass().getClassLoader();
- Stream<T> services = loadClassloaderServices(serviceType, lookup, classLoader, verbose);
- if (useTccl) {
- final ClassLoader contextClassLoader = LoaderUtil.getThreadContextClassLoader();
- if (contextClassLoader != classLoader) {
- services = Stream.concat(services,
- loadClassloaderServices(serviceType, lookup, contextClassLoader, verbose));
- }
- }
+ public static <S> Stream<S> safeStream(final ServiceLoader<S> serviceLoader) {
final Set<Class<?>> classes = new HashSet<>();
- // only the first occurrence of a class
- return services.filter(service -> classes.add(service.getClass()));
- }
-
- static <T> Stream<T> loadClassloaderServices(final Class<T> serviceType, final Lookup lookup,
- final ClassLoader classLoader, final boolean verbose) {
- return StreamSupport.stream(new ServiceLoaderSpliterator<T>(serviceType, lookup, classLoader, verbose), false);
- }
-
- static <T> Iterable<T> callServiceLoader(final Lookup lookup, final Class<T> serviceType, final ClassLoader classLoader,
- final boolean verbose) {
- try {
- // Creates a lambda in the caller's domain that calls `ServiceLoader`
- final MethodHandle loadHandle = lookup.findStatic(ServiceLoader.class, "load",
- MethodType.methodType(ServiceLoader.class, Class.class, ClassLoader.class));
- final CallSite callSite = LambdaMetafactory.metafactory(lookup,
- "run",
- MethodType.methodType(PrivilegedAction.class, Class.class, ClassLoader.class),
- MethodType.methodType(Object.class),
- loadHandle,
- MethodType.methodType(ServiceLoader.class));
- final PrivilegedAction<ServiceLoader<T>> action = (PrivilegedAction<ServiceLoader<T>>) callSite
- .getTarget()//
- .bindTo(serviceType)
- .bindTo(classLoader)
- .invoke();
- final ServiceLoader<T> serviceLoader;
- if (System.getSecurityManager() == null) {
- serviceLoader = action.run();
- } else {
- final MethodHandle privilegedHandle = lookup.findStatic(AccessController.class, "doPrivileged",
- MethodType.methodType(Object.class, PrivilegedAction.class));
- serviceLoader = (ServiceLoader<T>) privilegedHandle.invoke(action);
- }
- return serviceLoader;
- } catch (Throwable e) {
- if (verbose) {
- StatusLogger.getLogger().error("Unable to load services for service {}", serviceType, e);
- }
- }
- return Collections.emptyList();
+ return StreamSupport.stream(new ServiceLoaderSpliterator<>(serviceLoader), false)
+ // only the first occurrence of a class
+ .filter(service -> classes.add(service.getClass()));
}
- private static class ServiceLoaderSpliterator<S> implements Spliterator<S> {
-
+ private static class ServiceLoaderSpliterator<S> extends Spliterators.AbstractSpliterator<S> {
private final Iterator<S> serviceIterator;
- private final Logger logger;
private final String serviceName;
- public ServiceLoaderSpliterator(final Class<S> serviceType, final Lookup lookup, final ClassLoader classLoader,
- final boolean verbose) {
- this.serviceIterator = callServiceLoader(lookup, serviceType, classLoader, verbose).iterator();
- this.logger = verbose ? StatusLogger.getLogger() : null;
- this.serviceName = serviceType.toString();
+ private ServiceLoaderSpliterator(final ServiceLoader<S> serviceLoader) {
+ super(Long.MAX_VALUE, ORDERED);
+ serviceIterator = serviceLoader.iterator();
+ serviceName = serviceLoader.toString();
}
@Override
@@ -155,34 +63,14 @@ public final class ServiceLoaderUtil {
action.accept(serviceIterator.next());
return true;
}
- } catch (ServiceConfigurationError | LinkageError e) {
- if (logger != null) {
- logger.warn("Unable to load service class for service {}", serviceName, e);
- }
- } catch (Throwable e) {
- if (logger != null) {
- logger.warn("Unable to load service class for service {}", serviceName, e);
- }
+ } catch (final ServiceConfigurationError | LinkageError e) {
+ LowLevelLogUtil.logException("Unable to load implementation for " + serviceName, e);
+ } catch (final Throwable e) {
+ LowLevelLogUtil.logException("Unexpected exception while loading implementation for " + serviceName, e);
throw e;
}
}
return false;
}
-
- @Override
- public Spliterator<S> trySplit() {
- return null;
- }
-
- @Override
- public long estimateSize() {
- return Long.MAX_VALUE;
- }
-
- @Override
- public int characteristics() {
- return NONNULL | IMMUTABLE;
- }
-
}
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceRegistry.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceRegistry.java
deleted file mode 100644
index b73b5b6f8f..0000000000
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceRegistry.java
+++ /dev/null
@@ -1,81 +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.util;
-
-import java.lang.invoke.MethodHandles.Lookup;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * Registry for service instances loaded from {@link ServiceLoader}. This abstracts the differences between using a flat
- * classpath versus a module path.
- *
- * @since 3.0.0
- */
-@InternalApi
-public final class ServiceRegistry {
- private static final Lazy<ServiceRegistry> INSTANCE = Lazy.relaxed(ServiceRegistry::new);
-
-
- /**
- * Returns the singleton ServiceRegistry instance.
- */
- public static ServiceRegistry getInstance() {
- return INSTANCE.get();
- }
-
- private final Map<Class<?>, List<?>> registry = new ConcurrentHashMap<>();
-
- private ServiceRegistry() {
- }
-
- /**
- * Gets service instances loaded from the calling context and any previously registered bundle services. The {@code loaderCallerContext} parameter is
- * provided to ensure the caller can specify which calling function context to
- * load services.
- *
- * @param serviceType service class
- * @param lookup MethodHandle lookup created in same module as caller context
- * to use for loading services
- * @param validator if non-null, used to validate service instances,
- * removing invalid instances from the returned list
- * @param <S> type of service
- * @return loaded service instances
- */
- public <S> List<S> getServices(final Class<S> serviceType, final Lookup lookup, final Predicate<S> validator) {
- return getServices(serviceType, lookup, validator, true);
- }
-
- /**
- * Set 'verbose' to false if the `StatusLogger` is not available yet.
- */
- <S> List<S> getServices(final Class<S> serviceType, final Lookup lookup, final Predicate<S> validator, final boolean verbose) {
- final List<?> existing = registry.get(serviceType);
- if (existing != null) {
- return Cast.cast(existing);
- }
- final List<S> services = ServiceLoaderUtil.loadServices(serviceType, lookup, false, verbose)
- .filter(validator != null ? validator : unused -> true)
- .collect(Collectors.toList());
- final List<S> oldValue = Cast.cast(registry.putIfAbsent(serviceType, services));
- return oldValue != null ? oldValue : services;
- }
-}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 10feed227d..bb4befedec 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -16,7 +16,6 @@
*/
package org.apache.logging.log4j.core.config;
-import java.lang.invoke.MethodHandles;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
@@ -25,6 +24,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -35,7 +35,6 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Supplier;
-import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceConsumer;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
@@ -88,12 +87,12 @@ import org.apache.logging.log4j.util.Lazy;
import org.apache.logging.log4j.util.NameUtil;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.PropertyEnvironment;
-import org.apache.logging.log4j.util.ServiceRegistry;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
/**
* The base Configuration. Many configuration implementations will extend this class.
*/
-@ServiceConsumer(value = ScriptManagerFactory.class, resolution = Resolution.OPTIONAL)
+@ServiceConsumer(ScriptManagerFactory.class)
public abstract class AbstractConfiguration extends AbstractFilterable implements Configuration {
/**
@@ -291,9 +290,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
private void initializeScriptManager() {
try {
- ServiceRegistry.getInstance()
- .getServices(ScriptManagerFactory.class, MethodHandles.lookup(), null)
- .stream()
+ ServiceLoaderUtil.safeStream(ServiceLoader.load(ScriptManagerFactory.class, AbstractConfiguration.class.getClassLoader()))
.findFirst()
.ifPresent(factory -> setScriptManager(factory.createScriptManager(this, getWatchManager())));
} catch (final LinkageError | Exception e) {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
index db32a6852f..373df99619 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
@@ -16,17 +16,16 @@
*/
package org.apache.logging.log4j.core.impl;
-import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentLinkedDeque;
import aQute.bnd.annotation.Cardinality;
-import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceConsumer;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.ContextDataInjector;
@@ -34,7 +33,7 @@ import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.util.ContextDataProvider;
import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
-import org.apache.logging.log4j.util.ServiceRegistry;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
import org.apache.logging.log4j.util.StringMap;
/**
@@ -52,7 +51,7 @@ import org.apache.logging.log4j.util.StringMap;
* @see ContextDataInjectorFactory
* @since 2.7
*/
-@ServiceConsumer(value = ContextDataProvider.class, resolution = Resolution.OPTIONAL, cardinality = Cardinality.MULTIPLE)
+@ServiceConsumer(value = ContextDataProvider.class, cardinality = Cardinality.MULTIPLE)
public class ThreadContextDataInjector {
/**
@@ -65,13 +64,14 @@ public class ThreadContextDataInjector {
private static List<ContextDataProvider> getServiceProviders() {
final List<ContextDataProvider> providers = new ArrayList<>();
- final List<ContextDataProvider> services = ServiceRegistry.getInstance()
- .getServices(ContextDataProvider.class, MethodHandles.lookup(), null);
- for (final ContextDataProvider provider : services) {
- if (providers.stream().noneMatch((p) -> p.getClass().isAssignableFrom(provider.getClass()))) {
- providers.add(provider);
- }
- }
+ final ServiceLoader<ContextDataProvider> serviceLoader =
+ ServiceLoader.load(ContextDataProvider.class, ThreadContextDataInjector.class.getClassLoader());
+ ServiceLoaderUtil.safeStream(serviceLoader)
+ .forEachOrdered(provider -> {
+ if (providers.stream().noneMatch((p) -> p.getClass().isAssignableFrom(provider.getClass()))) {
+ providers.add(provider);
+ }
+ });
return Collections.unmodifiableList(providers);
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
index 9ed1f2dc5a..3e271182c8 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
@@ -17,21 +17,21 @@
package org.apache.logging.log4j.core.util;
import java.io.File;
-import java.lang.invoke.MethodHandles;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.ServiceLoader;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
import aQute.bnd.annotation.Cardinality;
-import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceConsumer;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.AbstractLifeCycle;
@@ -39,7 +39,7 @@ import org.apache.logging.log4j.core.config.ConfigurationScheduler;
import org.apache.logging.log4j.plugins.Inject;
import org.apache.logging.log4j.plugins.Singleton;
import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.ServiceRegistry;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
/**
* Manages {@link FileWatcher}s.
@@ -48,7 +48,7 @@ import org.apache.logging.log4j.util.ServiceRegistry;
* @see ConfigurationScheduler
*/
@Singleton
-@ServiceConsumer(value = WatchEventService.class, resolution = Resolution.OPTIONAL, cardinality = Cardinality.MULTIPLE)
+@ServiceConsumer(value = WatchEventService.class, cardinality = Cardinality.MULTIPLE)
public class WatchManager extends AbstractLifeCycle {
private static final class ConfigurationMonitor {
@@ -140,8 +140,8 @@ public class WatchManager extends AbstractLifeCycle {
@Inject
public WatchManager(final ConfigurationScheduler scheduler) {
this.scheduler = Objects.requireNonNull(scheduler, "scheduler");
- eventServiceList = ServiceRegistry.getInstance()
- .getServices(WatchEventService.class, MethodHandles.lookup(), null);
+ eventServiceList = ServiceLoaderUtil.safeStream(ServiceLoader.load(WatchEventService.class, WatchManager.class.getClassLoader()))
+ .collect(Collectors.toList());
}
public void checkFiles() {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DI.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DI.java
index f831f3d262..1a9a538c55 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DI.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DI.java
@@ -16,12 +16,12 @@
*/
package org.apache.logging.log4j.plugins.di;
-import java.lang.invoke.MethodHandles;
import java.util.Comparator;
+import java.util.ServiceLoader;
import org.apache.logging.log4j.plugins.di.spi.ConfigurableInstanceFactoryPostProcessor;
import org.apache.logging.log4j.plugins.util.OrderedComparator;
-import org.apache.logging.log4j.util.ServiceRegistry;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
/**
* Factory for {@linkplain InstanceFactory instance factories}.
@@ -75,9 +75,7 @@ public final class DI {
* @param factory the instance factory to initialize
*/
public static void initializeFactory(final ConfigurableInstanceFactory factory) {
- ServiceRegistry.getInstance()
- .getServices(ConfigurableInstanceFactoryPostProcessor.class, MethodHandles.lookup(), null)
- .stream()
+ ServiceLoaderUtil.safeStream(ServiceLoader.load(ConfigurableInstanceFactoryPostProcessor.class, DI.class.getClassLoader()))
.sorted(Comparator.comparing(ConfigurableInstanceFactoryPostProcessor::getClass, OrderedComparator.INSTANCE))
.forEachOrdered(processor -> processor.postProcessFactory(factory));
}