Refactor storage system

This commit is contained in:
Luck 2018-09-23 21:49:45 +01:00
parent 8b97439ffc
commit 8115fbaa98
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
70 changed files with 757 additions and 864 deletions

View File

@ -27,7 +27,7 @@ package me.lucko.luckperms.common.api;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
public final class ApiUtils { public final class ApiUtils {

View File

@ -33,7 +33,7 @@ import me.lucko.luckperms.common.command.abstraction.CommandException;
import me.lucko.luckperms.common.commands.user.UserMainCommand; import me.lucko.luckperms.common.commands.user.UserMainCommand;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.DateParser; import me.lucko.luckperms.common.utils.DateParser;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -45,7 +45,7 @@ import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -46,7 +46,7 @@ import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.node.factory.NodeFactory; import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -36,7 +36,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -39,7 +39,7 @@ import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -39,7 +39,7 @@ import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -38,7 +38,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.DurationFormatter; import me.lucko.luckperms.common.utils.DurationFormatter;
import me.lucko.luckperms.common.utils.Paginated; import me.lucko.luckperms.common.utils.Paginated;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;

View File

@ -38,7 +38,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.DurationFormatter; import me.lucko.luckperms.common.utils.DurationFormatter;
import me.lucko.luckperms.common.utils.Paginated; import me.lucko.luckperms.common.utils.Paginated;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;

View File

@ -25,9 +25,6 @@
package me.lucko.luckperms.common.commands.misc; package me.lucko.luckperms.common.commands.misc;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LookupSetting; import me.lucko.luckperms.api.LookupSetting;
import me.lucko.luckperms.api.caching.MetaContexts; import me.lucko.luckperms.api.caching.MetaContexts;
@ -50,6 +47,7 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.processors.PermissionProcessor; import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import me.lucko.luckperms.common.utils.gson.JArray; import me.lucko.luckperms.common.utils.gson.JArray;
import me.lucko.luckperms.common.utils.gson.JObject; import me.lucko.luckperms.common.utils.gson.JObject;
import me.lucko.luckperms.common.web.Pastebin; import me.lucko.luckperms.common.web.Pastebin;
@ -70,8 +68,6 @@ import java.util.function.BiConsumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class DebugCommand extends SingleCommand { public class DebugCommand extends SingleCommand {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
public DebugCommand(LocaleManager locale) { public DebugCommand(LocaleManager locale) {
super(CommandSpec.DEBUG.localize(locale), "Debug", CommandPermission.DEBUG, Predicates.alwaysFalse()); super(CommandSpec.DEBUG.localize(locale), "Debug", CommandPermission.DEBUG, Predicates.alwaysFalse());
} }
@ -85,7 +81,7 @@ public class DebugCommand extends SingleCommand {
BiConsumer<String, JObject> builder = (name, content) -> { BiConsumer<String, JObject> builder = (name, content) -> {
sb.append("-- ").append(name).append(" --\n"); sb.append("-- ").append(name).append(" --\n");
sb.append(GSON.toJson(content.toJson())); sb.append(GsonProvider.prettyPrinting().toJson(content.toJson()));
sb.append("\n\n"); sb.append("\n\n");
}; };
@ -124,7 +120,7 @@ public class DebugCommand extends SingleCommand {
return new JObject() return new JObject()
.add("storage", new JObject() .add("storage", new JObject()
.add("name", plugin.getStorage().getName()) .add("name", plugin.getStorage().getName())
.add("type", plugin.getStorage().getDao().getClass().getName()) .add("type", plugin.getStorage().getImplementation().getClass().getName())
.add("meta", () -> { .add("meta", () -> {
JObject metaObject = new JObject(); JObject metaObject = new JObject();
Map<String, String> meta = plugin.getStorage().getMeta(); Map<String, String> meta = plugin.getStorage().getMeta();

View File

@ -36,7 +36,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -41,7 +41,7 @@ import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -37,7 +37,7 @@ import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -41,7 +41,7 @@ import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -40,7 +40,7 @@ import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -38,7 +38,7 @@ import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -45,7 +45,7 @@ import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -45,7 +45,7 @@ import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.UserIdentifier; import me.lucko.luckperms.common.model.UserIdentifier;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Uuids; import me.lucko.luckperms.common.utils.Uuids;
import java.util.List; import java.util.List;

View File

@ -45,7 +45,7 @@ import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import java.util.List; import java.util.List;

View File

@ -43,8 +43,8 @@ import me.lucko.luckperms.common.primarygroup.AllParentsByWeightHolder;
import me.lucko.luckperms.common.primarygroup.ParentsByWeightHolder; import me.lucko.luckperms.common.primarygroup.ParentsByWeightHolder;
import me.lucko.luckperms.common.primarygroup.PrimaryGroupHolder; import me.lucko.luckperms.common.primarygroup.PrimaryGroupHolder;
import me.lucko.luckperms.common.primarygroup.StoredHolder; import me.lucko.luckperms.common.primarygroup.StoredHolder;
import me.lucko.luckperms.common.storage.SplitStorageType; import me.lucko.luckperms.common.storage.implementation.split.SplitStorageType;
import me.lucko.luckperms.common.storage.StorageCredentials; import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.lang.reflect.Field; import java.lang.reflect.Field;

View File

@ -25,12 +25,12 @@
package me.lucko.luckperms.common.config; package me.lucko.luckperms.common.config;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer; import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -70,7 +70,7 @@ public class ContextsFile {
boolean save = false; boolean save = false;
try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
JsonObject data = new Gson().fromJson(reader, JsonObject.class); JsonObject data = GsonProvider.normal().fromJson(reader, JsonObject.class);
if (data.has("context")) { if (data.has("context")) {
this.staticContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("context").getAsJsonObject()).makeImmutable(); this.staticContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("context").getAsJsonObject()).makeImmutable();

View File

@ -25,8 +25,6 @@
package me.lucko.luckperms.common.messaging; package me.lucko.luckperms.common.messaging;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
@ -46,6 +44,7 @@ import me.lucko.luckperms.common.messaging.message.UpdateMessageImpl;
import me.lucko.luckperms.common.messaging.message.UserUpdateMessageImpl; import me.lucko.luckperms.common.messaging.message.UserUpdateMessageImpl;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import me.lucko.luckperms.common.utils.gson.JObject; import me.lucko.luckperms.common.utils.gson.JObject;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -59,8 +58,6 @@ import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer { public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer {
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
private final LuckPermsPlugin plugin; private final LuckPermsPlugin plugin;
private final Set<UUID> receivedMessages; private final Set<UUID> receivedMessages;
private final PushUpdateBuffer updateBuffer; private final PushUpdateBuffer updateBuffer;
@ -169,7 +166,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
@Override @Override
public boolean consumeIncomingMessageAsString(@NonNull String encodedString) { public boolean consumeIncomingMessageAsString(@NonNull String encodedString) {
Objects.requireNonNull(encodedString, "encodedString"); Objects.requireNonNull(encodedString, "encodedString");
JsonObject decodedObject = GSON.fromJson(encodedString, JsonObject.class).getAsJsonObject(); JsonObject decodedObject = GsonProvider.normal().fromJson(encodedString, JsonObject.class).getAsJsonObject();
// extract id // extract id
JsonElement idElement = decodedObject.get("id"); JsonElement idElement = decodedObject.get("id");
@ -226,7 +223,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
}) })
.toJson(); .toJson();
return GSON.toJson(json); return GsonProvider.normal().toJson(json);
} }
private void processIncomingMessage(Message message) { private void processIncomingMessage(Message message) {

View File

@ -34,9 +34,9 @@ import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.messaging.redis.RedisMessenger; import me.lucko.luckperms.common.messaging.redis.RedisMessenger;
import me.lucko.luckperms.common.messaging.sql.SqlMessenger; import me.lucko.luckperms.common.messaging.sql.SqlMessenger;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.sql.SqlDao; import me.lucko.luckperms.common.storage.implementation.sql.SqlStorage;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MariaDbConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.MariaDbConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MySqlConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.MySqlConnectionFactory;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -57,9 +57,9 @@ public class MessagingFactory<P extends LuckPermsPlugin> {
messagingType = "redis"; messagingType = "redis";
} }
if (messagingType.equals("none") && this.plugin.getStorage().getDao() instanceof SqlDao) { if (messagingType.equals("none") && this.plugin.getStorage().getImplementation() instanceof SqlStorage) {
SqlDao dao = (SqlDao) this.plugin.getStorage().getDao(); SqlStorage dao = (SqlStorage) this.plugin.getStorage().getImplementation();
if (dao.getProvider() instanceof MySqlConnectionFactory || dao.getProvider() instanceof MariaDbConnectionFactory) { if (dao.getConnectionFactory() instanceof MySqlConnectionFactory || dao.getConnectionFactory() instanceof MariaDbConnectionFactory) {
messagingType = "sql"; messagingType = "sql";
} }
} }
@ -125,8 +125,8 @@ public class MessagingFactory<P extends LuckPermsPlugin> {
@Override @Override
public @NonNull Messenger obtain(@NonNull IncomingMessageConsumer incomingMessageConsumer) { public @NonNull Messenger obtain(@NonNull IncomingMessageConsumer incomingMessageConsumer) {
SqlDao dao = (SqlDao) getPlugin().getStorage().getDao(); SqlStorage dao = (SqlStorage) getPlugin().getStorage().getImplementation();
Preconditions.checkState(dao.getProvider() instanceof MySqlConnectionFactory || dao.getProvider() instanceof MariaDbConnectionFactory, "not a supported sql type"); Preconditions.checkState(dao.getConnectionFactory() instanceof MySqlConnectionFactory || dao.getConnectionFactory() instanceof MariaDbConnectionFactory, "not a supported sql type");
SqlMessenger sql = new SqlMessenger(getPlugin(), dao, incomingMessageConsumer); SqlMessenger sql = new SqlMessenger(getPlugin(), dao, incomingMessageConsumer);
sql.init(); sql.init();

View File

@ -29,7 +29,7 @@ import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter; import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask; import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
import me.lucko.luckperms.common.storage.dao.sql.SqlDao; import me.lucko.luckperms.common.storage.implementation.sql.SqlStorage;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
@ -37,15 +37,15 @@ import java.util.concurrent.TimeUnit;
public class SqlMessenger extends AbstractSqlMessenger { public class SqlMessenger extends AbstractSqlMessenger {
private final LuckPermsPlugin plugin; private final LuckPermsPlugin plugin;
private final SqlDao sqlDao; private final SqlStorage sqlStorage;
private SchedulerTask pollTask; private SchedulerTask pollTask;
private SchedulerTask housekeepingTask; private SchedulerTask housekeepingTask;
public SqlMessenger(LuckPermsPlugin plugin, SqlDao sqlDao, IncomingMessageConsumer consumer) { public SqlMessenger(LuckPermsPlugin plugin, SqlStorage sqlStorage, IncomingMessageConsumer consumer) {
super(consumer); super(consumer);
this.plugin = plugin; this.plugin = plugin;
this.sqlDao = sqlDao; this.sqlStorage = sqlStorage;
} }
@Override @Override
@ -81,11 +81,11 @@ public class SqlMessenger extends AbstractSqlMessenger {
@Override @Override
protected Connection getConnection() throws SQLException { protected Connection getConnection() throws SQLException {
return this.sqlDao.getProvider().getConnection(); return this.sqlStorage.getConnectionFactory().getConnection();
} }
@Override @Override
protected String getTableName() { protected String getTableName() {
return this.sqlDao.getStatementProcessor().apply("{prefix}messenger"); return this.sqlStorage.getStatementProcessor().apply("{prefix}messenger");
} }
} }

View File

@ -49,7 +49,7 @@ import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.Storage; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory; import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.storage.StorageType; import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.storage.dao.file.FileWatcher; import me.lucko.luckperms.common.storage.implementation.file.FileWatcher;
import me.lucko.luckperms.common.tasks.SyncTask; import me.lucko.luckperms.common.tasks.SyncTask;
import me.lucko.luckperms.common.treeview.PermissionRegistry; import me.lucko.luckperms.common.treeview.PermissionRegistry;
import me.lucko.luckperms.common.verbose.VerboseHandler; import me.lucko.luckperms.common.verbose.VerboseHandler;

View File

@ -49,7 +49,7 @@ import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener; import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.Storage; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.dao.file.FileWatcher; import me.lucko.luckperms.common.storage.implementation.file.FileWatcher;
import me.lucko.luckperms.common.tasks.SyncTask; import me.lucko.luckperms.common.tasks.SyncTask;
import me.lucko.luckperms.common.treeview.PermissionRegistry; import me.lucko.luckperms.common.treeview.PermissionRegistry;
import me.lucko.luckperms.common.verbose.VerboseHandler; import me.lucko.luckperms.common.verbose.VerboseHandler;

View File

@ -31,7 +31,7 @@ import me.lucko.luckperms.common.assignments.AssignmentRule;
import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.PlayerSaveResultImpl; import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;

View File

@ -1,304 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.PlayerSaveResult;
import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.event.cause.DeletionCause;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.api.delegates.model.ApiStorage;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.wrappings.PhasedStorage;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
/**
* Implements {@link Storage} using an {@link AbstractDao}.
*/
public class AbstractStorage implements Storage {
public static Storage create(LuckPermsPlugin plugin, AbstractDao backing) {
// make a base implementation
Storage base = new AbstractStorage(plugin, backing);
// wrap with a phaser
return PhasedStorage.wrap(base);
}
private final LuckPermsPlugin plugin;
private final AbstractDao dao;
private final ApiStorage apiDelegate;
private AbstractStorage(LuckPermsPlugin plugin, AbstractDao dao) {
this.plugin = plugin;
this.dao = dao;
this.apiDelegate = new ApiStorage(plugin, this);
}
@Override
public AbstractDao getDao() {
return this.dao;
}
@Override
public ApiStorage getApiDelegate() {
return this.apiDelegate;
}
private <T> CompletableFuture<T> makeFuture(Callable<T> supplier) {
return CompletableFuture.supplyAsync(() -> {
try {
return supplier.call();
} catch (Exception e) {
Throwables.propagateIfPossible(e);
throw new CompletionException(e);
}
}, this.dao.getPlugin().getBootstrap().getScheduler().async());
}
private CompletableFuture<Void> makeFuture(ThrowingRunnable runnable) {
return CompletableFuture.runAsync(() -> {
try {
runnable.run();
} catch (Exception e) {
Throwables.propagateIfPossible(e);
throw new CompletionException(e);
}
}, this.dao.getPlugin().getBootstrap().getScheduler().async());
}
private interface ThrowingRunnable {
void run() throws Exception;
}
@Override
public String getName() {
return this.dao.getName();
}
@Override
public void init() {
try {
this.dao.init();
} catch (Exception e) {
this.plugin.getLogger().severe("Failed to init storage dao");
e.printStackTrace();
}
}
@Override
public void shutdown() {
try {
this.dao.shutdown();
} catch (Exception e) {
this.plugin.getLogger().severe("Failed to shutdown storage dao");
e.printStackTrace();
}
}
@Override
public Map<String, String> getMeta() {
return this.dao.getMeta();
}
@Override
public CompletableFuture<Void> logAction(LogEntry entry) {
return makeFuture(() -> this.dao.logAction(entry));
}
@Override
public CompletableFuture<Log> getLog() {
return makeFuture(this.dao::getLog);
}
@Override
public CompletableFuture<Void> applyBulkUpdate(BulkUpdate bulkUpdate) {
return makeFuture(() -> this.dao.applyBulkUpdate(bulkUpdate));
}
@Override
public CompletableFuture<User> loadUser(UUID uuid, String username) {
return makeFuture(() -> {
User user = this.dao.loadUser(uuid, username);
if (user != null) {
this.plugin.getEventFactory().handleUserLoad(user);
}
return user;
});
}
@Override
public CompletableFuture<Void> saveUser(User user) {
return makeFuture(() -> this.dao.saveUser(user));
}
@Override
public CompletableFuture<Set<UUID>> getUniqueUsers() {
return makeFuture(this.dao::getUniqueUsers);
}
@Override
public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(Constraint constraint) {
return makeFuture(() -> {
List<HeldPermission<UUID>> result = this.dao.getUsersWithPermission(constraint);
result.removeIf(entry -> entry.asNode().hasExpired());
return ImmutableList.copyOf(result);
});
}
@Override
public CompletableFuture<Group> createAndLoadGroup(String name, CreationCause cause) {
return makeFuture(() -> {
Group group = this.dao.createAndLoadGroup(name);
if (group != null) {
this.plugin.getEventFactory().handleGroupCreate(group, cause);
}
return group;
});
}
@Override
public CompletableFuture<Optional<Group>> loadGroup(String name) {
return makeFuture(() -> {
Optional<Group> group = this.dao.loadGroup(name);
if (group.isPresent()) {
this.plugin.getEventFactory().handleGroupLoad(group.get());
}
return group;
});
}
@Override
public CompletableFuture<Void> loadAllGroups() {
return makeFuture(() -> {
this.dao.loadAllGroups();
this.plugin.getEventFactory().handleGroupLoadAll();
});
}
@Override
public CompletableFuture<Void> saveGroup(Group group) {
return makeFuture(() -> this.dao.saveGroup(group));
}
@Override
public CompletableFuture<Void> deleteGroup(Group group, DeletionCause cause) {
return makeFuture(() -> {
this.dao.deleteGroup(group);
this.plugin.getEventFactory().handleGroupDelete(group, cause);
});
}
@Override
public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(Constraint constraint) {
return makeFuture(() -> {
List<HeldPermission<String>> result = this.dao.getGroupsWithPermission(constraint);
result.removeIf(entry -> entry.asNode().hasExpired());
return ImmutableList.copyOf(result);
});
}
@Override
public CompletableFuture<Track> createAndLoadTrack(String name, CreationCause cause) {
return makeFuture(() -> {
Track track = this.dao.createAndLoadTrack(name);
if (track != null) {
this.plugin.getEventFactory().handleTrackCreate(track, cause);
}
return track;
});
}
@Override
public CompletableFuture<Optional<Track>> loadTrack(String name) {
return makeFuture(() -> {
Optional<Track> track = this.dao.loadTrack(name);
if (track.isPresent()) {
this.plugin.getEventFactory().handleTrackLoad(track.get());
}
return track;
});
}
@Override
public CompletableFuture<Void> loadAllTracks() {
return makeFuture(() -> {
this.dao.loadAllTracks();
this.plugin.getEventFactory().handleTrackLoadAll();
});
}
@Override
public CompletableFuture<Void> saveTrack(Track track) {
return makeFuture(() -> this.dao.saveTrack(track));
}
@Override
public CompletableFuture<Void> deleteTrack(Track track, DeletionCause cause) {
return makeFuture(() -> {
this.dao.deleteTrack(track);
this.plugin.getEventFactory().handleTrackDelete(track, cause);
});
}
@Override
public CompletableFuture<PlayerSaveResult> savePlayerData(UUID uuid, String username) {
return makeFuture(() -> {
PlayerSaveResult result = this.dao.savePlayerData(uuid, username);
if (result != null) {
this.plugin.getEventFactory().handlePlayerDataSave(uuid, username, result);
}
return result;
});
}
@Override
public CompletableFuture<UUID> getPlayerUuid(String username) {
return makeFuture(() -> this.dao.getPlayerUuid(username));
}
@Override
public CompletableFuture<String> getPlayerName(UUID uuid) {
return makeFuture(() -> this.dao.getPlayerName(uuid));
}
}

View File

@ -25,6 +25,8 @@
package me.lucko.luckperms.common.storage; package me.lucko.luckperms.common.storage;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.HeldPermission; import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.LogEntry; import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.PlayerSaveResult; import me.lucko.luckperms.api.PlayerSaveResult;
@ -37,71 +39,231 @@ import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint;
import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.storage.dao.AbstractDao; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.utils.ThrowingRunnable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
/** /**
* Main interface for all Storage providers. * Provides a {@link CompletableFuture} based API for interacting with a {@link StorageImplementation}.
*/ */
public interface Storage { public class Storage {
private final LuckPermsPlugin plugin;
private final StorageImplementation implementation;
ApiStorage getApiDelegate(); private final ApiStorage apiDelegate;
AbstractDao getDao(); public Storage(LuckPermsPlugin plugin, StorageImplementation implementation) {
this.plugin = plugin;
String getName(); this.implementation = implementation;
this.apiDelegate = new ApiStorage(plugin, this);
void init(); }
void shutdown(); public StorageImplementation getImplementation() {
return this.implementation;
Map<String, String> getMeta(); }
CompletableFuture<Void> logAction(LogEntry entry); public ApiStorage getApiDelegate() {
return this.apiDelegate;
CompletableFuture<Log> getLog(); }
CompletableFuture<Void> applyBulkUpdate(BulkUpdate bulkUpdate); private <T> CompletableFuture<T> makeFuture(Callable<T> supplier) {
return CompletableFuture.supplyAsync(() -> {
CompletableFuture<User> loadUser(UUID uuid, String username); try {
return supplier.call();
CompletableFuture<Void> saveUser(User user); } catch (Exception e) {
if (e instanceof RuntimeException) {
CompletableFuture<Set<UUID>> getUniqueUsers(); throw (RuntimeException) e;
}
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(Constraint constraint); throw new CompletionException(e);
}
CompletableFuture<Group> createAndLoadGroup(String name, CreationCause cause); }, this.plugin.getBootstrap().getScheduler().async());
}
CompletableFuture<Optional<Group>> loadGroup(String name);
private CompletableFuture<Void> makeFuture(ThrowingRunnable runnable) {
CompletableFuture<Void> loadAllGroups(); return CompletableFuture.runAsync(() -> {
try {
CompletableFuture<Void> saveGroup(Group group); runnable.run();
} catch (Exception e) {
CompletableFuture<Void> deleteGroup(Group group, DeletionCause cause); if (e instanceof RuntimeException) {
throw (RuntimeException) e;
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(Constraint constraint); }
throw new CompletionException(e);
CompletableFuture<Track> createAndLoadTrack(String name, CreationCause cause); }
}, this.plugin.getBootstrap().getScheduler().async());
CompletableFuture<Optional<Track>> loadTrack(String name); }
CompletableFuture<Void> loadAllTracks(); public String getName() {
return this.implementation.getImplementationName();
CompletableFuture<Void> saveTrack(Track track); }
CompletableFuture<Void> deleteTrack(Track track, DeletionCause cause); public void init() {
try {
CompletableFuture<PlayerSaveResult> savePlayerData(UUID uuid, String username); this.implementation.init();
} catch (Exception e) {
CompletableFuture<UUID> getPlayerUuid(String username); this.plugin.getLogger().severe("Failed to init storage dao");
e.printStackTrace();
CompletableFuture<String> getPlayerName(UUID uuid); }
}
public void shutdown() {
try {
this.implementation.shutdown();
} catch (Exception e) {
this.plugin.getLogger().severe("Failed to shutdown storage dao");
e.printStackTrace();
}
}
public Map<String, String> getMeta() {
return this.implementation.getMeta();
}
public CompletableFuture<Void> logAction(LogEntry entry) {
return makeFuture(() -> this.implementation.logAction(entry));
}
public CompletableFuture<Log> getLog() {
return makeFuture(this.implementation::getLog);
}
public CompletableFuture<Void> applyBulkUpdate(BulkUpdate bulkUpdate) {
return makeFuture(() -> this.implementation.applyBulkUpdate(bulkUpdate));
}
public CompletableFuture<User> loadUser(UUID uuid, String username) {
return makeFuture(() -> {
User user = this.implementation.loadUser(uuid, username);
if (user != null) {
this.plugin.getEventFactory().handleUserLoad(user);
}
return user;
});
}
public CompletableFuture<Void> saveUser(User user) {
return makeFuture(() -> this.implementation.saveUser(user));
}
public CompletableFuture<Set<UUID>> getUniqueUsers() {
return makeFuture(this.implementation::getUniqueUsers);
}
public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(Constraint constraint) {
return makeFuture(() -> {
List<HeldPermission<UUID>> result = this.implementation.getUsersWithPermission(constraint);
result.removeIf(entry -> entry.asNode().hasExpired());
return ImmutableList.copyOf(result);
});
}
public CompletableFuture<Group> createAndLoadGroup(String name, CreationCause cause) {
return makeFuture(() -> {
Group group = this.implementation.createAndLoadGroup(name);
if (group != null) {
this.plugin.getEventFactory().handleGroupCreate(group, cause);
}
return group;
});
}
public CompletableFuture<Optional<Group>> loadGroup(String name) {
return makeFuture(() -> {
Optional<Group> group = this.implementation.loadGroup(name);
if (group.isPresent()) {
this.plugin.getEventFactory().handleGroupLoad(group.get());
}
return group;
});
}
public CompletableFuture<Void> loadAllGroups() {
return makeFuture(() -> {
this.implementation.loadAllGroups();
this.plugin.getEventFactory().handleGroupLoadAll();
});
}
public CompletableFuture<Void> saveGroup(Group group) {
return makeFuture(() -> this.implementation.saveGroup(group));
}
public CompletableFuture<Void> deleteGroup(Group group, DeletionCause cause) {
return makeFuture(() -> {
this.implementation.deleteGroup(group);
this.plugin.getEventFactory().handleGroupDelete(group, cause);
});
}
public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(Constraint constraint) {
return makeFuture(() -> {
List<HeldPermission<String>> result = this.implementation.getGroupsWithPermission(constraint);
result.removeIf(entry -> entry.asNode().hasExpired());
return ImmutableList.copyOf(result);
});
}
public CompletableFuture<Track> createAndLoadTrack(String name, CreationCause cause) {
return makeFuture(() -> {
Track track = this.implementation.createAndLoadTrack(name);
if (track != null) {
this.plugin.getEventFactory().handleTrackCreate(track, cause);
}
return track;
});
}
public CompletableFuture<Optional<Track>> loadTrack(String name) {
return makeFuture(() -> {
Optional<Track> track = this.implementation.loadTrack(name);
if (track.isPresent()) {
this.plugin.getEventFactory().handleTrackLoad(track.get());
}
return track;
});
}
public CompletableFuture<Void> loadAllTracks() {
return makeFuture(() -> {
this.implementation.loadAllTracks();
this.plugin.getEventFactory().handleTrackLoadAll();
});
}
public CompletableFuture<Void> saveTrack(Track track) {
return makeFuture(() -> this.implementation.saveTrack(track));
}
public CompletableFuture<Void> deleteTrack(Track track, DeletionCause cause) {
return makeFuture(() -> {
this.implementation.deleteTrack(track);
this.plugin.getEventFactory().handleTrackDelete(track, cause);
});
}
public CompletableFuture<PlayerSaveResult> savePlayerData(UUID uuid, String username) {
return makeFuture(() -> {
PlayerSaveResult result = this.implementation.savePlayerData(uuid, username);
if (result != null) {
this.plugin.getEventFactory().handlePlayerDataSave(uuid, username, result);
}
return result;
});
}
public CompletableFuture<UUID> getPlayerUuid(String username) {
return makeFuture(() -> this.implementation.getPlayerUuid(username));
}
public CompletableFuture<String> getPlayerName(UUID uuid) {
return makeFuture(() -> this.implementation.getPlayerName(uuid));
}
} }

View File

@ -30,22 +30,23 @@ import com.google.common.collect.Maps;
import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.AbstractDao; import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.dao.SplitStorageDao; import me.lucko.luckperms.common.storage.implementation.custom.CustomStorageProviders;
import me.lucko.luckperms.common.storage.dao.file.CombinedConfigurateDao; import me.lucko.luckperms.common.storage.implementation.file.CombinedConfigurateStorage;
import me.lucko.luckperms.common.storage.dao.file.SeparatedConfigurateDao; import me.lucko.luckperms.common.storage.implementation.file.SeparatedConfigurateStorage;
import me.lucko.luckperms.common.storage.dao.file.loader.HoconLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.HoconLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.JsonLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.JsonLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.TomlLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.TomlLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.YamlLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.YamlLoader;
import me.lucko.luckperms.common.storage.dao.mongodb.MongoDao; import me.lucko.luckperms.common.storage.implementation.mongodb.MongoStorage;
import me.lucko.luckperms.common.storage.dao.sql.SqlDao; import me.lucko.luckperms.common.storage.implementation.split.SplitStorage;
import me.lucko.luckperms.common.storage.dao.sql.connection.file.H2ConnectionFactory; import me.lucko.luckperms.common.storage.implementation.split.SplitStorageType;
import me.lucko.luckperms.common.storage.dao.sql.connection.file.SQLiteConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.SqlStorage;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MariaDbConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.file.H2ConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MySqlConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.file.SQLiteConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.PostgreConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.MariaDbConnectionFactory;
import me.lucko.luckperms.common.storage.provider.StorageProviders; import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.MySqlConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.PostgreConnectionFactory;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.util.Map; import java.util.Map;
@ -97,11 +98,12 @@ public class StorageFactory {
}) })
.collect(ImmutableCollectors.toEnumMap(SplitStorageType.class, Map.Entry::getKey, Map.Entry::getValue)); .collect(ImmutableCollectors.toEnumMap(SplitStorageType.class, Map.Entry::getKey, Map.Entry::getValue));
Map<StorageType, AbstractDao> backing = mappedTypes.values().stream() Map<StorageType, StorageImplementation> backing = mappedTypes.values().stream()
.distinct() .distinct()
.collect(ImmutableCollectors.toEnumMap(StorageType.class, e -> e, this::makeDao)); .collect(ImmutableCollectors.toEnumMap(StorageType.class, e -> e, this::createNewImplementation));
storage = AbstractStorage.create(this.plugin, new SplitStorageDao(this.plugin, backing, mappedTypes)); // make a base implementation
storage = new Storage(this.plugin, new SplitStorage(this.plugin, backing, mappedTypes));
} else { } else {
String method = this.plugin.getConfiguration().get(ConfigKeys.STORAGE_METHOD); String method = this.plugin.getConfiguration().get(ConfigKeys.STORAGE_METHOD);
@ -119,66 +121,67 @@ public class StorageFactory {
} }
private Storage makeInstance(StorageType type) { private Storage makeInstance(StorageType type) {
return AbstractStorage.create(this.plugin, makeDao(type)); // make a base implementation
return new Storage(this.plugin, createNewImplementation(type));
} }
private AbstractDao makeDao(StorageType method) { private StorageImplementation createNewImplementation(StorageType method) {
switch (method) { switch (method) {
case CUSTOM: case CUSTOM:
return StorageProviders.getProvider().provide(this.plugin); return CustomStorageProviders.getProvider().provide(this.plugin);
case MARIADB: case MARIADB:
return new SqlDao( return new SqlStorage(
this.plugin, this.plugin,
new MariaDbConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)), new MariaDbConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX) this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
); );
case MYSQL: case MYSQL:
return new SqlDao( return new SqlStorage(
this.plugin, this.plugin,
new MySqlConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)), new MySqlConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX) this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
); );
case SQLITE: case SQLITE:
return new SqlDao( return new SqlStorage(
this.plugin, this.plugin,
new SQLiteConnectionFactory(this.plugin, this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-sqlite.db")), new SQLiteConnectionFactory(this.plugin, this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-sqlite.db")),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX) this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
); );
case H2: case H2:
return new SqlDao( return new SqlStorage(
this.plugin, this.plugin,
new H2ConnectionFactory(this.plugin, this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-h2")), new H2ConnectionFactory(this.plugin, this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-h2")),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX) this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
); );
case POSTGRESQL: case POSTGRESQL:
return new SqlDao( return new SqlStorage(
this.plugin, this.plugin,
new PostgreConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)), new PostgreConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX) this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
); );
case MONGODB: case MONGODB:
return new MongoDao( return new MongoStorage(
this.plugin, this.plugin,
this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES), this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES),
this.plugin.getConfiguration().get(ConfigKeys.MONGODB_COLLECTION_PREFIX), this.plugin.getConfiguration().get(ConfigKeys.MONGODB_COLLECTION_PREFIX),
this.plugin.getConfiguration().get(ConfigKeys.MONGODB_CONNECTION_URI) this.plugin.getConfiguration().get(ConfigKeys.MONGODB_CONNECTION_URI)
); );
case YAML: case YAML:
return new SeparatedConfigurateDao(this.plugin, new YamlLoader(), "YAML", ".yml", "yaml-storage"); return new SeparatedConfigurateStorage(this.plugin, "YAML", new YamlLoader(), ".yml", "yaml-storage");
case JSON: case JSON:
return new SeparatedConfigurateDao(this.plugin, new JsonLoader(), "JSON", ".json", "json-storage"); return new SeparatedConfigurateStorage(this.plugin, "JSON", new JsonLoader(), ".json", "json-storage");
case HOCON: case HOCON:
return new SeparatedConfigurateDao(this.plugin, new HoconLoader(), "HOCON", ".conf", "hocon-storage"); return new SeparatedConfigurateStorage(this.plugin, "HOCON", new HoconLoader(), ".conf", "hocon-storage");
case TOML: case TOML:
return new SeparatedConfigurateDao(this.plugin, new TomlLoader(), "TOML", ".toml", "toml-storage"); return new SeparatedConfigurateStorage(this.plugin, "TOML", new TomlLoader(), ".toml", "toml-storage");
case YAML_COMBINED: case YAML_COMBINED:
return new CombinedConfigurateDao(this.plugin, new YamlLoader(), "YAML Combined", ".yml", "yaml-storage"); return new CombinedConfigurateStorage(this.plugin, "YAML Combined", new YamlLoader(), ".yml", "yaml-storage");
case JSON_COMBINED: case JSON_COMBINED:
return new CombinedConfigurateDao(this.plugin, new JsonLoader(), "JSON Combined", ".json", "json-storage"); return new CombinedConfigurateStorage(this.plugin, "JSON Combined", new JsonLoader(), ".json", "json-storage");
case HOCON_COMBINED: case HOCON_COMBINED:
return new CombinedConfigurateDao(this.plugin, new HoconLoader(), "HOCON Combined", ".conf", "hocon-storage"); return new CombinedConfigurateStorage(this.plugin, "HOCON Combined", new HoconLoader(), ".conf", "hocon-storage");
case TOML_COMBINED: case TOML_COMBINED:
return new CombinedConfigurateDao(this.plugin, new TomlLoader(), "TOML Combined", ".toml", "toml-storage"); return new CombinedConfigurateStorage(this.plugin, "TOML Combined", new TomlLoader(), ".toml", "toml-storage");
default: default:
throw new RuntimeException("Unknown method: " + method); throw new RuntimeException("Unknown method: " + method);
} }

