diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java index 980900cd965..66631c194e6 100644 --- a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java +++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java @@ -16,15 +16,42 @@ */ package org.apache.logging.log4j.test.junit; +import aQute.bnd.annotation.baseline.BaselineIgnore; import org.junit.jupiter.api.parallel.ResourceLock; /** * Constants to use the {@link ResourceLock} annotation. - * */ -public class Resources { +@BaselineIgnore("2.24.0") +public final class Resources { + + /** + * Marks tests that require access to {@link org.apache.logging.log4j.LogManager} methods or change its + * underlying {@link org.apache.logging.log4j.spi.LoggerContextFactory} implementation. + */ + public static final String LOG_MANAGER = "log4j.LogManager"; + + /** + * Marks tests that require access to {@link org.apache.logging.log4j.ThreadContext} methods or change its + * underlying {@link org.apache.logging.log4j.spi.ThreadContextMap} implementation. + */ + public static final String THREAD_CONTEXT = "log4j.ThreadContext"; + + /** + * Marks tests that require access to {@link org.apache.logging.log4j.MarkerManager} methods. + */ + public static final String MARKER_MANAGER = "log4j.MarkerManager"; + + /** + * Marks tests that requires access to {@link org.apache.logging.log4j.Level} static methods to create new levels. + */ + public static final String LEVEL = "log4j.Level"; - public static final String THREAD_CONTEXT = "log4j2.ThreadContext"; + /** + * Marks tests that require access to {@link org.apache.logging.log4j.status.StatusLogger} static methods or + * change its underlying implementation. + */ + public static final String STATUS_LOGGER = "log4j.StatusLogger"; - public static final String MARKER_MANAGER = "log4j2.MarkerManager"; + private Resources() {} } diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java index 22e32873bee..3207042de87 100644 --- a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java +++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java @@ -15,7 +15,7 @@ * limitations under the license. */ @Export -@Version("2.23.1") +@Version("2.24.0") package org.apache.logging.log4j.test.junit; import org.osgi.annotation.bundle.Export; diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java index efcee80a159..9652034d70f 100644 --- a/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java +++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.fail; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -31,6 +32,7 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import org.apache.logging.log4j.util.ReadOnlyStringMap; import org.apache.logging.log4j.util.TriConsumer; import org.junit.jupiter.api.Test; @@ -238,32 +240,18 @@ public void testEqualsWhenOneValueDiffers() { @Test public void testForEachBiConsumer_JavaUtil() { - UnmodifiableArrayBackedMap map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters()); - Set keys = new HashSet<>(); - java.util.function.BiConsumer java_util_action = - new java.util.function.BiConsumer() { - @Override - public void accept(String key, String value) { - keys.add(key); - } - }; - map.forEach(java_util_action); + final Map map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters()); + final Collection keys = new HashSet<>(); + map.forEach((key, value) -> keys.add(key)); assertEquals(map.keySet(), keys); } @Test public void testForEachBiConsumer_Log4jUtil() { - UnmodifiableArrayBackedMap map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters()); - Set keys = new HashSet<>(); - org.apache.logging.log4j.util.BiConsumer log4j_util_action = - new org.apache.logging.log4j.util.BiConsumer() { - @Override - public void accept(String key, String value) { - keys.add(key); - } - }; - map.forEach(log4j_util_action); - assertEquals(map.keySet(), keys); + final ReadOnlyStringMap map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters()); + final Collection keys = new HashSet<>(); + map.forEach((key, value) -> keys.add(key)); + assertEquals(map.toMap().keySet(), keys); } @Test 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 09b489565c9..8ca74a0bee6 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 @@ -20,13 +20,15 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; -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; +import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.status.StatusData; +import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.test.BetterService; import org.apache.logging.log4j.test.ListStatusListener; import org.apache.logging.log4j.test.Service; @@ -35,14 +37,26 @@ public class ServiceLoaderUtilTest { + private static final Logger LOGGER = StatusLogger.getLogger(); + @Test public void testServiceResolution() { final List services = new ArrayList<>(); - assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(BetterService.class, MethodHandles.lookup(), false) + ServiceLoaderUtil.safeStream( + BetterService.class, + ServiceLoader.load(BetterService.class, getClass().getClassLoader()), + LOGGER); + assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream( + BetterService.class, + ServiceLoader.load(BetterService.class, getClass().getClassLoader()), + LOGGER) .forEach(services::add)); assertThat(services).hasSize(1); services.clear(); - assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(PropertySource.class, MethodHandles.lookup(), false) + assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream( + PropertySource.class, + ServiceLoader.load(PropertySource.class, getClass().getClassLoader()), + LOGGER) .forEach(services::add)); assertThat(services).hasSize(3); } @@ -51,7 +65,10 @@ public void testServiceResolution() { @UsingStatusListener public void testBrokenServiceFile(final ListStatusListener listener) { final List services = new ArrayList<>(); - assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(Service.class, MethodHandles.lookup(), false) + assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream( + Service.class, + ServiceLoader.load(Service.class, getClass().getClassLoader()), + LOGGER) .forEach(services::add)); assertEquals(2, services.size()); // A warning for each broken service diff --git a/log4j-api/pom.xml b/log4j-api/pom.xml index 082fd2f6574..853ebe4d4aa 100644 --- a/log4j-api/pom.xml +++ b/log4j-api/pom.xml @@ -36,6 +36,10 @@ true org.apache.logging.log4j + + + !sun.reflect + java.sql;static=true, diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/LogBuilder.java b/log4j-api/src/main/java/org/apache/logging/log4j/LogBuilder.java index 91d3083e4a3..992d2875138 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/LogBuilder.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/LogBuilder.java @@ -32,7 +32,7 @@ public interface LogBuilder { * @param marker The Marker to log. * @return The LogBuilder. */ - default LogBuilder withMarker(Marker marker) { + default LogBuilder withMarker(final Marker marker) { return this; } @@ -41,7 +41,7 @@ default LogBuilder withMarker(Marker marker) { * @param throwable The Throwable to log. * @return the LogBuilder. */ - default LogBuilder withThrowable(Throwable throwable) { + default LogBuilder withThrowable(final Throwable throwable) { return this; } @@ -59,7 +59,7 @@ default LogBuilder withLocation() { * @param location The stack trace element to include in the log event. * @return The LogBuilder. */ - default LogBuilder withLocation(StackTraceElement location) { + default LogBuilder withLocation(final StackTraceElement location) { return this; } @@ -67,13 +67,13 @@ default LogBuilder withLocation(StackTraceElement location) { * Causes all the data collected to be logged along with the message. Interface default method does nothing. * @param message The message to log. */ - default void log(CharSequence message) {} + default void log(final CharSequence message) {} /** * Causes all the data collected to be logged along with the message. Interface default method does nothing. * @param message The message to log. */ - default void log(String message) {} + default void log(final String message) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -83,7 +83,7 @@ default void log(String message) {} * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object... params) {} + default void log(final String message, final Object... params) {} /** * Causes all the data collected to be logged along with the message and parameters. @@ -91,21 +91,19 @@ default void log(String message, Object... params) {} * @param message The message. * @param params Parameters to the message. */ - @SuppressWarnings("deprecation") - default void log(String message, Supplier... params) {} + default void log(final String message, final Supplier... params) {} /** * Causes all the data collected to be logged along with the message. Interface default method does nothing. * @param message The message to log. */ - default void log(Message message) {} + default void log(final Message message) {} /** * Causes all the data collected to be logged along with the message. Interface default method does nothing. * @param messageSupplier The supplier of the message to log. */ - @SuppressWarnings("deprecation") - default void log(Supplier messageSupplier) {} + default void log(final Supplier messageSupplier) {} /** * Causes all the data collected to be logged along with the message. @@ -114,7 +112,6 @@ default void log(Supplier messageSupplier) {} * @return the message logger or {@code null} if no logging occurred. * @since 2.20 */ - @SuppressWarnings("deprecation") default Message logAndGet(final Supplier messageSupplier) { return null; } @@ -123,7 +120,7 @@ default Message logAndGet(final Supplier messageSupplier) { * Causes all the data collected to be logged along with the message. Interface default method does nothing. * @param message The message to log. */ - default void log(Object message) {} + default void log(final Object message) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -133,7 +130,7 @@ default void log(Object message) {} * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object p0) {} + default void log(final String message, final Object p0) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -144,7 +141,7 @@ default void log(String message, Object p0) {} * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object p0, Object p1) {} + default void log(final String message, final Object p0, final Object p1) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -156,7 +153,7 @@ default void log(String message, Object p0, Object p1) {} * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object p0, Object p1, Object p2) {} + default void log(final String message, final Object p0, final Object p1, final Object p2) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -169,7 +166,7 @@ default void log(String message, Object p0, Object p1, Object p2) {} * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object p0, Object p1, Object p2, Object p3) {} + default void log(final String message, final Object p0, final Object p1, final Object p2, final Object p3) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -183,7 +180,13 @@ default void log(String message, Object p0, Object p1, Object p2, Object p3) {} * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {} + default void log( + final String message, + final Object p0, + final Object p1, + final Object p2, + final Object p3, + final Object p4) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -198,7 +201,14 @@ default void log(String message, Object p0, Object p1, Object p2, Object p3, Obj * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {} + default void log( + final String message, + final Object p0, + final Object p1, + final Object p2, + final Object p3, + final Object p4, + final Object p5) {} /** * Logs a message with parameters. @@ -214,7 +224,15 @@ default void log(String message, Object p0, Object p1, Object p2, Object p3, Obj * * @see org.apache.logging.log4j.util.Unbox */ - default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {} + default void log( + final String message, + final Object p0, + final Object p1, + final Object p2, + final Object p3, + final Object p4, + final Object p5, + final Object p6) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -232,7 +250,15 @@ default void log(String message, Object p0, Object p1, Object p2, Object p3, Obj * @see org.apache.logging.log4j.util.Unbox */ default void log( - String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {} + final String message, + final Object p0, + final Object p1, + final Object p2, + final Object p3, + final Object p4, + final Object p5, + final Object p6, + final Object p7) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -251,16 +277,16 @@ default void log( * @see org.apache.logging.log4j.util.Unbox */ default void log( - String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8) {} + final String message, + final Object p0, + final Object p1, + final Object p2, + final Object p3, + final Object p4, + final Object p5, + final Object p6, + final Object p7, + final Object p8) {} /** * Logs a message with parameters. Interface default method does nothing. @@ -280,17 +306,17 @@ default void log( * @see org.apache.logging.log4j.util.Unbox */ default void log( - String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9) {} + final String message, + final Object p0, + final Object p1, + final Object p2, + final Object p3, + final Object p4, + final Object p5, + final Object p6, + final Object p7, + final Object p8, + final Object p9) {} /** * Causes all the data collected to be logged. Default implementatoin does nothing. diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java b/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java index d7def7ac7ee..cdb91c57658 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java @@ -41,7 +41,7 @@ public class LogManager { /** - * Log4j property to set to the fully qualified class name of a custom implementation of + * Log4j's property to set to the fully qualified class name of a custom implementation of * {@link LoggerContextFactory}. * @deprecated Replaced since 2.24.0 with {@value org.apache.logging.log4j.spi.Provider#PROVIDER_PROPERTY_NAME}. */ @@ -49,7 +49,7 @@ public class LogManager { public static final String FACTORY_PROPERTY_NAME = "log4j2.loggerContextFactory"; /** - * The name of the root Logger is {@value #ROOT_LOGGER_NAME}. + * The name of the root Logger. */ public static final String ROOT_LOGGER_NAME = Strings.EMPTY; @@ -315,10 +315,10 @@ protected static LoggerContext getContext( /** * Shutdown using the LoggerContext appropriate for the caller of this method. * This is equivalent to calling {@code LogManager.shutdown(false)}. - * - * This call is synchronous and will block until shut down is complete. - * This may include flushing pending log events over network connections. - * + *

+ * This call is synchronous and will block until shut down is complete. This may include flushing pending log + * events over network connections. + *

* @since 2.6 */ public static void shutdown() { @@ -328,9 +328,10 @@ public static void shutdown() { /** * Shutdown the logging system if the logging system supports it. * This is equivalent to calling {@code LogManager.shutdown(LogManager.getContext(currentContext))}. - * - * This call is synchronous and will block until shut down is complete. - * This may include flushing pending log events over network connections. + *

+ * This call is synchronous and will block until shut down is complete. This may include flushing pending log + * events over network connections. + *

* * @param currentContext if true a default LoggerContext (may not be the LoggerContext used to create a Logger * for the calling class) will be used. @@ -347,9 +348,10 @@ public static void shutdown(final boolean currentContext) { /** * Shutdown the logging system if the logging system supports it. * This is equivalent to calling {@code LogManager.shutdown(LogManager.getContext(currentContext))}. - * - * This call is synchronous and will block until shut down is complete. - * This may include flushing pending log events over network connections. + *

+ * This call is synchronous and will block until shut down is complete. This may include flushing pending log + * events over network connections. + *

* * @param currentContext if true a default LoggerContext (may not be the LoggerContext used to create a Logger * for the calling class) will be used. @@ -366,9 +368,10 @@ public static void shutdown(final boolean currentContext, final boolean allConte /** * Shutdown the logging system if the logging system supports it. - * - * This call is synchronous and will block until shut down is complete. - * This may include flushing pending log events over network connections. + *

+ * This call is synchronous and will block until shut down is complete. This may include flushing pending log + * events over network connections. + *

* * @param context the LoggerContext. * @since 2.6 @@ -461,7 +464,7 @@ public static Logger getFormatterLogger(final Class clazz) { * Short-hand for {@code getLogger(value, StringFormatterMessageFactory.INSTANCE)} *

* - * @param value The value's whose class name should be used as the Logger name. + * @param value The value whose class name should be used as the Logger name. * @return The Logger, created with a {@link StringFormatterMessageFactory} * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be * determined. diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java index 7dc872e21a1..ef461ddfe31 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java @@ -200,7 +200,6 @@ public interface Logger { * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void debug(Marker marker, String message, Supplier... paramSuppliers); /** @@ -222,7 +221,6 @@ public interface Logger { * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void debug(Marker marker, Supplier messageSupplier); /** @@ -235,7 +233,6 @@ public interface Logger { * @param throwable A Throwable or null. * @since 2.4 */ - @SuppressWarnings("deprecation") void debug(Marker marker, Supplier messageSupplier, Throwable throwable); /** @@ -329,7 +326,6 @@ public interface Logger { * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void debug(String message, Supplier... paramSuppliers); /** @@ -348,7 +344,6 @@ public interface Logger { * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void debug(Supplier messageSupplier); /** @@ -360,7 +355,6 @@ public interface Logger { * @param throwable the {@code Throwable} to log, including its stack trace. * @since 2.4 */ - @SuppressWarnings("deprecation") void debug(Supplier messageSupplier, Throwable throwable); /** @@ -811,7 +805,6 @@ void debug( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void error(Marker marker, String message, Supplier... paramSuppliers); /** @@ -833,7 +826,6 @@ void debug( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void error(Marker marker, Supplier messageSupplier); /** @@ -846,7 +838,6 @@ void debug( * @param throwable A Throwable or null. * @since 2.4 */ - @SuppressWarnings("deprecation") void error(Marker marker, Supplier messageSupplier, Throwable throwable); /** @@ -940,7 +931,6 @@ void debug( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void error(String message, Supplier... paramSuppliers); /** @@ -959,7 +949,6 @@ void debug( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void error(Supplier messageSupplier); /** @@ -971,7 +960,6 @@ void debug( * @param throwable the {@code Throwable} to log, including its stack trace. * @since 2.4 */ - @SuppressWarnings("deprecation") void error(Supplier messageSupplier, Throwable throwable); /** @@ -1414,7 +1402,6 @@ void error( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void fatal(Marker marker, String message, Supplier... paramSuppliers); /** @@ -1436,7 +1423,6 @@ void error( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void fatal(Marker marker, Supplier messageSupplier); /** @@ -1449,7 +1435,6 @@ void error( * @param throwable A Throwable or null. * @since 2.4 */ - @SuppressWarnings("deprecation") void fatal(Marker marker, Supplier messageSupplier, Throwable throwable); /** @@ -1543,7 +1528,6 @@ void error( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void fatal(String message, Supplier... paramSuppliers); /** @@ -1562,7 +1546,6 @@ void error( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void fatal(Supplier messageSupplier); /** @@ -1574,7 +1557,6 @@ void error( * @param throwable the {@code Throwable} to log, including its stack trace. * @since 2.4 */ - @SuppressWarnings("deprecation") void fatal(Supplier messageSupplier, Throwable throwable); /** @@ -1901,12 +1883,13 @@ void fatal( /** * Gets the message factory used to convert message Objects and Strings/CharSequences into actual log Messages. - * - * Since version 2.6, Log4j internally uses message factories that implement the {@link MessageFactory2} interface. - * From version 2.6.2, the return type of this method was changed from {@link MessageFactory} to - * {@code MF}. The returned factory will always implement {@link MessageFactory2}, - * but the return type of this method could not be changed to {@link MessageFactory2} without breaking binary - * compatibility. + *

+ * Since version 2.6, Log4j internally uses message factories that implement the {@link MessageFactory2} + * interface. From version 2.6.2, the return type of this method was changed from {@link MessageFactory} to + * {@code MF}. The returned factory will always implement {@link MessageFactory2}, + * but the return type of this method could not be changed to {@link MessageFactory2} without breaking binary + * compatibility. + *

* * @return the message factory, as an instance of {@link MessageFactory2} */ @@ -2030,7 +2013,6 @@ void fatal( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void info(Marker marker, String message, Supplier... paramSuppliers); /** @@ -2052,7 +2034,6 @@ void fatal( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void info(Marker marker, Supplier messageSupplier); /** @@ -2065,7 +2046,6 @@ void fatal( * @param throwable A Throwable or null. * @since 2.4 */ - @SuppressWarnings("deprecation") void info(Marker marker, Supplier messageSupplier, Throwable throwable); /** @@ -2159,7 +2139,6 @@ void fatal( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void info(String message, Supplier... paramSuppliers); /** @@ -2178,7 +2157,6 @@ void fatal( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void info(Supplier messageSupplier); /** @@ -2190,7 +2168,6 @@ void fatal( * @param throwable the {@code Throwable} to log, including its stack trace. * @since 2.4 */ - @SuppressWarnings("deprecation") void info(Supplier messageSupplier, Throwable throwable); /** @@ -2737,7 +2714,6 @@ void info( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void log(Level level, Marker marker, String message, Supplier... paramSuppliers); /** @@ -2760,7 +2736,6 @@ void info( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void log(Level level, Marker marker, Supplier messageSupplier); /** @@ -2774,7 +2749,6 @@ void info( * @param throwable A Throwable or null. * @since 2.4 */ - @SuppressWarnings("deprecation") void log(Level level, Marker marker, Supplier messageSupplier, Throwable throwable); /** @@ -2878,7 +2852,6 @@ void info( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void log(Level level, String message, Supplier... paramSuppliers); /** @@ -2899,7 +2872,6 @@ void info( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void log(Level level, Supplier messageSupplier); /** @@ -2912,7 +2884,6 @@ void info( * @param throwable the {@code Throwable} to log, including its stack log. * @since 2.4 */ - @SuppressWarnings("deprecation") void log(Level level, Supplier messageSupplier, Throwable throwable); /** @@ -3435,7 +3406,6 @@ void log( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void trace(Marker marker, String message, Supplier... paramSuppliers); /** @@ -3458,7 +3428,6 @@ void log( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void trace(Marker marker, Supplier messageSupplier); /** @@ -3471,7 +3440,6 @@ void log( * @param throwable A Throwable or null. * @since 2.4 */ - @SuppressWarnings("deprecation") void trace(Marker marker, Supplier messageSupplier, Throwable throwable); /** @@ -3567,7 +3535,6 @@ void log( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void trace(String message, Supplier... paramSuppliers); /** @@ -3587,7 +3554,6 @@ void log( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void trace(Supplier messageSupplier); /** @@ -3599,7 +3565,6 @@ void log( * @param throwable the {@code Throwable} to log, including its stack trace. * @since 2.4 */ - @SuppressWarnings("deprecation") void trace(Supplier messageSupplier, Throwable throwable); /** @@ -3967,7 +3932,6 @@ void trace( * * @since 2.6 */ - @SuppressWarnings("deprecation") EntryMessage traceEntry(Supplier... paramSuppliers); /** @@ -3986,7 +3950,6 @@ void trace( * * @since 2.6 */ - @SuppressWarnings("deprecation") EntryMessage traceEntry(String format, Supplier... paramSuppliers); /** @@ -4205,7 +4168,6 @@ void trace( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void warn(Marker marker, String message, Supplier... paramSuppliers); /** @@ -4227,7 +4189,6 @@ void trace( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void warn(Marker marker, Supplier messageSupplier); /** @@ -4240,7 +4201,6 @@ void trace( * @param throwable A Throwable or null. * @since 2.4 */ - @SuppressWarnings("deprecation") void warn(Marker marker, Supplier messageSupplier, Throwable throwable); /** @@ -4334,7 +4294,6 @@ void trace( * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters. * @since 2.4 */ - @SuppressWarnings("deprecation") void warn(String message, Supplier... paramSuppliers); /** @@ -4353,7 +4312,6 @@ void trace( * message factory. * @since 2.4 */ - @SuppressWarnings("deprecation") void warn(Supplier messageSupplier); /** @@ -4365,7 +4323,6 @@ void trace( * @param throwable the {@code Throwable} to log, including its stack warn. * @since 2.4 */ - @SuppressWarnings("deprecation") void warn(Supplier messageSupplier, Throwable throwable); /** @@ -4695,7 +4652,12 @@ void warn( * @since 2.13.0 */ default void logMessage( - Level level, Marker marker, String fqcn, StackTraceElement location, Message message, Throwable throwable) { + final Level level, + final Marker marker, + final String fqcn, + final StackTraceElement location, + final Message message, + final Throwable throwable) { // noop } @@ -4768,7 +4730,7 @@ default LogBuilder always() { * @return a LogBuilder. * @since 2.13.0 */ - default LogBuilder atLevel(Level level) { + default LogBuilder atLevel(final Level level) { return LogBuilder.NOOP; } } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java index 1c6fcd3f459..57dbd29b8ab 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java @@ -17,8 +17,6 @@ package org.apache.logging.log4j.message; import java.io.Serializable; -import org.apache.logging.log4j.spi.AbstractLogger; -import org.apache.logging.log4j.util.LoaderUtil; import org.apache.logging.log4j.util.StringBuilderFormattable; import org.apache.logging.log4j.util.StringBuilders; import org.apache.logging.log4j.util.Strings; @@ -34,9 +32,10 @@ public class DefaultFlowMessageFactory implements FlowMessageFactory, Serializab private static final String ENTRY_DEFAULT_PREFIX = "Enter"; private static final long serialVersionUID = 8578655591131397576L; + public static final FlowMessageFactory INSTANCE = new DefaultFlowMessageFactory(); + private final String entryText; private final String exitText; - private final MessageFactory messageFactory; /** * Constructs a message factory with {@code "Enter"} and {@code "Exit"} as the default flow strings. @@ -53,15 +52,6 @@ public DefaultFlowMessageFactory() { public DefaultFlowMessageFactory(final String entryText, final String exitText) { this.entryText = entryText; this.exitText = exitText; - this.messageFactory = createDefaultMessageFactory(); - } - - private static MessageFactory createDefaultMessageFactory() { - try { - return LoaderUtil.newInstanceOf(AbstractLogger.DEFAULT_MESSAGE_FACTORY_CLASS); - } catch (final ReflectiveOperationException e) { - throw new IllegalStateException(e); - } } private static class AbstractFlowMessage implements FlowMessage, StringBuilderFormattable { @@ -194,9 +184,9 @@ public EntryMessage newEntryMessage(final String format, final Object... params) final boolean hasFormat = Strings.isNotEmpty(format); final Message message; if (params == null || params.length == 0) { - message = hasFormat ? messageFactory.newMessage(format) : null; + message = hasFormat ? ParameterizedMessageFactory.INSTANCE.newMessage(format) : null; } else if (hasFormat) { - message = messageFactory.newMessage(format, params); + message = ParameterizedMessageFactory.INSTANCE.newMessage(format, params); } else { final StringBuilder sb = new StringBuilder("params("); for (int i = 0; i < params.length; i++) { @@ -206,7 +196,7 @@ public EntryMessage newEntryMessage(final String format, final Object... params) sb.append("{}"); } sb.append(")"); - message = messageFactory.newMessage(sb.toString(), params); + message = ParameterizedMessageFactory.INSTANCE.newMessage(sb.toString(), params); } return newEntryMessage(message); } @@ -233,9 +223,9 @@ public ExitMessage newExitMessage(final String format, final Object result) { final boolean hasFormat = Strings.isNotEmpty(format); final Message message; if (result == null) { - message = hasFormat ? messageFactory.newMessage(format) : null; + message = hasFormat ? ParameterizedMessageFactory.INSTANCE.newMessage(format) : null; } else { - message = messageFactory.newMessage(hasFormat ? format : "with({})", result); + message = ParameterizedMessageFactory.INSTANCE.newMessage(hasFormat ? format : "with({})", result); } return newExitMessage(message); } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java index d55b98ae700..053a5bf8f1c 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java @@ -135,26 +135,27 @@ private static Throwable determineThrowable(final Object[] args, final int argCo return null; } - ReusableParameterizedMessage set(final String messagePattern, final Object... arguments) { + public ReusableParameterizedMessage set(final String messagePattern, final Object... arguments) { init(messagePattern, arguments == null ? 0 : arguments.length, arguments); varargs = arguments; return this; } - ReusableParameterizedMessage set(final String messagePattern, final Object p0) { + public ReusableParameterizedMessage set(final String messagePattern, final Object p0) { params[0] = p0; init(messagePattern, 1, params); return this; } - ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1) { + public ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1) { params[0] = p0; params[1] = p1; init(messagePattern, 2, params); return this; } - ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1, final Object p2) { + public ReusableParameterizedMessage set( + final String messagePattern, final Object p0, final Object p1, final Object p2) { params[0] = p0; params[1] = p1; params[2] = p2; @@ -162,7 +163,7 @@ ReusableParameterizedMessage set(final String messagePattern, final Object p0, f return this; } - ReusableParameterizedMessage set( + public ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, final Object p2, final Object p3) { params[0] = p0; params[1] = p1; @@ -172,7 +173,7 @@ ReusableParameterizedMessage set( return this; } - ReusableParameterizedMessage set( + public ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -188,7 +189,7 @@ ReusableParameterizedMessage set( return this; } - ReusableParameterizedMessage set( + public ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -206,7 +207,7 @@ ReusableParameterizedMessage set( return this; } - ReusableParameterizedMessage set( + public ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -226,7 +227,7 @@ ReusableParameterizedMessage set( return this; } - ReusableParameterizedMessage set( + public ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -248,7 +249,7 @@ ReusableParameterizedMessage set( return this; } - ReusableParameterizedMessage set( + public ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -272,7 +273,7 @@ ReusableParameterizedMessage set( return this; } - ReusableParameterizedMessage set( + public ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, 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 18ed7befe4f..4ddbdc5c5f4 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 @@ -24,10 +24,11 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.Serializable; -import java.lang.invoke.MethodHandles; import java.util.HashMap; import java.util.Map; +import java.util.ServiceLoader; import org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory; +import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.Lazy; import org.apache.logging.log4j.util.ServiceLoaderUtil; import org.apache.logging.log4j.util.StringBuilderFormattable; @@ -61,7 +62,10 @@ private ThreadDumpMessage(final String formattedMsg, final String title) { } private static ThreadInfoFactory initFactory() { - return ServiceLoaderUtil.loadServices(ThreadInfoFactory.class, MethodHandles.lookup(), false) + return ServiceLoaderUtil.safeStream( + ThreadInfoFactory.class, + ServiceLoader.load(ThreadInfoFactory.class, ThreadDumpMessage.class.getClassLoader()), + StatusLogger.getLogger()) .findFirst() .orElseGet(BasicThreadInfoFactory::new); } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java index 49286fab779..24632f8d7b5 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java @@ -22,7 +22,7 @@ /** * Bumped to 2.22.0, since FormattedMessage behavior changed. */ -@Version("2.22.0") +@Version("2.24.0") package org.apache.logging.log4j.message; import org.osgi.annotation.bundle.Export; diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java index d9543f17b52..30d0cffef02 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java @@ -35,7 +35,6 @@ import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.Constants; import org.apache.logging.log4j.util.LambdaUtil; -import org.apache.logging.log4j.util.LoaderUtil; import org.apache.logging.log4j.util.MessageSupplier; import org.apache.logging.log4j.util.PerformanceSensitive; import org.apache.logging.log4j.util.StackLocatorUtil; @@ -198,12 +197,7 @@ protected Message catchingMsg(final Throwable throwable) { } private static MessageFactory2 createDefaultMessageFactory() { - try { - final MessageFactory result = LoaderUtil.newInstanceOf(DEFAULT_MESSAGE_FACTORY_CLASS); - return narrow(result); - } catch (final ReflectiveOperationException e) { - throw new IllegalStateException(e); - } + return ParameterizedMessageFactory.INSTANCE; } private static MessageFactory2 narrow(final MessageFactory result) { @@ -214,11 +208,7 @@ private static MessageFactory2 narrow(final MessageFactory result) { } private static FlowMessageFactory createDefaultFlowMessageFactory() { - try { - return LoaderUtil.newInstanceOf(DEFAULT_FLOW_MESSAGE_FACTORY_CLASS); - } catch (final ReflectiveOperationException e) { - throw new IllegalStateException(e); - } + return DefaultFlowMessageFactory.INSTANCE; } @Override diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java index 7be09f0431b..e7cedb6bb3b 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java @@ -24,12 +24,14 @@ * @see ReadOnlyStringMap * @since 2.7 */ -public interface BiConsumer { +@FunctionalInterface +public interface BiConsumer extends java.util.function.BiConsumer { /** * Performs the operation given the specified arguments. * @param k the first input argument * @param v the second input argument */ + @Override void accept(K k, V v); } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java index bab3171e7f3..ef1f3b0b321 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java @@ -35,7 +35,6 @@ private LambdaUtil() {} * @return an array containing the results of evaluating the lambda expressions (or {@code null} if the suppliers * array was {@code null} */ - @SuppressWarnings("deprecation") public static Object[] getAll(final Supplier... suppliers) { if (suppliers == null) { return null; @@ -54,7 +53,6 @@ public static Object[] getAll(final Supplier... suppliers) { * @return the results of evaluating the lambda expression (or {@code null} if the supplier * was {@code null} */ - @SuppressWarnings("deprecation") public static Object get(final Supplier supplier) { if (supplier == null) { return null; @@ -83,7 +81,6 @@ public static Message get(final MessageSupplier supplier) { * @return the Message resulting from evaluating the lambda expression or the Message created by the factory for * supplied values that are not of type Message */ - @SuppressWarnings("deprecation") public static Message getMessage(final Supplier supplier, final MessageFactory messageFactory) { if (supplier == null) { return null; diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java index 8b135713505..d3776a1a744 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java @@ -33,12 +33,14 @@ * * @since 2.4 */ -public interface MessageSupplier { +@FunctionalInterface +public interface MessageSupplier extends Supplier { /** * Gets a Message. * * @return a Message */ + @Override Message get(); } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java index d061ccbd6db..46157290c18 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java @@ -24,6 +24,7 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.wiring.BundleRevision; public class OsgiServiceLocator { @@ -57,29 +58,53 @@ public static Stream loadServices(final Class serviceType, final Looku public static Stream loadServices(final Class serviceType, final Lookup lookup, final boolean verbose) { final Class lookupClass = Objects.requireNonNull(lookup, "lookup").lookupClass(); - final Bundle bundle = FrameworkUtil.getBundle(Objects.requireNonNull(lookupClass, "lookupClass")); - if (bundle != null) { + return loadServices(serviceType, lookupClass, StatusLogger.getLogger()); + } + + static Stream loadServices(final Class serviceType, final Class callerClass, final Logger logger) { + final Bundle bundle = FrameworkUtil.getBundle(callerClass); + if (bundle != null && !isFragment(bundle)) { final BundleContext ctx = bundle.getBundleContext(); if (ctx == null) { - if (verbose) { - StatusLogger.getLogger() - .error( - "Unable to load OSGI services: The bundle has no valid BundleContext for serviceType = {}, lookup = {}, lookupClass = {}, bundle = {}", - serviceType, - lookup, - lookupClass, - bundle); - } + logger.warn( + "Unable to load OSGi services for service {}: bundle {} (state {}) does not have a valid BundleContext", + serviceType::getName, + bundle::getSymbolicName, + () -> { + switch (bundle.getState()) { + case Bundle.UNINSTALLED: + return "UNINSTALLED"; + case Bundle.INSTALLED: + return "INSTALLED"; + case Bundle.RESOLVED: + return "RESOLVED"; + case Bundle.STARTING: + return "STARTING"; + case Bundle.STOPPING: + return "STOPPING"; + case Bundle.ACTIVE: + return "ACTIVE"; + default: + return "UNKNOWN"; + } + }); + } else { try { return ctx.getServiceReferences(serviceType, null).stream().map(ctx::getService); - } catch (Throwable e) { - if (verbose) { - StatusLogger.getLogger().error("Unable to load OSGI services for service {}", serviceType, e); - } + } catch (final Exception e) { + logger.error("Unable to load OSGI services for service {}", serviceType, e); } } } return Stream.empty(); } + + private static boolean isFragment(final Bundle bundle) { + try { + return (bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0; + } catch (final SecurityException ignored) { + return false; + } + } } 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 daf9163203a..310f432edd4 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 @@ -21,7 +21,6 @@ import aQute.bnd.annotation.spi.ServiceConsumer; import java.io.IOException; import java.io.InputStream; -import java.lang.invoke.MethodHandles; import java.nio.charset.Charset; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -486,7 +485,10 @@ private Environment(final PropertySource propertySource) { } sources.add(propertySource); // We don't log anything on the status logger. - ServiceLoaderUtil.loadServices(PropertySource.class, MethodHandles.lookup(), false, false) + ServiceLoaderUtil.safeStream( + PropertySource.class, + ServiceLoader.load(PropertySource.class, PropertiesUtil.class.getClassLoader()), + LOGGER) .forEach(sources::add); reload(); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java index a669bf71433..c02526b4a0e 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java @@ -24,13 +24,13 @@ import aQute.bnd.annotation.spi.ServiceConsumer; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; -import java.lang.invoke.MethodHandles; import java.net.URL; import java.util.Collection; import java.util.Comparator; import java.util.Enumeration; import java.util.HashSet; import java.util.Properties; +import java.util.ServiceLoader; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -152,7 +152,10 @@ static void lazyInit() { STARTUP_LOCK.lockInterruptibly(); try { if (PROVIDER == null) { - ServiceLoaderUtil.loadServices(Provider.class, MethodHandles.lookup(), false) + ServiceLoaderUtil.safeStream( + Provider.class, + ServiceLoader.load(Provider.class, ProviderUtil.class.getClassLoader()), + LOGGER) .filter(provider -> validVersion(provider.getVersions())) .forEach(ProviderUtil::addProvider); 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 cf906eab69b..30b56f83b56 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,30 +16,41 @@ */ 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 static java.util.Objects.requireNonNull; + +import aQute.bnd.annotation.baseline.BaselineIgnore; +import java.util.Collection; 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. + * An utility class to retrieve services in a safe way. + *

+ * This class should be considered internal. + *

+ *

+ * A common source of {@link ServiceLoader} failures, when running in a multi-classloader environment, is the + * presence of multiple classes with the same class name in the same classloader hierarchy. Since {@code + * ServiceLoader} retrieves services by class name, it is entirely possible that the registered services don't + * extend the required interface and cause an exception to be thrown by {@code ServiceLoader}. + *

+ *

+ * The purpose of this class is to: + *

+ *
    + *
  1. skip faulty services, allowing for a partial retrieval of the good ones,
  2. + *
  3. allow to integrate other sources of services like OSGi services.
  4. + *
*/ @InternalApi +@BaselineIgnore("2.24.0") public final class ServiceLoaderUtil { private static final int MAX_BROKEN_SERVICES = 8; @@ -47,110 +58,43 @@ public final class ServiceLoaderUtil { private ServiceLoaderUtil() {} /** - * Retrieves the available services from the caller's classloader. - * - * Broken services will be ignored. - * - * @param The service type. - * @param serviceType The class of the service. - * @param lookup The calling class data. - * @return A stream of service instances. - */ - public static Stream loadServices(final Class 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 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. + * Retrieves services registered with {@link ServiceLoader} + *

+ * It ignores the most common service loading errors. + *

+ * @param serviceType The service type to use for OSGi service retrieval. + * @param serviceLoader The service loader instance to use. + * @param logger The logger to use to report service failures. + * @return A stream of all correctly loaded services. + * @since 2.24.0 */ - public static Stream loadServices(final Class serviceType, final Lookup lookup, final boolean useTccl) { - return loadServices(serviceType, lookup, useTccl, true); - } - - static Stream loadServices( - final Class serviceType, final Lookup lookup, final boolean useTccl, final boolean verbose) { - final ClassLoader classLoader = lookup.lookupClass().getClassLoader(); - Stream 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)); - } - } - if (OsgiServiceLocator.isAvailable()) { - services = Stream.concat(services, OsgiServiceLocator.loadServices(serviceType, lookup, verbose)); - } - final Set> classes = new HashSet<>(); - // only the first occurrence of a class - return services.filter(service -> classes.add(service.getClass())); - } - - static Stream loadClassloaderServices( - final Class serviceType, final Lookup lookup, final ClassLoader classLoader, final boolean verbose) { - return StreamSupport.stream(new ServiceLoaderSpliterator(serviceType, lookup, classLoader, verbose), false); + public static Stream safeStream( + final Class serviceType, final ServiceLoader serviceLoader, final Logger logger) { + requireNonNull(serviceLoader, "serviceLoader"); + final Collection> classes = new HashSet<>(); + final Stream services = + StreamSupport.stream(new ServiceLoaderSpliterator<>(serviceType, serviceLoader, logger), false); + // Caller class may be null + final Class callerClass = StackLocatorUtil.getCallerClass(2); + final Stream allServices = OsgiServiceLocator.isAvailable() && callerClass != null + ? Stream.concat(services, OsgiServiceLocator.loadServices(serviceType, callerClass, logger)) + : services; + return allServices + // only the first occurrence of a class + .filter(service -> classes.add(service.getClass())); } - static Iterable callServiceLoader( - final Lookup lookup, final Class 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> action = (PrivilegedAction>) - callSite.getTarget() // - .bindTo(serviceType) - .bindTo(classLoader) - .invoke(); - final ServiceLoader 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) privilegedHandle.invoke(action); - } - return serviceLoader; - } catch (Throwable e) { - if (verbose) { - StatusLogger.getLogger().error("Unable to load services for service {}", serviceType, e); - } - } - return Collections.emptyList(); - } - - private static class ServiceLoaderSpliterator implements Spliterator { - - private final Iterator serviceIterator; - private final Logger logger; + private static final class ServiceLoaderSpliterator extends Spliterators.AbstractSpliterator { private final String serviceName; + private final Iterator serviceIterator; + private final Logger logger; - public ServiceLoaderSpliterator( - final Class 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 Class serviceType, final Iterable serviceLoader, final Logger logger) { + super(Long.MAX_VALUE, ORDERED | NONNULL | IMMUTABLE); + this.serviceName = serviceType.getName(); + this.serviceIterator = serviceLoader.iterator(); + this.logger = logger; } @Override @@ -162,33 +106,14 @@ public boolean tryAdvance(final Consumer action) { 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) { + logger.warn("Unable to load implementation for service {}", serviceName, e); + } catch (final Exception e) { + logger.warn("Unexpected exception while loading implementation for service {}", serviceName, e); throw e; } } return false; } - - @Override - public Spliterator 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/StackLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java index bc20af0daf3..e5b50fc7ca2 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java @@ -69,7 +69,10 @@ public final class StackLocator { Method getCallerClassMethod; int java7u25CompensationOffset = 0; try { - final Class sunReflectionClass = LoaderUtil.loadClass("sun.reflect.Reflection"); + // Do not use `LoaderUtil` here, since it causes a cycle of dependencies: + // LoaderUtil -> PropertiesUtil -> ServiceLoaderUtil -> StackLocator + final Class sunReflectionClass = + Class.forName("sun.reflect.Reflection", true, ClassLoader.getSystemClassLoader()); getCallerClassMethod = sunReflectionClass.getDeclaredMethod("getCallerClass", int.class); Object o = getCallerClassMethod.invoke(null, 0); getCallerClassMethod.invoke(null, 0); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java index aaa4d9b89a1..45ad5c667d2 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java @@ -31,14 +31,15 @@ * * @since 2.4 */ +@FunctionalInterface @InternalApi -@Deprecated -public interface Supplier { +public interface Supplier extends java.util.function.Supplier { /** * Gets a value. * * @return a value */ + @Override T get(); } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java index c1299311eaa..b610603b4be 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java @@ -17,7 +17,7 @@ package org.apache.logging.log4j.core.appender; import java.io.Serializable; -import java.lang.invoke.MethodHandles; +import java.util.ServiceLoader; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Core; import org.apache.logging.log4j.core.Filter; @@ -45,6 +45,7 @@ import org.apache.logging.log4j.core.net.ssl.SslConfiguration; import org.apache.logging.log4j.core.util.Booleans; import org.apache.logging.log4j.core.util.Integers; +import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.ServiceLoaderUtil; import org.apache.logging.log4j.util.Strings; @@ -300,8 +301,11 @@ public SmtpAppender build() { bufferSize, sslConfiguration, getFilter().toString()); - final MailManagerFactory factory = ServiceLoaderUtil.loadServices( - MailManagerFactory.class, MethodHandles.lookup()) + final MailManagerFactory factory = ServiceLoaderUtil.safeStream( + MailManagerFactory.class, + ServiceLoader.load( + MailManagerFactory.class, getClass().getClassLoader()), + StatusLogger.getLogger()) .findAny() .orElseGet(() -> SmtpManager.FACTORY); final MailManager smtpManager = AbstractManager.getManager(data.getManagerName(), factory, data); 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 24f34936e6d..332b877a51f 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 @@ -19,13 +19,13 @@ import aQute.bnd.annotation.Cardinality; import aQute.bnd.annotation.Resolution; import aQute.bnd.annotation.spi.ServiceConsumer; -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 org.apache.logging.log4j.Logger; import org.apache.logging.log4j.ThreadContext; @@ -79,7 +79,10 @@ public static void initServiceProviders() {} private static List getServiceProviders() { final List providers = new ArrayList<>(); - ServiceLoaderUtil.loadServices(ContextDataProvider.class, MethodHandles.lookup(), false) + ServiceLoaderUtil.safeStream( + ContextDataProvider.class, + ServiceLoader.load(ContextDataProvider.class, ThreadContextDataInjector.class.getClassLoader()), + LOGGER) .forEach(providers::add); 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 491c212f6f0..1761498087b 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 @@ -20,12 +20,12 @@ import aQute.bnd.annotation.Resolution; import aQute.bnd.annotation.spi.ServiceConsumer; 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; @@ -143,7 +143,8 @@ public void run() { public WatchManager(final ConfigurationScheduler scheduler) { this.scheduler = Objects.requireNonNull(scheduler, "scheduler"); - eventServiceList = ServiceLoaderUtil.loadServices(WatchEventService.class, MethodHandles.lookup(), true) + eventServiceList = ServiceLoaderUtil.safeStream( + WatchEventService.class, ServiceLoader.load(WatchEventService.class), logger) .collect(Collectors.toList()); } diff --git a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java index 9022d9abeb8..0f371f43ef0 100644 --- a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java +++ b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java @@ -18,6 +18,7 @@ import aQute.bnd.annotation.Resolution; import aQute.bnd.annotation.spi.ServiceProvider; +import org.apache.logging.log4j.spi.LoggerContextFactory; import org.apache.logging.log4j.spi.Provider; /** @@ -27,7 +28,20 @@ */ @ServiceProvider(value = Provider.class, resolution = Resolution.OPTIONAL) public class JULProvider extends Provider { + private static final LoggerContextFactory CONTEXT_FACTORY = new JULLoggerContextFactory(); + public JULProvider() { - super(20, "2.6.0", JULLoggerContextFactory.class, null); + super(20, CURRENT_VERSION); + } + + @Override + public LoggerContextFactory getLoggerContextFactory() { + return CONTEXT_FACTORY; + } + + @Override + public String getThreadContextMap() { + // JUL does not provide an MDC implementation + return NO_OP_CONTEXT_MAP; } } diff --git a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java index f333fffe246..aa117c7995c 100644 --- a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java +++ b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java @@ -21,7 +21,7 @@ * @author Michael Vorburger.ch for Google */ @Export -@Version("2.20.1") +@Version("2.24.0") package org.apache.logging.log4j.tojul; import org.osgi.annotation.bundle.Export; diff --git a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java index b8514c4f632..318d7937f66 100644 --- a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java +++ b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java @@ -18,14 +18,30 @@ import aQute.bnd.annotation.Resolution; import aQute.bnd.annotation.spi.ServiceProvider; +import org.apache.logging.log4j.spi.LoggerContextFactory; import org.apache.logging.log4j.spi.Provider; +import org.apache.logging.log4j.spi.ThreadContextMap; /** * Bind the Log4j API to SLF4J. */ @ServiceProvider(value = Provider.class, resolution = Resolution.OPTIONAL) public class SLF4JProvider extends Provider { + + private static final LoggerContextFactory CONTEXT_FACTORY = new SLF4JLoggerContextFactory(); + private static final ThreadContextMap THREAD_CONTEXT_MAP = new MDCContextMap(); + public SLF4JProvider() { - super(15, "2.6.0", SLF4JLoggerContextFactory.class, MDCContextMap.class); + super(15, CURRENT_VERSION); + } + + @Override + public LoggerContextFactory getLoggerContextFactory() { + return CONTEXT_FACTORY; + } + + @Override + public ThreadContextMap getThreadContextMapInstance() { + return THREAD_CONTEXT_MAP; } } diff --git a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java index e354601ca71..ba4cb130be1 100644 --- a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java +++ b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java @@ -18,7 +18,7 @@ * SLF4J support. */ @Export -@Version("2.20.1") +@Version("2.24.0") package org.apache.logging.slf4j; import org.osgi.annotation.bundle.Export; diff --git a/src/changelog/.2.x.x/1539_graalvm_friendly.xml b/src/changelog/.2.x.x/1539_graalvm_friendly.xml new file mode 100644 index 00000000000..74964f43564 --- /dev/null +++ b/src/changelog/.2.x.x/1539_graalvm_friendly.xml @@ -0,0 +1,8 @@ + + + + Fix usage of `log4j-api` in GraalVM without additional reachability data. +