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

pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 41a9406ae6 NIFI-15647 Add SSL configuration support for ActiveMQ 
Artemis JMS connections
41a9406ae6 is described below

commit 41a9406ae671c9e7afbb9ccbc9a51f8ee0165bb7
Author: Chaffelson <[email protected]>
AuthorDate: Wed Feb 25 17:08:02 2026 +0000

    NIFI-15647 Add SSL configuration support for ActiveMQ Artemis JMS 
connections
    
    JMSConnectionFactoryHandler now augments the broker URL with SSL transport
    parameters (sslEnabled, trustStorePath, keyStorePath, etc.) when an
    SSLContextService is configured and the connection factory implementation
    is ActiveMQ Artemis. Previously, Artemis SSL settings were silently ignored
    because Artemis does not expose bean-style SSL setters like Classic 
ActiveMQ.
    
    This closes #10936.
    
    Signed-off-by: Pierre Villard <[email protected]>
---
 .../nifi/jms/cf/JMSConnectionFactoryHandler.java   |  70 +++++-
 .../nifi/jms/cf/JMSConnectionFactoryProvider.java  |  31 +++
 .../jms/cf/JMSConnectionFactoryProviderTest.java   | 264 +++++++++++++++++++++
 3 files changed, 364 insertions(+), 1 deletion(-)

diff --git 
a/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryHandler.java
 
b/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryHandler.java
index c585b9aad2..b6028afd7b 100644
--- 
a/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryHandler.java
+++ 
b/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryHandler.java
@@ -25,6 +25,8 @@ import org.apache.nifi.processor.ProcessContext;
 import org.apache.nifi.ssl.SSLContextService;
 
 import java.lang.reflect.Method;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -125,6 +127,7 @@ public class JMSConnectionFactoryHandler extends 
CachedJMSConnectionFactoryHandl
         String connectionFactoryValue = 
