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

Reply via email to