From d885932f4539f974750697a00fb52f6ab573ee7e Mon Sep 17 00:00:00 2001 From: Max Dor Date: Tue, 15 Jan 2019 06:19:34 +0100 Subject: [PATCH] Fix loading failures of JDBC drivers for SQL-based Identity stores --- build.gradle | 2 +- src/main/java/io/kamax/mxisd/Mxisd.java | 4 +- .../backend/sql/BuiltInDriverLoader.java | 55 +++++++++++++++++++ .../kamax/mxisd/backend/sql/DriverLoader.java | 26 +++++++++ .../io/kamax/mxisd/backend/sql/Drivers.java | 38 +++++++++++++ .../mxisd/backend/sql/SqlConnectionPool.java | 4 ++ .../exception/ConfigurationException.java | 2 +- ...iteStorage.java => OrmLiteSqlStorage.java} | 16 ++---- .../io.kamax.mxisd.backend.sql.DriverLoader | 1 + ...geTest.java => OrmLiteSqlStorageTest.java} | 8 +-- 10 files changed, 136 insertions(+), 20 deletions(-) create mode 100644 src/main/java/io/kamax/mxisd/backend/sql/BuiltInDriverLoader.java create mode 100644 src/main/java/io/kamax/mxisd/backend/sql/DriverLoader.java create mode 100644 src/main/java/io/kamax/mxisd/backend/sql/Drivers.java rename src/main/java/io/kamax/mxisd/storage/ormlite/{OrmLiteSqliteStorage.java => OrmLiteSqlStorage.java} (93%) create mode 100644 src/main/resources/META-INF/services/io.kamax.mxisd.backend.sql.DriverLoader rename src/test/java/io/kamax/mxisd/test/storage/{OrmLiteSqliteStorageTest.java => OrmLiteSqlStorageTest.java} (82%) diff --git a/build.gradle b/build.gradle index ba8f139..5078788 100644 --- a/build.gradle +++ b/build.gradle @@ -129,7 +129,7 @@ dependencies { compile 'org.xerial:sqlite-jdbc:3.20.0' // PostgreSQL - compile 'org.postgresql:postgresql:42.1.4' + compile 'org.postgresql:postgresql:42.2.5' // MariaDB/MySQL compile 'org.mariadb.jdbc:mariadb-java-client:2.1.2' diff --git a/src/main/java/io/kamax/mxisd/Mxisd.java b/src/main/java/io/kamax/mxisd/Mxisd.java index cfbe37f..4640f68 100644 --- a/src/main/java/io/kamax/mxisd/Mxisd.java +++ b/src/main/java/io/kamax/mxisd/Mxisd.java @@ -47,7 +47,7 @@ import io.kamax.mxisd.profile.ProfileManager; import io.kamax.mxisd.profile.ProfileProviders; import io.kamax.mxisd.session.SessionMananger; import io.kamax.mxisd.storage.IStorage; -import io.kamax.mxisd.storage.ormlite.OrmLiteSqliteStorage; +import io.kamax.mxisd.storage.ormlite.OrmLiteSqlStorage; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; @@ -88,7 +88,7 @@ public class Mxisd { srvFetcher = new RemoteIdentityServerFetcher(httpClient); - store = new OrmLiteSqliteStorage(cfg); + store = new OrmLiteSqlStorage(cfg); keyMgr = CryptoFactory.getKeyManager(cfg.getKey()); signMgr = CryptoFactory.getSignatureManager(keyMgr, cfg.getServer()); ClientDnsOverwrite clientDns = new ClientDnsOverwrite(cfg.getDns().getOverwrite()); diff --git a/src/main/java/io/kamax/mxisd/backend/sql/BuiltInDriverLoader.java b/src/main/java/io/kamax/mxisd/backend/sql/BuiltInDriverLoader.java new file mode 100644 index 0000000..fadafa0 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/BuiltInDriverLoader.java @@ -0,0 +1,55 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2019 Kamax Sàrl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql; + +import org.apache.commons.lang3.StringUtils; + +public class BuiltInDriverLoader implements DriverLoader { + + @Override + public void accept(String s) { + String className = null; + if (StringUtils.equals("sqlite", s)) { + className = "org.sqlite.JDBC"; + } + + if (StringUtils.equals("postgresql", s)) { + className = "org.postgresql.Driver"; + } + + if (StringUtils.equals("mariadb", s)) { + className = "org.mariadb.jdbc.Driver"; + } + + if (StringUtils.equals("mysql", s)) { + className = "org.mariadb.jdbc.Driver"; + } + + if (StringUtils.isNotEmpty(className)) { + try { + Class.forName(className); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/DriverLoader.java b/src/main/java/io/kamax/mxisd/backend/sql/DriverLoader.java new file mode 100644 index 0000000..35cb18b --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/DriverLoader.java @@ -0,0 +1,26 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2019 Kamax Sàrl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql; + +import java.util.function.Consumer; + +public interface DriverLoader extends Consumer { +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/Drivers.java b/src/main/java/io/kamax/mxisd/backend/sql/Drivers.java new file mode 100644 index 0000000..f0234e7 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/Drivers.java @@ -0,0 +1,38 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2019 Kamax Sàrl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql; + +import java.util.Objects; +import java.util.ServiceLoader; + +public class Drivers { + + private static ServiceLoader svcLoader; + + public static void load(String type) { + if (Objects.isNull(svcLoader)) { + svcLoader = ServiceLoader.load(DriverLoader.class); + } + + svcLoader.iterator().forEachRemaining(drv -> drv.accept(type)); + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java b/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java index 4f3224c..e73c244 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java @@ -37,11 +37,15 @@ public class SqlConnectionPool { private ComboPooledDataSource ds; public SqlConnectionPool(SqlConfig cfg) { + Drivers.load(cfg.getType()); + ds = new ComboPooledDataSource(); ds.setJdbcUrl("jdbc:" + cfg.getType() + ":" + cfg.getConnection()); ds.setMinPoolSize(1); ds.setMaxPoolSize(10); ds.setAcquireIncrement(2); + ds.setAcquireRetryAttempts(10); + ds.setAcquireRetryDelay(1000); } public Connection get() throws SQLException { diff --git a/src/main/java/io/kamax/mxisd/exception/ConfigurationException.java b/src/main/java/io/kamax/mxisd/exception/ConfigurationException.java index 02c6051..d6569ae 100644 --- a/src/main/java/io/kamax/mxisd/exception/ConfigurationException.java +++ b/src/main/java/io/kamax/mxisd/exception/ConfigurationException.java @@ -28,7 +28,7 @@ public class ConfigurationException extends RuntimeException { private String detailedMsg; public ConfigurationException(String key) { - super("Invalid or empty value for configuration item " + key); + super("Invalid or empty value for configuration item: " + key); } public ConfigurationException(Throwable t) { diff --git a/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqliteStorage.java b/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqlStorage.java similarity index 93% rename from src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqliteStorage.java rename to src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqlStorage.java index 26fef5c..0149a7b 100644 --- a/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqliteStorage.java +++ b/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqlStorage.java @@ -40,7 +40,6 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; import java.sql.SQLException; import java.time.Instant; @@ -49,9 +48,9 @@ import java.util.Collection; import java.util.List; import java.util.Optional; -public class OrmLiteSqliteStorage implements IStorage { +public class OrmLiteSqlStorage implements IStorage { - private transient final Logger log = LoggerFactory.getLogger(OrmLiteSqliteStorage.class); + private transient final Logger log = LoggerFactory.getLogger(OrmLiteSqlStorage.class); @FunctionalInterface private interface Getter { @@ -71,11 +70,11 @@ public class OrmLiteSqliteStorage implements IStorage { private Dao sessionDao; private Dao asTxnDao; - public OrmLiteSqliteStorage(MxisdConfig cfg) { + public OrmLiteSqlStorage(MxisdConfig cfg) { this(cfg.getStorage().getBackend(), cfg.getStorage().getProvider().getSqlite().getDatabase()); } - public OrmLiteSqliteStorage(String backend, String path) { + public OrmLiteSqlStorage(String backend, String path) { if (StringUtils.isBlank(backend)) { throw new ConfigurationException("storage.backend"); } @@ -85,13 +84,6 @@ public class OrmLiteSqliteStorage implements IStorage { } withCatcher(() -> { - if (path.startsWith("/") && !path.startsWith("//")) { - File parent = new File(path).getParentFile(); - if (!parent.mkdirs() && !parent.isDirectory()) { - throw new RuntimeException("Unable to create DB parent directory: " + parent); - } - } - ConnectionSource connPool = new JdbcConnectionSource("jdbc:" + backend + ":" + path); invDao = createDaoAndTable(connPool, ThreePidInviteIO.class); sessionDao = createDaoAndTable(connPool, ThreePidSessionDao.class); diff --git a/src/main/resources/META-INF/services/io.kamax.mxisd.backend.sql.DriverLoader b/src/main/resources/META-INF/services/io.kamax.mxisd.backend.sql.DriverLoader new file mode 100644 index 0000000..ef69d5b --- /dev/null +++ b/src/main/resources/META-INF/services/io.kamax.mxisd.backend.sql.DriverLoader @@ -0,0 +1 @@ +io.kamax.mxisd.backend.sql.BuiltInDriverLoader diff --git a/src/test/java/io/kamax/mxisd/test/storage/OrmLiteSqliteStorageTest.java b/src/test/java/io/kamax/mxisd/test/storage/OrmLiteSqlStorageTest.java similarity index 82% rename from src/test/java/io/kamax/mxisd/test/storage/OrmLiteSqliteStorageTest.java rename to src/test/java/io/kamax/mxisd/test/storage/OrmLiteSqlStorageTest.java index a83e5ae..3526820 100644 --- a/src/test/java/io/kamax/mxisd/test/storage/OrmLiteSqliteStorageTest.java +++ b/src/test/java/io/kamax/mxisd/test/storage/OrmLiteSqlStorageTest.java @@ -20,23 +20,23 @@ package io.kamax.mxisd.test.storage; -import io.kamax.mxisd.storage.ormlite.OrmLiteSqliteStorage; +import io.kamax.mxisd.storage.ormlite.OrmLiteSqlStorage; import org.junit.Test; import java.time.Instant; -public class OrmLiteSqliteStorageTest { +public class OrmLiteSqlStorageTest { @Test public void insertAsTxnDuplicate() { - OrmLiteSqliteStorage store = new OrmLiteSqliteStorage("sqlite", ":memory:"); + OrmLiteSqlStorage store = new OrmLiteSqlStorage("sqlite", ":memory:"); store.insertTransactionResult("mxisd", "1", Instant.now(), "{}"); store.insertTransactionResult("mxisd", "2", Instant.now(), "{}"); } @Test(expected = RuntimeException.class) public void insertAsTxnSame() { - OrmLiteSqliteStorage store = new OrmLiteSqliteStorage("sqlite", ":memory:"); + OrmLiteSqlStorage store = new OrmLiteSqlStorage("sqlite", ":memory:"); store.insertTransactionResult("mxisd", "1", Instant.now(), "{}"); store.insertTransactionResult("mxisd", "1", Instant.now(), "{}"); }