context.getProperty(JMS_CONNECTION_FACTORY_IMPL).evaluateAttributeExpressions().getValue();
         if (context.getProperty(JMS_BROKER_URI).isSet()) {
             String brokerValue = 
context.getProperty(JMS_BROKER_URI).evaluateAttributeExpressions().getValue();
+            // Matches both Classic ActiveMQ and Artemis, which both use 
setBrokerURL
             if (connectionFactoryValue.startsWith("org.apache.activemq")) {
                 setProperty(connectionFactory, "brokerURL", brokerValue);
             } else if (connectionFactoryValue.startsWith("com.tibco.tibjms")) {
@@ -159,7 +162,9 @@ public class JMSConnectionFactoryHandler extends 
CachedJMSConnectionFactoryHandl
         SSLContextService sslContextService = 
context.getProperty(JMS_SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
         if (sslContextService != null) {
             SSLContext sslContext = sslContextService.createContext();
-            if (connectionFactoryValue.startsWith("org.apache.activemq")) {
+            if 
(connectionFactoryValue.startsWith("org.apache.activemq.artemis")) {
+                configureArtemisSSL(connectionFactory, sslContextService);
+            } else if 
(connectionFactoryValue.startsWith("org.apache.activemq")) {
                 if (sslContextService.isTrustStoreConfigured()) {
                     setProperty(connectionFactory, "trustStore", 
sslContextService.getTrustStoreFile());
                     setProperty(connectionFactory, "trustStorePassword", 
sslContextService.getTrustStorePassword());
@@ -188,6 +193,69 @@ public class JMSConnectionFactoryHandler extends 
CachedJMSConnectionFactoryHandl
                 });
     }
 
+    /**
+     * Configures SSL for ActiveMQ Artemis by rebuilding the broker URL with 
SSL transport
+     * parameters. Artemis does not expose bean-style SSL setters like Classic 
ActiveMQ;
+     * instead, SSL configuration is parsed from the broker URL query string 
by the
+     * Artemis {@code ActiveMQConnectionFactory.setBrokerURL(String)} method.
+     * <p>
+     * Note: passwords are embedded in the broker URL as required by Artemis 
transport
+     * configuration. The augmented URL is not logged by NiFi, but the Artemis 
client
+     * library may log the connection URL internally at DEBUG level.
+     * <p>
+     * Parameter values are URL-encoded per Artemis {@code 
URISupport.parseQuery()} which
+     * applies {@code URLDecoder.decode()} when reading parameters back.
+     */
+    private void configureArtemisSSL(final ConnectionFactory 
connectionFactory, final SSLContextService sslContextService) {
+        if (!context.getProperty(JMS_BROKER_URI).isSet()) {
+            return;
+        }
+        final String brokerUrl = 
context.getProperty(JMS_BROKER_URI).evaluateAttributeExpressions().getValue();
+        final StringBuilder urlBuilder = new StringBuilder(brokerUrl);
+        final List<String> configuredParameters = new ArrayList<>();
+        char separator = brokerUrl.contains("?") ? '&' : '?';
+
+        if (!brokerUrl.matches(".*[?&]sslEnabled=.*")) {
+            urlBuilder.append(separator).append("sslEnabled=true");
+            separator = '&';
+            configuredParameters.add("sslEnabled");
+        }
+
+        if (sslContextService.isTrustStoreConfigured()) {
+            urlBuilder.append(separator).append("trustStorePath=")
+                    
.append(URLEncoder.encode(sslContextService.getTrustStoreFile(), 
StandardCharsets.UTF_8));
+            separator = '&';
+            configuredParameters.add("trustStorePath");
+            urlBuilder.append(separator).append("trustStorePassword=")
+                    
.append(URLEncoder.encode(sslContextService.getTrustStorePassword(), 
StandardCharsets.UTF_8));
+            configuredParameters.add("trustStorePassword");
+            if (sslContextService.getTrustStoreType() != null) {
+                urlBuilder.append(separator).append("trustStoreType=")
+                        
.append(URLEncoder.encode(sslContextService.getTrustStoreType(), 
StandardCharsets.UTF_8));
+                configuredParameters.add("trustStoreType");
+            }
+        }
+
+        if (sslContextService.isKeyStoreConfigured()) {
+            urlBuilder.append(separator).append("keyStorePath=")
+                    
.append(URLEncoder.encode(sslContextService.getKeyStoreFile(), 
StandardCharsets.UTF_8));
+            separator = '&';
+            configuredParameters.add("keyStorePath");
+            urlBuilder.append(separator).append("keyStorePassword=")
+                    
.append(URLEncoder.encode(sslContextService.getKeyStorePassword(), 
StandardCharsets.UTF_8));
+            configuredParameters.add("keyStorePassword");
+            if (sslContextService.getKeyStoreType() != null) {
+                urlBuilder.append(separator).append("keyStoreType=")
+                        
.append(URLEncoder.encode(sslContextService.getKeyStoreType(), 
StandardCharsets.UTF_8));
+                configuredParameters.add("keyStoreType");
+            }
+        }
+
+        final String augmentedUrl = urlBuilder.toString();
+        logger.info("Configured Artemis SSL broker URL with transport 
parameters {}", configuredParameters);
+        setProperty(connectionFactory, "brokerURL", augmentedUrl);
+    }
+
     /**
      * Sets corresponding {@link ConnectionFactory}'s property to a
      * 'propertyValue' by invoking a 'setter' method that corresponds to
diff --git 
a/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProvider.java
 
b/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProvider.java
index 1f725ff824..9ba363e8da 100644
--- 
a/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProvider.java
+++ 
b/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProvider.java
@@ -25,11 +25,15 @@ import org.apache.nifi.annotation.documentation.SeeAlso;
 import org.apache.nifi.annotation.documentation.Tags;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.components.RequiredPermission;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
 import org.apache.nifi.controller.ConfigurationContext;
 import org.apache.nifi.expression.ExpressionLanguageScope;
 import org.apache.nifi.logging.ComponentLog;
 import org.apache.nifi.migration.PropertyConfiguration;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -62,6 +66,33 @@ import java.util.List;
 )
 public class JMSConnectionFactoryProvider extends 
AbstractJMSConnectionFactoryProvider {
 
+    @Override
+    protected Collection<ValidationResult> customValidate(final 
ValidationContext validationContext) {
+        final List<ValidationResult> results = new 
ArrayList<>(super.customValidate(validationContext));
+
+        final String connectionFactoryImpl = 
validationContext.getProperty(JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL).getValue();
+        final boolean sslContextServiceSet = 
validationContext.getProperty(JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE).isSet();
+        final boolean brokerUriSet = 
validationContext.getProperty(JMSConnectionFactoryProperties.JMS_BROKER_URI).isSet();
+
+        if (connectionFactoryImpl != null
+                && 
connectionFactoryImpl.startsWith("org.apache.activemq.artemis")
+                && sslContextServiceSet
+                && brokerUriSet) {
+            final String brokerUriRaw = 
validationContext.getProperty(JMSConnectionFactoryProperties.JMS_BROKER_URI).getValue();
+            if (!validationContext.isExpressionLanguagePresent(brokerUriRaw)
+                    && brokerUriRaw.matches("(?i).*[?&;]sslEnabled=false.*")) {
+                results.add(new ValidationResult.Builder()
+                        
.subject(JMSConnectionFactoryProperties.JMS_BROKER_URI.getDisplayName())
+                        .valid(false)
+                        .explanation("JMS SSL Context Service is configured, 
but JMS Broker URI contains sslEnabled=false. "
+                                + "Remove sslEnabled=false from the broker URI 
or unset the SSL Context Service.")
+                        .build());
+            }
+        }
+
+        return results;
+    }
+
     @Override
     public void migrateProperties(PropertyConfiguration config) {
         
config.renameProperty(JMSConnectionFactoryProperties.OLD_JMS_CONNECTION_FACTORY_IMPL_PROPERTY_NAME,
 JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL.getName());
diff --git 
a/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/test/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProviderTest.java
 
b/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/test/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProviderTest.java
index 8c6578b775..40b5bfb2aa 100644
--- 
a/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/test/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProviderTest.java
+++ 
b/nifi-extension-bundles/nifi-jms-bundle/nifi-jms-processors/src/test/java/org/apache/nifi/jms/cf/JMSConnectionFactoryProviderTest.java
@@ -28,6 +28,8 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.Map;
 import javax.net.ssl.SSLContext;
@@ -62,6 +64,8 @@ public class JMSConnectionFactoryProviderTest {
 
     private static final String TEST_CONNECTION_FACTORY_IMPL = 
"org.apache.nifi.jms.testcflib.TestConnectionFactory";
     private static final String ACTIVEMQ_CONNECTION_FACTORY_IMPL = 
"org.apache.activemq.ActiveMQConnectionFactory";
+    private static final String ARTEMIS_CONNECTION_FACTORY_IMPL = 
"org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory";
+    private static final String SINGLE_ARTEMIS_BROKER = "tcp://myhost:61616";
     private static final String TIBCO_CONNECTION_FACTORY_IMPL = 
"com.tibco.tibjms.TibjmsConnectionFactory";
     private static final String IBM_MQ_CONNECTION_FACTORY_IMPL = 
"com.ibm.mq.jms.MQConnectionFactory";
     private static final String QPID_JMS_CONNECTION_FACTORY_IMPL = 
"org.apache.qpid.jms.JmsConnectionFactory";
@@ -411,6 +415,92 @@ public class JMSConnectionFactoryProviderTest {
                 cfProvider.getConfiguredProperties());
     }
 
+    @Test
+    public void propertiesSetOnArtemisWithSslConnectionFactory() throws 
Exception {
+        final JMSConnectionFactoryProviderForTest cfProvider = new 
JMSConnectionFactoryProviderForTest();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, SINGLE_ARTEMIS_BROKER);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        final String trustStoreFile = "/path/to/truststore";
+        final String trustStorePassword = "truststore_password";
+        final String trustStoreType = "JKS";
+        final String keyStoreFile = "/path/to/keystore";
+        final String keyStorePassword = "keystore_password";
+        final String keyStoreType = "PKCS12";
+
+        final SSLContextService sslContextService = 
mock(SSLContextService.class);
+        
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
+        
when(sslContextService.createContext()).thenReturn(SSLContext.getDefault());
+        when(sslContextService.isTrustStoreConfigured()).thenReturn(true);
+        when(sslContextService.getTrustStoreFile()).thenReturn(trustStoreFile);
+        
when(sslContextService.getTrustStorePassword()).thenReturn(trustStorePassword);
+        when(sslContextService.getTrustStoreType()).thenReturn(trustStoreType);
+        when(sslContextService.isKeyStoreConfigured()).thenReturn(true);
+        when(sslContextService.getKeyStoreFile()).thenReturn(keyStoreFile);
+        
when(sslContextService.getKeyStorePassword()).thenReturn(keyStorePassword);
+        when(sslContextService.getKeyStoreType()).thenReturn(keyStoreType);
+
+        runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
+
+        runner.enableControllerService(cfProvider);
+
+        final Map<String, Object> props = cfProvider.getConfiguredProperties();
+
+        final String expectedUrl = SINGLE_ARTEMIS_BROKER
+                + "?sslEnabled=true"
+                + "&trustStorePath=" + URLEncoder.encode(trustStoreFile, 
StandardCharsets.UTF_8)
+                + "&trustStorePassword=" + 
URLEncoder.encode(trustStorePassword, StandardCharsets.UTF_8)
+                + "&trustStoreType=" + URLEncoder.encode(trustStoreType, 
StandardCharsets.UTF_8)
+                + "&keyStorePath=" + URLEncoder.encode(keyStoreFile, 
StandardCharsets.UTF_8)
+                + "&keyStorePassword=" + URLEncoder.encode(keyStorePassword, 
StandardCharsets.UTF_8)
+                + "&keyStoreType=" + URLEncoder.encode(keyStoreType, 
StandardCharsets.UTF_8);
+
+        assertEquals(expectedUrl, props.get("brokerURL"));
+    }
+
+    @Test
+    public void propertiesSetOnArtemisWithSslPreservesExistingSslEnabled() 
throws Exception {
+        final JMSConnectionFactoryProviderForTest cfProvider = new 
JMSConnectionFactoryProviderForTest();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        final String brokerWithSsl = SINGLE_ARTEMIS_BROKER + 
"?sslEnabled=true";
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, brokerWithSsl);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        final String trustStoreFile = "/path/to/truststore";
+        final String trustStorePassword = "truststore_password";
+
+        final SSLContextService sslContextService = 
mock(SSLContextService.class);
+        
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
+        
when(sslContextService.createContext()).thenReturn(SSLContext.getDefault());
+        when(sslContextService.isTrustStoreConfigured()).thenReturn(true);
+        when(sslContextService.getTrustStoreFile()).thenReturn(trustStoreFile);
+        
when(sslContextService.getTrustStorePassword()).thenReturn(trustStorePassword);
+        when(sslContextService.getTrustStoreType()).thenReturn(null);
+        when(sslContextService.isKeyStoreConfigured()).thenReturn(false);
+
+        runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
+
+        runner.enableControllerService(cfProvider);
+
+        final Map<String, Object> props = cfProvider.getConfiguredProperties();
+        final String brokerURL = (String) props.get("brokerURL");
+
+        assertNotNull(brokerURL);
+        assertEquals(1, brokerURL.chars().filter(ch -> ch == '?').count(),
+                "Should not duplicate ? separator when sslEnabled already in 
URL");
+        assertEquals(brokerWithSsl
+                        + "&trustStorePath=" + 
URLEncoder.encode(trustStoreFile, StandardCharsets.UTF_8)
+                        + "&trustStorePassword=" + 
URLEncoder.encode(trustStorePassword, StandardCharsets.UTF_8),
+                brokerURL);
+    }
+
     @Test
     public void propertiesSetOnSingleTibcoBrokerConnectionFactory() throws 
InitializationException {
         JMSConnectionFactoryProviderForTest cfProvider = new 
JMSConnectionFactoryProviderForTest();
@@ -561,4 +651,178 @@ public class JMSConnectionFactoryProviderTest {
 
         assertEquals(Map.of("remoteURI", SINGLE_QPID_JMS_BROKER, "sslContext", 
sslContext), cfProvider.getConfiguredProperties());
     }
+
+    @Test
+    public void propertiesSetOnArtemisWithSslAndSpecialCharacters() throws 
Exception {
+        final JMSConnectionFactoryProviderForTest cfProvider = new 
JMSConnectionFactoryProviderForTest();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, SINGLE_ARTEMIS_BROKER);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        final String trustStoreFile = "/path/to/my trust store";
+        final String trustStorePassword = "p&ss=w?rd#1";
+        final String trustStoreType = "JKS";
+        final String keyStoreFile = "/path/to/keystore";
+        final String keyStorePassword = "key&store=pass";
+        final String keyStoreType = "PKCS12";
+
+        final SSLContextService sslContextService = 
mock(SSLContextService.class);
+        
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
+        
when(sslContextService.createContext()).thenReturn(SSLContext.getDefault());
+        when(sslContextService.isTrustStoreConfigured()).thenReturn(true);
+        when(sslContextService.getTrustStoreFile()).thenReturn(trustStoreFile);
+        
when(sslContextService.getTrustStorePassword()).thenReturn(trustStorePassword);
+        when(sslContextService.getTrustStoreType()).thenReturn(trustStoreType);
+        when(sslContextService.isKeyStoreConfigured()).thenReturn(true);
+        when(sslContextService.getKeyStoreFile()).thenReturn(keyStoreFile);
+        
when(sslContextService.getKeyStorePassword()).thenReturn(keyStorePassword);
+        when(sslContextService.getKeyStoreType()).thenReturn(keyStoreType);
+
+        runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
+
+        runner.enableControllerService(cfProvider);
+
+        final Map<String, Object> props = cfProvider.getConfiguredProperties();
+        final String brokerURL = (String) props.get("brokerURL");
+
+        final String expectedUrl = SINGLE_ARTEMIS_BROKER
+                + "?sslEnabled=true"
+                + "&trustStorePath=" + URLEncoder.encode(trustStoreFile, 
StandardCharsets.UTF_8)
+                + "&trustStorePassword=" + 
URLEncoder.encode(trustStorePassword, StandardCharsets.UTF_8)
+                + "&trustStoreType=" + URLEncoder.encode(trustStoreType, 
StandardCharsets.UTF_8)
+                + "&keyStorePath=" + URLEncoder.encode(keyStoreFile, 
StandardCharsets.UTF_8)
+                + "&keyStorePassword=" + URLEncoder.encode(keyStorePassword, 
StandardCharsets.UTF_8)
+                + "&keyStoreType=" + URLEncoder.encode(keyStoreType, 
StandardCharsets.UTF_8);
+
+        assertEquals(expectedUrl, brokerURL);
+    }
+
+    @Test
+    public void propertiesSetOnArtemisWithSslAndNoBrokerUri() throws Exception 
{
+        final JMSConnectionFactoryProviderForTest cfProvider = new 
JMSConnectionFactoryProviderForTest();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        final SSLContextService sslContextService = 
mock(SSLContextService.class);
+        
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
+        
when(sslContextService.createContext()).thenReturn(SSLContext.getDefault());
+        when(sslContextService.isTrustStoreConfigured()).thenReturn(true);
+        
when(sslContextService.getTrustStoreFile()).thenReturn("/path/to/truststore");
+        when(sslContextService.getTrustStorePassword()).thenReturn("password");
+        when(sslContextService.isKeyStoreConfigured()).thenReturn(false);
+
+        runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
+
+        runner.enableControllerService(cfProvider);
+
+        final Map<String, Object> props = cfProvider.getConfiguredProperties();
+        assertNotNull(props);
+        assertEquals(Map.of(), props);
+    }
+
+    @Test
+    public void propertiesSetOnSingleArtemisBrokerConnectionFactory() throws 
InitializationException {
+        final JMSConnectionFactoryProviderForTest cfProvider = new 
JMSConnectionFactoryProviderForTest();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, SINGLE_ARTEMIS_BROKER);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        runner.enableControllerService(cfProvider);
+
+        assertEquals(Map.of("brokerURL", SINGLE_ARTEMIS_BROKER), 
cfProvider.getConfiguredProperties());
+    }
+
+    @Test
+    public void invalidWhenArtemisWithSslAndSslEnabledFalse() throws 
InitializationException {
+        final JMSConnectionFactoryProvider cfProvider = new 
JMSConnectionFactoryProvider();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, SINGLE_ARTEMIS_BROKER + 
"?sslEnabled=false");
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        final SSLContextService sslContextService = 
mock(SSLContextService.class);
+        
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
+
+        runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
+
+        runner.assertNotValid(cfProvider);
+    }
+
+    @Test
+    public void validWhenArtemisWithSslAndSslEnabledTrue() throws 
InitializationException {
+        final JMSConnectionFactoryProvider cfProvider = new 
JMSConnectionFactoryProvider();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, SINGLE_ARTEMIS_BROKER + 
"?sslEnabled=true");
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        final SSLContextService sslContextService = 
mock(SSLContextService.class);
+        
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
+
+        runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
+
+        runner.assertValid(cfProvider);
+    }
+
+    @Test
+    public void validWhenArtemisWithSslEnabledFalseAndNoSsl() throws 
InitializationException {
+        final JMSConnectionFactoryProvider cfProvider = new 
JMSConnectionFactoryProvider();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, SINGLE_ARTEMIS_BROKER + 
"?sslEnabled=false");
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        runner.assertValid(cfProvider);
+    }
+
+    @Test
+    public void propertiesSetOnArtemisWithSslAndExistingQueryParams() throws 
Exception {
+        final JMSConnectionFactoryProviderForTest cfProvider = new 
JMSConnectionFactoryProviderForTest();
+        runner.addControllerService(CF_PROVIDER_SERVICE_ID, cfProvider);
+
+        final String brokerWithParams = SINGLE_ARTEMIS_BROKER + 
"?clientID=foo";
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_BROKER_URI, brokerWithParams);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CLIENT_LIBRARIES, dummyResource);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_CONNECTION_FACTORY_IMPL, 
ARTEMIS_CONNECTION_FACTORY_IMPL);
+
+        final String trustStoreFile = "/path/to/truststore";
+        final String trustStorePassword = "password";
+
+        final SSLContextService sslContextService = 
mock(SSLContextService.class);
+        
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
+        
when(sslContextService.createContext()).thenReturn(SSLContext.getDefault());
+        when(sslContextService.isTrustStoreConfigured()).thenReturn(true);
+        when(sslContextService.getTrustStoreFile()).thenReturn(trustStoreFile);
+        
when(sslContextService.getTrustStorePassword()).thenReturn(trustStorePassword);
+        when(sslContextService.getTrustStoreType()).thenReturn(null);
+        when(sslContextService.isKeyStoreConfigured()).thenReturn(false);
+
+        runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
+        runner.setProperty(cfProvider, 
JMSConnectionFactoryProperties.JMS_SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
+
+        runner.enableControllerService(cfProvider);
+
+        final Map<String, Object> props = cfProvider.getConfiguredProperties();
+        final String brokerURL = (String) props.get("brokerURL");
+
+        final String expectedUrl = brokerWithParams
+                + "&sslEnabled=true"
+                + "&trustStorePath=" + URLEncoder.encode(trustStoreFile, 
StandardCharsets.UTF_8)
+                + "&trustStorePassword=" + 
URLEncoder.encode(trustStorePassword, StandardCharsets.UTF_8);
+
+        assertEquals(expectedUrl, brokerURL);
+    }
 }

Reply via email to