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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3fe2194  ARTEMIS-2358 - Add user and pass to database store to allow 
encryption
     new 3e154ae  This closes #2684
3fe2194 is described below

commit 3fe21941392717152594b734753f64a4db6a72bd
Author: Andy <andy.tayl...@gmail.com>
AuthorDate: Wed May 29 10:22:13 2019 +0100

    ARTEMIS-2358 - Add user and pass to database store to allow encryption
    
    https://issues.apache.org/jira/browse/ARTEMIS-2358
---
 .../jdbc/store/drivers/AbstractJDBCDriver.java     | 31 ++++++++++++++-
 .../artemis/jdbc/store/file/JDBCFileUtils.java     |  4 ++
 .../jdbc/store/file/JDBCSequentialFileFactory.java |  4 +-
 .../jdbc/store/journal/JDBCJournalImpl.java        |  4 +-
 .../jdbc/file/JDBCSequentialFileFactoryTest.java   | 34 ++++++++++++++--
 .../storage/DatabaseStorageConfiguration.java      | 20 ++++++++++
 .../deployers/impl/FileConfigurationParser.java    | 16 ++++++--
 .../paging/impl/PagingStoreFactoryDatabase.java    |  2 +-
 .../impl/journal/JDBCJournalStorageManager.java    |  6 +--
 .../resources/schema/artemis-configuration.xsd     | 16 ++++++++
 .../impl/DatabaseStoreConfigurationTest.java       |  6 ++-
 .../src/test/resources/database-store-config.xml   |  2 +
 docs/user-manual/en/persistence.md                 | 17 ++++++++
 .../jdbc/store/journal/JDBCJournalTest.java        | 46 +++++++++++++++++++++-
 14 files changed, 191 insertions(+), 17 deletions(-)

diff --git 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java
 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java