View File

@ -1,116 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.dao;
import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.PlayerSaveResult;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
public abstract class AbstractDao {
protected final LuckPermsPlugin plugin;
public final String name;
protected AbstractDao(LuckPermsPlugin plugin, String name) {
this.plugin = plugin;
this.name = name;
}
public LuckPermsPlugin getPlugin() {
return this.plugin;
}
public String getName() {
return this.name;
}
public abstract void init() throws Exception;
public abstract void shutdown();
public Map<String, String> getMeta() {
return Collections.emptyMap();
}
public abstract void logAction(LogEntry entry) throws Exception;
public abstract Log getLog() throws Exception;
public abstract void applyBulkUpdate(BulkUpdate bulkUpdate) throws Exception;
public abstract User loadUser(UUID uuid, String username) throws Exception;
public abstract void saveUser(User user) throws Exception;
public abstract Set<UUID> getUniqueUsers() throws Exception;
public abstract List<HeldPermission<UUID>> getUsersWithPermission(Constraint constraint) throws Exception;
public abstract Group createAndLoadGroup(String name) throws Exception;
public abstract Optional<Group> loadGroup(String name) throws Exception;
public abstract void loadAllGroups() throws Exception;
public abstract void saveGroup(Group group) throws Exception;
public abstract void deleteGroup(Group group) throws Exception;
public abstract List<HeldPermission<String>> getGroupsWithPermission(Constraint constraint) throws Exception;
public abstract Track createAndLoadTrack(String name) throws Exception;
public abstract Optional<Track> loadTrack(String name) throws Exception;
public abstract void loadAllTracks() throws Exception;
public abstract void saveTrack(Track track) throws Exception;
public abstract void deleteTrack(Track track) throws Exception;
public abstract PlayerSaveResult savePlayerData(UUID uuid, String username) throws Exception;
public abstract @Nullable UUID getPlayerUuid(String username) throws Exception;
public abstract @Nullable String getPlayerName(UUID uuid) throws Exception;
}

