This is an automated email from the ASF dual-hosted git repository.

gtully pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git

commit f5973d53e67e6e7fc9eb5c45a30bedc02a76f437
Author: Gary Tully <gary.tu...@gmail.com>
AuthorDate: Thu May 9 11:30:57 2024 +0100

    ARTEMIS-4766 - validate type before newInstance calls
---
 .../apache/activemq/artemis/cli/commands/Run.java  |  4 +-
 .../cli/commands/messages/DestAbstract.java        |  3 +-
 .../factory/security/SecurityManagerHandler.java   |  2 +-
 .../activemq/artemis/utils/ClassloadingUtil.java   | 61 ++++++++++------------
 .../core/client/impl/ClientSessionFactoryImpl.java |  2 +-
 .../core/client/impl/ServerLocatorImpl.java        |  4 +-
 .../wireformat/FederationStreamConnectMessage.java |  3 +-
 .../remoting/impl/TransportConfigurationUtil.java  |  6 +--
 .../artemis/core/remoting/impl/ssl/SSLSupport.java |  2 +-
 .../jdbc/store/drivers/JDBCDataSourceUtils.java    |  3 +-
 .../jms/client/ActiveMQConnectionFactory.java      |  2 +-
 .../artemis-lockmanager-api/pom.xml                |  8 +++
 .../lockmanager/DistributedLockManager.java        |  8 ++-
 .../core/config/impl/ConfigurationImpl.java        | 43 ++++++++-------
 .../deployers/impl/FileConfigurationParser.java    |  6 +--
 .../core/server/impl/ServiceRegistryImpl.java      | 14 ++---
 .../artemis/component/WebServerComponent.java      |  3 +-
 17 files changed, 95 insertions(+), 79 deletions(-)

diff --git 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
index e5200a9727..219a581306 100644
--- 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
+++ 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
@@ -39,6 +39,7 @@ import org.apache.activemq.artemis.dto.ManagementContextDTO;
 import org.apache.activemq.artemis.integration.Broker;
 import 
org.apache.activemq.artemis.integration.bootstrap.ActiveMQBootstrapLogger;
 import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import org.apache.activemq.artemis.utils.ReusableLatch;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Option;
