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 me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.storage.misc.DataConstraints;
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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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.Paginated;
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.plugin.LuckPermsPlugin;
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.Paginated;
import me.lucko.luckperms.common.utils.Predicates;

View File

@ -25,9 +25,6 @@
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.LookupSetting;
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.sender.Sender;
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.JObject;
import me.lucko.luckperms.common.web.Pastebin;
@ -70,8 +68,6 @@ import java.util.function.BiConsumer;
import java.util.stream.Collectors;
public class DebugCommand extends SingleCommand {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
public DebugCommand(LocaleManager locale) {
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) -> {
sb.append("-- ").append(name).append(" --\n");
sb.append(GSON.toJson(content.toJson()));
sb.append(GsonProvider.prettyPrinting().toJson(content.toJson()));
sb.append("\n\n");
};
@ -124,7 +120,7 @@ public class DebugCommand extends SingleCommand {
return new JObject()
.add("storage", new JObject()
.add("name", plugin.getStorage().getName())
.add("type", plugin.getStorage().getDao().getClass().getName())
.add("type", plugin.getStorage().getImplementation().getClass().getName())
.add("meta", () -> {
JObject metaObject = new JObject();
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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.plugin.LuckPermsPlugin;
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 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.PrimaryGroupHolder;
import me.lucko.luckperms.common.primarygroup.StoredHolder;
import me.lucko.luckperms.common.storage.SplitStorageType;
import me.lucko.luckperms.common.storage.StorageCredentials;
import me.lucko.luckperms.common.storage.implementation.split.SplitStorageType;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.lang.reflect.Field;

View File

@ -25,12 +25,12 @@
package me.lucko.luckperms.common.config;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -70,7 +70,7 @@ public class ContextsFile {
boolean save = false;
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")) {
this.staticContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("context").getAsJsonObject()).makeImmutable();

View File

@ -25,8 +25,6 @@
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.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.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import me.lucko.luckperms.common.utils.gson.JObject;
import org.checkerframework.checker.nullness.qual.NonNull;
@ -59,8 +58,6 @@ import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer {
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
private final LuckPermsPlugin plugin;
private final Set<UUID> receivedMessages;
private final PushUpdateBuffer updateBuffer;
@ -169,7 +166,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
@Override
public boolean consumeIncomingMessageAsString(@NonNull String encodedString) {
Objects.requireNonNull(encodedString, "encodedString");
JsonObject decodedObject = GSON.fromJson(encodedString, JsonObject.class).getAsJsonObject();
JsonObject decodedObject = GsonProvider.normal().fromJson(encodedString, JsonObject.class).getAsJsonObject();
// extract id
JsonElement idElement = decodedObject.get("id");
@ -226,7 +223,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
})
.toJson();
return GSON.toJson(json);
return GsonProvider.normal().toJson(json);
}
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.sql.SqlMessenger;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.sql.SqlDao;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MariaDbConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MySqlConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.sql.SqlStorage;
import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.MariaDbConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.MySqlConnectionFactory;
import org.checkerframework.checker.nullness.qual.NonNull;
@ -57,9 +57,9 @@ public class MessagingFactory<P extends LuckPermsPlugin> {
messagingType = "redis";
}
if (messagingType.equals("none") && this.plugin.getStorage().getDao() instanceof SqlDao) {
SqlDao dao = (SqlDao) this.plugin.getStorage().getDao();
if (dao.getProvider() instanceof MySqlConnectionFactory || dao.getProvider() instanceof MariaDbConnectionFactory) {
if (messagingType.equals("none") && this.plugin.getStorage().getImplementation() instanceof SqlStorage) {
SqlStorage dao = (SqlStorage) this.plugin.getStorage().getImplementation();
if (dao.getConnectionFactory() instanceof MySqlConnectionFactory || dao.getConnectionFactory() instanceof MariaDbConnectionFactory) {
messagingType = "sql";
}
}
@ -125,8 +125,8 @@ public class MessagingFactory<P extends LuckPermsPlugin> {
@Override
public @NonNull Messenger obtain(@NonNull IncomingMessageConsumer incomingMessageConsumer) {
SqlDao dao = (SqlDao) getPlugin().getStorage().getDao();
Preconditions.checkState(dao.getProvider() instanceof MySqlConnectionFactory || dao.getProvider() instanceof MariaDbConnectionFactory, "not a supported sql type");
SqlStorage dao = (SqlStorage) getPlugin().getStorage().getImplementation();
Preconditions.checkState(dao.getConnectionFactory() instanceof MySqlConnectionFactory || dao.getConnectionFactory() instanceof MariaDbConnectionFactory, "not a supported sql type");
SqlMessenger sql = new SqlMessenger(getPlugin(), dao, incomingMessageConsumer);
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.scheduler.SchedulerAdapter;
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.SQLException;
@ -37,15 +37,15 @@ import java.util.concurrent.TimeUnit;
public class SqlMessenger extends AbstractSqlMessenger {
private final LuckPermsPlugin plugin;
private final SqlDao sqlDao;
private final SqlStorage sqlStorage;
private SchedulerTask pollTask;
private SchedulerTask housekeepingTask;
public SqlMessenger(LuckPermsPlugin plugin, SqlDao sqlDao, IncomingMessageConsumer consumer) {
public SqlMessenger(LuckPermsPlugin plugin, SqlStorage sqlStorage, IncomingMessageConsumer consumer) {
super(consumer);
this.plugin = plugin;
this.sqlDao = sqlDao;
this.sqlStorage = sqlStorage;
}
@Override
@ -81,11 +81,11 @@ public class SqlMessenger extends AbstractSqlMessenger {
@Override
protected Connection getConnection() throws SQLException {
return this.sqlDao.getProvider().getConnection();
return this.sqlStorage.getConnectionFactory().getConnection();
}
@Override
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.StorageFactory;
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.treeview.PermissionRegistry;
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.sender.Sender;
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.treeview.PermissionRegistry;
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.model.User;
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.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;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.LogEntry;
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.Track;
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.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;
/**
* 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;
this.implementation = implementation;
this.apiDelegate = new ApiStorage(plugin, this);
}
String getName();
public StorageImplementation getImplementation() {
return this.implementation;
}
void init();
public ApiStorage getApiDelegate() {
return this.apiDelegate;
}
void shutdown();
private <T> CompletableFuture<T> makeFuture(Callable<T> supplier) {
return CompletableFuture.supplyAsync(() -> {
try {
return supplier.call();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new CompletionException(e);
}
}, this.plugin.getBootstrap().getScheduler().async());
}
Map<String, String> getMeta();
private CompletableFuture<Void> makeFuture(ThrowingRunnable runnable) {
return CompletableFuture.runAsync(() -> {
try {
runnable.run();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new CompletionException(e);
}
}, this.plugin.getBootstrap().getScheduler().async());
}
CompletableFuture<Void> logAction(LogEntry entry);
public String getName() {
return this.implementation.getImplementationName();
}
CompletableFuture<Log> getLog();
public void init() {
try {
this.implementation.init();
} catch (Exception e) {
this.plugin.getLogger().severe("Failed to init storage dao");
e.printStackTrace();
}
}
CompletableFuture<Void> applyBulkUpdate(BulkUpdate bulkUpdate);
public void shutdown() {
try {
this.implementation.shutdown();
} catch (Exception e) {
this.plugin.getLogger().severe("Failed to shutdown storage dao");
e.printStackTrace();
}
}
CompletableFuture<User> loadUser(UUID uuid, String username);
public Map<String, String> getMeta() {
return this.implementation.getMeta();
}
CompletableFuture<Void> saveUser(User user);
public CompletableFuture<Void> logAction(LogEntry entry) {
return makeFuture(() -> this.implementation.logAction(entry));
}
CompletableFuture<Set<UUID>> getUniqueUsers();
public CompletableFuture<Log> getLog() {
return makeFuture(this.implementation::getLog);
}
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(Constraint constraint);
public CompletableFuture<Void> applyBulkUpdate(BulkUpdate bulkUpdate) {
return makeFuture(() -> this.implementation.applyBulkUpdate(bulkUpdate));
}
CompletableFuture<Group> createAndLoadGroup(String name, CreationCause cause);
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;
});
}
CompletableFuture<Optional<Group>> loadGroup(String name);
public CompletableFuture<Void> saveUser(User user) {
return makeFuture(() -> this.implementation.saveUser(user));
}
CompletableFuture<Void> loadAllGroups();
public CompletableFuture<Set<UUID>> getUniqueUsers() {
return makeFuture(this.implementation::getUniqueUsers);
}
CompletableFuture<Void> saveGroup(Group group);
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);
});
}
CompletableFuture<Void> deleteGroup(Group group, DeletionCause cause);
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;
});
}
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(Constraint constraint);
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;
});
}
CompletableFuture<Track> createAndLoadTrack(String name, CreationCause cause);
public CompletableFuture<Void> loadAllGroups() {
return makeFuture(() -> {
this.implementation.loadAllGroups();
this.plugin.getEventFactory().handleGroupLoadAll();
});
}
CompletableFuture<Optional<Track>> loadTrack(String name);
public CompletableFuture<Void> saveGroup(Group group) {
return makeFuture(() -> this.implementation.saveGroup(group));
}
CompletableFuture<Void> loadAllTracks();
public CompletableFuture<Void> deleteGroup(Group group, DeletionCause cause) {
return makeFuture(() -> {
this.implementation.deleteGroup(group);
this.plugin.getEventFactory().handleGroupDelete(group, cause);
});
}
CompletableFuture<Void> saveTrack(Track track);
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);
});
}
CompletableFuture<Void> deleteTrack(Track track, DeletionCause cause);
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;
});
}
CompletableFuture<PlayerSaveResult> savePlayerData(UUID uuid, String username);
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;
});
}
CompletableFuture<UUID> getPlayerUuid(String username);
public CompletableFuture<Void> loadAllTracks() {
return makeFuture(() -> {
this.implementation.loadAllTracks();
this.plugin.getEventFactory().handleTrackLoadAll();
});
}
CompletableFuture<String> getPlayerName(UUID uuid);
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.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.dao.SplitStorageDao;
import me.lucko.luckperms.common.storage.dao.file.CombinedConfigurateDao;
import me.lucko.luckperms.common.storage.dao.file.SeparatedConfigurateDao;
import me.lucko.luckperms.common.storage.dao.file.loader.HoconLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.JsonLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.TomlLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.YamlLoader;
import me.lucko.luckperms.common.storage.dao.mongodb.MongoDao;
import me.lucko.luckperms.common.storage.dao.sql.SqlDao;
import me.lucko.luckperms.common.storage.dao.sql.connection.file.H2ConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.file.SQLiteConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MariaDbConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.MySqlConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.PostgreConnectionFactory;
import me.lucko.luckperms.common.storage.provider.StorageProviders;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.implementation.custom.CustomStorageProviders;
import me.lucko.luckperms.common.storage.implementation.file.CombinedConfigurateStorage;
import me.lucko.luckperms.common.storage.implementation.file.SeparatedConfigurateStorage;
import me.lucko.luckperms.common.storage.implementation.file.loader.HoconLoader;
import me.lucko.luckperms.common.storage.implementation.file.loader.JsonLoader;
import me.lucko.luckperms.common.storage.implementation.file.loader.TomlLoader;
import me.lucko.luckperms.common.storage.implementation.file.loader.YamlLoader;
import me.lucko.luckperms.common.storage.implementation.mongodb.MongoStorage;
import me.lucko.luckperms.common.storage.implementation.split.SplitStorage;
import me.lucko.luckperms.common.storage.implementation.split.SplitStorageType;
import me.lucko.luckperms.common.storage.implementation.sql.SqlStorage;
import me.lucko.luckperms.common.storage.implementation.sql.connection.file.H2ConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.sql.connection.file.SQLiteConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.sql.connection.hikari.MariaDbConnectionFactory;
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 java.util.Map;
@ -97,11 +98,12 @@ public class StorageFactory {
})
.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()
.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 {
String method = this.plugin.getConfiguration().get(ConfigKeys.STORAGE_METHOD);
@ -119,66 +121,67 @@ public class StorageFactory {
}
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) {
case CUSTOM:
return StorageProviders.getProvider().provide(this.plugin);
return CustomStorageProviders.getProvider().provide(this.plugin);
case MARIADB:
return new SqlDao(
return new SqlStorage(
this.plugin,
new MariaDbConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
);
case MYSQL:
return new SqlDao(
return new SqlStorage(
this.plugin,
new MySqlConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
);
case SQLITE:
return new SqlDao(
return new SqlStorage(
this.plugin,
new SQLiteConnectionFactory(this.plugin, this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-sqlite.db")),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
);
case H2:
return new SqlDao(
return new SqlStorage(
this.plugin,
new H2ConnectionFactory(this.plugin, this.plugin.getBootstrap().getDataDirectory().resolve("luckperms-h2")),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
);
case POSTGRESQL:
return new SqlDao(
return new SqlStorage(
this.plugin,
new PostgreConnectionFactory(this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES)),
this.plugin.getConfiguration().get(ConfigKeys.SQL_TABLE_PREFIX)
);
case MONGODB:
return new MongoDao(
return new MongoStorage(
this.plugin,
this.plugin.getConfiguration().get(ConfigKeys.DATABASE_VALUES),
this.plugin.getConfiguration().get(ConfigKeys.MONGODB_COLLECTION_PREFIX),
this.plugin.getConfiguration().get(ConfigKeys.MONGODB_CONNECTION_URI)
);
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:
return new SeparatedConfigurateDao(this.plugin, new JsonLoader(), "JSON", ".json", "json-storage");
return new SeparatedConfigurateStorage(this.plugin, "JSON", new JsonLoader(), ".json", "json-storage");
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:
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:
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:
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:
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:
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:
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.
*/
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.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
/**
* A storage provider
*/
@FunctionalInterface
public interface StorageProvider {
public interface CustomStorageProvider {
AbstractDao provide(LuckPermsPlugin plugin);
StorageImplementation provide(LuckPermsPlugin plugin);
}

View File

@ -23,19 +23,19 @@
* 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
*/
public final class StorageProviders {
private static StorageProvider provider = null;
public final class CustomStorageProviders {
private static CustomStorageProvider provider = null;
public static void register(StorageProvider provider) {
StorageProviders.provider = provider;
public static void register(CustomStorageProvider provider) {
CustomStorageProviders.provider = provider;
}
public static StorageProvider getProvider() {
public static CustomStorageProvider getProvider() {
if (provider == null) {
throw new IllegalStateException("Provider not present.");
}
@ -43,6 +43,6 @@ public final class StorageProviders {
return provider;
}
private StorageProviders() {}
private CustomStorageProviders() {}
}

View File

@ -23,7 +23,7 @@
* 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.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.utils.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.dao.file.loader.ConfigurateLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.JsonLoader;
import me.lucko.luckperms.common.storage.dao.file.loader.YamlLoader;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
import me.lucko.luckperms.common.storage.implementation.file.loader.JsonLoader;
import me.lucko.luckperms.common.storage.implementation.file.loader.YamlLoader;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
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
* 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
protected final ConfigurateLoader loader;
@ -95,13 +98,24 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
// the file used to store uuid data
private Path uuidDataFile;
protected AbstractConfigurateDao(LuckPermsPlugin plugin, ConfigurateLoader loader, String name, String dataDirectoryName) {
super(plugin, name);
protected AbstractConfigurateStorage(LuckPermsPlugin plugin, String implementationName, ConfigurateLoader loader, String dataDirectoryName) {
this.plugin = plugin;
this.implementationName = implementationName;
this.loader = loader;
this.dataDirectoryName = dataDirectoryName;
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
*
@ -217,7 +231,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
saveFile(StorageLocation.USER, user.getUuid().toString(), null);
} else {
ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) {
if (this instanceof SeparatedConfigurateStorage) {
data.getNode("uuid").setValue(user.getUuid().toString());
}
data.getNode("name").setValue(user.getName().orElse("null"));
@ -247,7 +261,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
group.setNodes(NodeMapType.ENDURING, nodes);
} else {
ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) {
if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(group.getName());
}
@ -304,7 +318,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
group.getIoLock().lock();
try {
ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) {
if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(group.getName());
}
@ -347,7 +361,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
track.setGroups(groups);
} else {
ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) {
if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(name);
}
data.getNode("groups").setValue(track.getGroups());
@ -402,7 +416,7 @@ public abstract class AbstractConfigurateDao extends AbstractDao {
track.getIoLock().lock();
try {
ConfigurationNode data = SimpleConfigurationNode.root();
if (this instanceof SeparatedConfigurateDao) {
if (this instanceof SeparatedConfigurateStorage) {
data.getNode("name").setValue(track.getName());
}
data.getNode("groups").setValue(track.getGroups());

View File

@ -23,7 +23,7 @@
* 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.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.NodeHeldPermission;
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.loader.ConfigurationLoader;
@ -49,7 +49,7 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class CombinedConfigurateDao extends AbstractConfigurateDao {
public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
private final String fileExtension;
private Path usersFile;
@ -69,13 +69,13 @@ public class CombinedConfigurateDao extends AbstractConfigurateDao {
private CachedLoader(Path path) {
this.path = path;
this.loader = CombinedConfigurateDao.super.loader.loader(path);
this.loader = CombinedConfigurateStorage.super.loader.loader(path);
reload();
}
private void recordChange() {
if (CombinedConfigurateDao.this.watcher != null) {
CombinedConfigurateDao.this.watcher.recordChange(this.path.getFileName().toString());
if (CombinedConfigurateStorage.this.watcher != null) {
CombinedConfigurateStorage.this.watcher.recordChange(this.path.getFileName().toString());
}
}
@ -145,14 +145,13 @@ public class CombinedConfigurateDao extends AbstractConfigurateDao {
/**
* Creates a new configurate dao
*
* @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 dataFolderName the name of the folder used to store data
*/
public CombinedConfigurateDao(LuckPermsPlugin plugin, ConfigurateLoader loader, String name, String fileExtension, String dataFolderName) {
super(plugin, loader, name, dataFolderName);
public CombinedConfigurateStorage(LuckPermsPlugin plugin, String implementationName, ConfigurateLoader loader, String fileExtension, String dataFolderName) {
super(plugin, implementationName, loader, dataFolderName);
this.fileExtension = fileExtension;
}

View File

@ -23,12 +23,10 @@
* 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.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
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.buffers.BufferedRequest;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@ -48,8 +47,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
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
@ -95,7 +92,7 @@ public class FileActionLogger {
if (Files.exists(this.contentFile)) {
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) {
e.printStackTrace();
array = new JsonArray();
@ -112,7 +109,7 @@ public class FileActionLogger {
// write the full content back to the file
try (JsonWriter writer = new JsonWriter(Files.newBufferedWriter(this.contentFile, StandardCharsets.UTF_8))) {
writer.setIndent(" ");
GSON.toJson(array, writer);
GsonProvider.normal().toJson(array, writer);
}
} catch (IOException e) {
e.printStackTrace();
@ -125,7 +122,7 @@ public class FileActionLogger {
public Log getLog() throws IOException {
Log.Builder log = Log.builder();
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) {
log.add(LogEntryJsonSerializer.deserialize(element));
}

View File

@ -23,7 +23,7 @@
* 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.collect.Iterables;
@ -31,7 +31,7 @@ import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
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 org.checkerframework.checker.nullness.qual.NonNull;

View File

@ -23,7 +23,7 @@
* 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.utils.Iterators;

View File

@ -23,7 +23,7 @@
* 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.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.NodeHeldPermission;
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.Uuids;
@ -51,7 +51,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class SeparatedConfigurateDao extends AbstractConfigurateDao {
public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
private final String fileExtension;
private Path usersDirectory;
@ -64,14 +64,13 @@ public class SeparatedConfigurateDao extends AbstractConfigurateDao {
/**
* Creates a new configurate dao
*
* @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 dataFolderName the name of the folder used to store data
*/
public SeparatedConfigurateDao(LuckPermsPlugin plugin, ConfigurateLoader loader, String name, String fileExtension, String dataFolderName) {
super(plugin, loader, name, dataFolderName);
public SeparatedConfigurateStorage(LuckPermsPlugin plugin, String implementationName, ConfigurateLoader loader, String fileExtension, String dataFolderName) {
super(plugin, implementationName, loader, dataFolderName);
this.fileExtension = fileExtension;
}

View File

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

View File

@ -23,7 +23,7 @@
* 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.loader.ConfigurationLoader;

View File

@ -23,7 +23,7 @@
* 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.hocon.HoconConfigurationLoader;

View File

@ -23,7 +23,7 @@
* 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.gson.GsonConfigurationLoader;

View File

@ -23,7 +23,7 @@
* 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.loader.ConfigurationLoader;

View File

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

View File

@ -23,7 +23,7 @@
* 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.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.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.PlayerSaveResultImpl;
import me.lucko.luckperms.common.storage.StorageCredentials;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import org.bson.Document;
@ -77,7 +77,8 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class MongoDao extends AbstractDao {
public class MongoStorage implements StorageImplementation {
private final LuckPermsPlugin plugin;
private final StorageCredentials configuration;
private MongoClient mongoClient;
@ -85,13 +86,23 @@ public class MongoDao extends AbstractDao {
private final String prefix;
private final String connectionUri;
public MongoDao(LuckPermsPlugin plugin, StorageCredentials configuration, String prefix, String connectionUri) {
super(plugin, "MongoDB");
public MongoStorage(LuckPermsPlugin plugin, StorageCredentials configuration, String prefix, String connectionUri) {
this.plugin = plugin;
this.configuration = configuration;
this.prefix = prefix;
this.connectionUri = connectionUri;
}
@Override
public LuckPermsPlugin getPlugin() {
return this.plugin;
}
@Override
public String getImplementationName() {
return "MongoDB";
}
@Override
public void init() {
if (!Strings.isNullOrEmpty(this.connectionUri)) {
@ -215,7 +226,7 @@ public class MongoDao extends AbstractDao {
if (!nodes.equals(results)) {
List<Document> newNodes = results.stream()
.map(MongoDao::nodeToDoc)
.map(MongoStorage::nodeToDoc)
.collect(Collectors.toList());
d.append("permissions", newNodes).remove("perms");
@ -240,7 +251,7 @@ public class MongoDao extends AbstractDao {
if (!nodes.equals(results)) {
List<Document> newNodes = results.stream()
.map(MongoDao::nodeToDoc)
.map(MongoStorage::nodeToDoc)
.collect(Collectors.toList());
d.append("permissions", newNodes).remove("perms");
@ -628,7 +639,7 @@ public class MongoDao extends AbstractDao {
private static Document userToDoc(User user) {
List<Document> nodes = user.enduringData().immutable().values().stream()
.map(NodeDataContainer::fromNode)
.map(MongoDao::nodeToDoc)
.map(MongoStorage::nodeToDoc)
.collect(Collectors.toList());
return new Document("_id", user.getUuid())
@ -666,7 +677,7 @@ public class MongoDao extends AbstractDao {
private static Document groupToDoc(Group group) {
List<Document> nodes = group.enduringData().immutable().values().stream()
.map(NodeDataContainer::fromNode)
.map(MongoDao::nodeToDoc)
.map(MongoStorage::nodeToDoc)
.collect(Collectors.toList());
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) contributors
@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage.dao;
package me.lucko.luckperms.common.storage.implementation.split;
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.User;
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.implementation.StorageImplementation;
import java.util.LinkedHashMap;
import java.util.List;
@ -47,20 +47,31 @@ import java.util.Optional;
import java.util.Set;
import java.util.UUID;
public class SplitStorageDao extends AbstractDao {
private final Map<StorageType, AbstractDao> backing;
public class SplitStorage implements StorageImplementation {
private final LuckPermsPlugin plugin;
private final Map<StorageType, StorageImplementation> backing;
private final Map<SplitStorageType, StorageType> types;
public SplitStorageDao(LuckPermsPlugin plugin, Map<StorageType, AbstractDao> backing, Map<SplitStorageType, StorageType> types) {
super(plugin, "Split Storage");
public SplitStorage(LuckPermsPlugin plugin, Map<StorageType, StorageImplementation> backing, Map<SplitStorageType, StorageType> types) {
this.plugin = plugin;
this.backing = ImmutableMap.copyOf(backing);
this.types = ImmutableMap.copyOf(types);
}
@Override
public LuckPermsPlugin getPlugin() {
return this.plugin;
}
@Override
public String getImplementationName() {
return "Split Storage";
}
@Override
public void init() {
boolean failed = false;
for (AbstractDao ds : this.backing.values()) {
for (StorageImplementation ds : this.backing.values()) {
try {
ds.init();
} catch (Exception ex) {
@ -75,7 +86,7 @@ public class SplitStorageDao extends AbstractDao {
@Override
public void shutdown() {
for (AbstractDao ds : this.backing.values()) {
for (StorageImplementation ds : this.backing.values()) {
try {
ds.shutdown();
} catch (Exception e) {
@ -88,7 +99,7 @@ public class SplitStorageDao extends AbstractDao {
public Map<String, String> getMeta() {
Map<String, String> ret = new LinkedHashMap<>();
ret.put("Types", this.types.toString());
for (AbstractDao backing : this.backing.values()) {
for (StorageImplementation backing : this.backing.values()) {
ret.putAll(backing.getMeta());
}
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) contributors
@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage;
package me.lucko.luckperms.common.storage.implementation.split;
public enum SplitStorageType {
LOG, USER, GROUP, TRACK, UUID

View File

@ -23,10 +23,9 @@
* 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.gson.Gson;
import com.google.gson.reflect.TypeToken;
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.NodeHeldPermission;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.PlayerSaveResultImpl;
import me.lucko.luckperms.common.storage.dao.AbstractDao;
import me.lucko.luckperms.common.storage.dao.sql.connection.AbstractConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.file.SQLiteConnectionFactory;
import me.lucko.luckperms.common.storage.dao.sql.connection.hikari.PostgreConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.sql.connection.file.SQLiteConnectionFactory;
import me.lucko.luckperms.common.storage.implementation.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.InputStream;
@ -76,7 +76,7 @@ import java.util.UUID;
import java.util.function.Function;
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 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_SELECT_ALL = "SELECT * FROM {prefix}actions";
private final Gson gson;
private final AbstractConnectionFactory provider;
private final LuckPermsPlugin plugin;
private final ConnectionFactory connectionFactory;
private final Function<String, String> statementProcessor;
public SqlDao(LuckPermsPlugin plugin, AbstractConnectionFactory provider, String tablePrefix) {
super(plugin, provider.getName());
this.provider = provider;
this.statementProcessor = provider.getStatementProcessor().compose(s -> s.replace("{prefix}", tablePrefix));
this.gson = new Gson();
public SqlStorage(LuckPermsPlugin plugin, ConnectionFactory connectionFactory, String tablePrefix) {
this.plugin = plugin;
this.connectionFactory = connectionFactory;
this.statementProcessor = connectionFactory.getStatementProcessor().compose(s -> s.replace("{prefix}", tablePrefix));
}
public Gson getGson() {
return this.gson;
@Override
public LuckPermsPlugin getPlugin() {
return this.plugin;
}
public AbstractConnectionFactory getProvider() {
return this.provider;
@Override
public String getImplementationName() {
return this.connectionFactory.getImplementationName();
}
public ConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
public Function<String, String> getStatementProcessor() {
@ -142,7 +148,7 @@ public class SqlDao extends AbstractDao {
}
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)) {
while (rs.next()) {
if (rs.getString(3).equalsIgnoreCase(table)) {
@ -156,18 +162,18 @@ public class SqlDao extends AbstractDao {
@Override
public void init() throws Exception {
this.provider.init();
this.connectionFactory.init();
// Init tables
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)) {
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 (Connection connection = this.provider.getConnection()) {
try (Connection connection = this.connectionFactory.getConnection()) {
try (Statement s = connection.createStatement()) {
StringBuilder sb = new StringBuilder();
String line;
@ -196,8 +202,8 @@ public class SqlDao extends AbstractDao {
// migrations
try {
if (!(this.provider instanceof SQLiteConnectionFactory) && !(this.provider instanceof PostgreConnectionFactory)) {
try (Connection connection = this.provider.getConnection()) {
if (!(this.connectionFactory instanceof SQLiteConnectionFactory) && !(this.connectionFactory instanceof PostgreConnectionFactory)) {
try (Connection connection = this.connectionFactory.getConnection()) {
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 action VARCHAR(300)"));
@ -212,7 +218,7 @@ public class SqlDao extends AbstractDao {
@Override
public void shutdown() {
try {
this.provider.shutdown();
this.connectionFactory.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
@ -220,12 +226,12 @@ public class SqlDao extends AbstractDao {
@Override
public Map<String, String> getMeta() {
return this.provider.getMeta();
return this.connectionFactory.getMeta();
}
@Override
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))) {
ps.setLong(1, entry.getTimestamp());
ps.setString(2, entry.getActor().toString());
@ -242,7 +248,7 @@ public class SqlDao extends AbstractDao {
@Override
public Log getLog() throws SQLException {
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 (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@ -267,7 +273,7 @@ public class SqlDao extends AbstractDao {
@Override
public void applyBulkUpdate(BulkUpdate bulkUpdate) throws SQLException {
try (Connection c = this.provider.getConnection()) {
try (Connection c = this.connectionFactory.getConnection()) {
if (bulkUpdate.getDataType().isIncludingUsers()) {
String table = this.statementProcessor.apply("{prefix}user_permissions");
try (PreparedStatement ps = bulkUpdate.buildAsSql().build(c, q -> q.replace("{table}", table))) {
@ -294,7 +300,7 @@ public class SqlDao extends AbstractDao {
String userName = null;
// 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))) {
ps.setString(1, user.getUuid().toString());
@ -313,7 +319,7 @@ public class SqlDao extends AbstractDao {
}
// 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))) {
ps.setString(1, user.getUuid().toString());
@ -367,7 +373,7 @@ public class SqlDao extends AbstractDao {
try {
// Empty data - just delete from the DB.
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))) {
ps.setString(1, user.getUuid().toString());
ps.execute();
@ -383,7 +389,7 @@ public class SqlDao extends AbstractDao {
// Get a snapshot of current data.
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))) {
ps.setString(1, user.getUuid().toString());
@ -409,7 +415,7 @@ public class SqlDao extends AbstractDao {
Set<NodeDataContainer> toRemove = diff.getValue();
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))) {
for (NodeDataContainer nd : toRemove) {
ps.setString(1, user.getUuid().toString());
@ -418,7 +424,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld());
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.executeBatch();
@ -427,7 +433,7 @@ public class SqlDao extends AbstractDao {
}
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))) {
for (NodeDataContainer nd : toAdd) {
ps.setString(1, user.getUuid().toString());
@ -436,7 +442,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld());
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.executeBatch();
@ -444,7 +450,7 @@ public class SqlDao extends AbstractDao {
}
}
try (Connection c = this.provider.getConnection()) {
try (Connection c = this.connectionFactory.getConnection()) {
boolean hasPrimaryGroupSaved;
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_PRIMARY_GROUP_BY_UUID))) {
@ -480,7 +486,7 @@ public class SqlDao extends AbstractDao {
@Override
public Set<UUID> getUniqueUsers() throws SQLException {
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 (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@ -499,7 +505,7 @@ public class SqlDao extends AbstractDao {
constraint.appendSql(builder, "permission");
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 (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@ -523,7 +529,7 @@ public class SqlDao extends AbstractDao {
@Override
public Group createAndLoadGroup(String name) throws SQLException {
String query;
switch (this.provider.getName()) {
switch (this.connectionFactory.getImplementationName()) {
case "H2":
query = H2_GROUP_INSERT;
break;
@ -538,7 +544,7 @@ public class SqlDao extends AbstractDao {
break;
}
try (Connection c = this.provider.getConnection()) {
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(query))) {
ps.setString(1, name);
ps.execute();
@ -552,7 +558,7 @@ public class SqlDao extends AbstractDao {
public Optional<Group> loadGroup(String name) throws SQLException {
// Check the group actually exists
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 (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@ -572,7 +578,7 @@ public class SqlDao extends AbstractDao {
try {
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))) {
ps.setString(1, group.getName());
@ -606,7 +612,7 @@ public class SqlDao extends AbstractDao {
@Override
public void loadAllGroups() throws SQLException {
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 (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@ -642,7 +648,7 @@ public class SqlDao extends AbstractDao {
try {
// Empty data, just delete.
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))) {
ps.setString(1, group.getName());
ps.execute();
@ -653,7 +659,7 @@ public class SqlDao extends AbstractDao {
// Get a snapshot of current data
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))) {
ps.setString(1, group.getName());
@ -679,7 +685,7 @@ public class SqlDao extends AbstractDao {
Set<NodeDataContainer> toRemove = diff.getValue();
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))) {
for (NodeDataContainer nd : toRemove) {
ps.setString(1, group.getName());
@ -688,7 +694,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld());
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.executeBatch();
@ -697,7 +703,7 @@ public class SqlDao extends AbstractDao {
}
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))) {
for (NodeDataContainer nd : toAdd) {
ps.setString(1, group.getName());
@ -706,7 +712,7 @@ public class SqlDao extends AbstractDao {
ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld());
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.executeBatch();
@ -722,7 +728,7 @@ public class SqlDao extends AbstractDao {
public void deleteGroup(Group group) throws SQLException {
group.getIoLock().lock();
try {
try (Connection c = this.provider.getConnection()) {
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(GROUP_PERMISSIONS_DELETE))) {
ps.setString(1, group.getName());
ps.execute();
@ -746,7 +752,7 @@ public class SqlDao extends AbstractDao {
constraint.appendSql(builder, "permission");
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 (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@ -774,7 +780,7 @@ public class SqlDao extends AbstractDao {
try {
boolean exists = false;
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))) {
ps.setString(1, track.getName());
try (ResultSet rs = ps.executeQuery()) {
@ -788,10 +794,10 @@ public class SqlDao extends AbstractDao {
if (exists) {
// Track exists, let's load.
track.setGroups(this.gson.fromJson(groups, LIST_STRING_TYPE));
track.setGroups(GsonProvider.normal().fromJson(groups, LIST_STRING_TYPE));
} else {
String json = this.gson.toJson(track.getGroups());
try (Connection c = this.provider.getConnection()) {
String json = GsonProvider.normal().toJson(track.getGroups());
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_INSERT))) {
ps.setString(1, track.getName());
ps.setString(2, json);
@ -813,7 +819,7 @@ public class SqlDao extends AbstractDao {
}
try {
String groups;
try (Connection c = this.provider.getConnection()) {
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_SELECT))) {
ps.setString(1, name);
try (ResultSet rs = ps.executeQuery()) {
@ -831,7 +837,7 @@ public class SqlDao extends AbstractDao {
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);
} finally {
@ -844,7 +850,7 @@ public class SqlDao extends AbstractDao {
@Override
public void loadAllTracks() throws SQLException {
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 (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@ -878,8 +884,8 @@ public class SqlDao extends AbstractDao {
public void saveTrack(Track track) throws SQLException {
track.getIoLock().lock();
try {
String s = this.gson.toJson(track.getGroups());
try (Connection c = this.provider.getConnection()) {
String s = GsonProvider.normal().toJson(track.getGroups());
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_UPDATE))) {
ps.setString(1, s);
ps.setString(2, track.getName());
@ -895,7 +901,7 @@ public class SqlDao extends AbstractDao {
public void deleteTrack(Track track) throws SQLException {
track.getIoLock().lock();
try {
try (Connection c = this.provider.getConnection()) {
try (Connection c = this.connectionFactory.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(TRACK_DELETE))) {
ps.setString(1, track.getName());
ps.execute();
@ -917,7 +923,7 @@ public class SqlDao extends AbstractDao {
// do the insert
if (!username.equals(oldUsername)) {
try (Connection c = this.provider.getConnection()) {
try (Connection c = this.connectionFactory.getConnection()) {
if (oldUsername != null) {
try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_UPDATE_USERNAME_FOR_UUID))) {
ps.setString(1, username);
@ -938,7 +944,7 @@ public class SqlDao extends AbstractDao {
PlayerSaveResultImpl result = PlayerSaveResultImpl.determineBaseResult(username, oldUsername);
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))) {
ps.setString(1, username);
ps.setString(2, uuid.toString());
@ -952,7 +958,7 @@ public class SqlDao extends AbstractDao {
if (!conflicting.isEmpty()) {
// 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))) {
ps.setString(1, username);
ps.setString(2, uuid.toString());
@ -968,7 +974,7 @@ public class SqlDao extends AbstractDao {
@Override
public UUID getPlayerUuid(String username) throws SQLException {
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))) {
ps.setString(1, username);
try (ResultSet rs = ps.executeQuery()) {
@ -983,7 +989,7 @@ public class SqlDao extends AbstractDao {
@Override
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))) {
ps.setString(1, uuid.toString());
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) {
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.
*/
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.SQLException;
@ -31,28 +31,20 @@ import java.util.Collections;
import java.util.Map;
import java.util.function.Function;
public abstract class AbstractConnectionFactory {
public interface ConnectionFactory {
private final String name;
String getImplementationName();
public AbstractConnectionFactory(String name) {
this.name = name;
}
void init();
public String getName() {
return this.name;
}
void shutdown() throws Exception;
public abstract void init();
public abstract void shutdown() throws Exception;
public Map<String, String> getMeta() {
default Map<String, String> getMeta() {
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.
*/
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.nio.file.Files;
@ -34,13 +34,12 @@ import java.text.DecimalFormat;
import java.util.LinkedHashMap;
import java.util.Map;
abstract class FlatfileConnectionFactory extends AbstractConnectionFactory {
abstract class FlatfileConnectionFactory implements ConnectionFactory {
protected static final DecimalFormat DF = new DecimalFormat("#.##");
protected final Path file;
FlatfileConnectionFactory(String name, Path file) {
super(name);
FlatfileConnectionFactory(Path file) {
this.file = file;
}

View File

@ -23,7 +23,7 @@
* 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.classloader.IsolatedClassLoader;
@ -49,7 +49,7 @@ public class H2ConnectionFactory extends FlatfileConnectionFactory {
private NonClosableConnection connection;
public H2ConnectionFactory(LuckPermsPlugin plugin, Path file) {
super("H2", file);
super(file);
// backwards compat
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
public synchronized Connection getConnection() throws SQLException {
if (this.connection == null || this.connection.isClosed()) {

View File

@ -23,8 +23,10 @@
* 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.sql.Connection;
@ -43,22 +45,7 @@ public interface NonClosableConnection extends Connection {
return (NonClosableConnection) Proxy.newProxyInstance(
NonClosableConnection.class.getClassLoader(),
new Class[]{NonClosableConnection.class},
(proxy, method, args) -> {
// 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);
}
new Handler(connection)
);
}
@ -66,4 +53,29 @@ public interface NonClosableConnection extends Connection {
* Actually {@link #close() closes} the underlying connection.
*/
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.
*/
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.classloader.IsolatedClassLoader;
@ -48,7 +48,7 @@ public class SQLiteConnectionFactory extends FlatfileConnectionFactory {
private NonClosableConnection connection;
public SQLiteConnectionFactory(LuckPermsPlugin plugin, Path file) {
super("SQLite", file);
super(file);
// backwards compat
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 {
try {
return (Connection) this.createConnectionMethod.invoke(null, url, new Properties());

View File

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

View File

@ -23,11 +23,11 @@
* 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 me.lucko.luckperms.common.storage.StorageCredentials;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.util.Map;
import java.util.Set;
@ -36,7 +36,12 @@ import java.util.stream.Collectors;
public class MariaDbConnectionFactory extends HikariConnectionFactory {
public MariaDbConnectionFactory(StorageCredentials configuration) {
super("MariaDB", configuration);
super(configuration);
}
@Override
public String getImplementationName() {
return "MariaDB";
}
@Override

View File

@ -23,17 +23,22 @@
* 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 me.lucko.luckperms.common.storage.StorageCredentials;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.util.function.Function;
public class MySqlConnectionFactory extends HikariConnectionFactory {
public MySqlConnectionFactory(StorageCredentials configuration) {
super("MySQL", configuration);
super(configuration);
}
@Override
public String getImplementationName() {
return "MySQL";
}
@Override

View File

@ -23,17 +23,22 @@
* 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 me.lucko.luckperms.common.storage.StorageCredentials;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.util.function.Function;
public class PostgreConnectionFactory extends HikariConnectionFactory {
public PostgreConnectionFactory(StorageCredentials configuration) {
super("PostgreSQL", configuration);
super(configuration);
}
@Override
public String getImplementationName() {
return "PostgreSQL";
}
@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) contributors
@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage;
package me.lucko.luckperms.common.storage.misc;
import java.util.function.Predicate;
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) contributors
@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage;
package me.lucko.luckperms.common.storage.misc;
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) contributors
@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage;
package me.lucko.luckperms.common.storage.misc;
import java.util.Map;
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.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 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
*/
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;
/**

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;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import me.lucko.luckperms.common.utils.gson.GsonProvider;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
@ -60,7 +60,7 @@ public enum StandardPastebin implements Pastebin {
@Override
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();
}
@ -82,7 +82,7 @@ public enum StandardPastebin implements Pastebin {
@Override
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();
}
@ -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 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)) {
GSON.toJson(content, writer);
GsonProvider.prettyPrinting().toJson(content, writer);
} catch (IOException e) {
throw new RuntimeException(e);
}

View File

@ -26,7 +26,6 @@
package me.lucko.luckperms.common.web;
import com.google.common.base.Preconditions;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
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.sender.Sender;
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.JObject;
@ -63,8 +63,6 @@ import java.util.stream.Stream;
* Utility methods for interacting with the LuckPerms web permission editor.
*/
public final class WebEditor {
private static final Gson GSON = new Gson();
private static final String USER_ID_PATTERN = "user/";
private static final String GROUP_ID_PATTERN = "group/";
@ -159,7 +157,7 @@ public final class WebEditor {
try (InputStream inputStream = responseBody.byteStream()) {
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.StandardComparison;
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.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.model.SpongeGroup;

View File

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