View File

@ -0,0 +1,102 @@
/*
* This file is part of luckperms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.implementation;
import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.PlayerSaveResult;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
public interface StorageImplementation {
LuckPermsPlugin getPlugin();
String getImplementationName();
void init() throws Exception;
void shutdown();
default Map<String, String> getMeta() {
return Collections.emptyMap();
}
void logAction(LogEntry entry) throws Exception;
Log getLog() throws Exception;
void applyBulkUpdate(BulkUpdate bulkUpdate) throws Exception;
User loadUser(UUID uuid, String username) throws Exception;
void saveUser(User user) throws Exception;
Set<UUID> getUniqueUsers() throws Exception;
List<HeldPermission<UUID>> getUsersWithPermission(Constraint constraint) throws Exception;
Group createAndLoadGroup(String name) throws Exception;
Optional<Group> loadGroup(String name) throws Exception;
void loadAllGroups() throws Exception;
void saveGroup(Group group) throws Exception;
void deleteGroup(Group group) throws Exception;
List<HeldPermission<String>> getGroupsWithPermission(Constraint constraint) throws Exception;
Track createAndLoadTrack(String name) throws Exception;
Optional<Track> loadTrack(String name) throws Exception;
void loadAllTracks() throws Exception;
void saveTrack(Track track) throws Exception;
void deleteTrack(Track track) throws Exception;
PlayerSaveResult savePlayerData(UUID uuid, String username) throws Exception;
@Nullable UUID getPlayerUuid(String username) throws Exception;
@Nullable String getPlayerName(UUID uuid) throws Exception;
}

View File

@ -23,17 +23,17 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.provider; package me.lucko.luckperms.common.storage.implementation.custom;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.AbstractDao; import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
/** /**
* A storage provider * A storage provider
*/ */
@FunctionalInterface @FunctionalInterface
public interface StorageProvider { public interface CustomStorageProvider {
AbstractDao provide(LuckPermsPlugin plugin); StorageImplementation provide(LuckPermsPlugin plugin);
} }

