diff --git a/dbptk-modules/dbptk-module-ms-access/pom.xml b/dbptk-modules/dbptk-module-ms-access/pom.xml
index 83f4cba80..e874d3cad 100644
--- a/dbptk-modules/dbptk-module-ms-access/pom.xml
+++ b/dbptk-modules/dbptk-module-ms-access/pom.xml
@@ -29,12 +29,12 @@
io.github.spannm
ucanaccess
- 5.1.3
+ 5.1.8
- com.healthmarketscience.jackcess
+ io.github.spannm
jackcess-encrypt
- 4.0.3
+ 5.1.6
org.bouncycastle
diff --git a/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/MsAccessUCanAccessModuleFactory.java b/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/MsAccessUCanAccessModuleFactory.java
index c87028a72..e8f267e2d 100644
--- a/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/MsAccessUCanAccessModuleFactory.java
+++ b/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/MsAccessUCanAccessModuleFactory.java
@@ -85,7 +85,8 @@ public Parameters getExportModuleParameters() throws UnsupportedModuleException
}
@Override
- public DatabaseImportModule buildImportModule(Map parameters, Reporter reporter) throws ModuleException {
+ public DatabaseImportModule buildImportModule(Map parameters, Reporter reporter)
+ throws ModuleException {
String pAccessFilePath = parameters.get(accessFilePath);
String pAccessPassword = null;
diff --git a/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/in/MsAccessCryptCodecJackcessOpener.java b/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/in/MsAccessCryptCodecJackcessOpener.java
new file mode 100644
index 000000000..0b867711a
--- /dev/null
+++ b/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/in/MsAccessCryptCodecJackcessOpener.java
@@ -0,0 +1,58 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE file at the root of the source
+ * tree and available online at
+ *
+ * https://github.com/keeps/db-preservation-toolkit
+ */
+package com.databasepreservation.modules.msAccess.in;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+import org.apache.commons.lang3.StringUtils;
+
+import io.github.spannm.jackcess.Database;
+import io.github.spannm.jackcess.DatabaseBuilder;
+import io.github.spannm.jackcess.DateTimeType;
+import io.github.spannm.jackcess.encrypt.CryptCodecProvider;
+import net.ucanaccess.jdbc.IJackcessOpenerInterface;
+
+/**
+ * {@link IJackcessOpenerInterface} implementation that registers a
+ * {@link CryptCodecProvider} so that password-protected Microsoft Access
+ * databases (including the AES-encrypted format used by Access 2007+
+ * {@code .accdb} files) can actually be decoded. UCanAccess itself never wires
+ * up {@code jackcess-encrypt}, so without a custom opener like this one, any
+ * password passed to UCanAccess is silently ignored.
+ */
+public class MsAccessCryptCodecJackcessOpener implements IJackcessOpenerInterface {
+
+ @Override
+ public Database open(File fl, String pwd) throws IOException {
+ return open(fl, pwd, null);
+ }
+
+ @Override
+ public Database open(File fl, String pwd, Charset charset) throws IOException {
+ DatabaseBuilder dbd = new DatabaseBuilder()
+ .withFile(fl)
+ .withAutoSync(false)
+ .withCharset(charset);
+
+ if (StringUtils.isNotEmpty(pwd)) {
+ dbd.withCodecProvider(new CryptCodecProvider(pwd));
+ }
+
+ Database db;
+ try {
+ db = dbd.withReadOnly(false).open();
+ } catch (Exception ex) {
+ db = dbd.withReadOnly(true).open();
+ }
+ db.setDateTimeType(DateTimeType.LOCAL_DATE_TIME);
+ return db;
+ }
+
+}
diff --git a/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/in/MsAccessUCanAccessImportModule.java b/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/in/MsAccessUCanAccessImportModule.java
index 8ba98469c..359427553 100644
--- a/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/in/MsAccessUCanAccessImportModule.java
+++ b/dbptk-modules/dbptk-module-ms-access/src/main/java/com/databasepreservation/modules/msAccess/in/MsAccessUCanAccessImportModule.java
@@ -63,13 +63,13 @@ public MsAccessUCanAccessImportModule(String moduleName, File msAccessFile, Map<
super("net.ucanaccess.jdbc.UcanaccessDriver",
"jdbc:ucanaccess://" + msAccessFile.getAbsolutePath() + ";showSchema=true;", new MsAccessHelper(),
new MsAccessUCanAccessDatatypeImporter(), moduleName, properties);
- this.msAccessFile = msAccessFile;
+ this.msAccessFile = msAccessFile;
}
public MsAccessUCanAccessImportModule(String moduleName, File msAccessFile, String password) throws ModuleException {
this(moduleName, msAccessFile, MapUtils.buildMapFromObjects(MsAccessUCanAccessModuleFactory.PARAMETER_FILE,
msAccessFile, MsAccessUCanAccessModuleFactory.PARAMETER_PASSWORD, password));
- this.password = password;
+ this.password = password;
}
public MsAccessUCanAccessImportModule(String moduleName, String accessFilePath) throws ModuleException {
@@ -84,10 +84,12 @@ public MsAccessUCanAccessImportModule(String moduleName, String accessFilePath,
@Override
protected Connection createConnection() throws ModuleException {
- UcanaccessConnectionBuilder builder = new UcanaccessConnectionBuilder().withDbPath(msAccessFile).withProp(Property.showSchema, true);
- if (StringUtils.isNotEmpty(password)) {
- builder.withPassword(password);
- }
+ UcanaccessConnectionBuilder builder = new UcanaccessConnectionBuilder().withDbPath(msAccessFile).withProp(
+ Property.showSchema, true);
+ if (StringUtils.isNotEmpty(password)) {
+ builder.withPassword(password);
+ builder.withProp(Property.jackcessOpener, MsAccessCryptCodecJackcessOpener.class.getName());
+ }
return builder.build();
}