Initial commit

This commit is contained in:
Luck
2016-05-22 01:57:10 +01:00
Unverified
commit dc1e06ebce
70 changed files with 4044 additions and 0 deletions
@@ -0,0 +1,117 @@
package me.lucko.luckperms.data;
import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import java.util.UUID;
public abstract class Datastore {
protected final LuckPermsPlugin plugin;
@Getter
public String name;
@Getter
@Setter
private boolean acceptingLogins;
public Datastore(LuckPermsPlugin plugin, String name) {
this.plugin = plugin;
this.name = name;
this.acceptingLogins = true;
}
/**
* 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 void runCallback(boolean result, Callback callback) {
doSync(() -> callback.onComplete(result));
}
/*
These methods will block the thread that they're ran on.
*/
public abstract void init(DatastoreConfiguration configuration);
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 saveUUIDData(String username, UUID uuid);
public abstract UUID getUUID(String username);
/*
These methods will return as soon as they are called. The callback will be ran when the task is complete
They therefore will not block the thread that they're ran on
Callbacks are ran on the main server thread (if applicable)
*/
public void loadOrCreateUser(UUID uuid, String username, Callback callback) {
doAsync(() -> runCallback(loadOrCreateUser(uuid, username), callback));
}
public void loadUser(UUID uuid, Callback callback) {
doAsync(() -> runCallback(loadUser(uuid), callback));
}
public void saveUser(User user, Callback callback) {
doAsync(() -> runCallback(saveUser(user), callback));
}
public void createAndLoadGroup(String name, Callback callback) {
doAsync(() -> runCallback(createAndLoadGroup(name), callback));
}
public void loadGroup(String name, Callback callback) {
doAsync(() -> runCallback(loadGroup(name), callback));
}
public void loadAllGroups(Callback callback) {
doAsync(() -> runCallback(loadAllGroups(), callback));
}
public void saveGroup(Group group, Callback callback) {
doAsync(() -> runCallback(saveGroup(group), callback));
}
public void deleteGroup(Group group, Callback callback) {
doAsync(() -> runCallback(deleteGroup(group), callback));
}
public void saveUUIDData(String username, UUID uuid, Callback callback) {
doAsync(() -> runCallback(saveUUIDData(username, uuid), callback));
}
public void getUUID(String username, GetUUIDCallback callback) {
doAsync(() -> doSync(() -> callback.onComplete(getUUID(username))));
}
public interface Callback {
void onComplete(boolean success);
}
public interface GetUUIDCallback {
void onComplete(UUID uuid);
}
}
@@ -0,0 +1,15 @@
package me.lucko.luckperms.data;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class DatastoreConfiguration {
private final String address;
private final String database;
private final String username;
private final String password;
}
@@ -0,0 +1,338 @@
package me.lucko.luckperms.data;
import com.zaxxer.hikari.HikariDataSource;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.users.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
public class HikariDatastore extends Datastore {
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, `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 USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE name=?";
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
private static final String USER_SAVE = "UPDATE lp_users SET name=?, perms=? WHERE uuid=?";
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?) ON DUPLICATE KEY UPDATE perms=?";
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_SAVE = "UPDATE lp_groups SET perms=? WHERE name=?";
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?) ON DUPLICATE KEY UPDATE uuid=?";
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
private HikariDataSource hikari;
public HikariDatastore(LuckPermsPlugin plugin) {
super(plugin, "MySQL");
}
private static void executeQuery(Connection connection, String query) throws SQLException {
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.execute();
preparedStatement.close();
}
private boolean runQuery(Query query) {
boolean success = false;
Connection connection = null;
try {
connection = hikari.getConnection();
success = query.onRun(connection);
} catch (SQLException e) {
e.printStackTrace();
success = false;
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return success;
}
private void setupTables() {
boolean success = runQuery(connection -> {
executeQuery(connection, CREATETABLE_UUID);
executeQuery(connection, CREATETABLE_USERS);
executeQuery(connection, CREATETABLE_GROUPS);
return true;
});
if (!success) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst connecting to the database. All connections are disallowed.");
hikari.shutdown();
setAcceptingLogins(false);
}
}
@Override
public void init(DatastoreConfiguration configuration) {
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);
setupTables();
}
@Override
public boolean loadUser(UUID uuid) {
User user = plugin.getUserManager().makeUser(uuid);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SELECT);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
user.setName(resultSet.getString("name"));
user.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
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(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_INSERT);
preparedStatement.setString(1, uuid.toString());
preparedStatement.setString(2, username);
preparedStatement.setString(3, plugin.getConfiguration().getDefaultGroupNode());
preparedStatement.setString(4, username);
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(USER_SELECT);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
user.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return true;
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean saveUser(User user) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SAVE);
preparedStatement.setString(1, user.getName());
preparedStatement.setString(2, user.serializeNodes());
preparedStatement.setString(3, user.getUuid().toString());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_INSERT);
preparedStatement.setString(1, name);
preparedStatement.setString(2, "#");
preparedStatement.setString(3, "#");
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(GROUP_SELECT);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
}
group.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
group.loadNodes(nodes);
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadAllGroups() {
List<Group> groups = new ArrayList<>();
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT_ALL);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name"));
if (!resultSet.getString("perms").equals("#")) {
group.loadNodes(Arrays.asList(resultSet.getString("perms").split(":")));
}
groups.add(group);
}
preparedStatement.close();
resultSet.close();
return true;
});
GroupManager gm = plugin.getGroupManager();
if (success) {
groups.forEach(gm::setGroup);
}
return success;
}
@Override
public boolean saveGroup(Group group) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SAVE);
preparedStatement.setString(1, group.serializeNodes());
preparedStatement.setString(2, group.getName());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public boolean deleteGroup(Group group) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_DELETE);
preparedStatement.setString(1, group.getName());
preparedStatement.execute();
preparedStatement.close();
return true;
});
if (success) plugin.getGroupManager().unloadGroup(group);
return success;
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_INSERT);
preparedStatement.setString(1, username);
preparedStatement.setString(2, uuid.toString());
preparedStatement.setString(3, uuid.toString());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public UUID getUUID(String username) {
final UUID[] uuid = {null};
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_SELECT);
preparedStatement.setString(1, username);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
return success ? uuid[0] : null;
}
private interface Query {
boolean onRun(Connection connection) throws SQLException;
}
}