From a35b0915abbd65759b1a1753b5f9d0f148e26cea Mon Sep 17 00:00:00 2001 From: Luck Date: Fri, 23 Dec 2016 16:55:35 +0000 Subject: [PATCH] Refactor SQL storage - towards #77 --- .../common/storage/StorageFactory.java | 13 +- .../common/storage/backing/H2Backing.java | 139 ------------------ .../common/storage/backing/SQLBacking.java | 111 +++++++++----- .../FlatfileProvider.java} | 88 +++++------ .../backing/sqlprovider/H2Provider.java | 41 ++++++ .../MySQLProvider.java} | 48 +++--- .../backing/sqlprovider/SQLProvider.java | 78 ++++++++++ .../backing/sqlprovider/SQLiteProvider.java | 41 ++++++ 8 files changed, 297 insertions(+), 262 deletions(-) delete mode 100644 common/src/main/java/me/lucko/luckperms/common/storage/backing/H2Backing.java rename common/src/main/java/me/lucko/luckperms/common/storage/backing/{SQLiteBacking.java => sqlprovider/FlatfileProvider.java} (55%) create mode 100644 common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/H2Provider.java rename common/src/main/java/me/lucko/luckperms/common/storage/backing/{MySQLBacking.java => sqlprovider/MySQLProvider.java} (72%) create mode 100644 common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java create mode 100644 common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLiteProvider.java diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/StorageFactory.java b/common/src/main/java/me/lucko/luckperms/common/storage/StorageFactory.java index 50629d80f..d0d7438aa 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/StorageFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/StorageFactory.java @@ -28,12 +28,13 @@ import com.google.common.collect.ImmutableSet; import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.storage.backing.AbstractBacking; -import me.lucko.luckperms.common.storage.backing.H2Backing; import me.lucko.luckperms.common.storage.backing.JSONBacking; import me.lucko.luckperms.common.storage.backing.MongoDBBacking; -import me.lucko.luckperms.common.storage.backing.MySQLBacking; -import me.lucko.luckperms.common.storage.backing.SQLiteBacking; +import me.lucko.luckperms.common.storage.backing.SQLBacking; import me.lucko.luckperms.common.storage.backing.YAMLBacking; +import me.lucko.luckperms.common.storage.backing.sqlprovider.H2Provider; +import me.lucko.luckperms.common.storage.backing.sqlprovider.MySQLProvider; +import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLiteProvider; import me.lucko.luckperms.common.utils.ImmutableCollectors; import java.io.File; @@ -119,11 +120,11 @@ public class StorageFactory { private static AbstractBacking makeBacking(StorageType method, LuckPermsPlugin plugin) { switch (method) { case MYSQL: - return new MySQLBacking(plugin, plugin.getConfiguration().getDatabaseValues()); + return new SQLBacking(plugin, new MySQLProvider(plugin.getConfiguration().getDatabaseValues())); case SQLITE: - return new SQLiteBacking(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite")); + return new SQLBacking(plugin, new SQLiteProvider(new File(plugin.getDataFolder(), "luckperms.sqlite"))); case H2: - return new H2Backing(plugin, new File(plugin.getDataFolder(), "luckperms.db")); + return new SQLBacking(plugin, new H2Provider(new File(plugin.getDataFolder(), "luckperms.db"))); case MONGODB: return new MongoDBBacking(plugin, plugin.getConfiguration().getDatabaseValues()); case YAML: diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/H2Backing.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/H2Backing.java deleted file mode 100644 index a11792c76..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/H2Backing.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2016 Lucko (Luck) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.storage.backing; - -import me.lucko.luckperms.common.LuckPermsPlugin; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -public class H2Backing extends SQLBacking { - - private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;"; - - private final File file; - private final Object connectionLock = new Object(); - private Connection connection = null; - - public H2Backing(LuckPermsPlugin plugin, File file) { - super(plugin, "H2"); - this.file = file; - } - - @Override - public void init() { - if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) { - plugin.getLog().severe("Error occurred whilst initialising the database."); - shutdown(); - } else { - setAcceptingLogins(true); - } - } - - @Override - boolean runQuery(String query, QueryPS queryPS) { - boolean success = false; - - PreparedStatement preparedStatement = null; - - try { - Connection connection = getConnection(); - if (connection == null || connection.isClosed()) { - throw new IllegalStateException("SQL connection is null"); - } - - preparedStatement = connection.prepareStatement(query); - queryPS.onRun(preparedStatement); - - preparedStatement.execute(); - success = true; - } catch (SQLException e) { - e.printStackTrace(); - } finally { - close(preparedStatement); - } - return success; - } - - @Override - boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { - boolean success = false; - - PreparedStatement preparedStatement = null; - ResultSet resultSet = null; - - try { - Connection connection = getConnection(); - if (connection == null || connection.isClosed()) { - throw new IllegalStateException("SQL connection is null"); - } - - preparedStatement = connection.prepareStatement(query); - queryPS.onRun(preparedStatement); - - resultSet = preparedStatement.executeQuery(); - success = queryRS.onResult(resultSet); - } catch (SQLException e) { - e.printStackTrace(); - } finally { - close(resultSet); - close(preparedStatement); - } - return success; - } - - @Override - public void shutdown() { - try { - if (connection != null && !connection.isClosed()) { - connection.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - - @Override - Connection getConnection() throws SQLException { - synchronized (connectionLock) { - if (connection == null || connection.isClosed()) { - try { - Class.forName("org.h2.Driver"); - } catch (ClassNotFoundException ignored) { - } - - connection = DriverManager.getConnection("jdbc:h2:" + file.getAbsolutePath()); - } - } - - return connection; - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java index bad705e4b..561318029 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLBacking.java @@ -22,6 +22,7 @@ package me.lucko.luckperms.common.storage.backing; +import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -35,12 +36,11 @@ import me.lucko.luckperms.common.data.Log; import me.lucko.luckperms.common.managers.GroupManager; import me.lucko.luckperms.common.managers.TrackManager; import me.lucko.luckperms.common.managers.impl.GenericUserManager; +import me.lucko.luckperms.common.storage.backing.sqlprovider.H2Provider; +import me.lucko.luckperms.common.storage.backing.sqlprovider.MySQLProvider; +import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider; import java.lang.reflect.Type; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -49,13 +49,37 @@ import java.util.Set; import java.util.UUID; import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLegacy; +import static me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider.QueryPS; +import static me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider.QueryRS; -abstract class SQLBacking extends AbstractBacking { - private static final QueryPS EMPTY_PS = preparedStatement -> {}; - +public class SQLBacking extends AbstractBacking { private static final Type NM_TYPE = new TypeToken>() {}.getType(); private static final Type T_TYPE = new TypeToken>() {}.getType(); + + private static final String MYSQL_CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; + private static final String MYSQL_CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;"; + private static final String MYSQL_CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; + private static final String MYSQL_CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; + private static final String MYSQL_CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;"; + private static final String H2_CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; + private static final String H2_CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;"; + private static final String H2_CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; + private static final String H2_CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; + private static final String H2_CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;"; + + private static final String SQLITE_CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));"; + private static final String SQLITE_CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`));"; + private static final String SQLITE_CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`));"; + private static final String SQLITE_CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`));"; + private static final String SQLITE_CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INTEGER PRIMARY KEY NOT NULL, `time` BIG INT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL);"; + + private static final Map, String[]> INIT_QUERIES = ImmutableMap., String[]>builder() + .put(MySQLProvider.class, new String[]{MYSQL_CREATETABLE_UUID, MYSQL_CREATETABLE_USERS, MYSQL_CREATETABLE_GROUPS, MYSQL_CREATETABLE_TRACKS, MYSQL_CREATETABLE_ACTION}) + .put(H2Provider.class, new String[]{H2_CREATETABLE_UUID, H2_CREATETABLE_USERS, H2_CREATETABLE_GROUPS, H2_CREATETABLE_TRACKS, H2_CREATETABLE_ACTION}) + .put(SQLProvider.class, new String[]{SQLITE_CREATETABLE_UUID, SQLITE_CREATETABLE_USERS, SQLITE_CREATETABLE_GROUPS, SQLITE_CREATETABLE_TRACKS, SQLITE_CREATETABLE_ACTION}) + .build(); + private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?, ?)"; private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?"; private static final String USER_SELECT_ALL = "SELECT uuid FROM lp_users"; @@ -83,37 +107,32 @@ abstract class SQLBacking extends AbstractBacking { private static final String ACTION_INSERT = "INSERT INTO lp_actions(`time`, `actor_uuid`, `actor_name`, `type`, `acted_uuid`, `acted_name`, `action`) VALUES(?, ?, ?, ?, ?, ?, ?)"; private static final String ACTION_SELECT_ALL = "SELECT * FROM lp_actions"; - protected static void close(AutoCloseable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (Exception ignored) { - } - } - } - private final Gson gson; + private final SQLProvider provider; - SQLBacking(LuckPermsPlugin plugin, String name) { - super(plugin, name); + public SQLBacking(LuckPermsPlugin plugin, SQLProvider provider) { + super(plugin, provider.getName()); + this.provider = provider; gson = new Gson(); } - abstract Connection getConnection() throws SQLException; - - abstract boolean runQuery(String query, QueryPS queryPS); - - abstract boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS); - - boolean runQuery(String query) { - return runQuery(query, EMPTY_PS); + private boolean runQuery(String query, QueryPS queryPS) { + return provider.runQuery(query, queryPS); } - boolean runQuery(String query, QueryRS queryRS) { - return runQuery(query, EMPTY_PS, queryRS); + private boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { + return provider.runQuery(query, queryPS, queryRS); } - boolean setupTables(String... tableQueries) { + private boolean runQuery(String query) { + return provider.runQuery(query); + } + + private boolean runQuery(String query, QueryRS queryRS) { + return provider.runQuery(query, queryRS); + } + + private boolean setupTables(String[] tableQueries) { boolean success = true; for (String q : tableQueries) { if (!runQuery(q)) success = false; @@ -122,6 +141,32 @@ abstract class SQLBacking extends AbstractBacking { return success && cleanupUsers(); } + @Override + public void init() { + try { + provider.init(); + + if (!setupTables(INIT_QUERIES.get(provider.getClass()))) { + plugin.getLog().severe("Error occurred whilst initialising the database."); + shutdown(); + } else { + setAcceptingLogins(true); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void shutdown() { + try { + provider.shutdown(); + } catch (Exception e) { + e.printStackTrace(); + } + } + @Override public boolean logAction(LogEntry entry) { return runQuery(ACTION_INSERT, preparedStatement -> { @@ -635,12 +680,4 @@ abstract class SQLBacking extends AbstractBacking { return success ? name[0] : null; } - - interface QueryPS { - void onRun(PreparedStatement preparedStatement) throws SQLException; - } - - interface QueryRS { - boolean onResult(ResultSet resultSet) throws SQLException; - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLiteBacking.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/FlatfileProvider.java similarity index 55% rename from common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLiteBacking.java rename to common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/FlatfileProvider.java index f28757423..d5140c0bc 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/SQLiteBacking.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/FlatfileProvider.java @@ -20,9 +20,7 @@ * SOFTWARE. */ -package me.lucko.luckperms.common.storage.backing; - -import me.lucko.luckperms.common.LuckPermsPlugin; +package me.lucko.luckperms.common.storage.backing.sqlprovider; import java.io.File; import java.sql.Connection; @@ -30,36 +28,55 @@ import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.concurrent.locks.ReentrantLock; -public class SQLiteBacking extends SQLBacking { - - private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));"; - private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`));"; - private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`));"; - private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`));"; - private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INTEGER PRIMARY KEY NOT NULL, `time` BIG INT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL);"; +public abstract class FlatfileProvider extends SQLProvider { private final File file; - private final Object connectionLock = new Object(); - private Connection connection = null; + private final ReentrantLock lock = new ReentrantLock(); + private Connection connection; - public SQLiteBacking(LuckPermsPlugin plugin, File file) { - super(plugin, "SQLite"); + public FlatfileProvider(String name, File file) { + super(name); this.file = file; } + protected abstract String getDriverClass(); + protected abstract String getDriverId(); + @Override - public void init() { - if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) { - plugin.getLog().severe("Error occurred whilst initialising the database."); - shutdown(); - } else { - setAcceptingLogins(true); + public void init() throws Exception { + + } + + @Override + public void shutdown() throws Exception { + if (connection != null && !connection.isClosed()) { + connection.close(); } } @Override - boolean runQuery(String query, QueryPS queryPS) { + public Connection getConnection() throws SQLException { + lock.lock(); + try { + if (connection == null || connection.isClosed()) { + try { + Class.forName(getDriverClass()); + } catch (ClassNotFoundException ignored) {} + + connection = DriverManager.getConnection(getDriverId() + ":" + file.getAbsolutePath()); + } + + } finally { + lock.unlock(); + } + + return connection; + } + + @Override + public boolean runQuery(String query, QueryPS queryPS) { boolean success = false; PreparedStatement preparedStatement = null; @@ -84,7 +101,7 @@ public class SQLiteBacking extends SQLBacking { } @Override - boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { + public boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { boolean success = false; PreparedStatement preparedStatement = null; @@ -109,31 +126,4 @@ public class SQLiteBacking extends SQLBacking { } return success; } - - @Override - public void shutdown() { - try { - if (connection != null && !connection.isClosed()) { - connection.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - - @Override - Connection getConnection() throws SQLException { - synchronized (connectionLock) { - if (connection == null || connection.isClosed()) { - try { - Class.forName("org.sqlite.JDBC"); - } catch (ClassNotFoundException ignored) { - } - - connection = DriverManager.getConnection("jdbc:sqlite:" + file.getAbsolutePath()); - } - } - - return connection; - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/H2Provider.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/H2Provider.java new file mode 100644 index 000000000..ca05047bb --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/H2Provider.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.storage.backing.sqlprovider; + +import java.io.File; + +public class H2Provider extends FlatfileProvider { + public H2Provider(File file) { + super("H2", file); + } + + @Override + protected String getDriverClass() { + return "org.h2.Driver"; + } + + @Override + protected String getDriverId() { + return "jdbc:h2"; + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/MySQLBacking.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/MySQLProvider.java similarity index 72% rename from common/src/main/java/me/lucko/luckperms/common/storage/backing/MySQLBacking.java rename to common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/MySQLProvider.java index fea22c883..a1ca22d88 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/MySQLBacking.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/MySQLProvider.java @@ -20,12 +20,11 @@ * SOFTWARE. */ -package me.lucko.luckperms.common.storage.backing; +package me.lucko.luckperms.common.storage.backing.sqlprovider; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; -import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.storage.DatastoreConfiguration; import java.sql.Connection; @@ -34,24 +33,18 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.concurrent.TimeUnit; -public class MySQLBacking extends SQLBacking { - - private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;"; - private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;"; +public class MySQLProvider extends SQLProvider { private final DatastoreConfiguration configuration; private HikariDataSource hikari; - public MySQLBacking(LuckPermsPlugin plugin, DatastoreConfiguration configuration) { - super(plugin, "MySQL"); + public MySQLProvider(DatastoreConfiguration configuration) { + super("MySQL"); this.configuration = configuration; } @Override - public void init() { + public void init() throws Exception { HikariConfig config = new HikariConfig(); String address = configuration.getAddress(); @@ -87,17 +80,22 @@ public class MySQLBacking extends SQLBacking { config.setConnectionTestQuery("/* LuckPerms ping */ SELECT 1"); hikari = new HikariDataSource(config); + } - if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) { - plugin.getLog().severe("Error occurred whilst initialising the database."); - shutdown(); - } else { - setAcceptingLogins(true); + @Override + public void shutdown() throws Exception { + if (hikari != null) { + hikari.close(); } } @Override - boolean runQuery(String query, QueryPS queryPS) { + public Connection getConnection() throws SQLException { + return hikari.getConnection(); + } + + @Override + public boolean runQuery(String query, QueryPS queryPS) { boolean success = false; Connection connection = null; @@ -124,7 +122,7 @@ public class MySQLBacking extends SQLBacking { } @Override - boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { + public boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) { boolean success = false; Connection connection = null; @@ -151,16 +149,4 @@ public class MySQLBacking extends SQLBacking { } return success; } - - @Override - public void shutdown() { - if (hikari != null) { - hikari.close(); - } - } - - @Override - Connection getConnection() throws SQLException { - return hikari.getConnection(); - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java new file mode 100644 index 000000000..f1659c61d --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLProvider.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.storage.backing.sqlprovider; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +@RequiredArgsConstructor +public abstract class SQLProvider { + private static final QueryPS EMPTY_PS = preparedStatement -> {}; + + static void close(AutoCloseable closeable) { + if (closeable != null) { + try { + closeable.close(); + } catch (Exception ignored) { + } + } + } + + @Getter + private final String name; + + public abstract void init() throws Exception; + + public abstract void shutdown() throws Exception; + + public abstract Connection getConnection() throws SQLException; + + public abstract boolean runQuery(String query, QueryPS queryPS); + + public abstract boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS); + + public boolean runQuery(String query) { + return runQuery(query, EMPTY_PS); + } + + public boolean runQuery(String query, QueryRS queryRS) { + return runQuery(query, EMPTY_PS, queryRS); + } + + + @FunctionalInterface + public interface QueryPS { + void onRun(PreparedStatement preparedStatement) throws SQLException; + } + + @FunctionalInterface + public interface QueryRS { + boolean onResult(ResultSet resultSet) throws SQLException; + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLiteProvider.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLiteProvider.java new file mode 100644 index 000000000..73042d39a --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/sqlprovider/SQLiteProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.storage.backing.sqlprovider; + +import java.io.File; + +public class SQLiteProvider extends FlatfileProvider { + public SQLiteProvider(File file) { + super("SQLite", file); + } + + @Override + protected String getDriverClass() { + return "org.sqlite.JDBC"; + } + + @Override + protected String getDriverId() { + return "jdbc:sqlite"; + } +}