@@ -139,8 +140,7 @@ public class Run extends LockAbstract {
             "system-" + systemWebPropertyPrefix, System.getProperties(), 
systemWebPropertyPrefix);
 
          for (ComponentDTO componentDTO : broker.components) {
-            Class clazz = 
this.getClass().getClassLoader().loadClass(componentDTO.componentClassName);
-            ExternalComponent component = (ExternalComponent) 
clazz.getDeclaredConstructor(null).newInstance();
+            ExternalComponent component = (ExternalComponent) 
ClassloadingUtil.getInstanceWithTypeCheck(componentDTO.componentClassName, 
ExternalComponent.class, this.getClass().getClassLoader());
             component.configure(componentDTO, getBrokerInstance(), 
getBrokerHome());
             server.getServer().addExternalComponent(component, true);
             assert component.isStarted();
diff --git 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java
 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java
index 88c87c28f0..f059d10a03 100644
--- 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java
+++ 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java
@@ -25,6 +25,7 @@ import org.apache.activemq.artemis.cli.commands.ActionContext;
 import org.apache.activemq.artemis.cli.factory.serialize.MessageSerializer;
 import org.apache.activemq.artemis.cli.factory.serialize.XMLMessageSerializer;
 import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import picocli.CommandLine.Option;
 
 public class DestAbstract extends ConnectionAbstract {
@@ -53,7 +54,7 @@ public class DestAbstract extends ConnectionAbstract {
    protected MessageSerializer getMessageSerializer() {
       if (serializer != null) {
          try {
-            return (MessageSerializer) 
Class.forName(serializer).getConstructor().newInstance();
+            return (MessageSerializer) 
ClassloadingUtil.getInstanceWithTypeCheck(serializer, MessageSerializer.class, 
this.getClass().getClassLoader());
          } catch (Exception e) {
             getActionContext().err.println("Error: unable to instantiate 
serializer class: " + serializer);
             getActionContext().err.println("Defaulting to: " + 
XMLMessageSerializer.class.getName());
diff --git 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/security/SecurityManagerHandler.java
 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/security/SecurityManagerHandler.java
index 4c1e10b2d3..61d9839182 100644
--- 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/security/SecurityManagerHandler.java
+++ 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/security/SecurityManagerHandler.java
@@ -39,6 +39,6 @@ public class SecurityManagerHandler implements 
SecurityHandler {
             properties.put(property.key, property.value);
          }
       }
-      return 
AccessController.doPrivileged((PrivilegedAction<ActiveMQSecurityManager>) () -> 
(ActiveMQSecurityManager) 
ClassloadingUtil.newInstanceFromClassLoader(SecurityManagerHandler.class, 
clazz)).init(properties);
+      return 
AccessController.doPrivileged((PrivilegedAction<ActiveMQSecurityManager>) () -> 
(ActiveMQSecurityManager) 
ClassloadingUtil.newInstanceFromClassLoader(SecurityManagerHandler.class, 
clazz, ActiveMQSecurityManager.class)).init(properties);
    }
 }
diff --git 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
index 2a26c413a7..2a4019947f 100644
--- 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
+++ 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
@@ -16,6 +16,7 @@
  */
 package org.apache.activemq.artemis.utils;
 
+import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
 import java.util.Properties;
 
@@ -36,15 +37,16 @@ public final class ClassloadingUtil {
 
    private static final String INSTANTIATION_EXCEPTION_MESSAGE = "Your class 
must have a constructor without arguments. If it is an inner class, it must be 
static!";
 
-   public static Object newInstanceFromClassLoader(final String className) {
-      return newInstanceFromClassLoader(ClassloadingUtil.class, className);
+   public static Object newInstanceFromClassLoader(final String className, 
Class<?> expectedType) {
+      return newInstanceFromClassLoader(ClassloadingUtil.class, className, 
expectedType);
    }
 
-   public static Object newInstanceFromClassLoader(final Class<?> classOwner, 
final String className) {
+   public static Object newInstanceFromClassLoader(final Class<?> classOwner,
+                                                   final String className,
+                                                   Class<?> expectedType) {
       ClassLoader loader = classOwner.getClassLoader();
       try {
-         Class<?> clazz = loader.loadClass(className);
-         return clazz.newInstance();
+         return getInstanceWithTypeCheck(className, expectedType, loader);
       } catch (Throwable t) {
          if (t instanceof InstantiationException) {
             System.out.println(INSTANTIATION_EXCEPTION_MESSAGE);
@@ -54,48 +56,39 @@ public final class ClassloadingUtil {
             throw new RuntimeException("No local context classloader", t);
 
          try {
-            return loader.loadClass(className).newInstance();
+            return getInstanceWithTypeCheck(className, expectedType, loader);
          } catch (InstantiationException e) {
             throw new RuntimeException(INSTANTIATION_EXCEPTION_MESSAGE + " " + 
className, e);
          } catch (ClassNotFoundException e) {
             throw new IllegalStateException(e);
-         } catch (IllegalAccessException e) {
+         } catch (IllegalAccessException | InvocationTargetException | 
NoSuchMethodException e) {
             throw new RuntimeException(e);
          }
       }
    }
 
-   public static Object newInstanceFromClassLoader(final String className, 
Object... objs) {
-      return newInstanceFromClassLoader(ClassloadingUtil.class, className, 
objs);
+   public static Object getInstanceWithTypeCheck(String className,
+                                   Class<?> expectedType,
+                                   ClassLoader loader) throws 
ClassNotFoundException, InstantiationException, IllegalAccessException, 
InvocationTargetException, NoSuchMethodException {
+      final Class<?> clazz = loadWithCheck(className, expectedType, loader);
+      return clazz.getDeclaredConstructor().newInstance();
    }
 
-   public static Object newInstanceFromClassLoader(final Class<?> classOwner, 
final String className, Object... objs) {
-      ClassLoader loader = classOwner.getClassLoader();
-      try {
-         Class<?>[] parametersType = new Class<?>[objs.length];
-         for (int i = 0; i < objs.length; i++) {
-            parametersType[i] = objs[i].getClass();
-         }
-         Class<?> clazz = loader.loadClass(className);
-         return clazz.getConstructor(parametersType).newInstance(objs);
-      } catch (Throwable t) {
-         if (t instanceof InstantiationException) {
-            System.out.println(INSTANTIATION_EXCEPTION_MESSAGE);
-         }
-         loader = Thread.currentThread().getContextClassLoader();
-         if (loader == null)
-            throw new RuntimeException("No local context classloader", t);
+   public static Object getInstanceForParamsWithTypeCheck(String className,
+                                                 Class<?> expectedType,
+                                                 ClassLoader loader,  
Class<?>[] parameterTypes, Object... params) throws ClassNotFoundException, 
InstantiationException, IllegalAccessException, InvocationTargetException, 
NoSuchMethodException {
+      final Class<?> clazz = loadWithCheck(className, expectedType, loader);
+      return clazz.getDeclaredConstructor(parameterTypes).newInstance(params);
+   }
 
-         try {
-            return loader.loadClass(className).newInstance();
-         } catch (InstantiationException e) {
-            throw new RuntimeException(INSTANTIATION_EXCEPTION_MESSAGE + " " + 
className, e);
-         } catch (ClassNotFoundException e) {
-            throw new IllegalStateException(e);
-         } catch (IllegalAccessException e) {
-            throw new RuntimeException(e);
-         }
+   private static Class<?> loadWithCheck(String className,
+                                         Class<?> expectedType,
+                                         ClassLoader loader) throws 
ClassNotFoundException {
+      Class<?> clazz = loader.loadClass(className);
+      if (!expectedType.isAssignableFrom(clazz)) {
+         throw new IllegalStateException("clazz [" + className + "] is not 
assignable from expected type: " + expectedType);
       }
+      return clazz;
    }
 
    public static URL findResource(final String resourceName) {
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java
index d5fa8a6ac9..d7dc12f61b 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionFactoryImpl.java
@@ -1153,7 +1153,7 @@ public class ClientSessionFactoryImpl implements 
ClientSessionFactoryInternal, C
       return AccessController.doPrivileged(new 
PrivilegedAction<ConnectorFactory>() {
          @Override
          public ConnectorFactory run() {
-            return (ConnectorFactory) 
ClassloadingUtil.newInstanceFromClassLoader(ClientSessionFactoryImpl.class, 
connectorFactoryClassName);
+            return (ConnectorFactory) 
ClassloadingUtil.newInstanceFromClassLoader(ClientSessionFactoryImpl.class, 
connectorFactoryClassName, ConnectorFactory.class);
          }
       });
    }
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ServerLocatorImpl.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ServerLocatorImpl.java
index 9c67b3fe52..165b5518fe 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ServerLocatorImpl.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ServerLocatorImpl.java
@@ -256,7 +256,7 @@ public final class ServerLocatorImpl implements 
ServerLocatorInternal, Discovery
       AccessController.doPrivileged(new PrivilegedAction<Object>() {
          @Override
          public Object run() {
-               loadBalancingPolicy = (ConnectionLoadBalancingPolicy) 
ClassloadingUtil.newInstanceFromClassLoader(ServerLocatorImpl.class, 
config.connectionLoadBalancingPolicyClassName);
+               loadBalancingPolicy = (ConnectionLoadBalancingPolicy) 
ClassloadingUtil.newInstanceFromClassLoader(ServerLocatorImpl.class, 
config.connectionLoadBalancingPolicyClassName, 
ConnectionLoadBalancingPolicy.class);
                return null;
          }
       });
@@ -1949,7 +1949,7 @@ public final class ServerLocatorImpl implements 
ServerLocatorInternal, Discovery
 
             String[] arrayInterceptor = interceptorList.split(",");
             for (String strValue : arrayInterceptor) {
-               Interceptor interceptor = (Interceptor) 
ClassloadingUtil.newInstanceFromClassLoader(ServerLocatorImpl.class, 
strValue.trim());
+               Interceptor interceptor = (Interceptor) 
ClassloadingUtil.newInstanceFromClassLoader(ServerLocatorImpl.class, 
strValue.trim(), Interceptor.class);
                interceptors.add(interceptor);
             }
             return null;
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/FederationStreamConnectMessage.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/FederationStreamConnectMessage.java
index ac867dcd30..64bf82365f 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/FederationStreamConnectMessage.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/FederationStreamConnectMessage.java
@@ -25,6 +25,7 @@ import 
org.apache.activemq.artemis.core.config.federation.FederationPolicy;
 import 
org.apache.activemq.artemis.core.config.federation.FederationStreamConfiguration;
 import 
org.apache.activemq.artemis.core.config.federation.FederationTransformerConfiguration;
 import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import org.apache.activemq.artemis.utils.Preconditions;
 
 public abstract class FederationStreamConnectMessage <T extends 
FederationStreamConfiguration> extends PacketImpl {
@@ -148,7 +149,7 @@ public abstract class FederationStreamConnectMessage <T 
extends FederationStream
 
    private FederationPolicy getFederationPolicy(String clazz) {
       try {
-         return (FederationPolicy) 
Class.forName(clazz).getConstructor((Class<?>[]) null).newInstance();
+         return (FederationPolicy) 
ClassloadingUtil.getInstanceWithTypeCheck(clazz, FederationPolicy.class, 
this.getClass().getClassLoader());
       } catch (Exception e) {
          throw new IllegalStateException("Error. Unable to instantiate 
FederationPolicy: " + e.getMessage(), e);
       }
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
index 33bfbac36b..20839917eb 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
@@ -46,7 +46,7 @@ public class TransportConfigurationUtil {
       }
 
       if (!DEFAULTS.containsKey(className)) {
-         Object object = instantiateObject(className);
+         Object object = instantiateObject(className, 
TransportConfigurationHelper.class);
          if (object != null && object instanceof TransportConfigurationHelper) 
{
 
             DEFAULTS.put(className, ((TransportConfigurationHelper) 
object).getDefaults());
@@ -60,12 +60,12 @@ public class TransportConfigurationUtil {
       return cloneDefaults(DEFAULTS.get(className));
    }
 
-   private static Object instantiateObject(final String className) {
+   private static Object instantiateObject(final String className, final Class 
expectedType) {
       return AccessController.doPrivileged(new PrivilegedAction<Object>() {
          @Override
          public Object run() {
             try {
-               return 
ClassloadingUtil.newInstanceFromClassLoader(TransportConfigurationUtil.class, 
className);
+               return 
ClassloadingUtil.newInstanceFromClassLoader(TransportConfigurationUtil.class, 
className, expectedType);
             } catch (IllegalStateException e) {
                return null;
             }
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java
index eb4d04cdbe..8c600e4e25 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/SSLSupport.java
@@ -278,7 +278,7 @@ public class SSLSupport {
 
    private TrustManagerFactory loadTrustManagerFactory() throws Exception {
       if (trustManagerFactoryPlugin != null) {
-         return 
AccessController.doPrivileged((PrivilegedAction<TrustManagerFactory>) () -> 
((TrustManagerFactoryPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(SSLSupport.class, 
trustManagerFactoryPlugin)).getTrustManagerFactory());
+         return 
AccessController.doPrivileged((PrivilegedAction<TrustManagerFactory>) () -> 
((TrustManagerFactoryPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(SSLSupport.class, 
trustManagerFactoryPlugin, 
TrustManagerFactoryPlugin.class)).getTrustManagerFactory());
       } else if (trustAll) {
          //This is useful for testing but not should be used outside of that 
purpose
          return InsecureTrustManagerFactory.INSTANCE;
diff --git 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/JDBCDataSourceUtils.java
 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/JDBCDataSourceUtils.java
index d71e19b9ec..0018443800 100644
--- 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/JDBCDataSourceUtils.java
+++ 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/JDBCDataSourceUtils.java
@@ -17,6 +17,7 @@
 package org.apache.activemq.artemis.jdbc.store.drivers;
 
 import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import org.apache.commons.beanutils.PropertyUtils;
 
 import javax.sql.DataSource;
@@ -32,7 +33,7 @@ public class JDBCDataSourceUtils {
          .map(key -> key + "=" + (key.equalsIgnoreCase("password") ? "****" : 
dataSourceProperties.get(key)))
          .collect(Collectors.joining(", ", "{", "}")));
       try {
-         DataSource dataSource = (DataSource) 
Class.forName(dataSourceClassName).getDeclaredConstructor().newInstance();
+         DataSource dataSource = (DataSource) 
ClassloadingUtil.getInstanceWithTypeCheck(dataSourceClassName, 
DataSource.class, JDBCDataSourceUtils.class.getClassLoader());
          for (Map.Entry<String, Object> entry : 
dataSourceProperties.entrySet()) {
             PropertyUtils.setProperty(dataSource, entry.getKey(), 
entry.getValue());
          }
diff --git 
a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
 
b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
index 7927d4f273..b8e89c708f 100644
--- 
a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
+++ 
b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
@@ -158,7 +158,7 @@ public class ActiveMQConnectionFactory extends JNDIStorable 
implements Connectio
          AccessController.doPrivileged(new PrivilegedAction<Object>() {
             @Override
             public Object run() {
-               ClientProtocolManagerFactory protocolManagerFactory = 
(ClientProtocolManagerFactory) 
ClassloadingUtil.newInstanceFromClassLoader(ActiveMQConnectionFactory.class, 
protocolManagerFactoryStr);
+               ClientProtocolManagerFactory protocolManagerFactory = 
(ClientProtocolManagerFactory) 
ClassloadingUtil.newInstanceFromClassLoader(ActiveMQConnectionFactory.class, 
protocolManagerFactoryStr, ClientProtocolManagerFactory.class );
                serverLocator.setProtocolManagerFactory(protocolManagerFactory);
                return null;
             }
diff --git a/artemis-lockmanager/artemis-lockmanager-api/pom.xml 
b/artemis-lockmanager/artemis-lockmanager-api/pom.xml
index ef14152a2e..e8fe4c8e81 100644
--- a/artemis-lockmanager/artemis-lockmanager-api/pom.xml
+++ b/artemis-lockmanager/artemis-lockmanager-api/pom.xml
@@ -30,4 +30,12 @@
    <properties>
       <activemq.basedir>${project.basedir}/../..</activemq.basedir>
    </properties>
+
+   <dependencies>
+      <dependency>
+         <groupId>org.apache.activemq</groupId>
+         <artifactId>artemis-commons</artifactId>
+      </dependency>
+   </dependencies>
+
 </project>
diff --git 
a/artemis-lockmanager/artemis-lockmanager-api/src/main/java/org/apache/activemq/artemis/lockmanager/DistributedLockManager.java
 
b/artemis-lockmanager/artemis-lockmanager-api/src/main/java/org/apache/activemq/artemis/lockmanager/DistributedLockManager.java
index d58ddea790..d42f8e985f 100644
--- 
a/artemis-lockmanager/artemis-lockmanager-api/src/main/java/org/apache/activemq/artemis/lockmanager/DistributedLockManager.java
+++ 
b/artemis-lockmanager/artemis-lockmanager-api/src/main/java/org/apache/activemq/artemis/lockmanager/DistributedLockManager.java
@@ -21,10 +21,16 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
+
 public interface DistributedLockManager extends AutoCloseable {
 
    static DistributedLockManager newInstanceOf(String className, Map<String, 
String> properties) throws Exception {
-      return (DistributedLockManager) 
Class.forName(className).getDeclaredConstructor(Map.class).newInstance(properties);
+      return (DistributedLockManager) 
ClassloadingUtil.getInstanceForParamsWithTypeCheck(className,
+                                                                               
          DistributedLockManager.class,
+                                                                               
          DistributedLockManager.class.getClassLoader(),
+                                                                               
          new Class[]{Map.class},
+                                                                               
          properties);
    }
 
    @FunctionalInterface
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
index a8a0bc212c..0b78fab0c4 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
@@ -115,6 +115,7 @@ import org.apache.activemq.artemis.json.JsonArrayBuilder;
 import org.apache.activemq.artemis.json.JsonObject;
 import org.apache.activemq.artemis.json.JsonObjectBuilder;
 import org.apache.activemq.artemis.utils.ByteUtil;
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import org.apache.activemq.artemis.utils.Env;
 import org.apache.activemq.artemis.utils.JsonLoader;
 import org.apache.activemq.artemis.utils.ObjectInputStreamWithClassLoader;
@@ -800,8 +801,7 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
                      if (type != String.class && 
possibleDotClassValue.endsWith(DOT_CLASS)) {
                         final String clazzName = 
possibleDotClassValue.substring(0, possibleDotClassValue.length() - 
DOT_CLASS.length());
                         try {
-                           Class clazzType = 
this.getClass().getClassLoader().loadClass(clazzName);
-                           newValue = 
clazzType.getDeclaredConstructor().newInstance();
+                           newValue = 
ClassloadingUtil.getInstanceWithTypeCheck(clazzName, type, 
this.getClass().getClassLoader());
                         } catch (Exception e) {
                            throw new InvocationTargetException(e, " for dot 
class value: " + possibleDotClassValue + ", on: " + bean);
                         }
@@ -2352,6 +2352,11 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
       return brokerPlugins;
    }
 
+   // for properties type inference
+   public void addBrokerPlugin(ActiveMQServerBasePlugin type) {
+      registerBrokerPlugin(type);
+   }
+
    @Override
    public List<ActiveMQServerConnectionPlugin> getBrokerConnectionPlugins() {
       return brokerConnectionPlugins;
@@ -3584,27 +3589,27 @@ public class ConfigurationImpl implements 
Configuration, Serializable {
 
          Object instance = null;
          try {
+            // we don't know the type, infer from add method add(X x) or 
add(String key, X x)
+            final String addPropertyName = addPropertyNameBuilder.toString();
+            final Method[] methods = hostingBean.getClass().getMethods();
+            final Method candidate = Arrays.stream(methods).filter(method -> 
method.getName().equals(addPropertyName) && ((method.getParameterCount() == 1) 
|| (method.getParameterCount() == 2
+               // has a String key
+               && String.class.equals(method.getParameterTypes()[0])
+               // but not initialised from a String form (eg: uri)
+               && 
!String.class.equals(method.getParameterTypes()[1])))).sorted((method1, 
method2) -> method2.getParameterCount() - 
method1.getParameterCount()).findFirst().orElse(null);
+
+            if (candidate == null) {
+               throw new IllegalArgumentException("failed to locate add method 
for collection property " + addPropertyName);
+            }
+            Class type = 
candidate.getParameterTypes()[candidate.getParameterCount() - 1];
+
             if (name.indexOf(DOT_CLASS) > 0) {
                final String clazzName = name.substring(0, name.length() - 
DOT_CLASS.length());
-               instance = 
this.getClass().getClassLoader().loadClass(clazzName).getDeclaredConstructor().newInstance();
+               instance = ClassloadingUtil.getInstanceWithTypeCheck(clazzName, 
type, this.getClass().getClassLoader());
             } else {
-               // we don't know the type, infer from add method add(X x) or 
add(String key, X x)
-               final String addPropertyName = 
addPropertyNameBuilder.toString();
-               final Method[] methods = hostingBean.getClass().getMethods();
-               final Method candidate = Arrays.stream(methods).filter(method 
-> method.getName().equals(addPropertyName) && ((method.getParameterCount() == 
1) || (method.getParameterCount() == 2
-                  // has a String key
-                  && String.class.equals(method.getParameterTypes()[0])
-                  // but not initialised from a String form (eg: uri)
-                  && 
!String.class.equals(method.getParameterTypes()[1])))).sorted((method1, 
method2) -> method2.getParameterCount() - 
method1.getParameterCount()).findFirst().orElse(null);
-
-               if (candidate == null) {
-                  throw new IllegalArgumentException("failed to locate add 
method for collection property " + addPropertyName);
-               }
-
-               instance = 
candidate.getParameterTypes()[candidate.getParameterCount() - 
1].getDeclaredConstructor().newInstance();
+               instance = type.getDeclaredConstructor().newInstance();
             }
             // initialise with name
-
             try {
                beanUtilsBean.setProperty(instance, "name", name);
             } catch (Throwable ignored) {
@@ -3617,7 +3622,7 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
             if (logger.isDebugEnabled()) {
                logger.debug("Failed to add entry for {} to collection: {}", 
name, hostingBean, e);
             }
-            throw new IllegalArgumentException("failed to add entry for 
collection key " + name, e);
+            throw new IllegalArgumentException("failed to add entry for 
collection key " + name + ", cause " + e.getMessage(), e);
          }
       }
 
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
index 99012fd540..ac927ac5d2 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
@@ -987,7 +987,7 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       ActiveMQServerPlugin serverPlugin = AccessController.doPrivileged(new 
PrivilegedAction<ActiveMQServerPlugin>() {
          @Override
          public ActiveMQServerPlugin run() {
-            return (ActiveMQServerPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(FileConfigurationParser.class, 
clazz);
+            return (ActiveMQServerPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(FileConfigurationParser.class, 
clazz, ActiveMQServerPlugin.class);
          }
       });
 
@@ -1066,7 +1066,7 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       ActiveMQMetricsPlugin metricsPlugin = AccessController.doPrivileged(new 
PrivilegedAction<ActiveMQMetricsPlugin>() {
          @Override
          public ActiveMQMetricsPlugin run() {
-            return (ActiveMQMetricsPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(FileConfigurationParser.class, 
clazz);
+            return (ActiveMQMetricsPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(FileConfigurationParser.class, 
clazz, ActiveMQMetricsPlugin.class);
          }
       });
 
@@ -1273,7 +1273,7 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       SecuritySettingPlugin securitySettingPlugin = 
AccessController.doPrivileged(new PrivilegedAction<SecuritySettingPlugin>() {
          @Override
          public SecuritySettingPlugin run() {
-            return (SecuritySettingPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(FileConfigurationParser.class, 
clazz);
+            return (SecuritySettingPlugin) 
ClassloadingUtil.newInstanceFromClassLoader(FileConfigurationParser.class, 
clazz, SecuritySettingPlugin.class);
          }
       });
 
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServiceRegistryImpl.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServiceRegistryImpl.java
index 7a8df5f1d2..6603fb1f38 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServiceRegistryImpl.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServiceRegistryImpl.java
@@ -122,7 +122,7 @@ public class ServiceRegistryImpl implements ServiceRegistry 
{
       if (configs != null) {
          for (final ConnectorServiceConfiguration config : configs) {
             if (connectorServices.get(config.getConnectorName()) == null) {
-               ConnectorServiceFactory factory = 
loadClass(config.getFactoryClassName());
+               ConnectorServiceFactory factory = 
loadClass(config.getFactoryClassName(), ConnectorServiceFactory.class);
                addConnectorService(factory, config);
             }
          }
@@ -133,7 +133,7 @@ public class ServiceRegistryImpl implements ServiceRegistry 
{
 
    @Override
    public ConnectorServiceFactory 
getConnectorService(ConnectorServiceConfiguration configuration) {
-      return loadClass(configuration.getFactoryClassName());
+      return loadClass(configuration.getFactoryClassName(), 
ConnectorServiceFactory.class);
    }
 
    @Override
@@ -235,7 +235,7 @@ public class ServiceRegistryImpl implements ServiceRegistry 
{
       AcceptorFactory factory = acceptorFactories.get(name);
 
       if (factory == null && className != null) {
-         factory = loadClass(className);
+         factory = loadClass(className, AcceptorFactory.class);
          addAcceptorFactory(name, factory);
       }
 
@@ -248,11 +248,11 @@ public class ServiceRegistryImpl implements 
ServiceRegistry {
    }
 
    @SuppressWarnings("TypeParameterUnusedInFormals")
-   public <T> T loadClass(final String className) {
+   public <T> T loadClass(final String className, Class expectedType) {
       return AccessController.doPrivileged(new PrivilegedAction<T>() {
          @Override
          public T run() {
-            return (T) ClassloadingUtil.newInstanceFromClassLoader(className);
+            return (T) ClassloadingUtil.newInstanceFromClassLoader(className, 
expectedType);
          }
       });
    }
@@ -262,7 +262,7 @@ public class ServiceRegistryImpl implements ServiceRegistry 
{
 
       if (transformerConfiguration != null && 
transformerConfiguration.getClassName() != null) {
          try {
-            transformer = new 
RegisteredTransformer(loadClass(transformerConfiguration.getClassName()));
+            transformer = new 
RegisteredTransformer(loadClass(transformerConfiguration.getClassName(), 
Transformer.class));
             
transformer.init(Collections.unmodifiableMap(transformerConfiguration.getProperties()));
          } catch (Exception e) {
             throw 
ActiveMQMessageBundle.BUNDLE.errorCreatingTransformerClass(transformerConfiguration.getClassName(),
 e);
@@ -274,7 +274,7 @@ public class ServiceRegistryImpl implements ServiceRegistry 
{
    private void instantiateInterceptors(List<String> classNames, 
List<BaseInterceptor> interceptors) {
       if (classNames != null) {
          for (final String className : classNames) {
-            BaseInterceptor interceptor = loadClass(className);
+            BaseInterceptor interceptor = loadClass(className, 
BaseInterceptor.class);
             interceptors.add(interceptor);
          }
       }
diff --git 
a/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
 
b/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
index 2093cc3487..88c828e36f 100644
--- 
a/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
+++ 
b/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
@@ -41,6 +41,7 @@ import org.apache.activemq.artemis.dto.BindingDTO;
 import org.apache.activemq.artemis.dto.ComponentDTO;
 import org.apache.activemq.artemis.dto.WebServerDTO;
 import org.apache.activemq.artemis.marker.WebServerComponentMarker;
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import org.apache.activemq.artemis.utils.PemConfigUtil;
 import org.eclipse.jetty.security.DefaultAuthenticatorFactory;
 import org.eclipse.jetty.server.ConnectionFactory;
@@ -132,7 +133,7 @@ public class WebServerComponent implements 
ExternalComponent, WebServerComponent
 
       if (this.webServerConfig.customizer != null) {
          try {
-            httpConfiguration.addCustomizer((HttpConfiguration.Customizer) 
Class.forName(this.webServerConfig.customizer).getConstructor().newInstance());
+            httpConfiguration.addCustomizer((HttpConfiguration.Customizer) 
ClassloadingUtil.getInstanceWithTypeCheck(this.webServerConfig.customizer, 
HttpConfiguration.Customizer.class, this.getClass().getClassLoader()));
          } catch (Throwable t) {
             
ActiveMQWebLogger.LOGGER.customizerNotLoaded(this.webServerConfig.customizer, 
t);
          }


Reply via email to