Add logging, prepare for import/export system
This commit is contained in:
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public abstract class Datastore {
|
||||
protected final LuckPermsPlugin plugin;
|
||||
|
||||
@Getter
|
||||
public final String name;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean acceptingLogins = false;
|
||||
|
||||
/**
|
||||
* Execute a runnable asynchronously
|
||||
* @param r the task to run
|
||||
*/
|
||||
private void doAsync(Runnable r) {
|
||||
plugin.doAsync(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a runnable synchronously
|
||||
* @param r the task to run
|
||||
*/
|
||||
private void doSync(Runnable r) {
|
||||
plugin.doSync(r);
|
||||
}
|
||||
|
||||
private <T> void runCallback(T t, Callback<T> callback) {
|
||||
doSync(() -> callback.onComplete(t));
|
||||
}
|
||||
|
||||
/*
|
||||
These methods are called immediately and in the same thread as they are called in.
|
||||
*/
|
||||
public abstract void init();
|
||||
public abstract void shutdown();
|
||||
public abstract boolean loadOrCreateUser(UUID uuid, String username);
|
||||
public abstract boolean loadUser(UUID uuid);
|
||||
public abstract boolean saveUser(User user);
|
||||
public abstract boolean createAndLoadGroup(String name);
|
||||
public abstract boolean loadGroup(String name);
|
||||
public abstract boolean loadAllGroups();
|
||||
public abstract boolean saveGroup(Group group);
|
||||
public abstract boolean deleteGroup(Group group);
|
||||
public abstract boolean createAndLoadTrack(String name);
|
||||
public abstract boolean loadTrack(String name);
|
||||
public abstract boolean loadAllTracks();
|
||||
public abstract boolean saveTrack(Track track);
|
||||
public abstract boolean deleteTrack(Track track);
|
||||
public abstract boolean saveUUIDData(String username, UUID uuid);
|
||||
public abstract UUID getUUID(String username);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
These methods will schedule the operation to run async. The callback will be ran when the task is complete.
|
||||
Callbacks are ran on the main Bukkit server thread (if applicable)
|
||||
*/
|
||||
public void loadOrCreateUser(UUID uuid, String username, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(loadOrCreateUser(uuid, username), callback));
|
||||
}
|
||||
|
||||
public void loadUser(UUID uuid, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(loadUser(uuid), callback));
|
||||
}
|
||||
|
||||
public void saveUser(User user, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(saveUser(user), callback));
|
||||
}
|
||||
|
||||
public void createAndLoadGroup(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(createAndLoadGroup(name), callback));
|
||||
}
|
||||
|
||||
public void loadGroup(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(loadGroup(name), callback));
|
||||
}
|
||||
|
||||
public void loadAllGroups(Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(loadAllGroups(), callback));
|
||||
}
|
||||
|
||||
public void saveGroup(Group group, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(saveGroup(group), callback));
|
||||
}
|
||||
|
||||
public void deleteGroup(Group group, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(deleteGroup(group), callback));
|
||||
}
|
||||
|
||||
public void createAndLoadTrack(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(createAndLoadTrack(name), callback));
|
||||
}
|
||||
|
||||
public void loadTrack(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(loadTrack(name), callback));
|
||||
}
|
||||
|
||||
public void loadAllTracks(Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(loadAllTracks(), callback));
|
||||
}
|
||||
|
||||
public void saveTrack(Track track, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(saveTrack(track), callback));
|
||||
}
|
||||
|
||||
public void deleteTrack(Track track, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(deleteTrack(track), callback));
|
||||
}
|
||||
|
||||
public void saveUUIDData(String username, UUID uuid, Callback<Boolean> callback) {
|
||||
doAsync(() -> runCallback(saveUUIDData(username, uuid), callback));
|
||||
}
|
||||
|
||||
public void getUUID(String username, Callback<UUID> callback) {
|
||||
doAsync(() -> runCallback(getUUID(username), callback));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.Util;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Executes a list of commands sequentially in a single thread.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class Importer { // TODO: implement this
|
||||
|
||||
@Getter
|
||||
private boolean running = false;
|
||||
|
||||
private final CommandManager commandManager;
|
||||
|
||||
private Sender executor = null;
|
||||
private List<String> commands = null;
|
||||
private Map<Integer, Result> cmdResult = null;
|
||||
|
||||
private long lastMsg = 0;
|
||||
private int executing = -1;
|
||||
|
||||
public synchronized void start(Sender executor, List<String> commands) {
|
||||
if (isRunning()) {
|
||||
throw new IllegalStateException("Import already running.");
|
||||
}
|
||||
|
||||
running = true;
|
||||
this.executor = executor;
|
||||
this.commands = commands.stream()
|
||||
.map(s -> s.startsWith("/") ? s.substring(1) : s)
|
||||
.map(s -> s.startsWith("perms ") ? s.substring(5) : s)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
cmdResult = new HashMap<>();
|
||||
|
||||
run();
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
executor = null;
|
||||
commands = null;
|
||||
cmdResult = null;
|
||||
lastMsg = 0;
|
||||
executing = -1;
|
||||
running = false;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Message.IMPORT_START.send(executor);
|
||||
final Sender fake = new FakeSender(this);
|
||||
|
||||
int index = 0;
|
||||
for (String command : commands) {
|
||||
if (lastMsg < (System.currentTimeMillis() / 1000) - 5) {
|
||||
lastMsg = System.currentTimeMillis() / 1000;
|
||||
|
||||
sendProgress(index);
|
||||
}
|
||||
|
||||
executing = index;
|
||||
try {
|
||||
CommandResult result = commandManager.onCommand(fake, "perms", Arrays.asList(Patterns.SPACE.split(command)));
|
||||
getResult(index).setResult(result);
|
||||
|
||||
} catch (Exception e) {
|
||||
getResult(index).setResult(CommandResult.FAILURE);
|
||||
e.printStackTrace();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
double seconds = (endTime - startTime) / 1000.0;
|
||||
|
||||
int errors = 0;
|
||||
for (Map.Entry<Integer, Result> e : cmdResult.entrySet()) {
|
||||
if (e.getValue().getResult() != null && !e.getValue().getResult().booleanValue()) {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors == 0) {
|
||||
Message.IMPORT_END_COMPLETE.send(executor, seconds);
|
||||
} else if (errors == 1) {
|
||||
Message.IMPORT_END_COMPLETE_ERR_SIN.send(executor, seconds, errors);
|
||||
} else {
|
||||
Message.IMPORT_END_COMPLETE_ERR.send(executor, seconds, errors);
|
||||
}
|
||||
|
||||
int errIndex = 1;
|
||||
for (Map.Entry<Integer, Result> e : cmdResult.entrySet()) {
|
||||
if (e.getValue().getResult() != null && !e.getValue().getResult().booleanValue()) {
|
||||
Message.IMPORT_END_ERROR_HEADER.send(executor, errIndex, e.getKey());
|
||||
for (String s : e.getValue().getOutput()) {
|
||||
Message.IMPORT_END_ERROR_CONTENT.send(executor, s);
|
||||
}
|
||||
Message.IMPORT_END_ERROR_FOOTER.send(executor);
|
||||
errIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private void sendProgress(int executing) {
|
||||
int percent = (executing / commands.size()) * 100;
|
||||
int errors = 0;
|
||||
|
||||
for (Map.Entry<Integer, Result> e : cmdResult.entrySet()) {
|
||||
if (e.getValue().getResult() != null && !e.getValue().getResult().booleanValue()) {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors == 1) {
|
||||
Message.IMPORT_PROGRESS_SIN.send(executor, percent, executing, commands.size(), errors);
|
||||
} else {
|
||||
Message.IMPORT_PROGRESS.send(executor, percent, executing, commands.size(), errors);
|
||||
}
|
||||
}
|
||||
|
||||
private Result getResult(int executing) {
|
||||
if (!cmdResult.containsKey(executing)) {
|
||||
cmdResult.put(executing, new Result());
|
||||
}
|
||||
|
||||
return cmdResult.get(executing);
|
||||
}
|
||||
|
||||
private void logMessage(String msg) {
|
||||
getResult(executing).getOutput().add(Util.stripColor(msg));
|
||||
}
|
||||
|
||||
private static class FakeSender implements Sender {
|
||||
private final Importer instance;
|
||||
|
||||
public FakeSender(Importer instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return Constants.getImporterName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return Constants.getImporterUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String s) {
|
||||
instance.logMessage(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission permission) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Result {
|
||||
|
||||
@Getter
|
||||
private final List<String> output = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private CommandResult result = CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Log {
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private static final int PAGE_ENTRIES = 5;
|
||||
|
||||
@Getter
|
||||
private final SortedSet<LogEntry> content;
|
||||
|
||||
public Log(SortedSet<LogEntry> content) {
|
||||
this.content = ImmutableSortedSet.copyOf(content);
|
||||
}
|
||||
|
||||
public SortedSet<LogEntry> getRecent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public SortedMap<Integer, LogEntry> getRecent(int pageNo) {
|
||||
return getPage(content, pageNo, PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public int getRecentMaxPages() {
|
||||
return getMaxPages(content.size(), PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public SortedSet<LogEntry> getRecent(UUID actor) {
|
||||
return content.stream()
|
||||
.filter(e -> e.getActor().equals(actor))
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
public SortedMap<Integer, LogEntry> getRecent(int pageNo, UUID actor) {
|
||||
return getPage(getRecent(actor), pageNo, PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public int getRecentMaxPages(UUID actor) {
|
||||
return getMaxPages(content.stream()
|
||||
.filter(e -> e.getActor().equals(actor))
|
||||
.count(), PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public SortedSet<LogEntry> getUserHistory(UUID uuid) {
|
||||
return content.stream()
|
||||
.filter(e -> e.getType() == 'U')
|
||||
.filter(e -> e.getActed().equals(uuid))
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
public SortedMap<Integer, LogEntry> getUserHistory(int pageNo, UUID uuid) {
|
||||
return getPage(getUserHistory(uuid), pageNo, PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public int getUserHistoryMaxPages(UUID uuid) {
|
||||
return getMaxPages(content.stream()
|
||||
.filter(e -> e.getType() == 'U')
|
||||
.filter(e -> e.getActed().equals(uuid))
|
||||
.count(), PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public SortedSet<LogEntry> getGroupHistory(String name) {
|
||||
return content.stream()
|
||||
.filter(e -> e.getType() == 'G')
|
||||
.filter(e -> e.getActedName().equals(name))
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
public SortedMap<Integer, LogEntry> getGroupHistory(int pageNo, String name) {
|
||||
return getPage(getGroupHistory(name), pageNo, PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public int getGroupHistoryMaxPages(String name) {
|
||||
return getMaxPages(content.stream()
|
||||
.filter(e -> e.getType() == 'G')
|
||||
.filter(e -> e.getActedName().equals(name))
|
||||
.count(), PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public SortedSet<LogEntry> getTrackHistory(String name) {
|
||||
return content.stream()
|
||||
.filter(e -> e.getType() == 'T')
|
||||
.filter(e -> e.getActedName().equals(name))
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
public SortedMap<Integer, LogEntry> getTrackHistory(int pageNo, String name) {
|
||||
return getPage(getTrackHistory(name), pageNo, PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public int getTrackHistoryMaxPages(String name) {
|
||||
return getMaxPages(content.stream()
|
||||
.filter(e -> e.getType() == 'T')
|
||||
.filter(e -> e.getActedName().equals(name))
|
||||
.count(), PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public SortedSet<LogEntry> getSearch(String query) {
|
||||
return content.stream()
|
||||
.filter(e -> e.matchesSearch(query))
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
public SortedMap<Integer, LogEntry> getSearch(int pageNo, String query) {
|
||||
return getPage(getSearch(query), pageNo, PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
public int getSearchMaxPages(String query) {
|
||||
return getMaxPages(content.stream()
|
||||
.filter(e -> e.matchesSearch(query))
|
||||
.count(), PAGE_ENTRIES);
|
||||
}
|
||||
|
||||
private static SortedMap<Integer, LogEntry> getPage(Set<LogEntry> set, int pageNo, int entries) {
|
||||
if (pageNo < 1) {
|
||||
throw new IllegalArgumentException("pageNo cannot be less than 1: " + pageNo);
|
||||
}
|
||||
|
||||
int minimumEntries = ((pageNo * 5) - entries) + 1;
|
||||
if (set.size() < minimumEntries) {
|
||||
throw new IllegalStateException("Log does not contain that many entries. " +
|
||||
"Requested: " + minimumEntries + ", Log Count: " + set.size());
|
||||
}
|
||||
|
||||
final SortedMap<Integer, LogEntry> out = new TreeMap<>();
|
||||
|
||||
final int max = minimumEntries + entries - 1;
|
||||
int index = 0;
|
||||
for (LogEntry e : set) {
|
||||
index++;
|
||||
if (index >= minimumEntries) {
|
||||
out.put(index, e);
|
||||
}
|
||||
if (index == max) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private static int getMaxPages(int size, int entries) {
|
||||
return (int) Math.ceil((double) size / entries);
|
||||
}
|
||||
|
||||
private static int getMaxPages(long size, int entries) {
|
||||
return (int) Math.ceil((double) size / entries);
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static class Builder {
|
||||
private final SortedSet<LogEntry> content = new TreeSet<>();
|
||||
|
||||
public Builder add(LogEntry e) {
|
||||
content.add(e);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Log build() {
|
||||
return new Log(content);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LogEntryBuilder {
|
||||
private long timestamp = 0L;
|
||||
private UUID actor = null;
|
||||
private String actorName = null;
|
||||
private char type = Character.MIN_VALUE;
|
||||
private UUID acted = null;
|
||||
private String actedName = null;
|
||||
private String action = null;
|
||||
|
||||
public static LogEntryBuilder get() {
|
||||
return new LogEntryBuilder();
|
||||
}
|
||||
|
||||
public LogEntryBuilder timestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder actor(UUID actor) {
|
||||
this.actor = actor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder actorName(String actorName) {
|
||||
this.actorName = actorName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder actor(Sender actor) {
|
||||
this.actorName = actor.getName();
|
||||
this.actor = actor.getUuid();
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder type(char type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder type(String type) {
|
||||
this.type = type.toCharArray()[0];
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder type(Object object) {
|
||||
if (object instanceof User) {
|
||||
this.type = 'U';
|
||||
} else if (object instanceof Group) {
|
||||
this.type = 'G';
|
||||
} else if (object instanceof Track) {
|
||||
this.type = 'T';
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder acted(UUID acted) {
|
||||
this.acted = acted;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder actedName(String actedName) {
|
||||
this.actedName = actedName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder acted(PermissionHolder acted) {
|
||||
if (acted instanceof User) {
|
||||
this.actedName = ((User) acted).getName();
|
||||
this.acted = ((User) acted).getUuid();
|
||||
this.type = 'U';
|
||||
} else if (acted instanceof Group) {
|
||||
this.actedName = ((Group) acted).getName();
|
||||
this.type = 'G';
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder acted(Track track) {
|
||||
this.actedName = track.getName();
|
||||
this.type = 'T';
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogEntryBuilder action(String action) {
|
||||
this.action = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
private Set<String> getEmpty() {
|
||||
Set<String> s = new HashSet<>();
|
||||
if (actor == null) {
|
||||
s.add("actor");
|
||||
}
|
||||
if (actorName == null) {
|
||||
s.add("actorname");
|
||||
}
|
||||
if (type == Character.MIN_VALUE) {
|
||||
s.add("type");
|
||||
}
|
||||
if (actedName == null) {
|
||||
s.add("actedname");
|
||||
}
|
||||
if (action == null) {
|
||||
s.add("action");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public void submit(LuckPermsPlugin plugin) {
|
||||
final LogEntry entry = build();
|
||||
plugin.getDatastore().logAction(entry, Callback.empty());
|
||||
|
||||
final String msg = entry.getFormatted();
|
||||
|
||||
plugin.getSenders().stream()
|
||||
.filter(Permission.LOG_NOTIFY::isAuthorized)
|
||||
.filter(s -> !plugin.getIgnoringLogs().contains(s.getUuid()))
|
||||
.forEach(s -> Message.LOG.send(s, msg));
|
||||
}
|
||||
|
||||
public LogEntry build() {
|
||||
if (timestamp == 0L) {
|
||||
timestamp = System.currentTimeMillis() / 1000;
|
||||
}
|
||||
|
||||
if (!getEmpty().isEmpty()) {
|
||||
throw new IllegalStateException("Missing values: " + getEmpty().toString());
|
||||
}
|
||||
|
||||
return new LogEntry(timestamp, actor, actorName, type, acted, actedName, action);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class MySQLConfiguration implements me.lucko.luckperms.api.data.MySQLConfiguration {
|
||||
|
||||
private final String address;
|
||||
private final String database;
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
}
|
||||
@@ -1,547 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data.methods;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.data.Datastore;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings({"ResultOfMethodCallIgnored", "UnnecessaryLocalVariable"})
|
||||
public class FlatfileDatastore extends Datastore {
|
||||
|
||||
private Map<String, String> uuidCache = new ConcurrentHashMap<>();
|
||||
|
||||
private final File pluginDir;
|
||||
private File usersDir;
|
||||
private File groupsDir;
|
||||
private File tracksDir;
|
||||
private File uuidData;
|
||||
|
||||
public FlatfileDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||
super(plugin, "Flatfile - JSON");
|
||||
this.pluginDir = pluginDir;
|
||||
}
|
||||
|
||||
private boolean doWrite(File file, WriteOperation writeOperation) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup FileWriter fileWriter = new FileWriter(file);
|
||||
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
@Cleanup JsonWriter jsonWriter = new JsonWriter(bufferedWriter);
|
||||
jsonWriter.setIndent(" ");
|
||||
success = writeOperation.onRun(jsonWriter);
|
||||
jsonWriter.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private boolean doRead(File file, ReadOperation readOperation) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup FileReader fileReader = new FileReader(file);
|
||||
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
@Cleanup JsonReader jsonReader = new JsonReader(bufferedReader);
|
||||
success = readOperation.onRun(jsonReader);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
makeFiles();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
uuidCache.putAll(getUUIDCache());
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
|
||||
private void makeFiles() throws IOException {
|
||||
File data = new File(pluginDir, "data");
|
||||
data.mkdirs();
|
||||
|
||||
usersDir = new File(data, "users");
|
||||
usersDir.mkdir();
|
||||
|
||||
groupsDir = new File(data, "groups");
|
||||
groupsDir.mkdir();
|
||||
|
||||
tracksDir = new File(data, "tracks");
|
||||
tracksDir.mkdir();
|
||||
|
||||
uuidData = new File(data, "uuidcache.txt");
|
||||
uuidData.createNewFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
saveUUIDCache(uuidCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadOrCreateUser(UUID uuid, String username) {
|
||||
User user = plugin.getUserManager().makeUser(uuid, username);
|
||||
|
||||
File userFile = new File(usersDir, uuid.toString() + ".json");
|
||||
if (!userFile.exists()) {
|
||||
try {
|
||||
userFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
plugin.getUserManager().giveDefaults(user);
|
||||
|
||||
boolean success = doWrite(userFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("uuid").value(user.getUuid().toString());
|
||||
writer.name("name").value(user.getName());
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : user.getNodes().entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(userFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // uuid record
|
||||
reader.nextString(); // uuid
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // primaryGroup record
|
||||
user.setPrimaryGroup(reader.nextString()); // primaryGroup
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
user.getNodes().put(node, b);
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSetUser(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid) {
|
||||
User user = plugin.getUserManager().makeUser(uuid);
|
||||
|
||||
File userFile = new File(usersDir, uuid.toString() + ".json");
|
||||
if (!userFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(userFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // uuid record
|
||||
reader.nextString(); // uuid
|
||||
reader.nextName(); // name record
|
||||
user.setName(reader.nextString()); // name
|
||||
reader.nextName(); // primaryGroup record
|
||||
user.setPrimaryGroup(reader.nextString()); // primaryGroup
|
||||
reader.nextName(); // perms record
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
user.getNodes().put(node, b);
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSetUser(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
|
||||
if (!userFile.exists()) {
|
||||
try {
|
||||
userFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(userFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("uuid").value(user.getUuid().toString());
|
||||
writer.name("name").value(user.getName());
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : user.getNodes().entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().makeGroup(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doWrite(groupFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : group.getNodes().entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
group.getNodes().put(node, b);
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSetGroup(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().makeGroup(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
group.getNodes().put(node, b);
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSetGroup(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> groups = Arrays.stream(fileNames).map(s -> s.substring(0, s.length() - 5)).collect(Collectors.toList());
|
||||
|
||||
plugin.getGroupManager().unloadAll();
|
||||
groups.forEach(this::loadGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(groupFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : group.getNodes().entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||
if (groupFile.exists()) {
|
||||
groupFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().makeTrack(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doWrite(trackFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(track.getName());
|
||||
writer.name("groups");
|
||||
writer.beginArray();
|
||||
for (String s : track.getGroups()) {
|
||||
writer.value(s);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // groups record
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
groups.add(reader.nextString());
|
||||
}
|
||||
reader.endArray();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSetTrack(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().makeTrack(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // groups record
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
groups.add(reader.nextString());
|
||||
}
|
||||
reader.endArray();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSetTrack(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> tracks = Arrays.stream(fileNames).map(s -> s.substring(0, s.length() - 5)).collect(Collectors.toList());
|
||||
|
||||
plugin.getTrackManager().unloadAll();
|
||||
tracks.forEach(this::loadTrack);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(trackFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(track.getName());
|
||||
writer.name("groups");
|
||||
writer.beginArray();
|
||||
for (String s : track.getGroups()) {
|
||||
writer.value(s);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||
if (trackFile.exists()) {
|
||||
trackFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String, String> getUUIDCache() {
|
||||
Map<String, String> cache = new HashMap<>();
|
||||
|
||||
try {
|
||||
@Cleanup FileReader fileReader = new FileReader(uuidData);
|
||||
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
Properties props = new Properties();
|
||||
props.load(bufferedReader);
|
||||
for (String key : props.stringPropertyNames()) {
|
||||
cache.put(key, props.getProperty(key));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
private void saveUUIDCache(Map<String, String> cache) {
|
||||
try {
|
||||
@Cleanup FileWriter fileWriter = new FileWriter(uuidData);
|
||||
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(cache);
|
||||
properties.store(bufferedWriter, null);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(String username, UUID uuid) {
|
||||
username = username.toLowerCase();
|
||||
uuidCache.put(username, uuid.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String username) {
|
||||
username = username.toLowerCase();
|
||||
if (uuidCache.get(username) == null) return null;
|
||||
return UUID.fromString(uuidCache.get(username));
|
||||
}
|
||||
|
||||
interface WriteOperation {
|
||||
boolean onRun(JsonWriter writer) throws IOException;
|
||||
}
|
||||
|
||||
interface ReadOperation {
|
||||
boolean onRun(JsonReader reader) throws IOException;
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data.methods;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.data.MySQLConfiguration;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class MySQLDatastore extends SQLDatastore {
|
||||
|
||||
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
|
||||
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
|
||||
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
|
||||
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
|
||||
|
||||
private final MySQLConfiguration configuration;
|
||||
private HikariDataSource hikari;
|
||||
|
||||
public MySQLDatastore(LuckPermsPlugin plugin, MySQLConfiguration configuration) {
|
||||
super(plugin, "MySQL");
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
hikari = new HikariDataSource();
|
||||
|
||||
final String address = configuration.getAddress();
|
||||
final String database = configuration.getDatabase();
|
||||
final String username = configuration.getUsername();
|
||||
final String password = configuration.getPassword();
|
||||
|
||||
hikari.setMaximumPoolSize(10);
|
||||
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
|
||||
hikari.addDataSourceProperty("serverName", address.split(":")[0]);
|
||||
hikari.addDataSourceProperty("port", address.split(":")[1]);
|
||||
hikari.addDataSourceProperty("databaseName", database);
|
||||
hikari.addDataSourceProperty("user", username);
|
||||
hikari.addDataSourceProperty("password", password);
|
||||
|
||||
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
|
||||
plugin.getLog().severe("Error occurred whilst initialising the database. All connections are disallowed.");
|
||||
shutdown();
|
||||
} else {
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean runQuery(QueryPS queryPS) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup Connection connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
|
||||
queryPS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
success = true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean runQuery(QueryRS queryRS) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup Connection connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
|
||||
queryRS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
success = queryRS.onResult(resultSet);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (hikari != null) {
|
||||
hikari.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Connection getConnection() throws SQLException {
|
||||
return hikari.getConnection();
|
||||
}
|
||||
}
|
||||
@@ -1,468 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data.methods;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.data.Datastore;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
abstract class SQLDatastore extends Datastore {
|
||||
|
||||
private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>(){}.getType();
|
||||
private static final Type T_TYPE = new TypeToken<List<String>>(){}.getType();
|
||||
|
||||
private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?, ?)";
|
||||
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
|
||||
private static final String USER_UPDATE = "UPDATE lp_users SET name=?, primary_group = ?, perms=? WHERE uuid=?";
|
||||
|
||||
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?)";
|
||||
private static final String GROUP_SELECT = "SELECT perms FROM lp_groups WHERE name=?";
|
||||
private static final String GROUP_SELECT_ALL = "SELECT * FROM lp_groups";
|
||||
private static final String GROUP_UPDATE = "UPDATE lp_groups SET perms=? WHERE name=?";
|
||||
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
|
||||
|
||||
private static final String TRACK_INSERT = "INSERT INTO lp_tracks VALUES(?, ?)";
|
||||
private static final String TRACK_SELECT = "SELECT groups FROM lp_tracks WHERE name=?";
|
||||
private static final String TRACK_SELECT_ALL = "SELECT * FROM lp_tracks";
|
||||
private static final String TRACK_UPDATE = "UPDATE lp_tracks SET groups=? WHERE name=?";
|
||||
private static final String TRACK_DELETE = "DELETE FROM lp_tracks WHERE name=?";
|
||||
|
||||
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?)";
|
||||
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
|
||||
private static final String UUIDCACHE_UPDATE = "UPDATE lp_uuid SET uuid=? WHERE name=?";
|
||||
|
||||
private final Gson gson;
|
||||
|
||||
SQLDatastore(LuckPermsPlugin plugin, String name) {
|
||||
super(plugin, name);
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
abstract Connection getConnection() throws SQLException;
|
||||
|
||||
abstract boolean runQuery(QueryPS queryPS);
|
||||
abstract boolean runQuery(QueryRS queryRS);
|
||||
|
||||
boolean setupTables(String... tableQueries) {
|
||||
boolean success = true;
|
||||
for (String q : tableQueries) {
|
||||
if (!runQuery(new Query(q))) success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid) {
|
||||
User user = plugin.getUserManager().makeUser(uuid);
|
||||
boolean success = runQuery(new QueryRS(USER_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultSet.next()) {
|
||||
user.setName(resultSet.getString("name"));
|
||||
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
user.setPrimaryGroup(resultSet.getString("primary_group"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSetUser(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadOrCreateUser(UUID uuid, String username) {
|
||||
User user = plugin.getUserManager().makeUser(uuid, username);
|
||||
boolean success = runQuery(new QueryRS(USER_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
boolean success = true;
|
||||
if (!resultSet.next()) {
|
||||
plugin.getUserManager().giveDefaults(user);
|
||||
|
||||
success = runQuery(new QueryPS(USER_INSERT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
preparedStatement.setString(2, user.getName());
|
||||
preparedStatement.setString(3, user.getPrimaryGroup());
|
||||
preparedStatement.setString(4, gson.toJson(user.getNodes()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
user.setPrimaryGroup(resultSet.getString("primary_group"));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSetUser(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
boolean success = runQuery(new QueryPS(USER_UPDATE) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, user.getName());
|
||||
preparedStatement.setString(2, user.getPrimaryGroup());
|
||||
preparedStatement.setString(3, gson.toJson(user.getNodes()));
|
||||
preparedStatement.setString(4, user.getUuid().toString());
|
||||
}
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().makeGroup(name);
|
||||
boolean success = runQuery(new QueryRS(GROUP_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, group.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
boolean success = true;
|
||||
if (!resultSet.next()) {
|
||||
success = runQuery(new QueryPS(GROUP_INSERT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, group.getName());
|
||||
preparedStatement.setString(2, gson.toJson(group.getNodes()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSetGroup(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().makeGroup(name);
|
||||
boolean success = runQuery(new QueryRS(GROUP_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultSet.next()) {
|
||||
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSetGroup(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
List<Group> groups = new ArrayList<>();
|
||||
boolean success = runQuery(new QueryRS(GROUP_SELECT_ALL) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
while (resultSet.next()) {
|
||||
Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name"));
|
||||
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
groups.add(group);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) {
|
||||
GroupManager gm = plugin.getGroupManager();
|
||||
gm.unloadAll();
|
||||
groups.forEach(gm::setGroup);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
boolean success = runQuery(new QueryPS(GROUP_UPDATE) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, gson.toJson(group.getNodes()));
|
||||
preparedStatement.setString(2, group.getName());
|
||||
}
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
boolean success = runQuery(new QueryPS(GROUP_DELETE) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, group.getName());
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().unloadGroup(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().makeTrack(name);
|
||||
boolean success = runQuery(new QueryRS(TRACK_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, track.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
boolean success = true;
|
||||
if (!resultSet.next()) {
|
||||
success = runQuery(new QueryPS(TRACK_INSERT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, track.getName());
|
||||
preparedStatement.setString(2, gson.toJson(track.getGroups()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getTrackManager().updateOrSetTrack(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().makeTrack(name);
|
||||
boolean success = runQuery(new QueryRS(TRACK_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultSet.next()) {
|
||||
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getTrackManager().updateOrSetTrack(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
List<Track> tracks = new ArrayList<>();
|
||||
boolean success = runQuery(new QueryRS(TRACK_SELECT_ALL) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
while (resultSet.next()) {
|
||||
Track track = plugin.getTrackManager().makeTrack(resultSet.getString("name"));
|
||||
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
|
||||
tracks.add(track);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (success) {
|
||||
TrackManager tm = plugin.getTrackManager();
|
||||
tm.unloadAll();
|
||||
tracks.forEach(tm::setTrack);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
boolean success = runQuery(new QueryPS(TRACK_UPDATE) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, gson.toJson(track.getGroups()));
|
||||
preparedStatement.setString(2, track.getName());
|
||||
}
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
boolean success = runQuery(new QueryPS(TRACK_DELETE) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, track.getName());
|
||||
}
|
||||
});
|
||||
|
||||
if (success) plugin.getTrackManager().unloadTrack(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(String username, UUID uuid) {
|
||||
final String u = username.toLowerCase();
|
||||
boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, u);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
boolean success;
|
||||
if (resultSet.next()) {
|
||||
success = runQuery(new QueryPS(UUIDCACHE_UPDATE) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
preparedStatement.setString(2, u);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
success = runQuery(new QueryPS(UUIDCACHE_INSERT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, u);
|
||||
preparedStatement.setString(2, uuid.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
return success;
|
||||
}
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String username) {
|
||||
final String u = username.toLowerCase();
|
||||
final UUID[] uuid = {null};
|
||||
|
||||
boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, u);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultSet.next()) {
|
||||
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return success ? uuid[0] : null;
|
||||
}
|
||||
|
||||
private class Query extends QueryPS {
|
||||
Query(String query) {
|
||||
super(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
abstract class QueryPS {
|
||||
private final String query;
|
||||
abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
abstract class QueryRS {
|
||||
private final String query;
|
||||
abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
|
||||
abstract boolean onResult(ResultSet resultSet) throws SQLException;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* 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.data.methods;
|
||||
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
|
||||
public class SQLiteDatastore extends SQLDatastore {
|
||||
|
||||
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`));";
|
||||
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`));";
|
||||
|
||||
private final File file;
|
||||
private Connection connection = null;
|
||||
|
||||
public SQLiteDatastore(LuckPermsPlugin plugin, File file) {
|
||||
super(plugin, "SQLite");
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
|
||||
plugin.getLog().severe("Error occurred whilst initialising the database. All connections are disallowed.");
|
||||
shutdown();
|
||||
} else {
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean runQuery(QueryPS queryPS) {
|
||||
boolean success = false;
|
||||
try {
|
||||
Connection connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
|
||||
queryPS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
success = true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean runQuery(QueryRS queryRS) {
|
||||
boolean success = false;
|
||||
try {
|
||||
Connection connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
|
||||
queryRS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
success = queryRS.onResult(resultSet);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
try {
|
||||
if (connection != null && !connection.isClosed()) {
|
||||
connection.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Connection getConnection() throws SQLException {
|
||||
if (connection == null || connection.isClosed()) {
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
connection = DriverManager.getConnection("jdbc:sqlite:" + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user