diff --git a/common/src/main/java/me/lucko/luckperms/data/methods/FlatfileDatastore.java b/common/src/main/java/me/lucko/luckperms/data/methods/FlatfileDatastore.java index 3f816a44..984ba7d0 100644 --- a/common/src/main/java/me/lucko/luckperms/data/methods/FlatfileDatastore.java +++ b/common/src/main/java/me/lucko/luckperms/data/methods/FlatfileDatastore.java @@ -76,7 +76,7 @@ public class FlatfileDatastore extends Datastore { return success; } - private void close(AutoCloseable closeable) { + private static void close(AutoCloseable closeable) { if (closeable == null) return; try { closeable.close(); diff --git a/common/src/main/java/me/lucko/luckperms/data/methods/SQLDatastore.java b/common/src/main/java/me/lucko/luckperms/data/methods/SQLDatastore.java index e0c6e415..215f0f7d 100644 --- a/common/src/main/java/me/lucko/luckperms/data/methods/SQLDatastore.java +++ b/common/src/main/java/me/lucko/luckperms/data/methods/SQLDatastore.java @@ -2,6 +2,8 @@ package me.lucko.luckperms.data.methods; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import lombok.AllArgsConstructor; +import lombok.Getter; import me.lucko.luckperms.LuckPermsPlugin; import me.lucko.luckperms.data.Datastore; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; @@ -21,7 +23,7 @@ import java.util.UUID; import java.util.logging.Level; @SuppressWarnings("UnnecessaryLocalVariable") -public abstract class SQLDatastore extends Datastore { +abstract class SQLDatastore extends Datastore { private static final Type NM_TYPE = new TypeToken>(){}.getType(); @@ -48,47 +50,75 @@ public abstract class SQLDatastore extends Datastore { abstract Connection getConnection() throws SQLException; - private static void executeQuery(Connection connection, String query, Closer closer) throws SQLException { - PreparedStatement preparedStatement = connection.prepareStatement(query); - closer.add(preparedStatement); - preparedStatement.execute(); - preparedStatement.close(); + private static void close(AutoCloseable closeable) { + if (closeable == null) return; + try { + closeable.close(); + } catch (Exception e) { + e.printStackTrace(); + } } - private boolean runQuery(Query query) { + private boolean runQuery(QueryPS queryPS) { boolean success = false; Connection connection = null; - Closer c = new Closer(); + PreparedStatement preparedStatement = null; try { connection = getConnection(); if (connection == null) { throw new IllegalStateException("SQL connection is null"); } - success = query.onRun(connection, c); + + preparedStatement = connection.prepareStatement(queryPS.getQuery()); + queryPS.onRun(preparedStatement); + preparedStatement.execute(); + success = true; + } catch (SQLException e) { e.printStackTrace(); - success = false; } finally { - c.closeAll(); - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + close(preparedStatement); + close(connection); + } + return success; + } + + private boolean runQuery(QueryRS queryRS) { + boolean success = false; + + Connection connection = null; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + + try { + connection = getConnection(); + if (connection == null) { + throw new IllegalStateException("SQL connection is null"); } + + preparedStatement = connection.prepareStatement(queryRS.getQuery()); + queryRS.onRun(preparedStatement); + preparedStatement.execute(); + + resultSet = preparedStatement.executeQuery(); + success = queryRS.onResult(resultSet); + + } catch (SQLException e) { + e.printStackTrace(); + } finally { + close(resultSet); + close(preparedStatement); + close(connection); } return success; } void setupTables(String... tableQueries) { - boolean success = runQuery((connection, closer) -> { - for (String s : tableQueries) { - executeQuery(connection, s, closer); - } - return true; - }); + boolean success = true; + for (String q : tableQueries) { + if (!runQuery(new Query(q))) success = false; + } if (!success) { plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed."); @@ -100,19 +130,21 @@ public abstract class SQLDatastore extends Datastore { @Override public boolean loadUser(UUID uuid) { User user = plugin.getUserManager().makeUser(uuid); - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(USER_SELECT); - closer.add(preparedStatement); - preparedStatement.setString(1, uuid.toString()); - - ResultSet resultSet = preparedStatement.executeQuery(); - closer.add(resultSet); - if (resultSet.next()) { - user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); - user.setName(resultSet.getString("name")); - return true; + boolean success = runQuery(new QueryRS(USER_SELECT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, uuid.toString()); + } + + @Override + boolean onResult(ResultSet resultSet) throws SQLException { + if (resultSet.next()) { + user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); + user.setName(resultSet.getString("name")); + return true; + } + return false; } - return false; }); // User updating and loading should be done sync as permission attachments are updated @@ -126,24 +158,30 @@ public abstract class SQLDatastore extends Datastore { try { user.setPermission(plugin.getConfiguration().getDefaultGroupNode(), true); } catch (ObjectAlreadyHasException ignored) {} - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(USER_SELECT); - closer.add(preparedStatement); - preparedStatement.setString(1, user.getUuid().toString()); - ResultSet resultSet = preparedStatement.executeQuery(); - closer.add(resultSet); - if (!resultSet.next()) { - PreparedStatement preparedStatement1 = connection.prepareStatement(USER_INSERT); - closer.add(preparedStatement1); - preparedStatement1.setString(1, user.getUuid().toString()); - preparedStatement1.setString(2, user.getName()); - preparedStatement1.setString(3, gson.toJson(user.getNodes())); - preparedStatement1.execute(); - } else { - user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); + boolean success = runQuery(new QueryRS(USER_SELECT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, user.getUuid().toString()); + } + + @Override + boolean onResult(ResultSet resultSet) throws SQLException { + boolean success = true; + if (!resultSet.next()) { + success = runQuery(new QueryPS(USER_INSERT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, user.getUuid().toString()); + preparedStatement.setString(2, user.getName()); + preparedStatement.setString(3, gson.toJson(user.getNodes())); + } + }); + } else { + user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); + } + return success; } - return true; }); // User updating and loading should be done sync as permission attachments are updated @@ -153,14 +191,13 @@ public abstract class SQLDatastore extends Datastore { @Override public boolean saveUser(User user) { - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(USER_UPDATE); - closer.add(preparedStatement); - preparedStatement.setString(1, user.getName()); - preparedStatement.setString(2, gson.toJson(user.getNodes())); - preparedStatement.setString(3, user.getUuid().toString()); - preparedStatement.execute(); - return true; + boolean success = runQuery(new QueryPS(USER_UPDATE) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, user.getName()); + preparedStatement.setString(2, gson.toJson(user.getNodes())); + preparedStatement.setString(3, user.getUuid().toString()); + } }); return success; } @@ -168,25 +205,28 @@ public abstract class SQLDatastore extends Datastore { @Override public boolean createAndLoadGroup(String name) { Group group = plugin.getGroupManager().makeGroup(name); - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT); - closer.add(preparedStatement); - preparedStatement.setString(1, group.getName()); - - ResultSet resultSet = preparedStatement.executeQuery(); - closer.add(resultSet); - - if (!resultSet.next()) { - PreparedStatement preparedStatement1 = connection.prepareStatement(GROUP_INSERT); - closer.add(preparedStatement1); - preparedStatement1.setString(1, group.getName()); - preparedStatement1.setString(2, gson.toJson(group.getNodes())); - preparedStatement1.execute(); - - } else { - group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); + boolean success = runQuery(new QueryRS(GROUP_SELECT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, group.getName()); + } + + @Override + boolean onResult(ResultSet resultSet) throws SQLException { + boolean success = true; + if (!resultSet.next()) { + success = runQuery(new QueryPS(GROUP_INSERT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, group.getName()); + preparedStatement.setString(2, gson.toJson(group.getNodes())); + } + }); + } else { + group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); + } + return success; } - return true; }); if (success) plugin.getGroupManager().updateOrSetGroup(group); @@ -196,18 +236,20 @@ public abstract class SQLDatastore extends Datastore { @Override public boolean loadGroup(String name) { Group group = plugin.getGroupManager().makeGroup(name); - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT); - closer.add(preparedStatement); - preparedStatement.setString(1, name); - - ResultSet resultSet = preparedStatement.executeQuery(); - closer.add(resultSet); - if (resultSet.next()) { - group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); - return true; + boolean success = runQuery(new QueryRS(GROUP_SELECT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, name); + } + + @Override + boolean onResult(ResultSet resultSet) throws SQLException { + if (resultSet.next()) { + group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); + return true; + } + return false; } - return false; }); if (success) plugin.getGroupManager().updateOrSetGroup(group); @@ -217,18 +259,21 @@ public abstract class SQLDatastore extends Datastore { @Override public boolean loadAllGroups() { List groups = new ArrayList<>(); - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT_ALL); - closer.add(preparedStatement); + boolean success = runQuery(new QueryRS(GROUP_SELECT_ALL) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { - ResultSet resultSet = preparedStatement.executeQuery(); - closer.add(resultSet); - while (resultSet.next()) { - Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name")); - group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); - groups.add(group); } - return true; + + @Override + boolean onResult(ResultSet resultSet) throws SQLException { + while (resultSet.next()) { + Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name")); + group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); + groups.add(group); + } + return true; + } }); if (success) { @@ -241,97 +286,110 @@ public abstract class SQLDatastore extends Datastore { @Override public boolean saveGroup(Group group) { - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(GROUP_UPDATE); - closer.add(preparedStatement); - preparedStatement.setString(1, gson.toJson(group.getNodes())); - preparedStatement.setString(2, group.getName()); - preparedStatement.execute(); - return true; + boolean success = runQuery(new QueryPS(GROUP_UPDATE) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, gson.toJson(group.getNodes())); + preparedStatement.setString(2, group.getName()); + } }); return success; } @Override public boolean deleteGroup(Group group) { - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(GROUP_DELETE); - closer.add(preparedStatement); - preparedStatement.setString(1, group.getName()); - preparedStatement.execute(); - return true; + boolean success = runQuery(new QueryPS(GROUP_DELETE) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, group.getName()); + } }); + if (success) plugin.getGroupManager().unloadGroup(group); return success; } @Override public boolean saveUUIDData(String username, UUID uuid) { - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_SELECT); - closer.add(preparedStatement); - preparedStatement.setString(1, username); - - ResultSet resultSet = preparedStatement.executeQuery(); - closer.add(resultSet); - - PreparedStatement preparedStatement1; - if (resultSet.next()) { - preparedStatement1 = connection.prepareStatement(UUIDCACHE_UPDATE); - closer.add(preparedStatement1); - preparedStatement1.setString(1, uuid.toString()); - preparedStatement1.setString(2, username); - - } else { - preparedStatement1 = connection.prepareStatement(UUIDCACHE_INSERT); - closer.add(preparedStatement1); - preparedStatement1.setString(1, username); - preparedStatement1.setString(2, uuid.toString()); + boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, username); } - preparedStatement1.execute(); - return true; + @Override + boolean onResult(ResultSet resultSet) throws SQLException { + boolean success; + if (resultSet.next()) { + success = runQuery(new QueryPS(UUIDCACHE_UPDATE) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, uuid.toString()); + preparedStatement.setString(2, username); + } + }); + } else { + success = runQuery(new QueryPS(UUIDCACHE_INSERT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, username); + preparedStatement.setString(2, uuid.toString()); + } + }); + } + return success; + } }); + return success; } @Override public UUID getUUID(String username) { final UUID[] uuid = {null}; - boolean success = runQuery((connection, closer) -> { - PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_SELECT); - closer.add(preparedStatement); - preparedStatement.setString(1, username); - ResultSet resultSet = preparedStatement.executeQuery(); - closer.add(resultSet); - if (resultSet.next()) { - uuid[0] = UUID.fromString(resultSet.getString("uuid")); - return true; + boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) { + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + preparedStatement.setString(1, username); + } + + @Override + boolean onResult(ResultSet resultSet) throws SQLException { + if (resultSet.next()) { + uuid[0] = UUID.fromString(resultSet.getString("uuid")); + return true; + } + return false; } - return false; }); return success ? uuid[0] : null; } - interface Query { - boolean onRun(Connection connection, Closer closer) throws SQLException; + private class Query extends QueryPS { + Query(String query) { + super(query); + } + + @Override + void onRun(PreparedStatement preparedStatement) throws SQLException { + // Do nothing + } } - private class Closer { - private final List objects = new ArrayList<>(); + @Getter + @AllArgsConstructor + private abstract class QueryPS { + private final String query; + abstract void onRun(PreparedStatement preparedStatement) throws SQLException; + } - public void add(AutoCloseable a) { - objects.add(a); - } - - void closeAll() { - objects.stream().filter(a -> a != null).forEach(a -> { - try { - a.close(); - } catch (Exception ignored) {} - }); - } + @Getter + @AllArgsConstructor + private abstract class QueryRS { + private final String query; + abstract void onRun(PreparedStatement preparedStatement) throws SQLException; + abstract boolean onResult(ResultSet resultSet) throws SQLException; } }