View File

@ -23,19 +23,19 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.provider; package me.lucko.luckperms.common.storage.implementation.custom;
/** /**
* Hook to allow external code to provide a storage dao * Hook to allow external code to provide a storage dao
*/ */
public final class StorageProviders { public final class CustomStorageProviders {
private static StorageProvider provider = null; private static CustomStorageProvider provider = null;
public static void register(StorageProvider provider) { public static void register(CustomStorageProvider provider) {
StorageProviders.provider = provider; CustomStorageProviders.provider = provider;
} }
public static StorageProvider getProvider() { public static CustomStorageProvider getProvider() {
if (provider == null) { if (provider == null) {
throw new IllegalStateException("Provider not present."); throw new IllegalStateException("Provider not present.");
} }
@ -43,6 +43,6 @@ public final class StorageProviders {
return provider; return provider;
} }
private StorageProviders() {} private CustomStorageProviders() {}
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file; package me.lucko.luckperms.common.storage.implementation.file;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -46,10 +46,10 @@ import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeDataContainer; import me.lucko.luckperms.common.node.model.NodeDataContainer;
import me.lucko.luckperms.common.node.utils.MetaType; import me.lucko.luckperms.common.node.utils.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.AbstractDao; import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.dao.file.loader.ConfigurateLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.JsonLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.JsonLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.YamlLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.YamlLoader;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.utils.MoreFiles; import me.lucko.luckperms.common.utils.MoreFiles;
@ -77,7 +77,10 @@ import java.util.stream.Collectors;
* Abstract implementation using configurate {@link ConfigurationNode}s to serialize and deserialize * Abstract implementation using configurate {@link ConfigurationNode}s to serialize and deserialize
* data. * data.
*/ */
public abstract class AbstractConfigurateDao extends AbstractDao { public abstract class AbstractConfigurateStorage implements StorageImplementation {
protected final LuckPermsPlugin plugin;
private final String implementationName;
// the loader responsible for i/o // the loader responsible for i/o
protected final ConfigurateLoader loader; protected final ConfigurateLoader loader;
@ -95,13 +98,24 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
// the file used to store uuid data // the file used to store uuid data
private Path uuidDataFile; private Path uuidDataFile;
protected AbstractConfigurateDao(LuckPermsPlugin plugin, ConfigurateLoader loader, String name, String dataDirectoryName) { protected AbstractConfigurateStorage(LuckPermsPlugin plugin, String implementationName, ConfigurateLoader loader, String dataDirectoryName) {
super(plugin, name); this.plugin = plugin;
this.implementationName = implementationName;
this.loader = loader; this.loader = loader;
this.dataDirectoryName = dataDirectoryName; this.dataDirectoryName = dataDirectoryName;
this.actionLogger = new FileActionLogger(plugin); this.actionLogger = new FileActionLogger(plugin);
} }
@Override
public LuckPermsPlugin getPlugin() {
return this.plugin;
}
@Override
public String getImplementationName() {
return this.implementationName;
}
/** /**
* Reads a configuration node from the given location * Reads a configuration node from the given location
* *
@ -217,7 +231,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
saveFile(StorageLocation.USER, user.getUuid().toString(), null); saveFile(StorageLocation.USER, user.getUuid().toString(), null);
} else { } else {
ConfigurationNode data = SimpleConfigurationNode.root(); ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) { if (this instanceof SeparatedConfigurateStorage) {
data.getNode("uuid").setValue(user.getUuid().toString()); data.getNode("uuid").setValue(user.getUuid().toString());
} }
data.getNode("name").setValue(user.getName().orElse("null")); data.getNode("name").setValue(user.getName().orElse("null"));
@ -247,7 +261,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
group.setNodes(NodeMapType.ENDURING, nodes); group.setNodes(NodeMapType.ENDURING, nodes);
} else { } else {
ConfigurationNode data = SimpleConfigurationNode.root(); ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) { if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(group.getName()); data.getNode("name").setValue(group.getName());
} }
@ -304,7 +318,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
group.getIoLock().lock(); group.getIoLock().lock();
try { try {
ConfigurationNode data = SimpleConfigurationNode.root(); ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) { if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(group.getName()); data.getNode("name").setValue(group.getName());
} }
@ -347,7 +361,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
track.setGroups(groups); track.setGroups(groups);
} else { } else {
ConfigurationNode data = SimpleConfigurationNode.root(); ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) { if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(name); data.getNode("name").setValue(name);
} }
data.getNode("groups").setValue(track.getGroups()); data.getNode("groups").setValue(track.getGroups());
@ -402,7 +416,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
track.getIoLock().lock(); track.getIoLock().lock();
try { try {
ConfigurationNode data = SimpleConfigurationNode.root(); ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) { if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(track.getName()); data.getNode("name").setValue(track.getName());
} }
data.getNode("groups").setValue(track.getGroups()); data.getNode("groups").setValue(track.getGroups());

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file; package me.lucko.luckperms.common.storage.implementation.file;
import me.lucko.luckperms.api.HeldPermission; import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
@ -33,7 +33,7 @@ import me.lucko.luckperms.common.managers.track.TrackManager;
import me.lucko.luckperms.common.node.model.NodeDataContainer; import me.lucko.luckperms.common.node.model.NodeDataContainer;
import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.file.loader.ConfigurateLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.loader.ConfigurationLoader; import ninja.leaping.configurate.loader.ConfigurationLoader;
@ -49,7 +49,7 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class CombinedConfigurateDao extends AbstractConfigurateDao { public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
private final String fileExtension; private final String fileExtension;
private Path usersFile; private Path usersFile;
@ -69,13 +69,13 @@ public class CombinedConfigurateDao extends AbstractConfigurateDao {
private CachedLoader(Path path) { private CachedLoader(Path path) {
this.path = path; this.path = path;
this.loader = CombinedConfigurateDao.super.loader.loader(path); this.loader = CombinedConfigurateStorage.super.loader.loader(path);
reload(); reload();
} }
private void recordChange() { private void recordChange() {
if (CombinedConfigurateDao.this.watcher != null) { if (CombinedConfigurateStorage.this.watcher != null) {
CombinedConfigurateDao.this.watcher.recordChange(this.path.getFileName().toString()); CombinedConfigurateStorage.this.watcher.recordChange(this.path.getFileName().toString());
} }
} }
@ -145,14 +145,13 @@ public class CombinedConfigurateDao extends AbstractConfigurateDao {
/** /**
* Creates a new configurate dao * Creates a new configurate dao
*
* @param plugin the plugin instance * @param plugin the plugin instance
* @param name the name of this dao * @param implementationName the name of this dao
* @param fileExtension the file extension used by this instance, including a "." at the start * @param fileExtension the file extension used by this instance, including a "." at the start
* @param dataFolderName the name of the folder used to store data * @param dataFolderName the name of the folder used to store data
*/ */
public CombinedConfigurateDao(LuckPermsPlugin plugin, ConfigurateLoader loader, String name, String fileExtension, String dataFolderName) { public CombinedConfigurateStorage(LuckPermsPlugin plugin, String implementationName, ConfigurateLoader loader, String fileExtension, String dataFolderName) {
super(plugin, loader, name, dataFolderName); super(plugin, implementationName, loader, dataFolderName);
this.fileExtension = fileExtension; this.fileExtension = fileExtension;
} }

View File

@ -23,12 +23,10 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file; package me.lucko.luckperms.common.storage.implementation.file;
import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
@ -37,6 +35,7 @@ import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer; import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer;
import me.lucko.luckperms.common.buffers.BufferedRequest; import me.lucko.luckperms.common.buffers.BufferedRequest;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -48,8 +47,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
public class FileActionLogger { public class FileActionLogger {
private static final JsonParser JSON_PARSER = new JsonParser();
private static final Gson GSON = new Gson();
/** /**
* The path to save logger content to * The path to save logger content to
@ -95,7 +92,7 @@ public class FileActionLogger {
if (Files.exists(this.contentFile)) { if (Files.exists(this.contentFile)) {
try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) { try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) {
array = JSON_PARSER.parse(reader).getAsJsonArray(); array = GsonProvider.parser().parse(reader).getAsJsonArray();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
array = new JsonArray(); array = new JsonArray();
@ -112,7 +109,7 @@ public class FileActionLogger {
// write the full content back to the file // write the full content back to the file
try (JsonWriter writer = new JsonWriter(Files.newBufferedWriter(this.contentFile, StandardCharsets.UTF_8))) { try (JsonWriter writer = new JsonWriter(Files.newBufferedWriter(this.contentFile, StandardCharsets.UTF_8))) {
writer.setIndent(" "); writer.setIndent(" ");
GSON.toJson(array, writer); GsonProvider.normal().toJson(array, writer);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -125,7 +122,7 @@ public class FileActionLogger {
public Log getLog() throws IOException { public Log getLog() throws IOException {
Log.Builder log = Log.builder(); Log.Builder log = Log.builder();
try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) { try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) {
JsonArray array = JSON_PARSER.parse(reader).getAsJsonArray(); JsonArray array = GsonProvider.parser().parse(reader).getAsJsonArray();
for (JsonElement element : array) { for (JsonElement element : array) {
log.add(LogEntryJsonSerializer.deserialize(element)); log.add(LogEntryJsonSerializer.deserialize(element));
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file; package me.lucko.luckperms.common.storage.implementation.file;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -31,7 +31,7 @@ import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap; import com.google.common.collect.SetMultimap;
import me.lucko.luckperms.api.PlayerSaveResult; import me.lucko.luckperms.api.PlayerSaveResult;
import me.lucko.luckperms.common.storage.PlayerSaveResultImpl; import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
import me.lucko.luckperms.common.utils.Uuids; import me.lucko.luckperms.common.utils.Uuids;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file; package me.lucko.luckperms.common.storage.implementation.file;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Iterators; import me.lucko.luckperms.common.utils.Iterators;

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file; package me.lucko.luckperms.common.storage.implementation.file;
import me.lucko.luckperms.api.HeldPermission; import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
@ -34,7 +34,7 @@ import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.model.NodeDataContainer; import me.lucko.luckperms.common.node.model.NodeDataContainer;
import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.file.loader.ConfigurateLoader; import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
import me.lucko.luckperms.common.utils.MoreFiles; import me.lucko.luckperms.common.utils.MoreFiles;
import me.lucko.luckperms.common.utils.Uuids; import me.lucko.luckperms.common.utils.Uuids;
@ -51,7 +51,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class SeparatedConfigurateDao extends AbstractConfigurateDao { public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
private final String fileExtension; private final String fileExtension;
private Path usersDirectory; private Path usersDirectory;
@ -64,14 +64,13 @@ public class SeparatedConfigurateDao extends AbstractConfigurateDao {
/** /**
* Creates a new configurate dao * Creates a new configurate dao
*
* @param plugin the plugin instance * @param plugin the plugin instance
* @param name the name of this dao * @param implementationName the name of this dao
* @param fileExtension the file extension used by this instance, including a "." at the start * @param fileExtension the file extension used by this instance, including a "." at the start
* @param dataFolderName the name of the folder used to store data * @param dataFolderName the name of the folder used to store data
*/ */
public SeparatedConfigurateDao(LuckPermsPlugin plugin, ConfigurateLoader loader, String name, String fileExtension, String dataFolderName) { public SeparatedConfigurateStorage(LuckPermsPlugin plugin, String implementationName, ConfigurateLoader loader, String fileExtension, String dataFolderName) {
super(plugin, loader, name, dataFolderName); super(plugin, implementationName, loader, dataFolderName);
this.fileExtension = fileExtension; this.fileExtension = fileExtension;
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file; package me.lucko.luckperms.common.storage.implementation.file;
public enum StorageLocation { public enum StorageLocation {

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file.loader; package me.lucko.luckperms.common.storage.implementation.file.loader;
import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.loader.ConfigurationLoader; import ninja.leaping.configurate.loader.ConfigurationLoader;

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file.loader; package me.lucko.luckperms.common.storage.implementation.file.loader;
import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader; import ninja.leaping.configurate.hocon.HoconConfigurationLoader;

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file.loader; package me.lucko.luckperms.common.storage.implementation.file.loader;
import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.gson.GsonConfigurationLoader; import ninja.leaping.configurate.gson.GsonConfigurationLoader;

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file.loader; package me.lucko.luckperms.common.storage.implementation.file.loader;
import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.loader.ConfigurationLoader; import ninja.leaping.configurate.loader.ConfigurationLoader;

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.file.loader; package me.lucko.luckperms.common.storage.implementation.file.loader;
import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions;

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.mongodb; package me.lucko.luckperms.common.storage.implementation.mongodb;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.mongodb.MongoClient; import com.mongodb.MongoClient;
@ -60,9 +60,9 @@ import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeDataContainer; import me.lucko.luckperms.common.node.model.NodeDataContainer;
import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.PlayerSaveResultImpl; import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.StorageCredentials; import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
import me.lucko.luckperms.common.storage.dao.AbstractDao; import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import org.bson.Document; import org.bson.Document;
@ -77,7 +77,8 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MongoDao extends AbstractDao { public class MongoStorage implements StorageImplementation {
private final LuckPermsPlugin plugin;
private final StorageCredentials configuration; private final StorageCredentials configuration;
private MongoClient mongoClient; private MongoClient mongoClient;
@ -85,13 +86,23 @@ public class MongoDao extends AbstractDao {
private final String prefix; private final String prefix;
private final String connectionUri; private final String connectionUri;
public MongoDao(LuckPermsPlugin plugin, StorageCredentials configuration, String prefix, String connectionUri) { public MongoStorage(LuckPermsPlugin plugin, StorageCredentials configuration, String prefix, String connectionUri) {
super(plugin, "MongoDB"); this.plugin = plugin;
this.configuration = configuration; this.configuration = configuration;
this.prefix = prefix; this.prefix = prefix;
this.connectionUri = connectionUri; this.connectionUri = connectionUri;
} }
@Override
public LuckPermsPlugin getPlugin() {
return this.plugin;
}
@Override
public String getImplementationName() {
return "MongoDB";
}
@Override @Override
public void init() { public void init() {
if (!Strings.isNullOrEmpty(this.connectionUri)) { if (!Strings.isNullOrEmpty(this.connectionUri)) {
@ -215,7 +226,7 @@ public class MongoDao extends AbstractDao {
if (!nodes.equals(results)) { if (!nodes.equals(results)) {
List<Document> newNodes = results.stream() List<Document> newNodes = results.stream()
.map(MongoDao::nodeToDoc) .map(MongoStorage::nodeToDoc)
.collect(Collectors.toList()); .collect(Collectors.toList());
d.append("permissions", newNodes).remove("perms"); d.append("permissions", newNodes).remove("perms");
@ -240,7 +251,7 @@ public class MongoDao extends AbstractDao {
if (!nodes.equals(results)) { if (!nodes.equals(results)) {
List<Document> newNodes = results.stream() List<Document> newNodes = results.stream()
.map(MongoDao::nodeToDoc) .map(MongoStorage::nodeToDoc)
.collect(Collectors.toList()); .collect(Collectors.toList());
d.append("permissions", newNodes).remove("perms"); d.append("permissions", newNodes).remove("perms");
@ -628,7 +639,7 @@ public class MongoDao extends AbstractDao {
private static Document userToDoc(User user) { private static Document userToDoc(User user) {
List<Document> nodes = user.enduringData().immutable().values().stream() List<Document> nodes = user.enduringData().immutable().values().stream()
.map(NodeDataContainer::fromNode) .map(NodeDataContainer::fromNode)
.map(MongoDao::nodeToDoc) .map(MongoStorage::nodeToDoc)
.collect(Collectors.toList()); .collect(Collectors.toList());
return new Document("_id", user.getUuid()) return new Document("_id", user.getUuid())
@ -666,7 +677,7 @@ public class MongoDao extends AbstractDao {
private static Document groupToDoc(Group group) { private static Document groupToDoc(Group group) {
List<Document> nodes = group.enduringData().immutable().values().stream() List<Document> nodes = group.enduringData().immutable().values().stream()
.map(NodeDataContainer::fromNode) .map(NodeDataContainer::fromNode)
.map(MongoDao::nodeToDoc) .map(MongoStorage::nodeToDoc)
.collect(Collectors.toList()); .collect(Collectors.toList());
return new Document("_id", group.getName()).append("permissions", nodes); return new Document("_id", group.getName()).append("permissions", nodes);

View File

@ -1,5 +1,5 @@
/* /*
* This file is part of LuckPerms, licensed under the MIT License. * This file is part of luckperms, licensed under the MIT License.
* *
* Copyright (c) lucko (Luck) <luck@lucko.me> * Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors * Copyright (c) contributors
@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao; package me.lucko.luckperms.common.storage.implementation.split;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -37,8 +37,8 @@ import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.SplitStorageType;
import me.lucko.luckperms.common.storage.StorageType; import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -47,20 +47,31 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class SplitStorageDao extends AbstractDao { public class SplitStorage implements StorageImplementation {
private final Map<StorageType, AbstractDao> backing; private final LuckPermsPlugin plugin;
private final Map<StorageType, StorageImplementation> backing;
private final Map<SplitStorageType, StorageType> types; private final Map<SplitStorageType, StorageType> types;
public SplitStorageDao(LuckPermsPlugin plugin, Map<StorageType, AbstractDao> backing, Map<SplitStorageType, StorageType> types) { public SplitStorage(LuckPermsPlugin plugin, Map<StorageType, StorageImplementation> backing, Map<SplitStorageType, StorageType> types) {
super(plugin, "Split Storage"); this.plugin = plugin;
this.backing = ImmutableMap.copyOf(backing); this.backing = ImmutableMap.copyOf(backing);
this.types = ImmutableMap.copyOf(types); this.types = ImmutableMap.copyOf(types);
} }
@Override
public LuckPermsPlugin getPlugin() {
return this.plugin;
}
@Override
public String getImplementationName() {
return "Split Storage";
}
@Override @Override
public void init() { public void init() {
boolean failed = false; boolean failed = false;
for (AbstractDao ds : this.backing.values()) { for (StorageImplementation ds : this.backing.values()) {
try { try {
ds.init(); ds.init();
} catch (Exception ex) { } catch (Exception ex) {
@ -75,7 +86,7 @@ public class SplitStorageDao extends AbstractDao {
@Override @Override
public void shutdown() { public void shutdown() {
for (AbstractDao ds : this.backing.values()) { for (StorageImplementation ds : this.backing.values()) {
try { try {
ds.shutdown(); ds.shutdown();
} catch (Exception e) { } catch (Exception e) {
@ -88,7 +99,7 @@ public class SplitStorageDao extends AbstractDao {
public Map<String, String> getMeta() { public Map<String, String> getMeta() {
Map<String, String> ret = new LinkedHashMap<>(); Map<String, String> ret = new LinkedHashMap<>();
ret.put("Types", this.types.toString()); ret.put("Types", this.types.toString());
for (AbstractDao backing : this.backing.values()) { for (StorageImplementation backing : this.backing.values()) {
ret.putAll(backing.getMeta()); ret.putAll(backing.getMeta());
} }
return ret; return ret;

View File

@ -1,5 +1,5 @@
/* /*
* This file is part of LuckPerms, licensed under the MIT License. * This file is part of luckperms, licensed under the MIT License.
* *
* Copyright (c) lucko (Luck) <luck@lucko.me> * Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors * Copyright (c) contributors
@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage; package me.lucko.luckperms.common.storage.implementation.split;
public enum SplitStorageType { public enum SplitStorageType {
LOG, USER, GROUP, TRACK, UUID LOG, USER, GROUP, TRACK, UUID

View File

@ -23,10 +23,9 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql; package me.lucko.luckperms.common.storage.implementation.sql;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import me.lucko.luckperms.api.HeldPermission; import me.lucko.luckperms.api.HeldPermission;
@ -50,11 +49,12 @@ import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeDataContainer; import me.lucko.luckperms.common.node.model.NodeDataContainer;
import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.node.model.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.PlayerSaveResultImpl; import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.dao.AbstractDao; import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.AbstractConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.file.SQLiteConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.file.SQLiteConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.PostgreConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.PostgreConnectionFactory; import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStream; import java.io.InputStream;
@ -76,7 +76,7 @@ import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SqlDao extends AbstractDao { public class SqlStorage implements StorageImplementation {
private static final Type LIST_STRING_TYPE = new TypeToken<List<String>>(){}.getType(); 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_SELECT = "SELECT permission, value, server, world, expiry, contexts FROM {prefix}user_permissions WHERE uuid=?";
@ -118,23 +118,29 @@ public class SqlDao extends AbstractDao {
private static final String ACTION_INSERT = "INSERT INTO {prefix}actions(time, actor_uuid, actor_name, type, acted_uuid, acted_name, action) VALUES(?, ?, ?, ?, ?, ?, ?)"; private static final String ACTION_INSERT = "INSERT INTO {prefix}actions(time, actor_uuid, actor_name, type, acted_uuid, acted_name, action) VALUES(?, ?, ?, ?, ?, ?, ?)";
private static final String ACTION_SELECT_ALL = "SELECT * FROM {prefix}actions"; private static final String ACTION_SELECT_ALL = "SELECT * FROM {prefix}actions";
private final Gson gson; private final LuckPermsPlugin plugin;
private final AbstractConnectionFactory provider;
private final ConnectionFactory connectionFactory;
private final Function<String, String> statementProcessor; private final Function<String, String> statementProcessor;
public SqlDao(LuckPermsPlugin plugin, AbstractConnectionFactory provider, String tablePrefix) { public SqlStorage(LuckPermsPlugin plugin, ConnectionFactory connectionFactory, String tablePrefix) {
super(plugin, provider.getName()); this.plugin = plugin;
this.provider = provider; this.connectionFactory = connectionFactory;
this.statementProcessor = provider.getStatementProcessor().compose(s -> s.replace("{prefix}", tablePrefix)); this.statementProcessor = connectionFactory.getStatementProcessor().compose(s -> s.replace("{prefix}", tablePrefix));
this.gson = new Gson();
} }
public Gson getGson() { @Override
return this.gson; public LuckPermsPlugin getPlugin() {
return this.plugin;
} }
public AbstractConnectionFactory getProvider() { @Override
return this.provider; public String getImplementationName() {
return this.connectionFactory.getImplementationName();
}
public ConnectionFactory getConnectionFactory() {
return this.connectionFactory;
} }
public Function<String, String> getStatementProcessor() { public Function<String, String> getStatementProcessor() {
@ -142,7 +148,7 @@ public class SqlDao extends AbstractDao {
} }
private boolean tableExists(String table) throws SQLException { private boolean tableExists(String table) throws SQLException {
try (Connection connection = this.provider.getConnection()) { try (Connection connection = this.connectionFactory.getConnection()) {
try (ResultSet rs = connection.getMetaData().getTables(null, null, "%", null)) { try (ResultSet rs = connection.getMetaData().getTables(null, null, "%", null)) {
while (rs.next()) { while (rs.next()) {
if (rs.getString(3).equalsIgnoreCase(table)) { if (rs.getString(3).equalsIgnoreCase(table)) {
@ -156,18 +162,18 @@ public class SqlDao extends AbstractDao {
@Override @Override
public void init() throws Exception { public void init() throws Exception {
this.provider.init(); this.connectionFactory.init();
// Init tables // Init tables
if (!tableExists(this.statementProcessor.apply("{prefix}user_permissions"))) { if (!tableExists(this.statementProcessor.apply("{prefix}user_permissions"))) {
String schemaFileName = "me/lucko/luckperms/schema/" + this.provider.getName().toLowerCase() + ".sql"; String schemaFileName = "me/lucko/luckperms/schema/" + this.connectionFactory.getImplementationName().toLowerCase() + ".sql";
try (InputStream is = this.plugin.getBootstrap().getResourceStream(schemaFileName)) { try (InputStream is = this.plugin.getBootstrap().getResourceStream(schemaFileName)) {
if (is == null) { if (is == null) {
throw new Exception("Couldn't locate schema file for " + this.provider.getName()); throw new Exception("Couldn't locate schema file for " + this.connectionFactory.getImplementationName());
} }
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
try (Connection connection = this.provider.getConnection()) { try (Connection connection = this.connectionFactory.getConnection()) {
try (Statement s = connection.createStatement()) { try (Statement s = connection.createStatement()) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String line; String line;
@ -196,8 +202,8 @@ public class SqlDao extends AbstractDao {
// migrations // migrations
try { try {
if (!(this.provider instanceof SQLiteConnectionFactory) && !(this.provider instanceof PostgreConnectionFactory)) { if (!(this.connectionFactory instanceof SQLiteConnectionFactory) && !(this.connectionFactory instanceof PostgreConnectionFactory)) {
try (Connection connection = this.provider.getConnection()) { try (Connection connection = this.connectionFactory.getConnection()) {
try (Statement s = connection.createStatement()) { try (Statement s = connection.createStatement()) {
s.execute(this.statementProcessor.apply("ALTER TABLE {prefix}actions MODIFY COLUMN actor_name VARCHAR(100)")); s.execute(this.statementProcessor.apply("ALTER TABLE {prefix}actions MODIFY COLUMN actor_name VARCHAR(100)"));
s.execute(this.statementProcessor.apply("ALTER TABLE {prefix}actions MODIFY COLUMN action VARCHAR(300)")); s.execute(this.statementProcessor.apply("ALTER TABLE {prefix}actions MODIFY COLUMN action VARCHAR(300)"));
@ -212,7 +218,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public void shutdown() { public void shutdown() {
try { try {
this.provider.shutdown(); this.connectionFactory.shutdown();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -220,12 +226,12 @@ public class SqlDao extends AbstractDao {
@Override @Override
public Map<String, String> getMeta() { public Map<String, String> getMeta() {
return this.provider.getMeta(); return this.connectionFactory.getMeta();
} }
@Override @Override
public void logAction(LogEntry entry) throws SQLException { public void logAction(LogEntry entry) throws SQLException {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(ACTION_INSERT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(ACTION_INSERT))) {
ps.setLong(1, entry.getTimestamp()); ps.setLong(1, entry.getTimestamp());
ps.setString(2, entry.getActor().toString()); ps.setString(2, entry.getActor().toString());
@ -242,7 +248,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public Log getLog() throws SQLException { public Log getLog() throws SQLException {
final Log.Builder log = Log.builder(); final Log.Builder log = Log.builder();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(ACTION_SELECT_ALL))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(ACTION_SELECT_ALL))) {
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -267,7 +273,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public void applyBulkUpdate(BulkUpdate bulkUpdate) throws SQLException { public void applyBulkUpdate(BulkUpdate bulkUpdate) throws SQLException {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
if (bulkUpdate.getDataType().isIncludingUsers()) { if (bulkUpdate.getDataType().isIncludingUsers()) {
String table = this.statementProcessor.apply("{prefix}user_permissions"); String table = this.statementProcessor.apply("{prefix}user_permissions");
try (PreparedStatement ps = bulkUpdate.buildAsSql().build(c, q -> q.replace("{table}", table))) { try (PreparedStatement ps = bulkUpdate.buildAsSql().build(c, q -> q.replace("{table}", table))) {
@ -294,7 +300,7 @@ public class SqlDao extends AbstractDao {
String userName = null; String userName = null;
// Collect user permissions // Collect user permissions
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_SELECT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_SELECT))) {
ps.setString(1, user.getUuid().toString()); ps.setString(1, user.getUuid().toString());
@ -313,7 +319,7 @@ public class SqlDao extends AbstractDao {
} }
// Collect user meta (username & primary group) // Collect user meta (username & primary group)
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_BY_UUID))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_BY_UUID))) {
ps.setString(1, user.getUuid().toString()); ps.setString(1, user.getUuid().toString());
@ -367,7 +373,7 @@ public class SqlDao extends AbstractDao {
try { try {
// Empty data - just delete from the DB. // Empty data - just delete from the DB.
if (!this.plugin.getUserManager().shouldSave(user)) { if (!this.plugin.getUserManager().shouldSave(user)) {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_DELETE))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_DELETE))) {
ps.setString(1, user.getUuid().toString()); ps.setString(1, user.getUuid().toString());
ps.execute(); ps.execute();
@ -383,7 +389,7 @@ public class SqlDao extends AbstractDao {
// Get a snapshot of current data. // Get a snapshot of current data.
Set<NodeDataContainer> remote = new HashSet<>(); Set<NodeDataContainer> remote = new HashSet<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_SELECT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_SELECT))) {
ps.setString(1, user.getUuid().toString()); ps.setString(1, user.getUuid().toString());
@ -409,7 +415,7 @@ public class SqlDao extends AbstractDao {
Set<NodeDataContainer> toRemove = diff.getValue(); Set<NodeDataContainer> toRemove = diff.getValue();
if (!toRemove.isEmpty()) { if (!toRemove.isEmpty()) {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_DELETE_SPECIFIC))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_DELETE_SPECIFIC))) {
for (NodeDataContainer nd : toRemove) { for (NodeDataContainer nd : toRemove) {
ps.setString(1, user.getUuid().toString()); ps.setString(1, user.getUuid().toString());
@ -418,7 +424,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, this.gson.toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts()))); ps.setString(7, GsonProvider.normal().toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts())));
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -427,7 +433,7 @@ public class SqlDao extends AbstractDao {
} }
if (!toAdd.isEmpty()) { if (!toAdd.isEmpty()) {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_INSERT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_INSERT))) {
for (NodeDataContainer nd : toAdd) { for (NodeDataContainer nd : toAdd) {
ps.setString(1, user.getUuid().toString()); ps.setString(1, user.getUuid().toString());
@ -436,7 +442,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, this.gson.toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts()))); ps.setString(7, GsonProvider.normal().toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts())));
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -444,7 +450,7 @@ public class SqlDao extends AbstractDao {
} }
} }
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
boolean hasPrimaryGroupSaved; boolean hasPrimaryGroupSaved;
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_PRIMARY_GROUP_BY_UUID))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_PRIMARY_GROUP_BY_UUID))) {
@ -480,7 +486,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public Set<UUID> getUniqueUsers() throws SQLException { public Set<UUID> getUniqueUsers() throws SQLException {
Set<UUID> uuids = new HashSet<>(); Set<UUID> uuids = new HashSet<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_SELECT_DISTINCT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(USER_PERMISSIONS_SELECT_DISTINCT))) {
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -499,7 +505,7 @@ public class SqlDao extends AbstractDao {
constraint.appendSql(builder, "permission"); constraint.appendSql(builder, "permission");
List<HeldPermission<UUID>> held = new ArrayList<>(); List<HeldPermission<UUID>> held = new ArrayList<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = builder.build(c, this.statementProcessor)) { try (PreparedStatement ps = builder.build(c, this.statementProcessor)) {
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -523,7 +529,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public Group createAndLoadGroup(String name) throws SQLException { public Group createAndLoadGroup(String name) throws SQLException {
String query; String query;
switch (this.provider.getName()) { switch (this.connectionFactory.getImplementationName()) {
case "H2": case "H2":
query = H2_GROUP_INSERT; query = H2_GROUP_INSERT;
break; break;
@ -538,7 +544,7 @@ public class SqlDao extends AbstractDao {
break; break;
} }
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(query))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(query))) {
ps.setString(1, name); ps.setString(1, name);
ps.execute(); ps.execute();
@ -552,7 +558,7 @@ public class SqlDao extends AbstractDao {
public Optional<Group> loadGroup(String name) throws SQLException { public Optional<Group> loadGroup(String name) throws SQLException {
// Check the group actually exists // Check the group actually exists
List<String> groups = new ArrayList<>(); List<String> groups = new ArrayList<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_SELECT_ALL))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_SELECT_ALL))) {
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -572,7 +578,7 @@ public class SqlDao extends AbstractDao {
try { try {
List<NodeDataContainer> data = new ArrayList<>(); List<NodeDataContainer> data = new ArrayList<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_SELECT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_SELECT))) {
ps.setString(1, group.getName()); ps.setString(1, group.getName());
@ -606,7 +612,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public void loadAllGroups() throws SQLException { public void loadAllGroups() throws SQLException {
List<String> groups = new ArrayList<>(); List<String> groups = new ArrayList<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_SELECT_ALL))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_SELECT_ALL))) {
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -642,7 +648,7 @@ public class SqlDao extends AbstractDao {
try { try {
// Empty data, just delete. // Empty data, just delete.
if (group.enduringData().immutable().isEmpty()) { if (group.enduringData().immutable().isEmpty()) {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_DELETE))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_DELETE))) {
ps.setString(1, group.getName()); ps.setString(1, group.getName());
ps.execute(); ps.execute();
@ -653,7 +659,7 @@ public class SqlDao extends AbstractDao {
// Get a snapshot of current data // Get a snapshot of current data
Set<NodeDataContainer> remote = new HashSet<>(); Set<NodeDataContainer> remote = new HashSet<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_SELECT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_SELECT))) {
ps.setString(1, group.getName()); ps.setString(1, group.getName());
@ -679,7 +685,7 @@ public class SqlDao extends AbstractDao {
Set<NodeDataContainer> toRemove = diff.getValue(); Set<NodeDataContainer> toRemove = diff.getValue();
if (!toRemove.isEmpty()) { if (!toRemove.isEmpty()) {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_DELETE_SPECIFIC))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_DELETE_SPECIFIC))) {
for (NodeDataContainer nd : toRemove) { for (NodeDataContainer nd : toRemove) {
ps.setString(1, group.getName()); ps.setString(1, group.getName());
@ -688,7 +694,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, this.gson.toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts()))); ps.setString(7, GsonProvider.normal().toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts())));
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -697,7 +703,7 @@ public class SqlDao extends AbstractDao {
} }
if (!toAdd.isEmpty()) { if (!toAdd.isEmpty()) {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_INSERT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_INSERT))) {
for (NodeDataContainer nd : toAdd) { for (NodeDataContainer nd : toAdd) {
ps.setString(1, group.getName()); ps.setString(1, group.getName());
@ -706,7 +712,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, this.gson.toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts()))); ps.setString(7, GsonProvider.normal().toJson(ContextSetJsonSerializer.serializeContextSet(nd.getContexts())));
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -722,7 +728,7 @@ public class SqlDao extends AbstractDao {
public void deleteGroup(Group group) throws SQLException { public void deleteGroup(Group group) throws SQLException {
group.getIoLock().lock(); group.getIoLock().lock();
try { try {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_DELETE))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_DELETE))) {
ps.setString(1, group.getName()); ps.setString(1, group.getName());
ps.execute(); ps.execute();
@ -746,7 +752,7 @@ public class SqlDao extends AbstractDao {
constraint.appendSql(builder, "permission"); constraint.appendSql(builder, "permission");
List<HeldPermission<String>> held = new ArrayList<>(); List<HeldPermission<String>> held = new ArrayList<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = builder.build(c, this.statementProcessor)) { try (PreparedStatement ps = builder.build(c, this.statementProcessor)) {
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -774,7 +780,7 @@ public class SqlDao extends AbstractDao {
try { try {
boolean exists = false; boolean exists = false;
String groups = null; String groups = null;
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_SELECT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_SELECT))) {
ps.setString(1, track.getName()); ps.setString(1, track.getName());
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
@ -788,10 +794,10 @@ public class SqlDao extends AbstractDao {
if (exists) { if (exists) {
// Track exists, let's load. // Track exists, let's load.
track.setGroups(this.gson.fromJson(groups, LIST_STRING_TYPE)); track.setGroups(GsonProvider.normal().fromJson(groups, LIST_STRING_TYPE));
} else { } else {
String json = this.gson.toJson(track.getGroups()); String json = GsonProvider.normal().toJson(track.getGroups());
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_INSERT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_INSERT))) {
ps.setString(1, track.getName()); ps.setString(1, track.getName());
ps.setString(2, json); ps.setString(2, json);
@ -813,7 +819,7 @@ public class SqlDao extends AbstractDao {
} }
try { try {
String groups; String groups;
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_SELECT))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_SELECT))) {
ps.setString(1, name); ps.setString(1, name);
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
@ -831,7 +837,7 @@ public class SqlDao extends AbstractDao {
track.getIoLock().lock(); track.getIoLock().lock();
} }
track.setGroups(this.gson.fromJson(groups, LIST_STRING_TYPE)); track.setGroups(GsonProvider.normal().fromJson(groups, LIST_STRING_TYPE));
return Optional.of(track); return Optional.of(track);
} finally { } finally {
@ -844,7 +850,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public void loadAllTracks() throws SQLException { public void loadAllTracks() throws SQLException {
List<String> tracks = new ArrayList<>(); List<String> tracks = new ArrayList<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_SELECT_ALL))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_SELECT_ALL))) {
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -878,8 +884,8 @@ public class SqlDao extends AbstractDao {
public void saveTrack(Track track) throws SQLException { public void saveTrack(Track track) throws SQLException {
track.getIoLock().lock(); track.getIoLock().lock();
try { try {
String s = this.gson.toJson(track.getGroups()); String s = GsonProvider.normal().toJson(track.getGroups());
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_UPDATE))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_UPDATE))) {
ps.setString(1, s); ps.setString(1, s);
ps.setString(2, track.getName()); ps.setString(2, track.getName());
@ -895,7 +901,7 @@ public class SqlDao extends AbstractDao {
public void deleteTrack(Track track) throws SQLException { public void deleteTrack(Track track) throws SQLException {
track.getIoLock().lock(); track.getIoLock().lock();
try { try {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_DELETE))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_DELETE))) {
ps.setString(1, track.getName()); ps.setString(1, track.getName());
ps.execute(); ps.execute();
@ -917,7 +923,7 @@ public class SqlDao extends AbstractDao {
// do the insert // do the insert
if (!username.equals(oldUsername)) { if (!username.equals(oldUsername)) {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
if (oldUsername != null) { if (oldUsername != null) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_UPDATE_USERNAME_FOR_UUID))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_UPDATE_USERNAME_FOR_UUID))) {
ps.setString(1, username); ps.setString(1, username);
@ -938,7 +944,7 @@ public class SqlDao extends AbstractDao {
PlayerSaveResultImpl result = PlayerSaveResultImpl.determineBaseResult(username, oldUsername); PlayerSaveResultImpl result = PlayerSaveResultImpl.determineBaseResult(username, oldUsername);
Set<UUID> conflicting = new HashSet<>(); Set<UUID> conflicting = new HashSet<>();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_ALL_UUIDS_BY_USERNAME))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_ALL_UUIDS_BY_USERNAME))) {
ps.setString(1, username); ps.setString(1, username);
ps.setString(2, uuid.toString()); ps.setString(2, uuid.toString());
@ -952,7 +958,7 @@ public class SqlDao extends AbstractDao {
if (!conflicting.isEmpty()) { if (!conflicting.isEmpty()) {
// remove the mappings for conflicting uuids // remove the mappings for conflicting uuids
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_DELETE_ALL_UUIDS_BY_USERNAME))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_DELETE_ALL_UUIDS_BY_USERNAME))) {
ps.setString(1, username); ps.setString(1, username);
ps.setString(2, uuid.toString()); ps.setString(2, uuid.toString());
@ -968,7 +974,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public UUID getPlayerUuid(String username) throws SQLException { public UUID getPlayerUuid(String username) throws SQLException {
username = username.toLowerCase(); username = username.toLowerCase();
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_UUID_BY_USERNAME))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_UUID_BY_USERNAME))) {
ps.setString(1, username); ps.setString(1, username);
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
@ -983,7 +989,7 @@ public class SqlDao extends AbstractDao {
@Override @Override
public String getPlayerName(UUID uuid) throws SQLException { public String getPlayerName(UUID uuid) throws SQLException {
try (Connection c = this.provider.getConnection()) { try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_USERNAME_BY_UUID))) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_USERNAME_BY_UUID))) {
ps.setString(1, uuid.toString()); ps.setString(1, uuid.toString());
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
@ -1016,6 +1022,6 @@ public class SqlDao extends AbstractDao {
} }
private NodeDataContainer deserializeNode(String permission, boolean value, String server, String world, long expiry, String contexts) { private NodeDataContainer deserializeNode(String permission, boolean value, String server, String world, long expiry, String contexts) {
return NodeDataContainer.of(permission, value, server, world, expiry, ContextSetJsonSerializer.deserializeContextSet(this.gson, contexts).makeImmutable()); return NodeDataContainer.of(permission, value, server, world, expiry, ContextSetJsonSerializer.deserializeContextSet(GsonProvider.normal(), contexts).makeImmutable());
} }
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection; package me.lucko.luckperms.common.storage.implementation.sql.connection;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
@ -31,28 +31,20 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
public abstract class AbstractConnectionFactory { public interface ConnectionFactory {
private final String name; String getImplementationName();
public AbstractConnectionFactory(String name) { void init();
this.name = name;
}
public String getName() { void shutdown() throws Exception;
return this.name;
}
public abstract void init(); default Map<String, String> getMeta() {
public abstract void shutdown() throws Exception;
public Map<String, String> getMeta() {
return Collections.emptyMap(); return Collections.emptyMap();
} }
public abstract Function<String, String> getStatementProcessor(); Function<String, String> getStatementProcessor();
public abstract Connection getConnection() throws SQLException; Connection getConnection() throws SQLException;
} }

View File

@ -23,9 +23,9 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.file; package me.lucko.luckperms.common.storage.implementation.sql.connection.file;
import me.lucko.luckperms.common.storage.dao.sql.connection.AbstractConnectionFactory; import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -34,13 +34,12 @@ import java.text.DecimalFormat;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
abstract class FlatfileConnectionFactory extends AbstractConnectionFactory { abstract class FlatfileConnectionFactory implements ConnectionFactory {
protected static final DecimalFormat DF = new DecimalFormat("#.##"); protected static final DecimalFormat DF = new DecimalFormat("#.##");
protected final Path file; protected final Path file;
FlatfileConnectionFactory(String name, Path file) { FlatfileConnectionFactory(Path file) {
super(name);
this.file = file; this.file = file;
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.file; package me.lucko.luckperms.common.storage.implementation.sql.connection.file;
import me.lucko.luckperms.common.dependencies.Dependency; import me.lucko.luckperms.common.dependencies.Dependency;
import me.lucko.luckperms.common.dependencies.classloader.IsolatedClassLoader; import me.lucko.luckperms.common.dependencies.classloader.IsolatedClassLoader;
@ -49,7 +49,7 @@ public class H2ConnectionFactory extends FlatfileConnectionFactory {
private NonClosableConnection connection; private NonClosableConnection connection;
public H2ConnectionFactory(LuckPermsPlugin plugin, Path file) { public H2ConnectionFactory(LuckPermsPlugin plugin, Path file) {
super("H2", file); super(file);
// backwards compat // backwards compat
Path data = file.getParent().resolve("luckperms.db.mv.db"); Path data = file.getParent().resolve("luckperms.db.mv.db");
@ -72,6 +72,11 @@ public class H2ConnectionFactory extends FlatfileConnectionFactory {
} }
} }
@Override
public String getImplementationName() {
return "H2";
}
@Override @Override
public synchronized Connection getConnection() throws SQLException { public synchronized Connection getConnection() throws SQLException {
if (this.connection == null || this.connection.isClosed()) { if (this.connection == null || this.connection.isClosed()) {

View File

@ -23,8 +23,10 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.file; package me.lucko.luckperms.common.storage.implementation.sql.connection.file;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.sql.Connection; import java.sql.Connection;
@ -43,22 +45,7 @@ public interface NonClosableConnection extends Connection {
return (NonClosableConnection) Proxy.newProxyInstance( return (NonClosableConnection) Proxy.newProxyInstance(
NonClosableConnection.class.getClassLoader(), NonClosableConnection.class.getClassLoader(),
new Class[]{NonClosableConnection.class}, new Class[]{NonClosableConnection.class},
(proxy, method, args) -> { new Handler(connection)
// block calls directly to #close
if (method.getName().equals("close")) {
return null;
}
// proxy calls to #shutdown to the real #close method
if (method.getName().equals("shutdown")) {
connection.close();
return null;
}
// delegate all other calls
return method.invoke(connection, args);
}
); );
} }
@ -66,4 +53,29 @@ public interface NonClosableConnection extends Connection {
* Actually {@link #close() closes} the underlying connection. * Actually {@link #close() closes} the underlying connection.
*/ */
void shutdown(); void shutdown();
final class Handler implements InvocationHandler {
private final Connection connection;
Handler(Connection connection) {
this.connection = connection;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// block calls directly to #close
if (method.getName().equals("close")) {
return null;
}
// proxy calls to #shutdown to the real #close method
if (method.getName().equals("shutdown")) {
this.connection.close();
return null;
}
// delegate all other calls
return method.invoke(this.connection, args);
}
}
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.file; package me.lucko.luckperms.common.storage.implementation.sql.connection.file;
import me.lucko.luckperms.common.dependencies.Dependency; import me.lucko.luckperms.common.dependencies.Dependency;
import me.lucko.luckperms.common.dependencies.classloader.IsolatedClassLoader; import me.lucko.luckperms.common.dependencies.classloader.IsolatedClassLoader;
@ -48,7 +48,7 @@ public class SQLiteConnectionFactory extends FlatfileConnectionFactory {
private NonClosableConnection connection; private NonClosableConnection connection;
public SQLiteConnectionFactory(LuckPermsPlugin plugin, Path file) { public SQLiteConnectionFactory(LuckPermsPlugin plugin, Path file) {
super("SQLite", file); super(file);
// backwards compat // backwards compat
Path data = file.getParent().resolve("luckperms.sqlite"); Path data = file.getParent().resolve("luckperms.sqlite");
@ -70,6 +70,11 @@ public class SQLiteConnectionFactory extends FlatfileConnectionFactory {
} }
} }
@Override
public String getImplementationName() {
return "SQLite";
}
private Connection createConnection(String url) throws SQLException { private Connection createConnection(String url) throws SQLException {
try { try {
return (Connection) this.createConnectionMethod.invoke(null, url, new Properties()); return (Connection) this.createConnectionMethod.invoke(null, url, new Properties());

View File

@ -23,13 +23,13 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.hikari; package me.lucko.luckperms.common.storage.implementation.sql.connection.hikari;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import me.lucko.luckperms.common.storage.StorageCredentials; import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.AbstractConnectionFactory; import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
@ -37,13 +37,12 @@ import java.sql.Statement;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
public abstract class HikariConnectionFactory extends AbstractConnectionFactory { public abstract class HikariConnectionFactory implements ConnectionFactory {
protected final StorageCredentials configuration; protected final StorageCredentials configuration;
private HikariDataSource hikari; private HikariDataSource hikari;
public HikariConnectionFactory(String name, StorageCredentials configuration) { public HikariConnectionFactory(StorageCredentials configuration) {
super(name);
this.configuration = configuration; this.configuration = configuration;
} }

View File

@ -23,11 +23,11 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.hikari; package me.lucko.luckperms.common.storage.implementation.sql.connection.hikari;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import me.lucko.luckperms.common.storage.StorageCredentials; import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -36,7 +36,12 @@ import java.util.stream.Collectors;
public class MariaDbConnectionFactory extends HikariConnectionFactory { public class MariaDbConnectionFactory extends HikariConnectionFactory {
public MariaDbConnectionFactory(StorageCredentials configuration) { public MariaDbConnectionFactory(StorageCredentials configuration) {
super("MariaDB", configuration); super(configuration);
}
@Override
public String getImplementationName() {
return "MariaDB";
} }
@Override @Override

View File

@ -23,17 +23,22 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.hikari; package me.lucko.luckperms.common.storage.implementation.sql.connection.hikari;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import me.lucko.luckperms.common.storage.StorageCredentials; import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.util.function.Function; import java.util.function.Function;
public class MySqlConnectionFactory extends HikariConnectionFactory { public class MySqlConnectionFactory extends HikariConnectionFactory {
public MySqlConnectionFactory(StorageCredentials configuration) { public MySqlConnectionFactory(StorageCredentials configuration) {
super("MySQL", configuration); super(configuration);
}
@Override
public String getImplementationName() {
return "MySQL";
} }
@Override @Override

View File

@ -23,17 +23,22 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage.dao.sql.connection.hikari; package me.lucko.luckperms.common.storage.implementation.sql.connection.hikari;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import me.lucko.luckperms.common.storage.StorageCredentials; import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.util.function.Function; import java.util.function.Function;
public class PostgreConnectionFactory extends HikariConnectionFactory { public class PostgreConnectionFactory extends HikariConnectionFactory {
public PostgreConnectionFactory(StorageCredentials configuration) { public PostgreConnectionFactory(StorageCredentials configuration) {
super("PostgreSQL", configuration); super(configuration);
}
@Override
public String getImplementationName() {
return "PostgreSQL";
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* This file is part of LuckPerms, licensed under the MIT License. * This file is part of luckperms, licensed under the MIT License.
* *
* Copyright (c) lucko (Luck) <luck@lucko.me> * Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors * Copyright (c) contributors
@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage; package me.lucko.luckperms.common.storage.misc;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Pattern; import java.util.regex.Pattern;

View File

@ -1,5 +1,5 @@
/* /*
* This file is part of LuckPerms, licensed under the MIT License. * This file is part of luckperms, licensed under the MIT License.
* *
* Copyright (c) lucko (Luck) <luck@lucko.me> * Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors * Copyright (c) contributors
@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage; package me.lucko.luckperms.common.storage.misc;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;

View File

@ -1,5 +1,5 @@
/* /*
* This file is part of LuckPerms, licensed under the MIT License. * This file is part of luckperms, licensed under the MIT License.
* *
* Copyright (c) lucko (Luck) <luck@lucko.me> * Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors * Copyright (c) contributors
@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.storage; package me.lucko.luckperms.common.storage.misc;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;

View File

@ -1,89 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.wrappings;
import me.lucko.luckperms.common.storage.Storage;
import java.lang.reflect.Proxy;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* A storage wrapping that ensures all tasks are completed before {@link Storage#shutdown()} is called.
*/
public interface PhasedStorage extends Storage {
/**
* Creates a new instance of {@link PhasedStorage} which delegates called to the given
* {@link Storage} instance.
*
* @param delegate the delegate storage impl
* @return the new phased storage instance
*/
static PhasedStorage wrap(Storage delegate) {
// create a new phaser to be used by the instance
Phaser phaser = new Phaser();
// create and return a proxy instance which directs save calls through the phaser
return (PhasedStorage) Proxy.newProxyInstance(
PhasedStorage.class.getClassLoader(),
new Class[]{PhasedStorage.class},
(proxy, method, args) -> {
// direct delegation
switch (method.getName()) {
case "getDao":
case "getApiDelegate":
case "getName":
case "init":
case "getMeta":
return method.invoke(delegate, args);
}
// await the phaser on shutdown
if (method.getName().equals("shutdown")) {
try {
phaser.awaitAdvanceInterruptibly(phaser.getPhase(), 10, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
e.printStackTrace();
}
delegate.shutdown();
return null;
}
// for all other methods, run the call via the phaser
phaser.register();
try {
return method.invoke(delegate, args);
} finally {
phaser.arriveAndDeregister();
}
}
);
}
}

View File

@ -29,6 +29,8 @@ import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/** /**
* Translates unix timestamps / durations into a readable format * Translates unix timestamps / durations into a readable format
@ -37,7 +39,7 @@ import java.util.regex.Pattern;
* see: https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java * see: https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
*/ */
public final class DateParser { public final class DateParser {
private static final Pattern TIME_PATTERN = Pattern.compile("(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE); private static final Pattern TIME_PATTERN = Pattern.compile(Stream.of("y", "mo", "w", "d", "h", "m").map(i -> "(?:([0-9]+)\\s*" + i + "[a-z]*[,\\s]*)?").collect(Collectors.joining()) + "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE);
private static final int MAX_YEARS = 100000; private static final int MAX_YEARS = 100000;
/** /**

View File

@ -0,0 +1,32 @@
/*
* This file is part of luckperms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.utils;
public interface ThrowingRunnable {
void run() throws Exception;
}

View File

@ -0,0 +1,54 @@
/*
* This file is part of luckperms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.utils.gson;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;
public final class GsonProvider {
private static final Gson NORMAL = new GsonBuilder().disableHtmlEscaping().create();
private static final Gson PRETTY_PRINTING = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
private static final JsonParser NORMAL_PARSER = new JsonParser();
public static Gson normal() {
return NORMAL;
}
public static Gson prettyPrinting() {
return PRETTY_PRINTING;
}
public static JsonParser parser() {
return NORMAL_PARSER;
}
private GsonProvider() {
throw new AssertionError();
}
}

View File

@ -25,11 +25,11 @@
package me.lucko.luckperms.common.web; package me.lucko.luckperms.common.web;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
@ -60,7 +60,7 @@ public enum StandardPastebin implements Pastebin {
@Override @Override
protected String parseIdFromResult(BufferedReader reader) { protected String parseIdFromResult(BufferedReader reader) {
JsonObject object = GSON.fromJson(reader, JsonObject.class); JsonObject object = GsonProvider.prettyPrinting().fromJson(reader, JsonObject.class);
return object.get("key").getAsString(); return object.get("key").getAsString();
} }
@ -82,7 +82,7 @@ public enum StandardPastebin implements Pastebin {
@Override @Override
protected String parseIdFromResult(BufferedReader reader) { protected String parseIdFromResult(BufferedReader reader) {
JsonObject object = GSON.fromJson(reader, JsonObject.class); JsonObject object = GsonProvider.prettyPrinting().fromJson(reader, JsonObject.class);
return object.get("key").getAsString(); return object.get("key").getAsString();
} }
@ -92,7 +92,6 @@ public enum StandardPastebin implements Pastebin {
} }
}; };
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8"); private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
private static final MediaType PLAIN_TYPE = MediaType.parse("text/plain; charset=utf-8"); private static final MediaType PLAIN_TYPE = MediaType.parse("text/plain; charset=utf-8");
@ -115,7 +114,7 @@ public enum StandardPastebin implements Pastebin {
} }
try (Writer writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) { try (Writer writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) {
GSON.toJson(content, writer); GsonProvider.prettyPrinting().toJson(content, writer);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -26,7 +26,6 @@
package me.lucko.luckperms.common.web; package me.lucko.luckperms.common.web;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
@ -41,6 +40,7 @@ import me.lucko.luckperms.common.node.model.NodeDataContainer;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Uuids; import me.lucko.luckperms.common.utils.Uuids;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import me.lucko.luckperms.common.utils.gson.JArray; import me.lucko.luckperms.common.utils.gson.JArray;
import me.lucko.luckperms.common.utils.gson.JObject; import me.lucko.luckperms.common.utils.gson.JObject;
@ -63,8 +63,6 @@ import java.util.stream.Stream;
* Utility methods for interacting with the LuckPerms web permission editor. * Utility methods for interacting with the LuckPerms web permission editor.
*/ */
public final class WebEditor { public final class WebEditor {
private static final Gson GSON = new Gson();
private static final String USER_ID_PATTERN = "user/"; private static final String USER_ID_PATTERN = "user/";
private static final String GROUP_ID_PATTERN = "group/"; private static final String GROUP_ID_PATTERN = "group/";
@ -159,7 +157,7 @@ public final class WebEditor {
try (InputStream inputStream = responseBody.byteStream()) { try (InputStream inputStream = responseBody.byteStream()) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
return GSON.fromJson(reader, JsonObject.class); return GsonProvider.normal().fromJson(reader, JsonObject.class);
} }
} }
} }

View File

@ -39,7 +39,7 @@ import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint; import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparisons.StandardComparison; import me.lucko.luckperms.common.bulkupdate.comparisons.StandardComparison;
import me.lucko.luckperms.common.managers.group.AbstractGroupManager; import me.lucko.luckperms.common.managers.group.AbstractGroupManager;
import me.lucko.luckperms.common.storage.DataConstraints; import me.lucko.luckperms.common.storage.misc.DataConstraints;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.model.SpongeGroup; import me.lucko.luckperms.sponge.model.SpongeGroup;

View File

@ -26,12 +26,11 @@
package me.lucko.luckperms.sponge.service.persisted; package me.lucko.luckperms.sponge.service.persisted;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.utils.MoreFiles; import me.lucko.luckperms.common.utils.MoreFiles;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -56,11 +55,6 @@ public class SubjectStorage {
*/ */
private final LPPermissionService service; private final LPPermissionService service;
/**
* Gson instance
*/
private final Gson gson;
/** /**
* The root directory used to store files * The root directory used to store files
*/ */
@ -68,7 +62,6 @@ public class SubjectStorage {
public SubjectStorage(LPPermissionService service, Path container) { public SubjectStorage(LPPermissionService service, Path container) {
this.service = service; this.service = service;
this.gson = new GsonBuilder().setPrettyPrinting().create();
this.container = container; this.container = container;
} }
@ -131,7 +124,7 @@ public class SubjectStorage {
public void saveToFile(SubjectDataContainer container, Path file) throws IOException { public void saveToFile(SubjectDataContainer container, Path file) throws IOException {
MoreFiles.createDirectoriesIfNotExists(file.getParent()); MoreFiles.createDirectoriesIfNotExists(file.getParent());
try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
this.gson.toJson(container.serialize(), writer); GsonProvider.prettyPrinting().toJson(container.serialize(), writer);
writer.flush(); writer.flush();
} }
} }
@ -201,7 +194,7 @@ public class SubjectStorage {
String subjectName = fileName.substring(0, fileName.length() - ".json".length()); String subjectName = fileName.substring(0, fileName.length() - ".json".length());
try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
JsonObject data = this.gson.fromJson(reader, JsonObject.class); JsonObject data = GsonProvider.prettyPrinting().fromJson(reader, JsonObject.class);
SubjectDataContainer model = SubjectDataContainer.deserialize(this.service, data); SubjectDataContainer model = SubjectDataContainer.deserialize(this.service, data);
return new LoadedSubject(subjectName, model); return new LoadedSubject(subjectName, model);
} catch (Exception e) { } catch (Exception e) {