This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit e4dfd1d4b6d5ade816d548ea45d5383f6815b52a Author: Piotr P. Karwasz <[email protected]> AuthorDate: Mon Nov 13 10:20:52 2023 +0100 Replace `Class#newInstance` invocations with `LoaderUtil` --- .../src/main/java/org/apache/log4j/jmx/Agent.java | 11 +++--- .../log4j/message/DefaultFlowMessageFactory.java | 1 - .../org/apache/logging/log4j/util/LoaderUtil.java | 36 +++++++++++++++++-- .../core/async/AsyncQueueFullPolicyFactory.java | 12 ++++--- .../core/async/AsyncWaitStrategyFactoryConfig.java | 9 ++++- .../logging/log4j/core/async/DisruptorUtil.java | 42 ++++++++++------------ .../core/impl/ContextDataInjectorFactory.java | 25 ++++++------- .../logging/log4j/core/util/OptionConverter.java | 3 +- .../jpa/converter/ThrowableAttributeConverter.java | 2 +- 9 files changed, 84 insertions(+), 57 deletions(-) diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/jmx/Agent.java b/log4j-1.2-api/src/main/java/org/apache/log4j/jmx/Agent.java index e893de26b6..634bd86691 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/jmx/Agent.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/jmx/Agent.java @@ -25,6 +25,7 @@ import javax.management.MBeanServerFactory; import javax.management.ObjectName; import org.apache.log4j.Logger; +import org.apache.logging.log4j.util.LoaderUtil; /** * Manages an instance of com.sun.jdmk.comm.HtmlAdapterServer which was provided for demonstration purposes in the Java @@ -53,13 +54,9 @@ public class Agent { private static Object createServer() { Object newInstance = null; try { - newInstance = Class.forName("com.sun.jdmk.comm.HtmlAdapterServer").newInstance(); - } catch (final ClassNotFoundException ex) { - throw new RuntimeException(ex.toString()); - } catch (final InstantiationException ex) { - throw new RuntimeException(ex.toString()); - } catch (final IllegalAccessException ex) { - throw new RuntimeException(ex.toString()); + newInstance = LoaderUtil.newInstanceOf("com.sun.jdmk.comm.HtmlAdapterServer"); + } catch (final ReflectiveOperationException ex) { + throw new RuntimeException(ex); } return newInstance; } 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 e1a528e579..220233d3d2 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 @@ -48,7 +48,6 @@ public class DefaultFlowMessageFactory implements FlowMessageFactory { * @param exitText the text to use for trace exit, like {@code "Exit"}. */ public DefaultFlowMessageFactory(final String entryText, final String exitText) { - super(); this.entryText = entryText; this.exitText = exitText; this.messageFactory = LoggingSystem.getMessageFactory(); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java index 6f73e2d8fc..ec1299f326 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java @@ -215,7 +215,7 @@ public final class LoaderUtil { * @throws ExceptionInInitializerError if an exception is thrown during class initialization * @throws LinkageError if the linkage of the class fails for any other reason * @see #loadClass(String) - * @since 3.0.0 + * @since 2.22.0 */ public static Class<?> loadClassUnchecked(final String className) { try { @@ -259,7 +259,7 @@ public final class LoaderUtil { * @throws InternalException if an exception is thrown by the constructor * @throws InstantiationError if the provided class is abstract or an interface * @throws IllegalAccessError if the class cannot be accessed - * @since 3.0.0 + * @since 2.22.0 */ public static <T> T newInstanceOfUnchecked(final Class<T> clazz) { try { @@ -305,6 +305,35 @@ public final class LoaderUtil { return newInstanceOf(clazz); } + /** + * Loads and instantiates a class given by a property name. + * + * @param propertyKey The property name to look up a class name for. + * @param clazz The class to cast it to. + * @param defaultSupplier Supplier of a default value if the property is not present. + * @param <T> The type to cast it to. + * @return new instance of the class given in the property or {@code null} if the property was unset. + * @throws ClassNotFoundException if the class isn't available to the usual ClassLoaders + * @throws ExceptionInInitializerError if an exception was thrown while initializing the class + * @throws LinkageError if the linkage of the class fails for any other reason + * @throws ClassCastException if the class is not compatible with the generic type parameter provided + * @throws NoSuchMethodException if no zero-arg constructor exists + * @throws SecurityException if this class is not allowed to access declared members of the provided class + * @throws IllegalAccessException if the class can't be instantiated through a public constructor + * @throws InstantiationException if the provided class is abstract or an interface + * @throws InvocationTargetException if an exception is thrown by the constructor + * @since 3.0.0 + */ + public static <T> T newCheckedInstanceOfProperty( + final PropertyKey propertyKey, final Class<T> clazz, final Supplier<T> defaultSupplier) + throws ReflectiveOperationException { + final String className = PropertiesUtil.getProperties().getStringProperty(propertyKey); + if (className == null) { + return defaultSupplier.get(); + } + return newCheckedInstanceOf(className, clazz); + } + /** * Loads and instantiates a class by name using its default constructor. All checked reflective operation * exceptions are translated into corresponding {@link LinkageError} classes. @@ -321,6 +350,7 @@ public final class LoaderUtil { * @throws InstantiationError if the provided class is abstract or an interface * @throws IllegalAccessError if the class cannot be accessed * @throws LinkageError if the linkage of the class fails for any other reason + * @since 2.22.0 */ public static <T> T newInstanceOfUnchecked(final String className) { final Class<T> clazz = Cast.cast(loadClassUnchecked(className)); @@ -367,7 +397,7 @@ public final class LoaderUtil { * @throws InstantiationError if the provided class is abstract or an interface * @throws IllegalAccessError if the class cannot be accessed * @throws LinkageError if the linkage of the class fails for any other reason - * @since 3.0.0 + * @since 2.22.0 */ public static <T> T newInstanceOfUnchecked(final String className, final Class<T> supertype) { final Class<? extends T> clazz = loadClassUnchecked(className).asSubclass(supertype); diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncQueueFullPolicyFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncQueueFullPolicyFactory.java index 0f71b4bb2e..bc5753ed4c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncQueueFullPolicyFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncQueueFullPolicyFactory.java @@ -19,8 +19,8 @@ package org.apache.logging.log4j.core.async; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.impl.Log4jPropertyKey; -import org.apache.logging.log4j.core.util.Loader; import org.apache.logging.log4j.status.StatusLogger; +import org.apache.logging.log4j.util.LoaderUtil; import org.apache.logging.log4j.util.PropertiesUtil; import org.apache.logging.log4j.util.PropertyEnvironment; @@ -90,12 +90,14 @@ public class AsyncQueueFullPolicyFactory { private static AsyncQueueFullPolicy createCustomRouter(final String router) { try { - final Class<? extends AsyncQueueFullPolicy> cls = Loader.loadClass(router).asSubclass(AsyncQueueFullPolicy.class); LOGGER.debug("Creating custom AsyncQueueFullPolicy '{}'", router); - return cls.newInstance(); + return LoaderUtil.newCheckedInstanceOf(router, AsyncQueueFullPolicy.class); } catch (final Exception ex) { - LOGGER.debug("Using DefaultAsyncQueueFullPolicy. Could not create custom AsyncQueueFullPolicy '{}': {}", router, - ex.toString()); + LOGGER.debug( + "Using DefaultAsyncQueueFullPolicy. Could not create custom AsyncQueueFullPolicy '{}': {}", + router, + ex.getMessage(), + ex); return new DefaultAsyncQueueFullPolicy(); } } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfig.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfig.java index b6674ab9f8..7c8c661dcd 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfig.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfig.java @@ -88,8 +88,15 @@ public class AsyncWaitStrategyFactoryConfig { public AsyncWaitStrategyFactory createWaitStrategyFactory() { try { return LoaderUtil.newCheckedInstanceOf(factoryClassName, AsyncWaitStrategyFactory.class); + } catch (final ClassCastException e) { + LOGGER.error("Ignoring factory '{}': it is not assignable to AsyncWaitStrategyFactory", factoryClassName); + return null; } catch (ReflectiveOperationException | LinkageError e) { - LOGGER.info("Invalid implementation class name value: error creating AsyncWaitStrategyFactory {}: {}", factoryClassName, e); + LOGGER.info( + "Invalid implementation class name value: error creating AsyncWaitStrategyFactory {}: {}", + factoryClassName, + e.getMessage(), + e); return null; } } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java index b059ad8abf..71c1261f65 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java @@ -24,8 +24,8 @@ import com.lmax.disruptor.WaitStrategy; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.impl.Log4jPropertyKey; import org.apache.logging.log4j.core.util.Integers; -import org.apache.logging.log4j.core.util.Loader; import org.apache.logging.log4j.status.StatusLogger; +import org.apache.logging.log4j.util.LoaderUtil; import org.apache.logging.log4j.util.PropertiesUtil; import org.apache.logging.log4j.util.PropertyKey; @@ -84,35 +84,31 @@ final class DisruptorUtil { } static ExceptionHandler<RingBufferLogEvent> getAsyncLoggerExceptionHandler() { - final String cls = PropertiesUtil.getProperties().getStringProperty(Log4jPropertyKey.ASYNC_LOGGER_EXCEPTION_HANDLER_CLASS_NAME); - if (cls == null) { - return new AsyncLoggerDefaultExceptionHandler(); - } + ExceptionHandler<RingBufferLogEvent> handler = null; try { - @SuppressWarnings("unchecked") - final Class<? extends ExceptionHandler<RingBufferLogEvent>> klass = - (Class<? extends ExceptionHandler<RingBufferLogEvent>>) Loader.loadClass(cls); - return klass.newInstance(); - } catch (final Exception e) { - LOGGER.debug("Invalid {} value: error creating {}: ", Log4jPropertyKey.ASYNC_LOGGER_EXCEPTION_HANDLER_CLASS_NAME, cls, e); - return new AsyncLoggerDefaultExceptionHandler(); + handler = + LoaderUtil.newCheckedInstanceOfProperty(Log4jPropertyKey.ASYNC_LOGGER_EXCEPTION_HANDLER_CLASS_NAME, ExceptionHandler.class); + } catch (final ReflectiveOperationException e) { + LOGGER.debug("Invalid AsyncLogger.ExceptionHandler value: {}", e.getMessage(), e); + } + if (handler != null) { + return handler; } + return new AsyncLoggerDefaultExceptionHandler(); } static ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper> getAsyncLoggerConfigExceptionHandler() { - final String cls = PropertiesUtil.getProperties().getStringProperty(Log4jPropertyKey.ASYNC_CONFIG_EXCEPTION_HANDLER_CLASS_NAME); - if (cls == null) { - return new AsyncLoggerConfigDefaultExceptionHandler(); - } + ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper> handler = null; try { - @SuppressWarnings("unchecked") - final Class<? extends ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper>> klass = - (Class<? extends ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper>>) Loader.loadClass(cls); - return klass.newInstance(); - } catch (final Exception e) { - LOGGER.debug("Invalid {} value: error creating {}: ", Log4jPropertyKey.ASYNC_CONFIG_EXCEPTION_HANDLER_CLASS_NAME, cls, e); - return new AsyncLoggerConfigDefaultExceptionHandler(); + handler = LoaderUtil.newCheckedInstanceOfProperty( + Log4jPropertyKey.ASYNC_CONFIG_EXCEPTION_HANDLER_CLASS_NAME, ExceptionHandler.class); + } catch (final ReflectiveOperationException e) { + LOGGER.debug("Invalid AsyncLogger.ExceptionHandler value: {}", e.getMessage(), e); + } + if (handler != null) { + return handler; } + return new AsyncLoggerConfigDefaultExceptionHandler(); } /** diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataInjectorFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataInjectorFactory.java index b3c24254f2..ed014d9d52 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataInjectorFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataInjectorFactory.java @@ -19,12 +19,11 @@ package org.apache.logging.log4j.core.impl; import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.ContextDataInjector; import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.util.Loader; import org.apache.logging.log4j.spi.CopyOnWrite; import org.apache.logging.log4j.spi.DefaultThreadContextMap; import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap; import org.apache.logging.log4j.status.StatusLogger; -import org.apache.logging.log4j.util.PropertiesUtil; +import org.apache.logging.log4j.util.LoaderUtil; import org.apache.logging.log4j.util.ReadOnlyStringMap; /** @@ -66,21 +65,17 @@ public class ContextDataInjectorFactory { * @see ContextDataInjector */ public static ContextDataInjector createInjector() { - final String className = PropertiesUtil.getProperties().getStringProperty(Log4jPropertyKey.THREAD_CONTEXT_DATA_INJECTOR_CLASS_NAME); - if (className == null) { - return createDefaultInjector(); - } + ContextDataInjector injector = null; try { - final Class<? extends ContextDataInjector> cls = Loader.loadClass(className).asSubclass( - ContextDataInjector.class); - return cls.newInstance(); - } catch (final Exception dynamicFailed) { - final ContextDataInjector result = createDefaultInjector(); - StatusLogger.getLogger().warn( - "Could not create ContextDataInjector for '{}', using default {}: {}", - className, result.getClass().getName(), dynamicFailed); - return result; + injector = + LoaderUtil.newCheckedInstanceOfProperty(Log4jPropertyKey.THREAD_CONTEXT_DATA_INJECTOR_CLASS_NAME, ContextDataInjector.class); + } catch (final ReflectiveOperationException e) { + StatusLogger.getLogger().warn("Could not create ContextDataInjector: {}", e.getMessage(), e); + } + if (injector != null) { + return injector; } + return createDefaultInjector(); } private static ContextDataInjector createDefaultInjector() { diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OptionConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OptionConverter.java index 8339b12f6f..9d7af6d5e6 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OptionConverter.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/OptionConverter.java @@ -24,6 +24,7 @@ import java.util.Properties; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.status.StatusLogger; +import org.apache.logging.log4j.util.LoaderUtil; import org.apache.logging.log4j.util.PropertiesUtil; import org.apache.logging.log4j.util.Strings; @@ -303,7 +304,7 @@ public final class OptionConverter { superClass.getName(), superClass.getClassLoader(), classObj.getTypeName(), classObj.getName()); return defaultValue; } - return classObj.newInstance(); + return LoaderUtil.newInstanceOf(classObj); } catch (final Exception e) { LOGGER.error("Could not instantiate class [{}].", className, e); } diff --git a/log4j-jpa/src/main/java/org/apache/logging/log4j/jpa/converter/ThrowableAttributeConverter.java b/log4j-jpa/src/main/java/org/apache/logging/log4j/jpa/converter/ThrowableAttributeConverter.java index 2d850592d6..e003de57c1 100644 --- a/log4j-jpa/src/main/java/org/apache/logging/log4j/jpa/converter/ThrowableAttributeConverter.java +++ b/log4j-jpa/src/main/java/org/apache/logging/log4j/jpa/converter/ThrowableAttributeConverter.java @@ -230,7 +230,7 @@ public class ThrowableAttributeConverter implements AttributeConverter<Throwable private Throwable getThrowable(final Class<Throwable> throwableClass) { try { - return throwableClass.newInstance(); + return LoaderUtil.newInstanceOf(throwableClass); } catch (final Exception e) { return null; }
