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