index 7bfe42a..9629587 100644
--- 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java
+++ 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java
@@ -56,13 +56,19 @@ public abstract class AbstractJDBCDriver {
 
    private int networkTimeoutMillis;
 
+   private String user;
+
+   private String password;
+
    public AbstractJDBCDriver() {
       this.networkTimeoutExecutor = null;
       this.networkTimeoutMillis = -1;
    }
 
-   public AbstractJDBCDriver(SQLProvider sqlProvider, String 
jdbcConnectionUrl, String jdbcDriverClass) {
+   public AbstractJDBCDriver(SQLProvider sqlProvider, String 
jdbcConnectionUrl, String user, String password, String jdbcDriverClass) {
       this.jdbcConnectionUrl = jdbcConnectionUrl;
+      this.user = user;
+      this.password = password;
       this.jdbcDriverClass = jdbcDriverClass;
       this.sqlProvider = sqlProvider;
       this.networkTimeoutExecutor = null;
@@ -140,7 +146,12 @@ public abstract class AbstractJDBCDriver {
                   throw new IllegalStateException("jdbcConnectionUrl is null 
or empty!");
                }
                final Driver dbDriver = getDriver(jdbcDriverClass);
-               connection = dbDriver.connect(jdbcConnectionUrl, new 
Properties());
+               Properties properties = new Properties();
+               if (user != null) {
+                  properties.setProperty("user", user);
+                  properties.setProperty("password", password);
+               }
+               connection = dbDriver.connect(jdbcConnectionUrl, properties);
 
                if (logger.isTraceEnabled() && !(connection instanceof 
LoggingConnection)) {
                   this.connection = new LoggingConnection(connection, logger);
@@ -328,6 +339,22 @@ public abstract class AbstractJDBCDriver {
       this.jdbcConnectionUrl = jdbcConnectionUrl;
    }
 
+   public String getUser() {
+      return user;
+   }
+
+   public void setUser(String user) {
+      this.user = user;
+   }
+
+   public String getPassword() {
+      return password;
+   }
+
+   public void setPassword(String password) {
+      this.password = password;
+   }
+
    public void setJdbcDriverClass(String jdbcDriverClass) {
       this.jdbcDriverClass = jdbcDriverClass;
    }
diff --git 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java
 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java
index 478b503..58ac5b9 100644
--- 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java
+++ 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java
@@ -31,6 +31,8 @@ class JDBCFileUtils {
 
    static JDBCSequentialFileFactoryDriver getDBFileDriver(String driverClass,
                                                           String 
jdbcConnectionUrl,
+                                                          String user,
+                                                          String password,
                                                           SQLProvider 
provider) throws SQLException {
       final JDBCSequentialFileFactoryDriver dbDriver;
       final PropertySQLProvider.Factory.SQLDialect sqlDialect = 
PropertySQLProvider.Factory.identifyDialect(driverClass);
@@ -44,6 +46,8 @@ class JDBCFileUtils {
       dbDriver.setSqlProvider(provider);
       dbDriver.setJdbcConnectionUrl(jdbcConnectionUrl);
       dbDriver.setJdbcDriverClass(driverClass);
+      dbDriver.setUser(user);
+      dbDriver.setPassword(password);
       return dbDriver;
    }
 
diff --git 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java
 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java
index 8f520f2..4cd19fd 100644
--- 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java
+++ 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCSequentialFileFactory.java
@@ -69,6 +69,8 @@ public class JDBCSequentialFileFactory implements 
SequentialFileFactory, ActiveM
    }
 
    public JDBCSequentialFileFactory(final String connectionUrl,
+                                    String userName,
+                                    String password,
                                     final String className,
                                     final SQLProvider sqlProvider,
                                     Executor executor,
@@ -76,7 +78,7 @@ public class JDBCSequentialFileFactory implements 
SequentialFileFactory, ActiveM
       this.executor = executor;
       this.criticalErrorListener = criticalErrorListener;
       try {
-         this.dbDriver = JDBCFileUtils.getDBFileDriver(className, 
connectionUrl, sqlProvider);
+         this.dbDriver = JDBCFileUtils.getDBFileDriver(className, 
connectionUrl, userName, password, sqlProvider);
       } catch (SQLException e) {
          criticalErrorListener.onIOException(e, "Failed to start JDBC Driver", 
null);
       }
diff --git 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
index 8ec451d..079a457 100644
--- 
a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
+++ 
b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
@@ -109,13 +109,15 @@ public class JDBCJournalImpl extends AbstractJDBCDriver 
implements Journal {
    }
 
    public JDBCJournalImpl(String jdbcUrl,
+                          String user,
+                          String password,
                           String jdbcDriverClass,
                           SQLProvider sqlProvider,
                           ScheduledExecutorService scheduledExecutorService,
                           Executor completeExecutor,
                           IOCriticalErrorListener criticalIOErrorListener,
                           long syncDelay) {
-      super(sqlProvider, jdbcUrl, jdbcDriverClass);
+      super(sqlProvider, jdbcUrl, user, password, jdbcDriverClass);
       records = new ArrayList<>();
       this.scheduledExecutorService = scheduledExecutorService;
       this.completeExecutor = completeExecutor;
diff --git 
a/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/file/JDBCSequentialFileFactoryTest.java
 
b/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/file/JDBCSequentialFileFactoryTest.java
index 7b6dc39..d74a76c 100644
--- 
a/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/file/JDBCSequentialFileFactoryTest.java
+++ 
b/artemis-jdbc-store/src/test/java/org/apache/activemq/artemis/jdbc/file/JDBCSequentialFileFactoryTest.java
@@ -19,6 +19,8 @@ package org.apache.activemq.artemis.jdbc.file;
 import java.nio.ByteBuffer;
 import java.sql.DriverManager;
 import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -46,12 +48,15 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+@RunWith(Parameterized.class)
 public class JDBCSequentialFileFactoryTest {
 
    @Rule
@@ -63,13 +68,28 @@ public class JDBCSequentialFileFactoryTest {
 
    private ExecutorService executor;
 
+   @Parameterized.Parameter
+   public boolean useAuthentication;
+   private String user = null;
+   private String password = null;
+
+   @Parameterized.Parameters(name = "authentication = {0}")
+   public static Collection<Object[]> data() {
+      return Arrays.asList(new Object[][]{{false}, {true}});
+   }
+
    @Before
    public void setup() throws Exception {
       executor = 
Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory());
-
+      if (useAuthentication) {
+         user = "testuser";
+         password = "testpassword";
+         System.setProperty("derby.connection.requireAuthentication", "true");
+         System.setProperty("derby.user." + user, password);
+      }
       String connectionUrl = "jdbc:derby:target/data;create=true";
       String tableName = "FILES";
-      factory = new JDBCSequentialFileFactory(connectionUrl, className, 
JDBCUtils.getSQLProvider(className, tableName, 
SQLProvider.DatabaseStoreType.PAGE), executor, new IOCriticalErrorListener() {
+      factory = new JDBCSequentialFileFactory(connectionUrl, user, password, 
className, JDBCUtils.getSQLProvider(className, tableName, 
SQLProvider.DatabaseStoreType.PAGE), executor, new IOCriticalErrorListener() {
          @Override
          public void onIOException(Throwable code, String message, 
SequentialFile file) {
          }
@@ -86,9 +106,17 @@ public class JDBCSequentialFileFactoryTest {
    @After
    public void shutdownDerby() {
       try {
-         DriverManager.getConnection("jdbc:derby:;shutdown=true");
+         if (useAuthentication) {
+            DriverManager.getConnection("jdbc:derby:;shutdown=true", user, 
password);
+         } else {
+            DriverManager.getConnection("jdbc:derby:;shutdown=true");
+         }
       } catch (Exception ignored) {
       }
+      if (useAuthentication) {
+         System.clearProperty("derby.connection.requireAuthentication");
+         System.clearProperty("derby.user." + user);
+      }
    }
 
    @Test
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/DatabaseStorageConfiguration.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/DatabaseStorageConfiguration.java
index 2707fb7..4762181 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/DatabaseStorageConfiguration.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/DatabaseStorageConfiguration.java
@@ -36,6 +36,10 @@ public class DatabaseStorageConfiguration implements 
StoreConfiguration {
 
    private String jdbcConnectionUrl = 
ActiveMQDefaultConfiguration.getDefaultDatabaseUrl();
 
+   private String jdbcUser;
+
+   private String jdbcPassword;
+
    private String jdbcDriverClassName = 
ActiveMQDefaultConfiguration.getDefaultDriverClassName();
 
    private DataSource dataSource;
@@ -105,6 +109,22 @@ public class DatabaseStorageConfiguration implements 
StoreConfiguration {
       return jdbcConnectionUrl;
    }
 
+   public String getJdbcUser() {
+      return jdbcUser;
+   }
+
+   public void setJdbcUser(String jdbcUser) {
+      this.jdbcUser = jdbcUser;
+   }
+
+   public String getJdbcPassword() {
+      return jdbcPassword;
+   }
+
+   public void setJdbcPassword(String jdbcPassword) {
+      this.jdbcPassword = jdbcPassword;
+   }
+
    public void setJdbcDriverClassName(String jdbcDriverClassName) {
       this.jdbcDriverClassName = jdbcDriverClassName;
    }
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 edd667b..b232cc9 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
@@ -1323,13 +1323,13 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       STORE_TYPE_LIST.add("file-store");
    }
 
-   private void parseStoreConfiguration(final Element e, final Configuration 
mainConfig) {
+   private void parseStoreConfiguration(final Element e, final Configuration 
mainConfig) throws Exception {
       for (String storeType : STORE_TYPE_LIST) {
          NodeList storeNodeList = e.getElementsByTagName(storeType);
          if (storeNodeList.getLength() > 0) {
             Element storeNode = (Element) storeNodeList.item(0);
             if (storeNode.getTagName().equals("database-store")) {
-               
mainConfig.setStoreConfiguration(createDatabaseStoreConfig(storeNode));
+               
mainConfig.setStoreConfiguration(createDatabaseStoreConfig(storeNode, 
mainConfig));
             } else if (storeNode.getTagName().equals("file-store")) {
                
mainConfig.setStoreConfiguration(createFileStoreConfig(storeNode));
             }
@@ -1561,7 +1561,7 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       return null;
    }
 
-   private DatabaseStorageConfiguration createDatabaseStoreConfig(Element 
storeNode) {
+   private DatabaseStorageConfiguration createDatabaseStoreConfig(Element 
storeNode, Configuration mainConfig) throws Exception {
       DatabaseStorageConfiguration conf = new DatabaseStorageConfiguration();
       conf.setBindingsTableName(getString(storeNode, "bindings-table-name", 
conf.getBindingsTableName(), Validators.NO_CHECK));
       conf.setMessageTableName(getString(storeNode, "message-table-name", 
conf.getMessageTableName(), Validators.NO_CHECK));
@@ -1574,6 +1574,16 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       conf.setJdbcLockRenewPeriodMillis(getLong(storeNode, 
"jdbc-lock-renew-period", conf.getJdbcLockRenewPeriodMillis(), 
Validators.NO_CHECK));
       conf.setJdbcLockExpirationMillis(getLong(storeNode, 
"jdbc-lock-expiration", conf.getJdbcLockExpirationMillis(), 
Validators.NO_CHECK));
       conf.setJdbcJournalSyncPeriodMillis(getLong(storeNode, 
"jdbc-journal-sync-period", conf.getJdbcJournalSyncPeriodMillis(), 
Validators.NO_CHECK));
+      String jdbcUser = getString(storeNode, "jdbc-user", conf.getJdbcUser(), 
Validators.NO_CHECK);
+      if (jdbcUser != null) {
+         jdbcUser = 
PasswordMaskingUtil.resolveMask(mainConfig.isMaskPassword(), jdbcUser, 
mainConfig.getPasswordCodec());
+      }
+      conf.setJdbcUser(jdbcUser);
+      String password = getString(storeNode, "jdbc-password", 
conf.getJdbcPassword(), Validators.NO_CHECK);
+      if (password != null) {
+         password = 
PasswordMaskingUtil.resolveMask(mainConfig.isMaskPassword(), password, 
mainConfig.getPasswordCodec());
+      }
+      conf.setJdbcPassword(password);
       return conf;
    }
 
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingStoreFactoryDatabase.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingStoreFactoryDatabase.java
index 6dc11f3..e665a87 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingStoreFactoryDatabase.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagingStoreFactoryDatabase.java
@@ -131,7 +131,7 @@ public class PagingStoreFactoryDatabase implements 
PagingStoreFactory {
             pagingFactoryFileFactory = new 
JDBCSequentialFileFactory(dbConf.getDataSource(), 
sqlProviderFactory.create(pageStoreTableNamePrefix, 
SQLProvider.DatabaseStoreType.PAGE), executorFactory.getExecutor(), 
criticalErrorListener);
          } else {
             String driverClassName = dbConf.getJdbcDriverClassName();
-            pagingFactoryFileFactory = new 
JDBCSequentialFileFactory(dbConf.getJdbcConnectionUrl(), driverClassName, 
JDBCUtils.getSQLProvider(driverClassName, pageStoreTableNamePrefix, 
SQLProvider.DatabaseStoreType.PAGE), executorFactory.getExecutor(), 
criticalErrorListener);
+            pagingFactoryFileFactory = new 
JDBCSequentialFileFactory(dbConf.getJdbcConnectionUrl(), null, null, 
driverClassName, JDBCUtils.getSQLProvider(driverClassName, 
pageStoreTableNamePrefix, SQLProvider.DatabaseStoreType.PAGE), 
executorFactory.getExecutor(), criticalErrorListener);
          }
          final int jdbcNetworkTimeout = dbConf.getJdbcNetworkTimeout();
          if (jdbcNetworkTimeout >= 0) {
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/JDBCJournalStorageManager.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/JDBCJournalStorageManager.java
index 3c68f98..629405b 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/JDBCJournalStorageManager.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/JDBCJournalStorageManager.java
@@ -72,9 +72,9 @@ public class JDBCJournalStorageManager extends 
JournalStorageManager {
             largeMessagesFactory = new 
JDBCSequentialFileFactory(dbConf.getDataSource(), 
sqlProviderFactory.create(dbConf.getLargeMessageTableName(), 
SQLProvider.DatabaseStoreType.LARGE_MESSAGE), executorFactory.getExecutor(), 
criticalErrorListener);
          } else {
             String driverClassName = dbConf.getJdbcDriverClassName();
-            bindingsJournal = new 
JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), driverClassName, 
JDBCUtils.getSQLProvider(driverClassName, dbConf.getBindingsTableName(), 
SQLProvider.DatabaseStoreType.BINDINGS_JOURNAL), scheduledExecutorService, 
executorFactory.getExecutor(), criticalErrorListener, 
dbConf.getJdbcJournalSyncPeriodMillis());
-            messageJournal = new 
JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), driverClassName, 
JDBCUtils.getSQLProvider(driverClassName, dbConf.getMessageTableName(), 
SQLProvider.DatabaseStoreType.MESSAGE_JOURNAL), scheduledExecutorService, 
executorFactory.getExecutor(), criticalErrorListener, 
dbConf.getJdbcJournalSyncPeriodMillis());
-            largeMessagesFactory = new 
JDBCSequentialFileFactory(dbConf.getJdbcConnectionUrl(), driverClassName, 
JDBCUtils.getSQLProvider(driverClassName, dbConf.getLargeMessageTableName(), 
SQLProvider.DatabaseStoreType.LARGE_MESSAGE), executorFactory.getExecutor(), 
criticalErrorListener);
+            bindingsJournal = new 
JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), dbConf.getJdbcUser(), 
dbConf.getJdbcPassword(), driverClassName, 
JDBCUtils.getSQLProvider(driverClassName, dbConf.getBindingsTableName(), 
SQLProvider.DatabaseStoreType.BINDINGS_JOURNAL), scheduledExecutorService, 
executorFactory.getExecutor(), criticalErrorListener, 
dbConf.getJdbcJournalSyncPeriodMillis());
+            messageJournal = new 
JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), dbConf.getJdbcUser(), 
dbConf.getJdbcPassword(), driverClassName, 
JDBCUtils.getSQLProvider(driverClassName, dbConf.getMessageTableName(), 
SQLProvider.DatabaseStoreType.MESSAGE_JOURNAL), scheduledExecutorService, 
executorFactory.getExecutor(), criticalErrorListener, 
dbConf.getJdbcJournalSyncPeriodMillis());
+            largeMessagesFactory = new 
JDBCSequentialFileFactory(dbConf.getJdbcConnectionUrl(), dbConf.getJdbcUser(), 
dbConf.getJdbcPassword(), driverClassName, 
JDBCUtils.getSQLProvider(driverClassName, dbConf.getLargeMessageTableName(), 
SQLProvider.DatabaseStoreType.LARGE_MESSAGE), executorFactory.getExecutor(), 
criticalErrorListener);
          }
          final int networkTimeout = dbConf.getJdbcNetworkTimeout();
          if (networkTimeout >= 0) {
diff --git a/artemis-server/src/main/resources/schema/artemis-configuration.xsd 
b/artemis-server/src/main/resources/schema/artemis-configuration.xsd
index 8fc8216..e24facf 100644
--- a/artemis-server/src/main/resources/schema/artemis-configuration.xsd
+++ b/artemis-server/src/main/resources/schema/artemis-configuration.xsd
@@ -2131,6 +2131,22 @@
                </xsd:documentation>
             </xsd:annotation>
          </xsd:element>
+         <xsd:element name="jdbc-user" type="xsd:string" minOccurs="0" 
maxOccurs="1">
+            <xsd:annotation>
+               <xsd:documentation>
+                  The JDBC User to use for connecting to the database, NB this 
will only work with drivers where support
+                  DriverManager.getConnection(String url, String user, String 
password). This can be encrypted.
+               </xsd:documentation>
+            </xsd:annotation>
+         </xsd:element>
+         <xsd:element name="jdbc-password" type="xsd:string" minOccurs="0" 
maxOccurs="1">
+            <xsd:annotation>
+               <xsd:documentation>
+                  The JDBC Password to use for connecting to the database, NB 
this will only work with drivers where support
+                  DriverManager.getConnection(String url, String user, String 
password). This can be encrypted.
+               </xsd:documentation>
+            </xsd:annotation>
+         </xsd:element>
          <xsd:element name="message-table-name" type="xsd:string" 
minOccurs="1" maxOccurs="1">
             <xsd:annotation>
                <xsd:documentation>
diff --git 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DatabaseStoreConfigurationTest.java
 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DatabaseStoreConfigurationTest.java
index 930eaa3..d990841 100644
--- 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DatabaseStoreConfigurationTest.java
+++ 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DatabaseStoreConfigurationTest.java
@@ -19,6 +19,7 @@ package org.apache.activemq.artemis.core.config.impl;
 import org.apache.activemq.artemis.core.config.Configuration;
 import org.apache.activemq.artemis.core.config.FileDeploymentManager;
 import org.apache.activemq.artemis.core.config.StoreConfiguration;
+import 
org.apache.activemq.artemis.core.config.storage.DatabaseStorageConfiguration;
 import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
 import org.apache.activemq.artemis.jdbc.store.sql.PropertySQLProvider;
 import org.apache.activemq.artemis.jdbc.store.sql.SQLProvider;
@@ -33,7 +34,10 @@ public class DatabaseStoreConfigurationTest extends 
ActiveMQTestBase {
    public void databaseStoreConfigTest() throws Exception {
       Configuration configuration = 
createConfiguration("database-store-config.xml");
       ActiveMQServerImpl server = new ActiveMQServerImpl(configuration);
-      assertEquals(StoreConfiguration.StoreType.DATABASE, 
server.getConfiguration().getStoreConfiguration().getStoreType());
+      DatabaseStorageConfiguration storeConfiguration = 
(DatabaseStorageConfiguration) 
server.getConfiguration().getStoreConfiguration();
+      assertEquals(StoreConfiguration.StoreType.DATABASE, 
storeConfiguration.getStoreType());
+      assertEquals("sourcepassword", storeConfiguration.getJdbcUser());
+      assertEquals("targetpassword", storeConfiguration.getJdbcPassword());
    }
 
    @Test
diff --git a/artemis-server/src/test/resources/database-store-config.xml 
b/artemis-server/src/test/resources/database-store-config.xml
index 69f9da7..47fd81d 100644
--- a/artemis-server/src/test/resources/database-store-config.xml
+++ b/artemis-server/src/test/resources/database-store-config.xml
@@ -22,6 +22,8 @@
       <store>
          <database-store>
             
<jdbc-connection-url>jdbc:derby:target/derby/database-store;create=true</jdbc-connection-url>
+            <jdbc-user>ENC(5493dd76567ee5ec269d11823973462f)</jdbc-user>
+            
<jdbc-password>ENC(56a0db3b71043054269d11823973462f)</jdbc-password>
             <bindings-table-name>BINDINGS_TABLE</bindings-table-name>
             <message-table-name>MESSAGE_TABLE</message-table-name>
             
<large-message-table-name>LARGE_MESSAGE_TABLE</large-message-table-name>
diff --git a/docs/user-manual/en/persistence.md 
b/docs/user-manual/en/persistence.md
index c8994da..c575a63 100644
--- a/docs/user-manual/en/persistence.md
+++ b/docs/user-manual/en/persistence.md
@@ -488,6 +488,23 @@ To configure Apache ActiveMQ Artemis to use a database for 
persisting messages a
 
 Note that some DBMS (e.g. Oracle, 30 chars) have restrictions on the size of 
table names, this should be taken into consideration when configuring table 
names for the Artemis database store, pay particular attention to the page 
store table name, which can be appended with a unique ID of up to 20 
characters.  (for Oracle this would mean configuring a page-store-table-name of 
max size of 10 chars).
 
+It is also possible to explicitly add the user and password rather than in the 
JDBC url if you need to encode it, this would look like:
+
+```xml
+<store>
+   <database-store>
+      
<jdbc-connection-url>jdbc:derby:data/derby/database-store;create=true</jdbc-connection-url>
+      <jdbc-user>ENC(dasfn353cewc)</jdbc-user>
+      <jdbc-password>ENC(ucwiurfjtew345)</jdbc-password>
+      <bindings-table-name>BINDINGS_TABLE</bindings-table-name>
+      <message-table-name>MESSAGE_TABLE</message-table-name>
+      <page-store-table-name>MESSAGE_TABLE</page-store-table-name>
+      <large-message-table-name>LARGE_MESSAGES_TABLE</large-message-table-name>
+      
<node-manager-store-table-name>NODE_MANAGER_TABLE</node-manager-store-table-name>
+      
<jdbc-driver-class-name>org.apache.derby.jdbc.EmbeddedDriver</jdbc-driver-class-name>
+   </database-store>
+</store>
+```
 ## Zero Persistence
 
 In some situations, zero persistence is sometimes required for a
diff --git 
a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jdbc/store/journal/JDBCJournalTest.java
 
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jdbc/store/journal/JDBCJournalTest.java
index 018a3de..0b832a8 100644
--- 
a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jdbc/store/journal/JDBCJournalTest.java
+++ 
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jdbc/store/journal/JDBCJournalTest.java
@@ -19,6 +19,8 @@ package 
org.apache.activemq.artemis.tests.integration.jdbc.store.journal;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
@@ -43,7 +45,10 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
+@RunWith(Parameterized.class)
 public class JDBCJournalTest extends ActiveMQTestBase {
 
    @Rule
@@ -59,31 +64,66 @@ public class JDBCJournalTest extends ActiveMQTestBase {
 
    private DatabaseStorageConfiguration dbConf;
 
+   @Parameterized.Parameter
+   public boolean useAuthentication;
+
+   @Parameterized.Parameters(name = "authentication = {0}")
+   public static Collection<Object[]> data() {
+      return Arrays.asList(new Object[][]{{false}, {true}});
+   }
+
    @After
    @Override
    public void tearDown() throws Exception {
       journal.destroy();
       try {
-         DriverManager.getConnection("jdbc:derby:;shutdown=true");
+         if (useAuthentication) {
+            DriverManager.getConnection("jdbc:derby:;shutdown=true", 
getJdbcUser(), getJdbcPassword());
+         } else {
+            DriverManager.getConnection("jdbc:derby:;shutdown=true");
+         }
       } catch (Exception ignored) {
       }
+      if (useAuthentication) {
+         System.clearProperty("derby.connection.requireAuthentication");
+         System.clearProperty("derby.user." + getJdbcUser());
+      }
       scheduledExecutorService.shutdown();
       scheduledExecutorService = null;
       executorService.shutdown();
       executorService = null;
+   }
 
+   protected String getJdbcUser() {
+      if (useAuthentication) {
+         return System.getProperty("jdbc.user", "testuser");
+      } else {
+         return null;
+      }
+   }
+
+   protected String getJdbcPassword() {
+      if (useAuthentication) {
+         return System.getProperty("jdbc.password", "testpassword");
+      } else {
+         return null;
+      }
    }
 
    @Before
    public void setup() throws Exception {
       dbConf = createDefaultDatabaseStorageConfiguration();
+      if (useAuthentication) {
+         System.setProperty("derby.connection.requireAuthentication", "true");
+         System.setProperty("derby.user." + getJdbcUser(), getJdbcPassword());
+      }
       sqlProvider = JDBCUtils.getSQLProvider(
          dbConf.getJdbcDriverClassName(),
          dbConf.getMessageTableName(),
          SQLProvider.DatabaseStoreType.MESSAGE_JOURNAL);
       scheduledExecutorService = new ScheduledThreadPoolExecutor(5);
       executorService = Executors.newSingleThreadExecutor();
-      journal = new JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), 
dbConf.getJdbcDriverClassName(), sqlProvider, scheduledExecutorService, 
executorService, new IOCriticalErrorListener() {
+      journal = new JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), 
getJdbcUser(), getJdbcPassword(), dbConf.getJdbcDriverClassName(), sqlProvider, 
scheduledExecutorService, executorService, new IOCriticalErrorListener() {
          @Override
          public void onIOException(Throwable code, String message, 
SequentialFile file) {
 
@@ -106,6 +146,8 @@ public class JDBCJournalTest extends ActiveMQTestBase {
       Assert.assertTrue(journal.isStarted());
       Assert.assertEquals(0, journal.getNumberOfRecords());
       final JDBCJournalImpl secondJournal = new 
JDBCJournalImpl(dbConf.getJdbcConnectionUrl(),
+                                                                          
getJdbcUser(),
+                                                                          
getJdbcPassword(),
                                                                           
dbConf.getJdbcDriverClassName(),
                                                                           
sqlProvider, scheduledExecutorService,
                                                                           
executorService, (code, message, file) -> {

Reply via email to