Refactor SQLBacking - still towards #77
This commit is contained in:
parent
a54046907d
commit
9f2b59f2a2
@ -22,6 +22,7 @@
|
||||
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@ -46,11 +47,13 @@ import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -62,6 +65,7 @@ public class SQLBacking extends AbstractBacking {
|
||||
private static final Type LIST_STRING_TYPE = new TypeToken<List<String>>(){}.getType();
|
||||
|
||||
private static final String USER_PERMISSIONS_SELECT = "SELECT permission, value, server, world, expiry, contexts FROM {prefix}user_permissions WHERE uuid=?";
|
||||
private static final String USER_PERMISSIONS_DELETE_SPECIFIC = "DELETE FROM {prefix}user_permissions WHERE uuid=?, permission=?, value=?, server=?, world=?, expiry=?, contexts=?";
|
||||
private static final String USER_PERMISSIONS_DELETE = "DELETE FROM {prefix}user_permissions WHERE uuid=?";
|
||||
private static final String USER_PERMISSIONS_INSERT = "INSERT INTO {prefix}user_permissions(uuid, permission, value, server, world, expiry, contexts) VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String USER_PERMISSIONS_SELECT_DISTINCT = "SELECT DISTINCT uuid FROM {prefix}user_permissions";
|
||||
@ -75,9 +79,10 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
private static final String GROUP_PERMISSIONS_SELECT = "SELECT permission, value, server, world, expiry, contexts FROM {prefix}group_permissions WHERE name=?";
|
||||
private static final String GROUP_PERMISSIONS_DELETE = "DELETE FROM {prefix}group_permissions WHERE name=?";
|
||||
private static final String GROUP_PERMISSIONS_DELETE_SPECIFIC = "DELETE FROM {prefix}group_permissions WHERE name=?, permission=?, value=?, server=?, world=?, expiry=?, contexts=?";
|
||||
private static final String GROUP_PERMISSIONS_INSERT = "INSERT INTO {prefix}group_permissions(name, permission, value, server, world, expiry, contexts) VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String GROUP_SELECT = "SELECT name FROM {prefix}groups";
|
||||
private static final String GROUP_SELECT_ALL = "SELECT name FROM {prefix}groups";
|
||||
private static final String GROUP_INSERT = "INSERT INTO {prefix}groups VALUES(?)";
|
||||
private static final String GROUP_DELETE = "DELETE FROM {prefix}groups WHERE name=?";
|
||||
|
||||
@ -102,22 +107,6 @@ public class SQLBacking extends AbstractBacking {
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, SQLProvider.QueryPS queryPS) {
|
||||
return provider.runQuery(query, queryPS);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, SQLProvider.QueryPS queryPS, SQLProvider.QueryRS queryRS) {
|
||||
return provider.runQuery(query, queryPS, queryRS);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query) {
|
||||
return provider.runQuery(query);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, SQLProvider.QueryRS queryRS) {
|
||||
return provider.runQuery(query, queryRS);
|
||||
}
|
||||
|
||||
private boolean tableExists(String table) throws SQLException {
|
||||
try (Connection connection = provider.getConnection()) {
|
||||
return connection.getMetaData().getTables(null, null, table.toUpperCase(), null).next();
|
||||
@ -184,7 +173,8 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean logAction(LogEntry entry) {
|
||||
return runQuery(prefix.apply(ACTION_INSERT), ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(ACTION_INSERT))) {
|
||||
ps.setLong(1, entry.getTimestamp());
|
||||
ps.setString(2, entry.getActor().toString());
|
||||
ps.setString(3, entry.getActorName());
|
||||
@ -192,14 +182,21 @@ public class SQLBacking extends AbstractBacking {
|
||||
ps.setString(5, entry.getActed() == null ? "null" : entry.getActed().toString());
|
||||
ps.setString(6, entry.getActedName());
|
||||
ps.setString(7, entry.getAction());
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
final Log.Builder log = Log.builder();
|
||||
boolean success = runQuery(prefix.apply(ACTION_SELECT_ALL), rs -> {
|
||||
while (rs.next()) {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(ACTION_SELECT_ALL))) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
final String actedUuid = rs.getString("acted_uuid");
|
||||
LogEntry e = new LogEntry(
|
||||
rs.getLong("time"),
|
||||
@ -212,9 +209,12 @@ public class SQLBacking extends AbstractBacking {
|
||||
);
|
||||
log.add(e);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return success ? log.build() : null;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return log.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,10 +225,13 @@ public class SQLBacking extends AbstractBacking {
|
||||
List<NodeDataHolder> data = new ArrayList<>();
|
||||
AtomicReference<String> primaryGroup = new AtomicReference<>(null);
|
||||
AtomicReference<String> userName = new AtomicReference<>();
|
||||
boolean s = runQuery(
|
||||
prefix.apply(USER_PERMISSIONS_SELECT),
|
||||
ps -> ps.setString(1, user.getUuid().toString()),
|
||||
rs -> {
|
||||
|
||||
// Collect user permissions
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(USER_PERMISSIONS_SELECT))) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
String permission = rs.getString("permission");
|
||||
boolean value = rs.getBoolean("value");
|
||||
@ -238,26 +241,31 @@ public class SQLBacking extends AbstractBacking {
|
||||
String contexts = rs.getString("contexts");
|
||||
data.add(NodeDataHolder.of(permission, value, server, world, expiry, contexts));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean s2 = runQuery(
|
||||
prefix.apply(PLAYER_SELECT),
|
||||
ps -> ps.setString(1, user.getUuid().toString()),
|
||||
rs -> {
|
||||
// Collect user meta (username & primary group)
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_SELECT))) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
userName.set(rs.getString("username"));
|
||||
primaryGroup.set(rs.getString("primary_group"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s || !s2) {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the user has any data in storage
|
||||
if (!data.isEmpty()) {
|
||||
Set<Node> nodes = data.stream().map(NodeDataHolder::toNode).collect(Collectors.toSet());
|
||||
user.setNodes(nodes);
|
||||
@ -273,11 +281,14 @@ public class SQLBacking extends AbstractBacking {
|
||||
name = "null";
|
||||
}
|
||||
|
||||
// Check the user has *at least* some sort of default group.
|
||||
boolean save = plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||
|
||||
// Update their username if it has changed since last login.
|
||||
if (user.getName() == null || user.getName().equalsIgnoreCase("null")) {
|
||||
user.setName(name);
|
||||
} else {
|
||||
// The name in storage is not the same as their actual name.
|
||||
if (!name.equals(user.getName())) {
|
||||
save = true;
|
||||
}
|
||||
@ -285,64 +296,12 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
// Save back to the store if there was a username change
|
||||
if (save) {
|
||||
boolean s3 = runQuery(prefix.apply(USER_PERMISSIONS_DELETE), ps -> {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
});
|
||||
|
||||
if (!s3) return false;
|
||||
|
||||
List<NodeDataHolder> newData = user.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toList());
|
||||
if (newData.isEmpty()) return true;
|
||||
|
||||
try (Connection connection = provider.getConnection()) {
|
||||
try (PreparedStatement ps = connection.prepareStatement(prefix.apply(USER_PERMISSIONS_INSERT))) {
|
||||
for (NodeDataHolder nd : newData) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
ps.setString(2, nd.getPermission());
|
||||
ps.setBoolean(3, nd.isValue());
|
||||
ps.setString(4, nd.getServer());
|
||||
ps.setString(5, nd.getWorld());
|
||||
ps.setLong(6, nd.getExpiry());
|
||||
ps.setString(7, nd.getContexts());
|
||||
ps.addBatch();
|
||||
}
|
||||
ps.executeBatch();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
AtomicBoolean exists = new AtomicBoolean(false);
|
||||
boolean success = runQuery(
|
||||
prefix.apply(PLAYER_SELECT_USERNAME),
|
||||
ps -> ps.setString(1, uuid.toString()),
|
||||
rs -> {
|
||||
if (rs.next()) {
|
||||
exists.set(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists.get()) {
|
||||
return runQuery(prefix.apply(PLAYER_UPDATE_FULL), ps -> {
|
||||
ps.setString(1, user.getName().toLowerCase());
|
||||
ps.setString(2, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup());
|
||||
ps.setString(3, uuid.toString());
|
||||
});
|
||||
} else {
|
||||
return runQuery(prefix.apply(PLAYER_INSERT), ps -> {
|
||||
ps.setString(1, uuid.toString());
|
||||
ps.setString(2, user.getName().toLowerCase());
|
||||
ps.setString(3, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup());
|
||||
});
|
||||
}
|
||||
// This should be fine, as the lock will be acquired by the same thread.
|
||||
saveUser(user);
|
||||
}
|
||||
|
||||
} else {
|
||||
// User has no data in storage.
|
||||
if (GenericUserManager.shouldSave(user)) {
|
||||
user.clearNodes();
|
||||
user.setPrimaryGroup(null);
|
||||
@ -359,23 +318,55 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
boolean shouldSave = GenericUserManager.shouldSave(user);
|
||||
|
||||
user.getIoLock().lock();
|
||||
try {
|
||||
boolean s = runQuery(prefix.apply(USER_PERMISSIONS_DELETE), ps -> {
|
||||
// Empty data - just delete from the DB.
|
||||
if (!GenericUserManager.shouldSave(user)) {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(USER_PERMISSIONS_DELETE))) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!s) return false;
|
||||
if (!shouldSave) return true;
|
||||
// Get a snapshot of current data.
|
||||
Set<NodeDataHolder> remote = new HashSet<>();
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(USER_PERMISSIONS_SELECT))) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
|
||||
List<NodeDataHolder> data = user.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toList());
|
||||
if (data.isEmpty()) return true;
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
String permission = rs.getString("permission");
|
||||
boolean value = rs.getBoolean("value");
|
||||
String server = rs.getString("server");
|
||||
String world = rs.getString("world");
|
||||
long expiry = rs.getLong("expiry");
|
||||
String contexts = rs.getString("contexts");
|
||||
remote.add(NodeDataHolder.of(permission, value, server, world, expiry, contexts));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try (Connection connection = provider.getConnection()) {
|
||||
try (PreparedStatement ps = connection.prepareStatement(prefix.apply(USER_PERMISSIONS_INSERT))) {
|
||||
for (NodeDataHolder nd : data) {
|
||||
Set<NodeDataHolder> local = user.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toSet());
|
||||
|
||||
Map.Entry<Set<NodeDataHolder>, Set<NodeDataHolder>> diff = compareSets(local, remote);
|
||||
|
||||
Set<NodeDataHolder> toAdd = diff.getKey();
|
||||
Set<NodeDataHolder> toRemove = diff.getValue();
|
||||
|
||||
if (!toAdd.isEmpty()) {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(USER_PERMISSIONS_INSERT))) {
|
||||
for (NodeDataHolder nd : toAdd) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
ps.setString(2, nd.getPermission());
|
||||
ps.setBoolean(3, nd.isValue());
|
||||
@ -389,36 +380,75 @@ public class SQLBacking extends AbstractBacking {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(USER_PERMISSIONS_DELETE_SPECIFIC))) {
|
||||
for (NodeDataHolder nd : toRemove) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
ps.setString(2, nd.getPermission());
|
||||
ps.setBoolean(3, nd.isValue());
|
||||
ps.setString(4, nd.getServer());
|
||||
ps.setString(5, nd.getWorld());
|
||||
ps.setLong(6, nd.getExpiry());
|
||||
ps.setString(7, nd.getContexts());
|
||||
ps.addBatch();
|
||||
}
|
||||
ps.executeBatch();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AtomicBoolean exists = new AtomicBoolean(false);
|
||||
boolean success = runQuery(
|
||||
prefix.apply(PLAYER_SELECT_USERNAME),
|
||||
ps -> ps.setString(1, user.getUuid().toString()),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_SELECT_USERNAME))) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
exists.set(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if (!success) {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists.get()) {
|
||||
return runQuery(prefix.apply(PLAYER_UPDATE_FULL), ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_UPDATE_FULL))) {
|
||||
ps.setString(1, user.getName().toLowerCase());
|
||||
ps.setString(2, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup());
|
||||
ps.setString(3, user.getUuid().toString());
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
return runQuery(prefix.apply(PLAYER_INSERT), ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_INSERT))) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
ps.setString(2, user.getName().toLowerCase());
|
||||
ps.setString(3, user.getPrimaryGroup() == null ? "default" : user.getPrimaryGroup());
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
}
|
||||
@ -432,38 +462,48 @@ public class SQLBacking extends AbstractBacking {
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
|
||||
boolean success = runQuery(prefix.apply(USER_PERMISSIONS_SELECT_DISTINCT), rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(USER_PERMISSIONS_SELECT_DISTINCT))) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
String uuid = rs.getString("uuid");
|
||||
uuids.add(UUID.fromString(uuid));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return success ? uuids : null;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return uuids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
List<String> groups = new ArrayList<>();
|
||||
runQuery(
|
||||
prefix.apply(GROUP_SELECT),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_SELECT_ALL))) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
groups.add(rs.getString("name").toLowerCase());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!groups.contains(name)) {
|
||||
runQuery(
|
||||
prefix.apply(GROUP_INSERT),
|
||||
ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_INSERT))) {
|
||||
ps.setString(1, name);
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return loadGroup(name);
|
||||
@ -471,16 +511,21 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
// Check the group actually exists
|
||||
List<String> groups = new ArrayList<>();
|
||||
runQuery(
|
||||
prefix.apply(GROUP_SELECT),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_SELECT_ALL))) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
groups.add(rs.getString("name").toLowerCase());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!groups.contains(name)) {
|
||||
return false;
|
||||
@ -490,10 +535,12 @@ public class SQLBacking extends AbstractBacking {
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
List<NodeDataHolder> data = new ArrayList<>();
|
||||
boolean s = runQuery(
|
||||
prefix.apply(GROUP_PERMISSIONS_SELECT),
|
||||
ps -> ps.setString(1, group.getName()),
|
||||
rs -> {
|
||||
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_PERMISSIONS_SELECT))) {
|
||||
ps.setString(1, group.getName());
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
String permission = rs.getString("permission");
|
||||
boolean value = rs.getBoolean("value");
|
||||
@ -503,11 +550,10 @@ public class SQLBacking extends AbstractBacking {
|
||||
String contexts = rs.getString("contexts");
|
||||
data.add(NodeDataHolder.of(permission, value, server, world, expiry, contexts));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -527,55 +573,88 @@ public class SQLBacking extends AbstractBacking {
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
List<String> groups = new ArrayList<>();
|
||||
boolean b = runQuery(
|
||||
prefix.apply(GROUP_SELECT),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_SELECT_ALL))) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
groups.add(rs.getString("name").toLowerCase());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!b) {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = true;
|
||||
for (String g : groups) {
|
||||
if (!loadGroup(g)) {
|
||||
b = false;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (b) {
|
||||
if (success) {
|
||||
GroupManager gm = plugin.getGroupManager();
|
||||
gm.getAll().values().stream()
|
||||
.filter(g -> !groups.contains(g.getName()))
|
||||
.forEach(gm::unload);
|
||||
}
|
||||
return b;
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
boolean s = runQuery(prefix.apply(GROUP_PERMISSIONS_DELETE), ps -> {
|
||||
// Empty data, just delete.
|
||||
if (group.getNodes().isEmpty()) {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_PERMISSIONS_DELETE))) {
|
||||
ps.setString(1, group.getName());
|
||||
});
|
||||
if (!s) {
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
List<NodeDataHolder> data = group.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toList());
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try (Connection connection = provider.getConnection()) {
|
||||
try (PreparedStatement ps = connection.prepareStatement(prefix.apply(GROUP_PERMISSIONS_INSERT))) {
|
||||
for (NodeDataHolder nd : data) {
|
||||
// Get a snapshot of current data
|
||||
Set<NodeDataHolder> remote = new HashSet<>();
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_PERMISSIONS_SELECT))) {
|
||||
ps.setString(1, group.getName());
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
String permission = rs.getString("permission");
|
||||
boolean value = rs.getBoolean("value");
|
||||
String server = rs.getString("server");
|
||||
String world = rs.getString("world");
|
||||
long expiry = rs.getLong("expiry");
|
||||
String contexts = rs.getString("contexts");
|
||||
remote.add(NodeDataHolder.of(permission, value, server, world, expiry, contexts));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<NodeDataHolder> local = group.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toSet());
|
||||
|
||||
Map.Entry<Set<NodeDataHolder>, Set<NodeDataHolder>> diff = compareSets(local, remote);
|
||||
|
||||
Set<NodeDataHolder> toAdd = diff.getKey();
|
||||
Set<NodeDataHolder> toRemove = diff.getValue();
|
||||
|
||||
if (!toAdd.isEmpty()) {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_PERMISSIONS_INSERT))) {
|
||||
for (NodeDataHolder nd : toAdd) {
|
||||
ps.setString(1, group.getName());
|
||||
ps.setString(2, nd.getPermission());
|
||||
ps.setBoolean(3, nd.isValue());
|
||||
@ -589,6 +668,29 @@ public class SQLBacking extends AbstractBacking {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_PERMISSIONS_DELETE_SPECIFIC))) {
|
||||
for (NodeDataHolder nd : toRemove) {
|
||||
ps.setString(1, group.getName());
|
||||
ps.setString(2, nd.getPermission());
|
||||
ps.setBoolean(3, nd.isValue());
|
||||
ps.setString(4, nd.getServer());
|
||||
ps.setString(5, nd.getWorld());
|
||||
ps.setLong(6, nd.getExpiry());
|
||||
ps.setString(7, nd.getContexts());
|
||||
ps.addBatch();
|
||||
}
|
||||
ps.executeBatch();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -601,16 +703,22 @@ public class SQLBacking extends AbstractBacking {
|
||||
public boolean deleteGroup(Group group) {
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
|
||||
boolean s = runQuery(
|
||||
prefix.apply(GROUP_PERMISSIONS_DELETE),
|
||||
ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_PERMISSIONS_DELETE))) {
|
||||
ps.setString(1, group.getName());
|
||||
ps.execute();
|
||||
}
|
||||
);
|
||||
return s && runQuery(prefix.apply(GROUP_DELETE), ps -> {
|
||||
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_DELETE))) {
|
||||
ps.setString(1, group.getName());
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
@ -625,19 +733,18 @@ public class SQLBacking extends AbstractBacking {
|
||||
AtomicBoolean exists = new AtomicBoolean(false);
|
||||
AtomicReference<String> groups = new AtomicReference<>(null);
|
||||
|
||||
boolean s = runQuery(
|
||||
prefix.apply(TRACK_SELECT),
|
||||
ps -> ps.setString(1, track.getName()),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(TRACK_SELECT))) {
|
||||
ps.setString(1, track.getName());
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
exists.set(true);
|
||||
groups.set(rs.getString("groups"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -647,10 +754,17 @@ public class SQLBacking extends AbstractBacking {
|
||||
return true;
|
||||
} else {
|
||||
String json = gson.toJson(track.getGroups());
|
||||
return runQuery(prefix.apply(TRACK_INSERT), ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(TRACK_INSERT))) {
|
||||
ps.setString(1, track.getName());
|
||||
ps.setString(2, json);
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} finally {
|
||||
@ -664,19 +778,17 @@ public class SQLBacking extends AbstractBacking {
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
AtomicReference<String> groups = new AtomicReference<>(null);
|
||||
boolean s = runQuery(
|
||||
prefix.apply(TRACK_SELECT),
|
||||
ps -> ps.setString(1, name),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(TRACK_SELECT))) {
|
||||
ps.setString(1, track.getName());
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
groups.set(rs.getString("groups"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -691,34 +803,33 @@ public class SQLBacking extends AbstractBacking {
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
List<String> tracks = new ArrayList<>();
|
||||
boolean b = runQuery(
|
||||
prefix.apply(TRACK_SELECT_ALL),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(TRACK_SELECT_ALL))) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
String name = rs.getString("name");
|
||||
tracks.add(name);
|
||||
tracks.add(rs.getString("name").toLowerCase());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!b) {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = true;
|
||||
for (String t : tracks) {
|
||||
if (!loadTrack(t)) {
|
||||
b = false;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (b) {
|
||||
if (success) {
|
||||
TrackManager tm = plugin.getTrackManager();
|
||||
tm.getAll().values().stream()
|
||||
.filter(t -> !tracks.contains(t.getName()))
|
||||
.forEach(tm::unload);
|
||||
}
|
||||
return b;
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -726,13 +837,17 @@ public class SQLBacking extends AbstractBacking {
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
String s = gson.toJson(track.getGroups());
|
||||
return runQuery(
|
||||
prefix.apply(TRACK_UPDATE),
|
||||
ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(TRACK_UPDATE))) {
|
||||
ps.setString(1, s);
|
||||
ps.setString(2, track.getName());
|
||||
ps.execute();
|
||||
}
|
||||
);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
@ -741,20 +856,22 @@ public class SQLBacking extends AbstractBacking {
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
track.getIoLock().lock();
|
||||
boolean success;
|
||||
try {
|
||||
success = runQuery(
|
||||
prefix.apply(TRACK_DELETE),
|
||||
ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(TRACK_DELETE))) {
|
||||
ps.setString(1, track.getName());
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
|
||||
if (success) plugin.getTrackManager().unload(track);
|
||||
return success;
|
||||
plugin.getTrackManager().unload(track);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -762,32 +879,45 @@ public class SQLBacking extends AbstractBacking {
|
||||
final String u = username.toLowerCase();
|
||||
AtomicBoolean exists = new AtomicBoolean(false);
|
||||
|
||||
boolean success = runQuery(
|
||||
prefix.apply(PLAYER_SELECT_USERNAME),
|
||||
ps -> ps.setString(1, uuid.toString()),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_SELECT_USERNAME))) {
|
||||
ps.setString(1, uuid.toString());
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
exists.set(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists.get()) {
|
||||
return runQuery(prefix.apply(PLAYER_UPDATE), ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_UPDATE))) {
|
||||
ps.setString(1, u);
|
||||
ps.setString(2, uuid.toString());
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return runQuery(prefix.apply(PLAYER_INSERT), ps -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_INSERT))) {
|
||||
ps.setString(1, uuid.toString());
|
||||
ps.setString(2, u);
|
||||
ps.setString(3, "default");
|
||||
});
|
||||
ps.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,37 +926,60 @@ public class SQLBacking extends AbstractBacking {
|
||||
final String u = username.toLowerCase();
|
||||
final AtomicReference<UUID> uuid = new AtomicReference<>(null);
|
||||
|
||||
boolean success = runQuery(
|
||||
prefix.apply(PLAYER_SELECT_UUID),
|
||||
ps -> ps.setString(1, u),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_SELECT_UUID))) {
|
||||
ps.setString(1, u);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
uuid.set(UUID.fromString(rs.getString("uuid")));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return success ? uuid.get() : null;
|
||||
return uuid.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
final AtomicReference<String> name = new AtomicReference<>(null);
|
||||
|
||||
boolean success = runQuery(
|
||||
prefix.apply(PLAYER_SELECT_USERNAME),
|
||||
ps -> ps.setString(1, uuid.toString()),
|
||||
rs -> {
|
||||
try (Connection c = provider.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement(prefix.apply(PLAYER_SELECT_USERNAME))) {
|
||||
ps.setString(1, uuid.toString());
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
name.set(rs.getString("username"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return success ? name.get() : null;
|
||||
return name.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two sets
|
||||
* @param local the local set
|
||||
* @param remote the remote set
|
||||
* @return the entries to add to remote, and the entries to remove from remote
|
||||
*/
|
||||
private static Map.Entry<Set<NodeDataHolder>, Set<NodeDataHolder>> compareSets(Set<NodeDataHolder> local, Set<NodeDataHolder> remote) {
|
||||
// entries in local but not remote need to be added
|
||||
// entries in remote but not local need to be removed
|
||||
|
||||
Set<NodeDataHolder> toAdd = new HashSet<>(local);
|
||||
toAdd.removeAll(remote);
|
||||
|
||||
Set<NodeDataHolder> toRemove = new HashSet<>(remote);
|
||||
toRemove.removeAll(local);
|
||||
|
||||
return Maps.immutableEntry(toAdd, toRemove);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user