cache = new ConcurrentHashMap<>();
+ private final JsonCache jsonCache = new JsonCache();
- /**
- * Constructor for LimboCache.
- *
- * @param plugin AuthMe
- */
- private LimboCache(AuthMe plugin) {
- this.plugin = plugin;
- this.cache = new ConcurrentHashMap<>();
- this.jsonCache = new JsonCache();
- }
+ @Inject
+ private PermissionsManager permissionsManager;
+ @Inject
+ private SpawnLoader spawnLoader;
- /**
- * Method getInstance.
- *
- * @return LimboCache
- */
- public static LimboCache getInstance() {
- if (singleton == null) {
- singleton = new LimboCache(AuthMe.getInstance());
- }
- return singleton;
+ @Inject
+ LimboCache(PermissionsManager permissionsManager, SpawnLoader spawnLoader) {
+ this.permissionsManager = permissionsManager;
+ this.spawnLoader = spawnLoader;
}
/**
@@ -50,13 +38,12 @@ public class LimboCache {
*/
public void addLimboPlayer(Player player) {
String name = player.getName().toLowerCase();
- Location loc = player.getLocation();
+ Location location = player.isDead() ? spawnLoader.getSpawnLocation(player) : player.getLocation();
boolean operator = player.isOp();
boolean flyEnabled = player.getAllowFlight();
String playerGroup = "";
- PermissionsManager permsMan = plugin.getPermissionsManager();
- if (permsMan.hasGroupSupport()) {
- playerGroup = permsMan.getPrimaryGroup(player);
+ if (permissionsManager.hasGroupSupport()) {
+ playerGroup = permissionsManager.getPrimaryGroup(player);
}
if (jsonCache.doesCacheExist(player)) {
@@ -68,11 +55,8 @@ public class LimboCache {
}
}
- if (player.isDead()) {
- loc = plugin.getSpawnLocation(player);
- }
- cache.put(name, new LimboPlayer(name, loc, operator, playerGroup, flyEnabled));
+ cache.put(name, new LimboPlayer(name, location, operator, playerGroup, flyEnabled));
}
/**
@@ -83,9 +67,9 @@ public class LimboCache {
public void deleteLimboPlayer(String name) {
checkNotNull(name);
name = name.toLowerCase();
- if (cache.containsKey(name)) {
- cache.get(name).clearTasks();
- cache.remove(name);
+ LimboPlayer cachedPlayer = cache.remove(name);
+ if (cachedPlayer != null) {
+ cachedPlayer.clearTasks();
}
}
diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java
index 22a3f05c..36ad6da6 100644
--- a/src/main/java/fr/xephi/authme/command/CommandDescription.java
+++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java
@@ -1,6 +1,5 @@
package fr.xephi.authme.command;
-import fr.xephi.authme.permission.DefaultPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
@@ -14,7 +13,7 @@ import static java.util.Arrays.asList;
/**
* Command description – defines which labels ("names") will lead to a command and points to the
* {@link ExecutableCommand} implementation that executes the logic of the command.
- *
+ *
* CommandDescription instances are built hierarchically: they have one parent, or {@code null} for base commands
* (main commands such as {@code /authme}), and may have multiple children extending the mapping of the parent: e.g. if
* {@code /authme} has a child whose label is {@code "register"}, then {@code /authme register} is the command that
@@ -36,9 +35,9 @@ public class CommandDescription {
*/
private String detailedDescription;
/**
- * The executable command instance described by this object.
+ * The class implementing the command described by this object.
*/
- private ExecutableCommand executableCommand;
+ private Class extends ExecutableCommand> executableCommand;
/**
* The parent command.
*/
@@ -52,13 +51,13 @@ public class CommandDescription {
*/
private List arguments;
/**
- * Command permissions required to execute this command.
+ * Permission node required to execute this command.
*/
- private CommandPermissions permissions;
+ private PermissionNode permission;
/**
* Private constructor. Use {@link CommandDescription#builder()} to create instances of this class.
- *
+ *
* Note for developers: Instances should be created with {@link CommandDescription#createInstance} to be properly
* registered in the command tree.
*/
@@ -68,21 +67,20 @@ public class CommandDescription {
/**
* Create an instance.
*
- * @param labels List of command labels.
- * @param description Command description.
- * @param detailedDescription Detailed comment description.
- * @param executableCommand The executable command, or null.
- * @param parent Parent command.
- * @param arguments Command arguments.
- * @param permissions The permissions required to execute this command.
+ * @param labels command labels
+ * @param description description of the command
+ * @param detailedDescription detailed command description
+ * @param executableCommand class of the command implementation
+ * @param parent parent command
+ * @param arguments command arguments
+ * @param permission permission node required to execute this command
*
- * @return The created instance
+ * @return the created instance
* @see CommandDescription#builder()
*/
private static CommandDescription createInstance(List labels, String description,
- String detailedDescription, ExecutableCommand executableCommand,
- CommandDescription parent, List arguments,
- CommandPermissions permissions) {
+ String detailedDescription, Class extends ExecutableCommand> executableCommand, CommandDescription parent,
+ List arguments, PermissionNode permission) {
CommandDescription instance = new CommandDescription();
instance.labels = labels;
instance.description = description;
@@ -90,7 +88,7 @@ public class CommandDescription {
instance.executableCommand = executableCommand;
instance.parent = parent;
instance.arguments = arguments;
- instance.permissions = permissions;
+ instance.permission = permission;
if (parent != null) {
parent.addChild(instance);
@@ -114,7 +112,7 @@ public class CommandDescription {
}
/**
- * Check whether this command description has a specific command.
+ * Check whether this command description has the given label.
*
* @param commandLabel The label to check for.
*
@@ -130,18 +128,18 @@ public class CommandDescription {
}
/**
- * Return the {@link ExecutableCommand} instance defined by the command description.
+ * Return the {@link ExecutableCommand} class implementing this command.
*
- * @return The executable command object.
+ * @return The executable command class
*/
- public ExecutableCommand getExecutableCommand() {
+ public Class extends ExecutableCommand> getExecutableCommand() {
return executableCommand;
}
/**
* Return the parent.
*
- * @return The parent command, or null for base commands.
+ * @return The parent command, or null for base commands
*/
public CommandDescription getParent() {
return parent;
@@ -196,12 +194,12 @@ public class CommandDescription {
}
/**
- * Return the permissions required to execute the command.
+ * Return the permission node required to execute the command.
*
- * @return The command permissions, or null if none are required to execute the command.
+ * @return The permission node, or null if none are required to execute the command.
*/
- public CommandPermissions getCommandPermissions() {
- return permissions;
+ public PermissionNode getPermission() {
+ return permission;
}
/**
@@ -220,10 +218,10 @@ public class CommandDescription {
private List labels;
private String description;
private String detailedDescription;
- private ExecutableCommand executableCommand;
+ private Class extends ExecutableCommand> executableCommand;
private CommandDescription parent;
private List arguments = new ArrayList<>();
- private CommandPermissions permissions;
+ private PermissionNode permission;
/**
* Build a CommandDescription from the builder or throw an exception if a mandatory
@@ -239,7 +237,7 @@ public class CommandDescription {
// parents and permissions may be null; arguments may be empty
return createInstance(labels, description, detailedDescription, executableCommand,
- parent, arguments, permissions);
+ parent, arguments, permission);
}
public CommandBuilder labels(List labels) {
@@ -261,7 +259,7 @@ public class CommandDescription {
return this;
}
- public CommandBuilder executableCommand(ExecutableCommand executableCommand) {
+ public CommandBuilder executableCommand(Class extends ExecutableCommand> executableCommand) {
this.executableCommand = executableCommand;
return this;
}
@@ -286,9 +284,14 @@ public class CommandDescription {
return this;
}
- public CommandBuilder permissions(DefaultPermission defaultPermission,
- PermissionNode... permissionNodes) {
- this.permissions = new CommandPermissions(asList(permissionNodes), defaultPermission);
+ /**
+ * Add a permission node that a user must have to execute the command.
+ *
+ * @param permission The PermissionNode to add
+ * @return The builder
+ */
+ public CommandBuilder permission(PermissionNode permission) {
+ this.permission = permission;
return this;
}
}
diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java
index 37c1a2a1..da5299e2 100644
--- a/src/main/java/fr/xephi/authme/command/CommandHandler.java
+++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java
@@ -1,18 +1,23 @@
package fr.xephi.authme.command;
-import java.util.ArrayList;
-import java.util.List;
-
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.help.HelpProvider;
+import fr.xephi.authme.initialization.AuthMeServiceInitializer;
+import fr.xephi.authme.permission.PermissionsManager;
+import fr.xephi.authme.util.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
-import fr.xephi.authme.util.StringUtils;
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
- * The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription}
- * or to display help messages for unknown invocations.
+ * The AuthMe command handler, responsible for invoking the correct {@link ExecutableCommand} based on incoming
+ * command labels or for displaying a help message for unknown command labels.
*/
public class CommandHandler {
@@ -22,15 +27,22 @@ public class CommandHandler {
*/
private static final double SUGGEST_COMMAND_THRESHOLD = 0.75;
- private final CommandService commandService;
+ private final CommandMapper commandMapper;
+ private final PermissionsManager permissionsManager;
+ private final HelpProvider helpProvider;
/**
- * Create a command handler.
- *
- * @param commandService The CommandService instance
+ * Map with ExecutableCommand children. The key is the type of the value.
*/
- public CommandHandler(CommandService commandService) {
- this.commandService = commandService;
+ private Map, ExecutableCommand> commands = new HashMap<>();
+
+ @Inject
+ public CommandHandler(AuthMeServiceInitializer initializer, CommandMapper commandMapper,
+ PermissionsManager permissionsManager, HelpProvider helpProvider) {
+ this.commandMapper = commandMapper;
+ this.permissionsManager = permissionsManager;
+ this.helpProvider = helpProvider;
+ initializeCommands(initializer, commandMapper.getCommandClasses());
}
/**
@@ -48,7 +60,7 @@ public class CommandHandler {
List parts = skipEmptyArguments(bukkitArgs);
parts.add(0, bukkitCommandLabel);
- FoundCommandResult result = commandService.mapPartsToCommand(sender, parts);
+ FoundCommandResult result = commandMapper.mapPartsToCommand(sender, parts);
handleCommandResult(sender, result);
return !FoundResultStatus.MISSING_BASE_COMMAND.equals(result.getResultStatus());
}
@@ -75,6 +87,18 @@ public class CommandHandler {
}
}
+ /**
+ * Initialize all required ExecutableCommand objects.
+ *
+ * @param commandClasses the classes to instantiate
+ */
+ private void initializeCommands(AuthMeServiceInitializer initializer,
+ Set> commandClasses) {
+ for (Class extends ExecutableCommand> clazz : commandClasses) {
+ commands.put(clazz, initializer.newInstance(clazz));
+ }
+ }
+
/**
* Execute the command for the given command sender.
*
@@ -82,9 +106,9 @@ public class CommandHandler {
* @param result The mapped result
*/
private void executeCommand(CommandSender sender, FoundCommandResult result) {
- ExecutableCommand executableCommand = result.getCommandDescription().getExecutableCommand();
+ ExecutableCommand executableCommand = commands.get(result.getCommandDescription().getExecutableCommand());
List arguments = result.getArguments();
- executableCommand.executeCommand(sender, arguments, commandService);
+ executableCommand.executeCommand(sender, arguments);
}
/**
@@ -125,14 +149,14 @@ public class CommandHandler {
private void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result) {
CommandDescription command = result.getCommandDescription();
- if (!commandService.getPermissionsManager().hasPermission(sender, command)) {
+ if (!permissionsManager.hasPermission(sender, command.getPermission())) {
sendPermissionDeniedError(sender);
return;
}
// Show the command argument help
sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!");
- commandService.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS);
+ helpProvider.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS);
List labels = result.getLabels();
String childLabel = labels.size() >= 2 ? labels.get(1) : "";
diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java
index 6635545f..ce02b9a8 100644
--- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java
+++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java
@@ -41,25 +41,33 @@ import java.util.Collection;
import java.util.List;
import java.util.Set;
-import static fr.xephi.authme.permission.DefaultPermission.ALLOWED;
-import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY;
-
/**
* Initializes all available AuthMe commands.
*/
-public final class CommandInitializer {
+public class CommandInitializer {
- private CommandInitializer() {
- // Helper class
+ private Set commands;
+
+ public CommandInitializer() {
+ buildCommands();
}
- public static Set buildCommands() {
+ /**
+ * Returns the description of all AuthMe commands.
+ *
+ * @return the command descriptions
+ */
+ public Set getCommands() {
+ return commands;
+ }
+
+ private void buildCommands() {
// Register the base AuthMe Reloaded command
final CommandDescription AUTHME_BASE = CommandDescription.builder()
.labels("authme")
.description("Main command")
.detailedDescription("The main AuthMeReloaded command. The root for all admin commands.")
- .executableCommand(new AuthMeCommand())
+ .executableCommand(AuthMeCommand.class)
.build();
// Register the register command
@@ -70,8 +78,8 @@ public final class CommandInitializer {
.detailedDescription("Register the specified player with the specified password.")
.withArgument("player", "Player name", false)
.withArgument("password", "Password", false)
- .permissions(OP_ONLY, AdminPermission.REGISTER)
- .executableCommand(new RegisterAdminCommand())
+ .permission(AdminPermission.REGISTER)
+ .executableCommand(RegisterAdminCommand.class)
.build();
// Register the unregister command
@@ -81,8 +89,8 @@ public final class CommandInitializer {
.description("Unregister a player")
.detailedDescription("Unregister the specified player.")
.withArgument("player", "Player name", false)
- .permissions(OP_ONLY, AdminPermission.UNREGISTER)
- .executableCommand(new UnregisterAdminCommand())
+ .permission(AdminPermission.UNREGISTER)
+ .executableCommand(UnregisterAdminCommand.class)
.build();
// Register the forcelogin command
@@ -92,8 +100,8 @@ public final class CommandInitializer {
.description("Enforce login player")
.detailedDescription("Enforce the specified player to login.")
.withArgument("player", "Online player name", true)
- .permissions(OP_ONLY, AdminPermission.FORCE_LOGIN)
- .executableCommand(new ForceLoginCommand())
+ .permission(AdminPermission.FORCE_LOGIN)
+ .executableCommand(ForceLoginCommand.class)
.build();
// Register the changepassword command
@@ -104,8 +112,8 @@ public final class CommandInitializer {
.detailedDescription("Change the password of a player.")
.withArgument("player", "Player name", false)
.withArgument("pwd", "New password", false)
- .permissions(OP_ONLY, AdminPermission.CHANGE_PASSWORD)
- .executableCommand(new ChangePasswordAdminCommand())
+ .permission(AdminPermission.CHANGE_PASSWORD)
+ .executableCommand(ChangePasswordAdminCommand.class)
.build();
// Register the last login command
@@ -115,8 +123,8 @@ public final class CommandInitializer {
.description("Player's last login")
.detailedDescription("View the date of the specified players last login.")
.withArgument("player", "Player name", true)
- .permissions(OP_ONLY, AdminPermission.LAST_LOGIN)
- .executableCommand(new LastLoginCommand())
+ .permission(AdminPermission.LAST_LOGIN)
+ .executableCommand(LastLoginCommand.class)
.build();
// Register the accounts command
@@ -126,8 +134,8 @@ public final class CommandInitializer {
.description("Display player accounts")
.detailedDescription("Display all accounts of a player by his player name or IP.")
.withArgument("player", "Player name or IP", true)
- .permissions(OP_ONLY, AdminPermission.ACCOUNTS)
- .executableCommand(new AccountsCommand())
+ .permission(AdminPermission.ACCOUNTS)
+ .executableCommand(AccountsCommand.class)
.build();
// Register the getemail command
@@ -137,8 +145,8 @@ public final class CommandInitializer {
.description("Display player's email")
.detailedDescription("Display the email address of the specified player if set.")
.withArgument("player", "Player name", true)
- .permissions(OP_ONLY, AdminPermission.GET_EMAIL)
- .executableCommand(new GetEmailCommand())
+ .permission(AdminPermission.GET_EMAIL)
+ .executableCommand(GetEmailCommand.class)
.build();
// Register the setemail command
@@ -149,8 +157,8 @@ public final class CommandInitializer {
.detailedDescription("Change the email address of the specified player.")
.withArgument("player", "Player name", false)
.withArgument("email", "Player email", false)
- .permissions(OP_ONLY, AdminPermission.CHANGE_EMAIL)
- .executableCommand(new SetEmailCommand())
+ .permission(AdminPermission.CHANGE_EMAIL)
+ .executableCommand(SetEmailCommand.class)
.build();
// Register the getip command
@@ -160,8 +168,8 @@ public final class CommandInitializer {
.description("Get player's IP")
.detailedDescription("Get the IP address of the specified online player.")
.withArgument("player", "Player name", false)
- .permissions(OP_ONLY, AdminPermission.GET_IP)
- .executableCommand(new GetIpCommand())
+ .permission(AdminPermission.GET_IP)
+ .executableCommand(GetIpCommand.class)
.build();
// Register the spawn command
@@ -170,8 +178,8 @@ public final class CommandInitializer {
.labels("spawn", "home")
.description("Teleport to spawn")
.detailedDescription("Teleport to the spawn.")
- .permissions(OP_ONLY, AdminPermission.SPAWN)
- .executableCommand(new SpawnCommand())
+ .permission(AdminPermission.SPAWN)
+ .executableCommand(SpawnCommand.class)
.build();
// Register the setspawn command
@@ -180,8 +188,8 @@ public final class CommandInitializer {
.labels("setspawn", "chgspawn")
.description("Change the spawn")
.detailedDescription("Change the player's spawn to your current position.")
- .permissions(OP_ONLY, AdminPermission.SET_SPAWN)
- .executableCommand(new SetSpawnCommand())
+ .permission(AdminPermission.SET_SPAWN)
+ .executableCommand(SetSpawnCommand.class)
.build();
// Register the firstspawn command
@@ -190,8 +198,8 @@ public final class CommandInitializer {
.labels("firstspawn", "firsthome")
.description("Teleport to first spawn")
.detailedDescription("Teleport to the first spawn.")
- .permissions(OP_ONLY, AdminPermission.FIRST_SPAWN)
- .executableCommand(new FirstSpawnCommand())
+ .permission(AdminPermission.FIRST_SPAWN)
+ .executableCommand(FirstSpawnCommand.class)
.build();
// Register the setfirstspawn command
@@ -200,8 +208,8 @@ public final class CommandInitializer {
.labels("setfirstspawn", "chgfirstspawn")
.description("Change the first spawn")
.detailedDescription("Change the first player's spawn to your current position.")
- .permissions(OP_ONLY, AdminPermission.SET_FIRST_SPAWN)
- .executableCommand(new SetFirstSpawnCommand())
+ .permission(AdminPermission.SET_FIRST_SPAWN)
+ .executableCommand(SetFirstSpawnCommand.class)
.build();
// Register the purge command
@@ -211,8 +219,8 @@ public final class CommandInitializer {
.description("Purge old data")
.detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.")
.withArgument("days", "Number of days", false)
- .permissions(OP_ONLY, AdminPermission.PURGE)
- .executableCommand(new PurgeCommand())
+ .permission(AdminPermission.PURGE)
+ .executableCommand(PurgeCommand.class)
.build();
// Register the purgelastposition command
@@ -223,8 +231,8 @@ public final class CommandInitializer {
.description("Purge player's last position")
.detailedDescription("Purge the last know position of the specified player or all of them.")
.withArgument("player/*", "Player name or * for all players", false)
- .permissions(OP_ONLY, AdminPermission.PURGE_LAST_POSITION)
- .executableCommand(new PurgeLastPositionCommand())
+ .permission(AdminPermission.PURGE_LAST_POSITION)
+ .executableCommand(PurgeLastPositionCommand.class)
.build();
// Register the purgebannedplayers command
@@ -233,8 +241,8 @@ public final class CommandInitializer {
.labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer")
.description("Purge banned players data")
.detailedDescription("Purge all AuthMeReloaded data for banned players.")
- .permissions(OP_ONLY, AdminPermission.PURGE_BANNED_PLAYERS)
- .executableCommand(new PurgeBannedPlayersCommand())
+ .permission(AdminPermission.PURGE_BANNED_PLAYERS)
+ .executableCommand(PurgeBannedPlayersCommand.class)
.build();
// Register the switchantibot command
@@ -244,8 +252,8 @@ public final class CommandInitializer {
.description("Switch AntiBot mode")
.detailedDescription("Switch or toggle the AntiBot mode to the specified state.")
.withArgument("mode", "ON / OFF", true)
- .permissions(OP_ONLY, AdminPermission.SWITCH_ANTIBOT)
- .executableCommand(new SwitchAntiBotCommand())
+ .permission(AdminPermission.SWITCH_ANTIBOT)
+ .executableCommand(SwitchAntiBotCommand.class)
.build();
// Register the reload command
@@ -254,8 +262,8 @@ public final class CommandInitializer {
.labels("reload", "rld")
.description("Reload plugin")
.detailedDescription("Reload the AuthMeReloaded plugin.")
- .permissions(OP_ONLY, AdminPermission.RELOAD)
- .executableCommand(new ReloadCommand())
+ .permission(AdminPermission.RELOAD)
+ .executableCommand(ReloadCommand.class)
.build();
// Register the version command
@@ -265,7 +273,7 @@ public final class CommandInitializer {
.description("Version info")
.detailedDescription("Show detailed information about the installed AuthMeReloaded version, the "
+ "developers, contributors, and license.")
- .executableCommand(new VersionCommand())
+ .executableCommand(VersionCommand.class)
.build();
CommandDescription.builder()
@@ -275,19 +283,19 @@ public final class CommandInitializer {
.detailedDescription("Converter command for AuthMeReloaded.")
.withArgument("job", "Conversion job: xauth / crazylogin / rakamak / " +
"royalauth / vauth / sqlitetosql", false)
- .permissions(OP_ONLY, AdminPermission.CONVERTER)
- .executableCommand(new ConverterCommand())
+ .permission(AdminPermission.CONVERTER)
+ .executableCommand(ConverterCommand.class)
.build();
// Register the base login command
final CommandDescription LOGIN_BASE = CommandDescription.builder()
.parent(null)
- .labels("login", "l")
+ .labels("login", "l", "log")
.description("Login command")
.detailedDescription("Command to log in using AuthMeReloaded.")
.withArgument("password", "Login password", false)
- .permissions(ALLOWED, PlayerPermission.LOGIN)
- .executableCommand(new LoginCommand())
+ .permission(PlayerPermission.LOGIN)
+ .executableCommand(LoginCommand.class)
.build();
// Register the base logout command
@@ -296,8 +304,8 @@ public final class CommandInitializer {
.labels("logout")
.description("Logout command")
.detailedDescription("Command to logout using AuthMeReloaded.")
- .permissions(ALLOWED, PlayerPermission.LOGOUT)
- .executableCommand(new LogoutCommand())
+ .permission(PlayerPermission.LOGOUT)
+ .executableCommand(LogoutCommand.class)
.build();
// Register the base register command
@@ -308,19 +316,19 @@ public final class CommandInitializer {
.detailedDescription("Command to register using AuthMeReloaded.")
.withArgument("password", "Password", true)
.withArgument("verifyPassword", "Verify password", true)
- .permissions(ALLOWED, PlayerPermission.REGISTER)
- .executableCommand(new RegisterCommand())
+ .permission(PlayerPermission.REGISTER)
+ .executableCommand(RegisterCommand.class)
.build();
// Register the base unregister command
CommandDescription UNREGISTER_BASE = CommandDescription.builder()
.parent(null)
- .labels("unreg", "unregister")
+ .labels("unregister", "unreg")
.description("Unregistration Command")
.detailedDescription("Command to unregister using AuthMeReloaded.")
.withArgument("password", "Password", false)
- .permissions(ALLOWED, PlayerPermission.UNREGISTER)
- .executableCommand(new UnregisterCommand())
+ .permission(PlayerPermission.UNREGISTER)
+ .executableCommand(UnregisterCommand.class)
.build();
// Register the base changepassword command
@@ -331,17 +339,17 @@ public final class CommandInitializer {
.detailedDescription("Command to change your password using AuthMeReloaded.")
.withArgument("oldPassword", "Old Password", false)
.withArgument("newPassword", "New Password.", false)
- .permissions(ALLOWED, PlayerPermission.CHANGE_PASSWORD)
- .executableCommand(new ChangePasswordCommand())
+ .permission(PlayerPermission.CHANGE_PASSWORD)
+ .executableCommand(ChangePasswordCommand.class)
.build();
// Register the base Email command
CommandDescription EMAIL_BASE = CommandDescription.builder()
.parent(null)
- .labels("email", "mail")
+ .labels("email")
.description("Email command")
.detailedDescription("The AuthMeReloaded Email command base.")
- .executableCommand(new EmailBaseCommand())
+ .executableCommand(EmailBaseCommand.class)
.build();
// Register the add command
@@ -352,8 +360,8 @@ public final class CommandInitializer {
.detailedDescription("Add a new email address to your account.")
.withArgument("email", "Email address", false)
.withArgument("verifyEmail", "Email address verification", false)
- .permissions(ALLOWED, PlayerPermission.ADD_EMAIL)
- .executableCommand(new AddEmailCommand())
+ .permission(PlayerPermission.ADD_EMAIL)
+ .executableCommand(AddEmailCommand.class)
.build();
// Register the change command
@@ -364,8 +372,8 @@ public final class CommandInitializer {
.detailedDescription("Change an email address of your account.")
.withArgument("oldEmail", "Old email address", false)
.withArgument("newEmail", "New email address", false)
- .permissions(ALLOWED, PlayerPermission.CHANGE_EMAIL)
- .executableCommand(new ChangeEmailCommand())
+ .permission(PlayerPermission.CHANGE_EMAIL)
+ .executableCommand(ChangeEmailCommand.class)
.build();
// Register the recover command
@@ -376,19 +384,19 @@ public final class CommandInitializer {
.detailedDescription("Recover your account using an Email address by sending a mail containing " +
"a new password.")
.withArgument("email", "Email address", false)
- .permissions(ALLOWED, PlayerPermission.RECOVER_EMAIL)
- .executableCommand(new RecoverEmailCommand())
+ .permission(PlayerPermission.RECOVER_EMAIL)
+ .executableCommand(RecoverEmailCommand.class)
.build();
// Register the base captcha command
CommandDescription CAPTCHA_BASE = CommandDescription.builder()
.parent(null)
- .labels("captcha", "capt")
+ .labels("captcha")
.description("Captcha Command")
.detailedDescription("Captcha command for AuthMeReloaded.")
.withArgument("captcha", "The Captcha", false)
- .permissions(ALLOWED, PlayerPermission.CAPTCHA)
- .executableCommand(new CaptchaCommand())
+ .permission(PlayerPermission.CAPTCHA)
+ .executableCommand(CaptchaCommand.class)
.build();
Set baseCommands = ImmutableSet.of(
@@ -402,16 +410,15 @@ public final class CommandInitializer {
CAPTCHA_BASE);
setHelpOnAllBases(baseCommands);
- return baseCommands;
+ commands = baseCommands;
}
/**
- * Set the help command on all base commands, e.g. to register /authme help or /register help.
+ * Sets the help command on all base commands, e.g. to register /authme help or /register help.
*
- * @param commands The list of base commands to register a help child command on
+ * @param commands the list of base commands to register a help child command on
*/
- private static void setHelpOnAllBases(Collection commands) {
- final HelpCommand helpCommandExecutable = new HelpCommand();
+ private void setHelpOnAllBases(Collection commands) {
final List helpCommandLabels = Arrays.asList("help", "hlp", "h", "sos", "?");
for (CommandDescription base : commands) {
@@ -421,7 +428,7 @@ public final class CommandInitializer {
.description("View help")
.detailedDescription("View detailed help for /" + base.getLabels().get(0) + " commands.")
.withArgument("query", "The command or query to view help for.", true)
- .executableCommand(helpCommandExecutable)
+ .executableCommand(HelpCommand.class)
.build();
}
}
diff --git a/src/main/java/fr/xephi/authme/command/CommandMapper.java b/src/main/java/fr/xephi/authme/command/CommandMapper.java
index e43ee4bb..44d5b583 100644
--- a/src/main/java/fr/xephi/authme/command/CommandMapper.java
+++ b/src/main/java/fr/xephi/authme/command/CommandMapper.java
@@ -6,7 +6,9 @@ import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -15,8 +17,7 @@ import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
/**
- * The AuthMe command handler, responsible for mapping incoming
- * command parts to the correct {@link CommandDescription}.
+ * Maps incoming command parts to the correct {@link CommandDescription}.
*/
public class CommandMapper {
@@ -28,8 +29,9 @@ public class CommandMapper {
private final Set baseCommands;
private final PermissionsManager permissionsManager;
- public CommandMapper(Set baseCommands, PermissionsManager permissionsManager) {
- this.baseCommands = baseCommands;
+ @Inject
+ public CommandMapper(CommandInitializer commandInitializer, PermissionsManager permissionsManager) {
+ this.baseCommands = commandInitializer.getCommands();
this.permissionsManager = permissionsManager;
}
@@ -67,6 +69,23 @@ public class CommandMapper {
return getCommandWithSmallestDifference(base, parts);
}
+ /**
+ * Return all {@link ExecutableCommand} classes referenced in {@link CommandDescription} objects.
+ *
+ * @return all classes
+ * @see CommandInitializer#getCommands
+ */
+ public Set> getCommandClasses() {
+ Set> classes = new HashSet<>(50);
+ for (CommandDescription command : baseCommands) {
+ classes.add(command.getExecutableCommand());
+ for (CommandDescription child : command.getChildren()) {
+ classes.add(child.getExecutableCommand());
+ }
+ }
+ return classes;
+ }
+
private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List parts) {
// Return the base command with incorrect arg count error if we only have one part
if (parts.size() <= 1) {
@@ -139,7 +158,7 @@ public class CommandMapper {
private static FoundCommandResult transformResultForHelp(FoundCommandResult result) {
if (result.getCommandDescription() != null
- && HELP_COMMAND_CLASS.isAssignableFrom(result.getCommandDescription().getExecutableCommand().getClass())) {
+ && HELP_COMMAND_CLASS == result.getCommandDescription().getExecutableCommand()) {
// For "/authme help register" we have labels = [authme, help] and arguments = [register]
// But for the help command we want labels = [authme, help] and arguments = [authme, register],
// so we can use the arguments as the labels to the command to show help for
@@ -152,7 +171,7 @@ public class CommandMapper {
}
private FoundResultStatus getPermissionAwareStatus(CommandSender sender, CommandDescription command) {
- if (sender != null && !permissionsManager.hasPermission(sender, command)) {
+ if (sender != null && !permissionsManager.hasPermission(sender, command.getPermission())) {
return FoundResultStatus.NO_PERMISSION;
}
return FoundResultStatus.SUCCESS;
diff --git a/src/main/java/fr/xephi/authme/command/CommandPermissions.java b/src/main/java/fr/xephi/authme/command/CommandPermissions.java
deleted file mode 100644
index 0082b858..00000000
--- a/src/main/java/fr/xephi/authme/command/CommandPermissions.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package fr.xephi.authme.command;
-
-import fr.xephi.authme.permission.DefaultPermission;
-import fr.xephi.authme.permission.PermissionNode;
-
-import java.util.List;
-
-/**
- */
-public class CommandPermissions {
-
- /**
- * Defines the permission nodes required to have permission to execute this command.
- */
- private List permissionNodes;
- /**
- * Defines the default permission if the permission nodes couldn't be used.
- */
- private DefaultPermission defaultPermission;
-
- /**
- * Constructor.
- *
- * @param permissionNodes The permission nodes required to execute a command.
- * @param defaultPermission The default permission if the permission nodes couldn't be used.
- */
- public CommandPermissions(List permissionNodes, DefaultPermission defaultPermission) {
- this.permissionNodes = permissionNodes;
- this.defaultPermission = defaultPermission;
- }
-
- /**
- * Get the permission nodes required to execute this command.
- *
- * @return The permission nodes required to execute this command.
- */
- public List getPermissionNodes() {
- return this.permissionNodes;
- }
-
-
- /**
- * Get the default permission if the permission nodes couldn't be used.
- *
- * @return The default permission.
- */
- public DefaultPermission getDefaultPermission() {
- return this.defaultPermission;
- }
-
-
-}
diff --git a/src/main/java/fr/xephi/authme/command/CommandService.java b/src/main/java/fr/xephi/authme/command/CommandService.java
index 5c5abfcc..5efe79e8 100644
--- a/src/main/java/fr/xephi/authme/command/CommandService.java
+++ b/src/main/java/fr/xephi/authme/command/CommandService.java
@@ -1,26 +1,13 @@
package fr.xephi.authme.command;
-import fr.xephi.authme.AntiBot;
-import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.cache.auth.PlayerCache;
-import fr.xephi.authme.command.help.HelpProvider;
-import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
-import fr.xephi.authme.permission.PermissionsManager;
-import fr.xephi.authme.process.Management;
-import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.settings.NewSetting;
-import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
-import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.ValidationService;
import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import java.util.Collection;
-import java.util.List;
+import javax.inject.Inject;
/**
* Service for implementations of {@link ExecutableCommand} to execute some common tasks.
@@ -28,39 +15,12 @@ import java.util.List;
*/
public class CommandService {
- private final AuthMe authMe;
- private final Messages messages;
- private final HelpProvider helpProvider;
- private final CommandMapper commandMapper;
- private final PasswordSecurity passwordSecurity;
- private final PermissionsManager permissionsManager;
- private final NewSetting settings;
- private final PluginHooks pluginHooks;
- private final SpawnLoader spawnLoader;
- private final AntiBot antiBot;
- private final ValidationService validationService;
- private final BukkitService bukkitService;
-
- /*
- * Constructor.
- */
- public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
- PasswordSecurity passwordSecurity, PermissionsManager permissionsManager, NewSetting settings,
- PluginHooks pluginHooks, SpawnLoader spawnLoader, AntiBot antiBot,
- ValidationService validationService, BukkitService bukkitService) {
- this.authMe = authMe;
- this.messages = messages;
- this.helpProvider = helpProvider;
- this.commandMapper = commandMapper;
- this.passwordSecurity = passwordSecurity;
- this.permissionsManager = permissionsManager;
- this.settings = settings;
- this.pluginHooks = pluginHooks;
- this.spawnLoader = spawnLoader;
- this.antiBot = antiBot;
- this.validationService = validationService;
- this.bukkitService = bukkitService;
- }
+ @Inject
+ private Messages messages;
+ @Inject
+ private NewSetting settings;
+ @Inject
+ private ValidationService validationService;
/**
* Send a message to a player.
@@ -83,86 +43,6 @@ public class CommandService {
messages.send(sender, messageKey, replacements);
}
- /**
- * Map command parts to a command description.
- *
- * @param sender The command sender issuing the request (for permission check), or null to skip permissions
- * @param commandParts The received command parts to map to a command
- * @return The computed mapping result
- */
- public FoundCommandResult mapPartsToCommand(CommandSender sender, List commandParts) {
- return commandMapper.mapPartsToCommand(sender, commandParts);
- }
-
- /**
- * Run the given task asynchronously with the Bukkit scheduler.
- *
- * @param task The task to run
- */
- public void runTaskAsynchronously(Runnable task) {
- authMe.getServer().getScheduler().runTaskAsynchronously(authMe, task);
- }
-
- /**
- * Return the AuthMe data source.
- *
- * @return The used data source
- */
- public DataSource getDataSource() {
- return authMe.getDataSource();
- }
-
- /**
- * Return the AuthMe instance for further manipulation. Use only if other methods from
- * the command service cannot be used.
- *
- * @return The AuthMe instance
- */
- public AuthMe getAuthMe() {
- return authMe;
- }
-
- /**
- * Return the PasswordSecurity instance.
- *
- * @return The password security instance
- */
- public PasswordSecurity getPasswordSecurity() {
- return passwordSecurity;
- }
-
- /**
- * Output the help for a given command.
- *
- * @param sender The sender to output the help to
- * @param result The result to output information about
- * @param options Output options, see {@link HelpProvider}
- */
- public void outputHelp(CommandSender sender, FoundCommandResult result, int options) {
- List lines = helpProvider.printHelp(sender, result, options);
- for (String line : lines) {
- sender.sendMessage(line);
- }
- }
-
- /**
- * Return the management instance of the plugin.
- *
- * @return The Management instance linked to the AuthMe instance
- */
- public Management getManagement() {
- return authMe.getManagement();
- }
-
- /**
- * Return the permissions manager.
- *
- * @return the permissions manager
- */
- public PermissionsManager getPermissionsManager() {
- return permissionsManager;
- }
-
/**
* Retrieve a message by its message key.
*
@@ -193,33 +73,6 @@ public class CommandService {
return settings;
}
- public PlayerCache getPlayerCache() {
- return PlayerCache.getInstance();
- }
-
- public PluginHooks getPluginHooks() {
- return pluginHooks;
- }
-
- public SpawnLoader getSpawnLoader() {
- return spawnLoader;
- }
-
- public AntiBot getAntiBot() {
- return antiBot;
- }
-
- /**
- * Verifies whether a password is valid according to the plugin settings.
- *
- * @param password the password to verify
- * @param username the username the password is associated with
- * @return message key with the password error, or {@code null} if password is valid
- */
- public MessageKey validatePassword(String password, String username) {
- return validationService.validatePassword(password, username);
- }
-
public boolean validateEmail(String email) {
return validationService.validateEmail(email);
}
@@ -228,16 +81,4 @@ public class CommandService {
return validationService.isEmailFreeForRegistration(email, sender);
}
- public Player getPlayer(String name) {
- return bukkitService.getPlayerExact(name);
- }
-
- public Collection extends Player> getOnlinePlayers() {
- return bukkitService.getOnlinePlayers();
- }
-
- public BukkitService getBukkitService() {
- return bukkitService;
- }
-
}
diff --git a/src/main/java/fr/xephi/authme/command/ExecutableCommand.java b/src/main/java/fr/xephi/authme/command/ExecutableCommand.java
index 9567089f..ceda12ef 100644
--- a/src/main/java/fr/xephi/authme/command/ExecutableCommand.java
+++ b/src/main/java/fr/xephi/authme/command/ExecutableCommand.java
@@ -10,12 +10,11 @@ import java.util.List;
public interface ExecutableCommand {
/**
- * Execute the command with the given arguments.
+ * Executes the command with the given arguments.
*
- * @param sender The command sender.
- * @param arguments The arguments.
- * @param commandService The command service.
+ * @param sender the command sender (initiator of the command)
+ * @param arguments the arguments
*/
- void executeCommand(CommandSender sender, List arguments, CommandService commandService);
+ void executeCommand(CommandSender sender, List arguments);
}
diff --git a/src/main/java/fr/xephi/authme/command/PlayerCommand.java b/src/main/java/fr/xephi/authme/command/PlayerCommand.java
index 2d7aca0b..8ce6e05f 100644
--- a/src/main/java/fr/xephi/authme/command/PlayerCommand.java
+++ b/src/main/java/fr/xephi/authme/command/PlayerCommand.java
@@ -1,19 +1,19 @@
package fr.xephi.authme.command;
-import java.util.List;
-
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import java.util.List;
+
/**
* Common base type for player-only commands, handling the verification that the command sender is indeed a player.
*/
public abstract class PlayerCommand implements ExecutableCommand {
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
if (sender instanceof Player) {
- runCommand((Player) sender, arguments, commandService);
+ runCommand((Player) sender, arguments);
} else {
String alternative = getAlternativeCommand();
if (alternative != null) {
@@ -25,19 +25,18 @@ public abstract class PlayerCommand implements ExecutableCommand {
}
/**
- * Run the command with the given player and arguments.
+ * Runs the command with the given player and arguments.
*
- * @param player The player who initiated the command
- * @param arguments The arguments supplied with the command
- * @param commandService The command service
+ * @param player the player who initiated the command
+ * @param arguments the arguments supplied with the command
*/
- protected abstract void runCommand(Player player, List arguments, CommandService commandService);
+ protected abstract void runCommand(Player player, List arguments);
/**
- * Return an alternative command (textual representation) that is not restricted to players only.
- * Example: {@code "authme register "}
+ * Returns an alternative command (textual representation) that is not restricted to players only.
+ * Example: {@code "/authme register "}
*
- * @return Alternative command not only for players, or null if not applicable
+ * @return Alternative command not restricted to players, or null if not applicable
*/
protected String getAlternativeCommand() {
return null;
diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java
index 89256535..2076bcbc 100644
--- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java
@@ -1,6 +1,6 @@
package fr.xephi.authme.command.executable;
-import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.command.CommandMapper;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.FoundCommandResult;
@@ -9,6 +9,7 @@ import fr.xephi.authme.command.help.HelpProvider;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
@@ -16,11 +17,18 @@ import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
public class HelpCommand implements ExecutableCommand {
+ @Inject
+ private CommandMapper commandMapper;
+
+ @Inject
+ private HelpProvider helpProvider;
+
+
// Convention: arguments is not the actual invoked arguments but the command that was invoked,
// e.g. "/authme help register" would typically be arguments = [register], but here we pass [authme, register]
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
- FoundCommandResult result = commandService.mapPartsToCommand(sender, arguments);
+ public void executeCommand(CommandSender sender, List arguments) {
+ FoundCommandResult result = commandMapper.mapPartsToCommand(sender, arguments);
FoundResultStatus resultStatus = result.getResultStatus();
if (MISSING_BASE_COMMAND.equals(resultStatus)) {
@@ -38,9 +46,9 @@ public class HelpCommand implements ExecutableCommand {
int mappedCommandLevel = result.getCommandDescription().getLabelCount();
if (mappedCommandLevel == 1) {
- commandService.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN);
+ helpProvider.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN);
} else {
- commandService.outputHelp(sender, result, HelpProvider.ALL_OPTIONS);
+ helpProvider.outputHelp(sender, result, HelpProvider.ALL_OPTIONS);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java
index d3698cfd..3b446a7f 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java
@@ -3,10 +3,13 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -14,25 +17,27 @@ import java.util.List;
*/
public class AccountsCommand implements ExecutableCommand {
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private BukkitService bukkitService;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void executeCommand(final CommandSender sender, List arguments,
- final CommandService commandService) {
+ public void executeCommand(final CommandSender sender, List arguments) {
final String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
// Assumption: a player name cannot contain '.'
- if (!playerName.contains(".")) {
- commandService.runTaskAsynchronously(new Runnable() {
+ if (playerName.contains(".")) {
+ bukkitService.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
- PlayerAuth auth = commandService.getDataSource().getAuth(playerName.toLowerCase());
- if (auth == null) {
- commandService.send(sender, MessageKey.UNKNOWN_USER);
- return;
- }
-
- List accountList = commandService.getDataSource().getAllAuthsByIp(auth.getIp());
+ List accountList = dataSource.getAllAuthsByIp(playerName);
if (accountList.isEmpty()) {
- commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
+ sender.sendMessage("[AuthMe] This IP does not exist in the database.");
} else if (accountList.size() == 1) {
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
} else {
@@ -41,12 +46,18 @@ public class AccountsCommand implements ExecutableCommand {
}
});
} else {
- commandService.runTaskAsynchronously(new Runnable() {
+ bukkitService.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
- List accountList = commandService.getDataSource().getAllAuthsByIp(playerName);
+ PlayerAuth auth = dataSource.getAuth(playerName.toLowerCase());
+ if (auth == null) {
+ commandService.send(sender, MessageKey.UNKNOWN_USER);
+ return;
+ }
+
+ List accountList = dataSource.getAllAuthsByIp(auth.getIp());
if (accountList.isEmpty()) {
- sender.sendMessage("[AuthMe] This IP does not exist in the database.");
+ commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
} else if (accountList.size() == 1) {
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
} else {
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java
index 2c0ef601..2648177e 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java
@@ -1,7 +1,6 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -14,7 +13,7 @@ import java.util.List;
public class AuthMeCommand implements ExecutableCommand {
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v"
+ AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3");
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme help" + ChatColor.YELLOW
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java
index 867443ed..729a4b4e 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java
@@ -2,13 +2,19 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
+import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
+import fr.xephi.authme.util.BukkitService;
+import fr.xephi.authme.util.ValidationService;
+import fr.xephi.authme.util.ValidationService.ValidationResult;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -16,30 +22,46 @@ import java.util.List;
*/
public class ChangePasswordAdminCommand implements ExecutableCommand {
+ @Inject
+ private PasswordSecurity passwordSecurity;
+
+ @Inject
+ private PlayerCache playerCache;
+
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private BukkitService bukkitService;
+
+ @Inject
+ private ValidationService validationService;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void executeCommand(final CommandSender sender, List arguments,
- final CommandService commandService) {
+ public void executeCommand(final CommandSender sender, List arguments) {
// Get the player and password
final String playerName = arguments.get(0);
final String playerPass = arguments.get(1);
// Validate the password
- MessageKey passwordError = commandService.validatePassword(playerPass, playerName);
- if (passwordError != null) {
- commandService.send(sender, passwordError);
+ ValidationResult validationResult = validationService.validatePassword(playerPass, playerName);
+ if (validationResult.hasError()) {
+ commandService.send(sender, validationResult.getMessageKey(), validationResult.getArgs());
return;
}
// Set the password
final String playerNameLowerCase = playerName.toLowerCase();
- commandService.runTaskAsynchronously(new Runnable() {
+ bukkitService.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
- DataSource dataSource = commandService.getDataSource();
PlayerAuth auth = null;
- if (commandService.getPlayerCache().isAuthenticated(playerNameLowerCase)) {
- auth = commandService.getPlayerCache().getAuth(playerNameLowerCase);
+ if (playerCache.isAuthenticated(playerNameLowerCase)) {
+ auth = playerCache.getAuth(playerNameLowerCase);
} else if (dataSource.isAuthAvailable(playerNameLowerCase)) {
auth = dataSource.getAuth(playerNameLowerCase);
}
@@ -48,15 +70,14 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
return;
}
- HashedPassword hashedPassword = commandService.getPasswordSecurity()
- .computeHash(playerPass, playerNameLowerCase);
+ HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
auth.setPassword(hashedPassword);
- if (!dataSource.updatePassword(auth)) {
- commandService.send(sender, MessageKey.ERROR);
- } else {
+ if (dataSource.updatePassword(auth)) {
commandService.send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
ConsoleLogger.info(playerNameLowerCase + "'s password changed");
+ } else {
+ commandService.send(sender, MessageKey.ERROR);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java
index e3414480..e18c9dc4 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java
@@ -1,6 +1,6 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.AuthMe;
+import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.converter.Converter;
@@ -10,18 +10,30 @@ import fr.xephi.authme.converter.RoyalAuthConverter;
import fr.xephi.authme.converter.SqliteToSql;
import fr.xephi.authme.converter.vAuthConverter;
import fr.xephi.authme.converter.xAuthConverter;
+import fr.xephi.authme.initialization.AuthMeServiceInitializer;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.util.BukkitService;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
+/**
+ * Converter command: launches conversion based on its parameters.
+ */
public class ConverterCommand implements ExecutableCommand {
- @Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
- // AuthMe plugin instance
- final AuthMe plugin = AuthMe.getInstance();
+ @Inject
+ private CommandService commandService;
+ @Inject
+ private BukkitService bukkitService;
+
+ @Inject
+ private AuthMeServiceInitializer initializer;
+
+ @Override
+ public void executeCommand(final CommandSender sender, List arguments) {
// Get the conversion job
String job = arguments.get(0);
@@ -33,49 +45,35 @@ public class ConverterCommand implements ExecutableCommand {
}
// Get the proper converter instance
- Converter converter = null;
- switch (jobType) {
- case XAUTH:
- converter = new xAuthConverter(plugin, sender);
- break;
- case CRAZYLOGIN:
- converter = new CrazyLoginConverter(plugin, sender);
- break;
- case RAKAMAK:
- converter = new RakamakConverter(plugin, sender);
- break;
- case ROYALAUTH:
- converter = new RoyalAuthConverter(plugin);
- break;
- case VAUTH:
- converter = new vAuthConverter(plugin, sender);
- break;
- case SQLITETOSQL:
- converter = new SqliteToSql(plugin, sender, commandService.getSettings());
- break;
- default:
- break;
- }
+ final Converter converter = initializer.newInstance(jobType.getConverterClass());
// Run the convert job
- commandService.runTaskAsynchronously(converter);
+ bukkitService.runTaskAsynchronously(new Runnable() {
+ @Override
+ public void run() {
+ converter.execute(sender);
+ }
+ });
// Show a status message
sender.sendMessage("[AuthMe] Successfully converted from " + jobType.getName());
}
- public enum ConvertType {
- XAUTH("xauth"),
- CRAZYLOGIN("crazylogin"),
- RAKAMAK("rakamak"),
- ROYALAUTH("royalauth"),
- VAUTH("vauth"),
- SQLITETOSQL("sqlitetosql");
+ @VisibleForTesting
+ enum ConvertType {
+ XAUTH("xauth", xAuthConverter.class),
+ CRAZYLOGIN("crazylogin", CrazyLoginConverter.class),
+ RAKAMAK("rakamak", RakamakConverter.class),
+ ROYALAUTH("royalauth", RoyalAuthConverter.class),
+ VAUTH("vauth", vAuthConverter.class),
+ SQLITETOSQL("sqlitetosql", SqliteToSql.class);
- final String name;
+ private final String name;
+ private final Class extends Converter> converterClass;
- ConvertType(String name) {
+ ConvertType(String name, Class extends Converter> converterClass) {
this.name = name;
+ this.converterClass = converterClass;
}
public static ConvertType fromName(String name) {
@@ -87,8 +85,12 @@ public class ConverterCommand implements ExecutableCommand {
return null;
}
- String getName() {
+ public String getName() {
return this.name;
}
+
+ public Class extends Converter> getConverterClass() {
+ return converterClass;
+ }
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java
index 50b3b169..acfc59be 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java
@@ -1,9 +1,10 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
+import fr.xephi.authme.settings.SpawnLoader;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -11,12 +12,15 @@ import java.util.List;
*/
public class FirstSpawnCommand extends PlayerCommand {
+ @Inject
+ private SpawnLoader spawnLoader;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
- if (commandService.getSpawnLoader().getFirstSpawn() != null) {
- player.teleport(commandService.getSpawnLoader().getFirstSpawn());
- } else {
+ public void runCommand(Player player, List arguments) {
+ if (spawnLoader.getFirstSpawn() == null) {
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
+ } else {
+ player.teleport(spawnLoader.getFirstSpawn());
}
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java
index c974e7ea..706e313e 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java
@@ -1,10 +1,13 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.permission.PermissionsManager;
+import fr.xephi.authme.process.Management;
+import fr.xephi.authme.util.BukkitService;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
import static fr.xephi.authme.permission.PlayerPermission.CAN_LOGIN_BE_FORCED;
@@ -14,18 +17,27 @@ import static fr.xephi.authme.permission.PlayerPermission.CAN_LOGIN_BE_FORCED;
*/
public class ForceLoginCommand implements ExecutableCommand {
+ @Inject
+ private PermissionsManager permissionsManager;
+
+ @Inject
+ private Management management;
+
+ @Inject
+ private BukkitService bukkitService;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
// Get the player query
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
- Player player = commandService.getPlayer(playerName);
+ Player player = bukkitService.getPlayerExact(playerName);
if (player == null || !player.isOnline()) {
sender.sendMessage("Player needs to be online!");
- } else if (!commandService.getPermissionsManager().hasPermission(player, CAN_LOGIN_BE_FORCED)) {
+ } else if (!permissionsManager.hasPermission(player, CAN_LOGIN_BE_FORCED)) {
sender.sendMessage("You cannot force login the player " + playerName + "!");
} else {
- commandService.getManagement().performLogin(player, "dontneed", true);
+ management.performLogin(player, "dontneed", true);
sender.sendMessage("Force login for " + playerName + " performed!");
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java
index 53a3051c..07ee57d3 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java
@@ -3,9 +3,11 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -13,11 +15,17 @@ import java.util.List;
*/
public class GetEmailCommand implements ExecutableCommand {
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
- PlayerAuth auth = commandService.getDataSource().getAuth(playerName);
+ PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
commandService.send(sender, MessageKey.UNKNOWN_USER);
} else {
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java
index 59379aa7..773f01b4 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java
@@ -1,20 +1,24 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.util.BukkitService;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
public class GetIpCommand implements ExecutableCommand {
+ @Inject
+ private BukkitService bukkitService;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
// Get the player query
String playerName = arguments.get(0);
- Player player = commandService.getPlayer(playerName);
+ Player player = bukkitService.getPlayerExact(playerName);
if (player == null) {
sender.sendMessage("The player is not online");
return;
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java
index 05fdab2b..376499fb 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java
@@ -3,9 +3,11 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.Date;
import java.util.List;
@@ -14,12 +16,18 @@ import java.util.List;
*/
public class LastLoginCommand implements ExecutableCommand {
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
// Get the player
String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName();
- PlayerAuth auth = commandService.getDataSource().getAuth(playerName);
+ PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
return;
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java
index 0ace9424..c80a790d 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java
@@ -1,14 +1,18 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
-import fr.xephi.authme.settings.properties.PurgeSettings;
+import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.task.PurgeTask;
+import fr.xephi.authme.util.BukkitService;
+import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
-import java.util.ArrayList;
+import javax.inject.Inject;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Command for purging data of banned players. Depending on the settings
@@ -16,30 +20,30 @@ import java.util.List;
*/
public class PurgeBannedPlayersCommand implements ExecutableCommand {
- @Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
- // AuthMe plugin instance
- final AuthMe plugin = commandService.getAuthMe();
+ @Inject
+ private DataSource dataSource;
+ @Inject
+ private AuthMe plugin;
+
+ @Inject
+ private BukkitService bukkitService;
+
+ @Override
+ public void executeCommand(CommandSender sender, List arguments) {
// Get the list of banned players
- List bannedPlayers = new ArrayList<>();
- for (OfflinePlayer offlinePlayer : plugin.getServer().getBannedPlayers()) {
- bannedPlayers.add(offlinePlayer.getName().toLowerCase());
+ Set namedBanned = new HashSet<>();
+ Set bannedPlayers = bukkitService.getBannedPlayers();
+ for (OfflinePlayer offlinePlayer : bannedPlayers) {
+ namedBanned.add(offlinePlayer.getName().toLowerCase());
}
+ //todo: note this should may run async because it may executes a SQL-Query
// Purge the banned players
- commandService.getDataSource().purgeBanned(bannedPlayers);
- if (commandService.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES)
- && commandService.getPluginHooks().isEssentialsAvailable())
- plugin.dataManager.purgeEssentials(bannedPlayers);
- if (commandService.getProperty(PurgeSettings.REMOVE_PLAYER_DAT))
- plugin.dataManager.purgeDat(bannedPlayers);
- if (commandService.getProperty(PurgeSettings.REMOVE_LIMITED_CREATIVE_INVENTORIES))
- plugin.dataManager.purgeLimitedCreative(bannedPlayers);
- if (commandService.getProperty(PurgeSettings.REMOVE_ANTI_XRAY_FILE))
- plugin.dataManager.purgeAntiXray(bannedPlayers);
+ dataSource.purgeBanned(namedBanned);
// Show a status message
- sender.sendMessage("[AuthMe] Database has been purged correctly");
+ sender.sendMessage(ChatColor.GOLD + "Purging user accounts...");
+ new PurgeTask(plugin, sender, namedBanned, bannedPlayers).runTaskTimer(plugin, 0, 1);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java
index 43e1daa5..73e8e7c0 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java
@@ -1,14 +1,16 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
-import fr.xephi.authme.settings.properties.PurgeSettings;
+import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.task.PurgeTask;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.Calendar;
import java.util.List;
+import java.util.Set;
/**
* Command for purging the data of players which have not been since for a given number
@@ -18,8 +20,14 @@ public class PurgeCommand implements ExecutableCommand {
private static final int MINIMUM_LAST_SEEN_DAYS = 30;
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private AuthMe plugin;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
// Get the days parameter
String daysStr = arguments.get(0);
@@ -44,25 +52,13 @@ public class PurgeCommand implements ExecutableCommand {
calendar.add(Calendar.DATE, -days);
long until = calendar.getTimeInMillis();
+ //todo: note this should may run async because it may executes a SQL-Query
// Purge the data, get the purged values
- List purged = commandService.getDataSource().autoPurgeDatabase(until);
+ Set purged = dataSource.autoPurgeDatabase(until);
// Show a status message
sender.sendMessage(ChatColor.GOLD + "Deleted " + purged.size() + " user accounts");
-
- // Purge other data
- AuthMe plugin = commandService.getAuthMe();
- if (commandService.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES) &&
- commandService.getPluginHooks().isEssentialsAvailable())
- plugin.dataManager.purgeEssentials(purged);
- if (commandService.getProperty(PurgeSettings.REMOVE_PLAYER_DAT))
- plugin.dataManager.purgeDat(purged);
- if (commandService.getProperty(PurgeSettings.REMOVE_LIMITED_CREATIVE_INVENTORIES))
- plugin.dataManager.purgeLimitedCreative(purged);
- if (commandService.getProperty(PurgeSettings.REMOVE_ANTI_XRAY_FILE))
- plugin.dataManager.purgeAntiXray(purged);
-
- // Show a status message
- sender.sendMessage(ChatColor.GREEN + "[AuthMe] Database has been purged correctly");
+ sender.sendMessage(ChatColor.GOLD + "Purging user accounts...");
+ new PurgeTask(plugin, sender, purged).runTaskTimer(plugin, 0, 1);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java
index 118f8460..ca6a0200 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java
@@ -3,9 +3,11 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -13,26 +15,32 @@ import java.util.List;
*/
public class PurgeLastPositionCommand implements ExecutableCommand {
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void executeCommand(final CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(final CommandSender sender, List arguments) {
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
if ("*".equals(playerName)) {
- for (PlayerAuth auth : commandService.getDataSource().getAllAuths()) {
+ for (PlayerAuth auth : dataSource.getAllAuths()) {
resetLastPosition(auth);
- commandService.getDataSource().updateQuitLoc(auth);
+ dataSource.updateQuitLoc(auth);
}
sender.sendMessage("All players last position locations are now reset");
} else {
// Get the user auth and make sure the user exists
- PlayerAuth auth = commandService.getDataSource().getAuth(playerName);
+ PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
commandService.send(sender, MessageKey.UNKNOWN_USER);
return;
}
resetLastPosition(auth);
- commandService.getDataSource().updateQuitLoc(auth);
+ dataSource.updateQuitLoc(auth);
sender.sendMessage(playerName + "'s last position location is now reset");
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java
index 2c842aee..a4931e96 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java
@@ -1,68 +1,85 @@
package fr.xephi.authme.command.executable.authme;
-import java.util.List;
-
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
+import fr.xephi.authme.util.BukkitService;
+import fr.xephi.authme.util.ValidationService;
+import fr.xephi.authme.util.ValidationService.ValidationResult;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import javax.inject.Inject;
+import java.util.List;
/**
* Admin command to register a user.
*/
public class RegisterAdminCommand implements ExecutableCommand {
+ @Inject
+ private PasswordSecurity passwordSecurity;
+
+ @Inject
+ private CommandService commandService;
+
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private BukkitService bukkitService;
+
+ @Inject
+ private ValidationService validationService;
+
@Override
- public void executeCommand(final CommandSender sender, List arguments,
- final CommandService commandService) {
+ public void executeCommand(final CommandSender sender, List arguments) {
// Get the player name and password
final String playerName = arguments.get(0);
final String playerPass = arguments.get(1);
final String playerNameLowerCase = playerName.toLowerCase();
// Command logic
- MessageKey passwordError = commandService.validatePassword(playerPass, playerName);
- if (passwordError != null) {
- commandService.send(sender, passwordError);
+ ValidationResult passwordValidation = validationService.validatePassword(playerPass, playerName);
+ if (passwordValidation.hasError()) {
+ commandService.send(sender, passwordValidation.getMessageKey(), passwordValidation.getArgs());
return;
}
- commandService.runTaskAsynchronously(new Runnable() {
+ bukkitService.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
- if (commandService.getDataSource().isAuthAvailable(playerNameLowerCase)) {
+ if (dataSource.isAuthAvailable(playerNameLowerCase)) {
commandService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
return;
}
- HashedPassword hashedPassword = commandService.getPasswordSecurity()
- .computeHash(playerPass, playerNameLowerCase);
+ HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
PlayerAuth auth = PlayerAuth.builder()
.name(playerNameLowerCase)
.realName(playerName)
.password(hashedPassword)
.build();
- if (!commandService.getDataSource().saveAuth(auth)) {
+ if (!dataSource.saveAuth(auth)) {
commandService.send(sender, MessageKey.ERROR);
return;
}
- commandService.getDataSource().setUnlogged(playerNameLowerCase);
+ dataSource.setUnlogged(playerNameLowerCase);
commandService.send(sender, MessageKey.REGISTER_SUCCESS);
ConsoleLogger.info(sender.getName() + " registered " + playerName);
- Player player = commandService.getPlayer(playerName);
+ final Player player = bukkitService.getPlayerExact(playerName);
if (player != null) {
- final Player p = player;
- p.getServer().getScheduler().scheduleSyncDelayedTask(commandService.getAuthMe(), new Runnable() {
+ bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
- p.kickPlayer("An admin just registered you, please log in again");
+ player.kickPlayer("An admin just registered you, please log in again");
}
});
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java
index 91df5832..73534902 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java
@@ -4,9 +4,14 @@ import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.initialization.AuthMeServiceInitializer;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.properties.DatabaseSettings;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -14,11 +19,32 @@ import java.util.List;
*/
public class ReloadCommand implements ExecutableCommand {
+ @Inject
+ private AuthMe plugin;
+
+ @Inject
+ private AuthMeServiceInitializer initializer;
+
+ @Inject
+ private NewSetting settings;
+
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
- AuthMe plugin = commandService.getAuthMe();
+ public void executeCommand(CommandSender sender, List arguments) {
try {
- plugin.reload();
+ settings.reload();
+ ConsoleLogger.setLoggingOptions(settings);
+ // We do not change database type for consistency issues, but we'll output a note in the logs
+ if (!settings.getProperty(DatabaseSettings.BACKEND).equals(dataSource.getType())) {
+ ConsoleLogger.info("Note: cannot change database type during /authme reload");
+ sender.sendMessage("Note: cannot change database type during /authme reload");
+ }
+ initializer.performReloadOnServices();
commandService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
} catch (Exception e) {
sender.sendMessage("Error occurred during reload of AuthMe: aborting");
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java
index 0e7bcf35..76ef4959 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java
@@ -6,8 +6,10 @@ import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.util.BukkitService;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -15,9 +17,20 @@ import java.util.List;
*/
public class SetEmailCommand implements ExecutableCommand {
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private CommandService commandService;
+
+ @Inject
+ private PlayerCache playerCache;
+
+ @Inject
+ private BukkitService bukkitService;
+
@Override
- public void executeCommand(final CommandSender sender, List arguments,
- final CommandService commandService) {
+ public void executeCommand(final CommandSender sender, List arguments) {
// Get the player name and email address
final String playerName = arguments.get(0);
final String playerEmail = arguments.get(1);
@@ -28,11 +41,10 @@ public class SetEmailCommand implements ExecutableCommand {
return;
}
- commandService.runTaskAsynchronously(new Runnable() {
+ bukkitService.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
// Validate the user
- DataSource dataSource = commandService.getDataSource();
PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
commandService.send(sender, MessageKey.UNKNOWN_USER);
@@ -50,8 +62,8 @@ public class SetEmailCommand implements ExecutableCommand {
}
// Update the player cache
- if (PlayerCache.getInstance().getAuth(playerName) != null) {
- PlayerCache.getInstance().updatePlayer(auth);
+ if (playerCache.getAuth(playerName) != null) {
+ playerCache.updatePlayer(auth);
}
// Show a status message
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java
index a3cc7d45..899a1103 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java
@@ -1,16 +1,20 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
+import fr.xephi.authme.settings.SpawnLoader;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
public class SetFirstSpawnCommand extends PlayerCommand {
+ @Inject
+ private SpawnLoader spawnLoader;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
- if (commandService.getSpawnLoader().setFirstSpawn(player.getLocation())) {
+ public void runCommand(Player player, List arguments) {
+ if (spawnLoader.setFirstSpawn(player.getLocation())) {
player.sendMessage("[AuthMe] Correctly defined new first spawn point");
} else {
player.sendMessage("[AuthMe] SetFirstSpawn has failed, please retry");
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java
index 3201ea4c..fc9a67b9 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java
@@ -1,16 +1,20 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
+import fr.xephi.authme.settings.SpawnLoader;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
public class SetSpawnCommand extends PlayerCommand {
+ @Inject
+ private SpawnLoader spawnLoader;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
- if (commandService.getSpawnLoader().setSpawn(player.getLocation())) {
+ public void runCommand(Player player, List arguments) {
+ if (spawnLoader.setSpawn(player.getLocation())) {
player.sendMessage("[AuthMe] Correctly defined new spawn point");
} else {
player.sendMessage("[AuthMe] SetSpawn has failed, please retry");
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java
index 04f8e563..3c011e6d 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java
@@ -1,19 +1,23 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
+import fr.xephi.authme.settings.SpawnLoader;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
public class SpawnCommand extends PlayerCommand {
+ @Inject
+ private SpawnLoader spawnLoader;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
- if (commandService.getSpawnLoader().getSpawn() != null) {
- player.teleport(commandService.getSpawnLoader().getSpawn());
- } else {
+ public void runCommand(Player player, List arguments) {
+ if (spawnLoader.getSpawn() == null) {
player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
+ } else {
+ player.teleport(spawnLoader.getSpawn());
}
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java
index 3c36c169..64a7241f 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java
@@ -1,13 +1,14 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AntiBot;
-import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.command.CommandMapper;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.FoundCommandResult;
import fr.xephi.authme.command.help.HelpProvider;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.Arrays;
import java.util.List;
@@ -16,9 +17,17 @@ import java.util.List;
*/
public class SwitchAntiBotCommand implements ExecutableCommand {
+ @Inject
+ private AntiBot antiBot;
+
+ @Inject
+ private CommandMapper commandMapper;
+
+ @Inject
+ private HelpProvider helpProvider;
+
@Override
- public void executeCommand(final CommandSender sender, List arguments, CommandService commandService) {
- AntiBot antiBot = commandService.getAntiBot();
+ public void executeCommand(final CommandSender sender, List arguments) {
if (arguments.isEmpty()) {
sender.sendMessage("[AuthMe] AntiBot status: " + antiBot.getAntiBotStatus().name());
return;
@@ -35,8 +44,8 @@ public class SwitchAntiBotCommand implements ExecutableCommand {
sender.sendMessage("[AuthMe] AntiBot Manual Override: disabled!");
} else {
sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!");
- FoundCommandResult result = commandService.mapPartsToCommand(sender, Arrays.asList("authme", "antibot"));
- commandService.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS);
+ FoundCommandResult result = commandMapper.mapPartsToCommand(sender, Arrays.asList("authme", "antibot"));
+ helpProvider.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS);
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/authme help antibot");
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java
index 5c8196dd..2e746f0d 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java
@@ -1,24 +1,25 @@
package fr.xephi.authme.command.executable.authme;
-import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.permission.AuthGroupHandler;
+import fr.xephi.authme.permission.AuthGroupType;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
-import fr.xephi.authme.task.MessageTask;
-import fr.xephi.authme.task.TimeoutTask;
+import fr.xephi.authme.task.LimboPlayerTaskManager;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-import org.bukkit.scheduler.BukkitTask;
+import javax.inject.Inject;
import java.util.List;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
@@ -28,31 +29,53 @@ import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
*/
public class UnregisterAdminCommand implements ExecutableCommand {
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private CommandService commandService;
+
+ @Inject
+ private PlayerCache playerCache;
+
+ @Inject
+ private BukkitService bukkitService;
+
+ @Inject
+ private LimboCache limboCache;
+
+ @Inject
+ private LimboPlayerTaskManager limboPlayerTaskManager;
+
+ @Inject
+ private AuthGroupHandler authGroupHandler;
+
+
@Override
- public void executeCommand(final CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(final CommandSender sender, List arguments) {
// Get the player name
String playerName = arguments.get(0);
String playerNameLowerCase = playerName.toLowerCase();
// Make sure the user is valid
- if (!commandService.getDataSource().isAuthAvailable(playerNameLowerCase)) {
+ if (!dataSource.isAuthAvailable(playerNameLowerCase)) {
commandService.send(sender, MessageKey.UNKNOWN_USER);
return;
}
// Remove the player
- if (!commandService.getDataSource().removeAuth(playerNameLowerCase)) {
+ if (!dataSource.removeAuth(playerNameLowerCase)) {
commandService.send(sender, MessageKey.ERROR);
return;
}
// Unregister the player
- Player target = commandService.getPlayer(playerNameLowerCase);
- PlayerCache.getInstance().removePlayer(playerNameLowerCase);
- Utils.setGroup(target, Utils.GroupType.UNREGISTERED);
+ Player target = bukkitService.getPlayerExact(playerNameLowerCase);
+ playerCache.removePlayer(playerNameLowerCase);
+ authGroupHandler.setGroup(target, AuthGroupType.UNREGISTERED);
if (target != null && target.isOnline()) {
if (commandService.getProperty(RegistrationSettings.FORCE)) {
- applyUnregisteredEffectsAndTasks(target, commandService);
+ applyUnregisteredEffectsAndTasks(target);
}
commandService.send(target, MessageKey.UNREGISTERED_SUCCESS);
}
@@ -68,27 +91,18 @@ public class UnregisterAdminCommand implements ExecutableCommand {
* timeout kick, blindness.
*
* @param target the player that was unregistered
- * @param service the command service
*/
- private void applyUnregisteredEffectsAndTasks(Player target, CommandService service) {
- final AuthMe plugin = service.getAuthMe();
- final BukkitService bukkitService = service.getBukkitService();
- final String playerNameLowerCase = target.getName().toLowerCase();
-
+ private void applyUnregisteredEffectsAndTasks(Player target) {
+ // TODO #765: Remove use of Utils method and behave according to settings
Utils.teleportToSpawn(target);
- LimboCache.getInstance().addLimboPlayer(target);
- int timeOut = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
- int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
- if (timeOut != 0) {
- BukkitTask id = bukkitService.runTaskLater(new TimeoutTask(plugin, playerNameLowerCase, target), timeOut);
- LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTask(id);
- }
- LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTask(
- bukkitService.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
- playerNameLowerCase, MessageKey.REGISTER_MESSAGE, interval)));
- if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
- target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
+ limboCache.addLimboPlayer(target);
+ limboPlayerTaskManager.registerTimeoutTask(target);
+ limboPlayerTaskManager.registerMessageTask(target.getName(), false);
+
+ final int timeout = commandService.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
+ if (commandService.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
+ target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeout, 2));
}
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java
index 1a15dc04..a7e6575e 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java
@@ -3,10 +3,12 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
+import fr.xephi.authme.util.BukkitService;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.Collection;
import java.util.List;
@@ -14,15 +16,21 @@ import static fr.xephi.authme.settings.properties.PluginSettings.HELP_HEADER;
public class VersionCommand implements ExecutableCommand {
+ @Inject
+ private BukkitService bukkitService;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
+ public void executeCommand(CommandSender sender, List arguments) {
// Show some version info
sender.sendMessage(ChatColor.GOLD + "==========[ " + commandService.getProperty(HELP_HEADER)
+ " ABOUT ]==========");
sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName()
+ " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")");
sender.sendMessage(ChatColor.GOLD + "Developers:");
- Collection extends Player> onlinePlayers = commandService.getOnlinePlayers();
+ Collection extends Player> onlinePlayers = bukkitService.getOnlinePlayers();
printDeveloper(sender, "Xephi", "xephi59", "Lead Developer", onlinePlayers);
printDeveloper(sender, "DNx5", "DNx5", "Developer", onlinePlayers);
printDeveloper(sender, "games647", "games647", "Developer", onlinePlayers);
diff --git a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java
index aba0a950..1577c7ad 100644
--- a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java
@@ -1,55 +1,47 @@
package fr.xephi.authme.command.executable.captcha;
-import fr.xephi.authme.AuthMe;
+import fr.xephi.authme.cache.CaptchaManager;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
-import fr.xephi.authme.security.RandomString;
-import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
public class CaptchaCommand extends PlayerCommand {
+ @Inject
+ private PlayerCache playerCache;
+
+ @Inject
+ private CaptchaManager captchaManager;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
- final String playerNameLowerCase = player.getName().toLowerCase();
- final String captcha = arguments.get(0);
- final AuthMe plugin = commandService.getAuthMe();
- PlayerCache playerCache = PlayerCache.getInstance();
+ public void runCommand(Player player, List arguments) {
+ final String playerName = player.getName().toLowerCase();
- // Command logic
- if (playerCache.isAuthenticated(playerNameLowerCase)) {
+ if (playerCache.isAuthenticated(playerName)) {
commandService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
- return;
- }
-
- if (!commandService.getProperty(SecuritySettings.USE_CAPTCHA)) {
+ } else if (!captchaManager.isCaptchaRequired(playerName)) {
commandService.send(player, MessageKey.USAGE_LOGIN);
- return;
+ } else {
+ checkCaptcha(player, arguments.get(0));
}
+ }
- if (!plugin.cap.containsKey(playerNameLowerCase)) {
- commandService.send(player, MessageKey.USAGE_LOGIN);
- return;
+ private void checkCaptcha(Player player, String captchaCode) {
+ final boolean isCorrectCode = captchaManager.checkCode(player.getName(), captchaCode);
+ if (isCorrectCode) {
+ commandService.send(player, MessageKey.CAPTCHA_SUCCESS);
+ commandService.send(player, MessageKey.LOGIN_MESSAGE);
+ } else {
+ String newCode = captchaManager.generateCode(player.getName());
+ commandService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, newCode);
}
-
- if (!captcha.equals(plugin.cap.get(playerNameLowerCase))) {
- plugin.cap.remove(playerNameLowerCase);
- int captchaLength = commandService.getProperty(SecuritySettings.CAPTCHA_LENGTH);
- String randStr = RandomString.generate(captchaLength);
- plugin.cap.put(playerNameLowerCase, randStr);
- commandService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, plugin.cap.get(playerNameLowerCase));
- return;
- }
-
- plugin.captcha.remove(playerNameLowerCase);
- plugin.cap.remove(playerNameLowerCase);
-
- // Show a status message
- commandService.send(player, MessageKey.CAPTCHA_SUCCESS);
- commandService.send(player, MessageKey.LOGIN_MESSAGE);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java b/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java
index 7d378ca8..68377390 100644
--- a/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java
@@ -1,13 +1,15 @@
package fr.xephi.authme.command.executable.changepassword;
-import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
-import fr.xephi.authme.task.ChangePasswordTask;
+import fr.xephi.authme.process.Management;
+import fr.xephi.authme.util.ValidationService;
+import fr.xephi.authme.util.ValidationService.ValidationResult;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -15,27 +17,37 @@ import java.util.List;
*/
public class ChangePasswordCommand extends PlayerCommand {
+ @Inject
+ private CommandService commandService;
+
+ @Inject
+ private PlayerCache playerCache;
+
+ @Inject
+ private ValidationService validationService;
+
+ @Inject
+ private Management management;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
+ public void runCommand(Player player, List arguments) {
String oldPassword = arguments.get(0);
String newPassword = arguments.get(1);
String name = player.getName().toLowerCase();
- final PlayerCache playerCache = commandService.getPlayerCache();
if (!playerCache.isAuthenticated(name)) {
commandService.send(player, MessageKey.NOT_LOGGED_IN);
return;
}
// Make sure the password is allowed
- MessageKey passwordError = commandService.validatePassword(newPassword, name);
- if (passwordError != null) {
- commandService.send(player, passwordError);
+ ValidationResult passwordValidation = validationService.validatePassword(newPassword, name);
+ if (passwordValidation.hasError()) {
+ commandService.send(player, passwordValidation.getMessageKey(), passwordValidation.getArgs());
return;
}
- AuthMe plugin = AuthMe.getInstance();
// TODO ljacqu 20160117: Call async task via Management
- commandService.runTaskAsynchronously(new ChangePasswordTask(plugin, player, oldPassword, newPassword));
+ management.performPasswordChange(player, oldPassword, newPassword);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java
index cd92ebf4..842d866d 100644
--- a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java
@@ -3,8 +3,10 @@ package fr.xephi.authme.command.executable.email;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.process.Management;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -12,14 +14,20 @@ import java.util.List;
*/
public class AddEmailCommand extends PlayerCommand {
+ @Inject
+ private Management management;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
+ public void runCommand(Player player, List arguments) {
String email = arguments.get(0);
String emailConfirmation = arguments.get(1);
if (email.equals(emailConfirmation)) {
// Closer inspection of the mail address handled by the async task
- commandService.getManagement().performAddEmail(player, email);
+ management.performAddEmail(player, email);
} else {
commandService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE);
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java
index 6d7281ac..1f9051e3 100644
--- a/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java
@@ -1,9 +1,10 @@
package fr.xephi.authme.command.executable.email;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
+import fr.xephi.authme.process.Management;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -11,11 +12,14 @@ import java.util.List;
*/
public class ChangeEmailCommand extends PlayerCommand {
+ @Inject
+ private Management management;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
+ public void runCommand(Player player, List arguments) {
String playerMailOld = arguments.get(0);
String playerMailNew = arguments.get(1);
- commandService.getManagement().performChangeEmail(player, playerMailOld, playerMailNew);
+ management.performChangeEmail(player, playerMailOld, playerMailNew);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/email/EmailBaseCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/EmailBaseCommand.java
index 3a79843e..0484e218 100644
--- a/src/main/java/fr/xephi/authme/command/executable/email/EmailBaseCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/email/EmailBaseCommand.java
@@ -1,11 +1,12 @@
package fr.xephi.authme.command.executable.email;
-import fr.xephi.authme.command.CommandService;
+import fr.xephi.authme.command.CommandMapper;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.FoundCommandResult;
import fr.xephi.authme.command.help.HelpProvider;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.Collections;
import java.util.List;
@@ -14,9 +15,15 @@ import java.util.List;
*/
public class EmailBaseCommand implements ExecutableCommand {
+ @Inject
+ private CommandMapper commandMapper;
+
+ @Inject
+ private HelpProvider helpProvider;
+
@Override
- public void executeCommand(CommandSender sender, List arguments, CommandService commandService) {
- FoundCommandResult result = commandService.mapPartsToCommand(sender, Collections.singletonList("email"));
- commandService.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN);
+ public void executeCommand(CommandSender sender, List arguments) {
+ FoundCommandResult result = commandMapper.mapPartsToCommand(sender, Collections.singletonList("email"));
+ helpProvider.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java
index f4a319a5..fac517ea 100644
--- a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java
@@ -8,28 +8,44 @@ import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
public class RecoverEmailCommand extends PlayerCommand {
+ @Inject
+ private PasswordSecurity passwordSecurity;
+
+ @Inject
+ private CommandService commandService;
+
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private PlayerCache playerCache;
+
+ @Inject
+ // TODO #655: Remove injected AuthMe instance once Authme#mail is encapsulated
+ private AuthMe plugin;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
+ public void runCommand(Player player, List arguments) {
final String playerMail = arguments.get(0);
final String playerName = player.getName();
- final AuthMe plugin = commandService.getAuthMe();
if (plugin.mail == null) {
ConsoleLogger.showError("Mail API is not set");
commandService.send(player, MessageKey.ERROR);
return;
}
- DataSource dataSource = commandService.getDataSource();
if (dataSource.isAuthAvailable(playerName)) {
if (PlayerCache.getInstance().isAuthenticated(playerName)) {
commandService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
@@ -37,10 +53,10 @@ public class RecoverEmailCommand extends PlayerCommand {
}
String thePass = RandomString.generate(commandService.getProperty(EmailSettings.RECOVERY_PASSWORD_LENGTH));
- HashedPassword hashNew = commandService.getPasswordSecurity().computeHash(thePass, playerName);
+ HashedPassword hashNew = passwordSecurity.computeHash(thePass, playerName);
PlayerAuth auth;
- if (PlayerCache.getInstance().isAuthenticated(playerName)) {
- auth = PlayerCache.getInstance().getAuth(playerName);
+ if (playerCache.isAuthenticated(playerName)) {
+ auth = playerCache.getAuth(playerName);
} else if (dataSource.isAuthAvailable(playerName)) {
auth = dataSource.getAuth(playerName);
} else {
diff --git a/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java
index 5689ec63..8b4054ac 100644
--- a/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java
@@ -1,9 +1,10 @@
package fr.xephi.authme.command.executable.login;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
+import fr.xephi.authme.process.Management;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -11,9 +12,12 @@ import java.util.List;
*/
public class LoginCommand extends PlayerCommand {
+ @Inject
+ private Management management;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
+ public void runCommand(Player player, List arguments) {
final String password = arguments.get(0);
- commandService.getManagement().performLogin(player, password, false);
+ management.performLogin(player, password, false);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java b/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java
index 598d1738..83b17882 100644
--- a/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java
@@ -1,9 +1,10 @@
package fr.xephi.authme.command.executable.logout;
-import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
+import fr.xephi.authme.process.Management;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
/**
@@ -11,8 +12,11 @@ import java.util.List;
*/
public class LogoutCommand extends PlayerCommand {
+ @Inject
+ private Management management;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
- commandService.getManagement().performLogout(player);
+ public void runCommand(Player player, List arguments) {
+ management.performLogout(player);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java
index d060c56b..ed9f9eef 100644
--- a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java
@@ -4,12 +4,14 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
import static fr.xephi.authme.settings.properties.EmailSettings.RECOVERY_PASSWORD_LENGTH;
@@ -19,25 +21,31 @@ import static fr.xephi.authme.settings.properties.RestrictionSettings.ENABLE_PAS
public class RegisterCommand extends PlayerCommand {
+ @Inject
+ private Management management;
+
+ @Inject
+ private CommandService commandService;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
+ public void runCommand(Player player, List arguments) {
if (commandService.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
//for two factor auth we don't need to check the usage
- commandService.getManagement().performRegister(player, "", "");
+ management.performRegister(player, "", "", true);
return;
}
// Ensure that there is 1 argument, or 2 if confirmation is required
- final boolean useConfirmation = isConfirmationRequired(commandService);
+ final boolean useConfirmation = isConfirmationRequired();
if (arguments.isEmpty() || useConfirmation && arguments.size() < 2) {
commandService.send(player, MessageKey.USAGE_REGISTER);
return;
}
if (commandService.getProperty(USE_EMAIL_REGISTRATION)) {
- handleEmailRegistration(player, arguments, commandService);
+ handleEmailRegistration(player, arguments);
} else {
- handlePasswordRegistration(player, arguments, commandService);
+ handlePasswordRegistration(player, arguments);
}
}
@@ -46,15 +54,15 @@ public class RegisterCommand extends PlayerCommand {
return "/authme register ";
}
- private void handlePasswordRegistration(Player player, List arguments, CommandService commandService) {
+ private void handlePasswordRegistration(Player player, List arguments) {
if (commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION) && !arguments.get(0).equals(arguments.get(1))) {
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
} else {
- commandService.getManagement().performRegister(player, arguments.get(0), "");
+ management.performRegister(player, arguments.get(0), "", true);
}
}
- private void handleEmailRegistration(Player player, List arguments, CommandService commandService) {
+ private void handleEmailRegistration(Player player, List arguments) {
if (commandService.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) {
player.sendMessage("Cannot register: no email address is set for the server. "
+ "Please contact an administrator");
@@ -70,17 +78,16 @@ public class RegisterCommand extends PlayerCommand {
commandService.send(player, MessageKey.USAGE_REGISTER);
} else {
String thePass = RandomString.generate(commandService.getProperty(RECOVERY_PASSWORD_LENGTH));
- commandService.getManagement().performRegister(player, thePass, email);
+ management.performRegister(player, thePass, email, true);
}
}
/**
* Return whether the password or email has to be confirmed.
*
- * @param commandService The command service
* @return True if the confirmation is needed, false otherwise
*/
- private boolean isConfirmationRequired(CommandService commandService) {
+ private boolean isConfirmationRequired() {
return commandService.getProperty(USE_EMAIL_REGISTRATION)
? commandService.getProperty(ENABLE_CONFIRM_EMAIL)
: commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION);
diff --git a/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java
index 195f659e..720b136e 100644
--- a/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java
@@ -4,24 +4,35 @@ import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.process.Management;
import org.bukkit.entity.Player;
+import javax.inject.Inject;
import java.util.List;
public class UnregisterCommand extends PlayerCommand {
+ @Inject
+ private Management management;
+
+ @Inject
+ private CommandService commandService;
+
+ @Inject
+ private PlayerCache playerCache;
+
@Override
- public void runCommand(Player player, List arguments, CommandService commandService) {
+ public void runCommand(Player player, List arguments) {
String playerPass = arguments.get(0);
final String playerNameLowerCase = player.getName().toLowerCase();
// Make sure the player is authenticated
- if (!PlayerCache.getInstance().isAuthenticated(playerNameLowerCase)) {
+ if (!playerCache.isAuthenticated(playerNameLowerCase)) {
commandService.send(player, MessageKey.NOT_LOGGED_IN);
return;
}
// Unregister the player
- commandService.getManagement().performUnregister(player, playerPass, false);
+ management.performUnregister(player, playerPass, false);
}
}
diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java
index 7bc06f03..4e07639d 100644
--- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java
+++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java
@@ -4,16 +4,18 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import fr.xephi.authme.command.CommandArgumentDescription;
import fr.xephi.authme.command.CommandDescription;
-import fr.xephi.authme.command.CommandPermissions;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.command.FoundCommandResult;
+import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.permission.DefaultPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.permission.PermissionsManager;
-import fr.xephi.authme.util.CollectionUtils;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.properties.PluginSettings;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
@@ -23,7 +25,7 @@ import static java.util.Collections.singletonList;
/**
* Help syntax generator for AuthMe commands.
*/
-public class HelpProvider {
+public class HelpProvider implements SettingsDependent {
// --- Bit flags ---
/** Set to not show the command. */
@@ -43,14 +45,15 @@ public class HelpProvider {
public static final int ALL_OPTIONS = ~HIDE_COMMAND;
private final PermissionsManager permissionsManager;
- private final String helpHeader;
+ private String helpHeader;
- public HelpProvider(PermissionsManager permissionsManager, String helpHeader) {
+ @Inject
+ HelpProvider(PermissionsManager permissionsManager, NewSetting settings) {
this.permissionsManager = permissionsManager;
- this.helpHeader = helpHeader;
+ loadSettings(settings);
}
- public List printHelp(CommandSender sender, FoundCommandResult result, int options) {
+ private List printHelp(CommandSender sender, FoundCommandResult result, int options) {
if (result.getCommandDescription() == null) {
return singletonList(ChatColor.DARK_RED + "Failed to retrieve any help information!");
}
@@ -84,6 +87,25 @@ public class HelpProvider {
return lines;
}
+ /**
+ * Output the help for a given command.
+ *
+ * @param sender The sender to output the help to
+ * @param result The result to output information about
+ * @param options Output options, see {@link HelpProvider}
+ */
+ public void outputHelp(CommandSender sender, FoundCommandResult result, int options) {
+ List lines = printHelp(sender, result, options);
+ for (String line : lines) {
+ sender.sendMessage(line);
+ }
+ }
+
+ @Override
+ public void loadSettings(NewSetting settings) {
+ helpHeader = settings.getProperty(PluginSettings.HELP_HEADER);
+ }
+
private static void printDetailedDescription(CommandDescription command, List lines) {
lines.add(ChatColor.GOLD + "Short description: " + ChatColor.WHITE + command.getDescription());
lines.add(ChatColor.GOLD + "Detailed description:");
@@ -110,7 +132,6 @@ public class HelpProvider {
}
private static void printAlternatives(CommandDescription command, List correctLabels, List lines) {
- // TODO ljacqu 20151219: Need to show alternatives for base labels too? E.g. /r for /register
if (command.getLabels().size() <= 1 || correctLabels.size() <= 1) {
return;
}
@@ -130,25 +151,22 @@ public class HelpProvider {
private static void printPermissions(CommandDescription command, CommandSender sender,
PermissionsManager permissionsManager, List lines) {
- CommandPermissions permissions = command.getCommandPermissions();
- // TODO ljacqu 20151224: Isn't it possible to have a default permission but no permission nodes?
- if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) {
+ PermissionNode permission = command.getPermission();
+ if (permission == null) {
return;
}
lines.add(ChatColor.GOLD + "Permissions:");
- for (PermissionNode node : permissions.getPermissionNodes()) {
- boolean hasPermission = permissionsManager.hasPermission(sender, node);
- final String nodePermsString = "" + ChatColor.GRAY + ChatColor.ITALIC
- + (hasPermission ? " (You have permission)" : " (No permission)");
- lines.add(" " + ChatColor.YELLOW + ChatColor.ITALIC + node.getNode() + nodePermsString);
- }
+ boolean hasPermission = permissionsManager.hasPermission(sender, permission);
+ final String nodePermsString = "" + ChatColor.GRAY + ChatColor.ITALIC
+ + (hasPermission ? " (You have permission)" : " (No permission)");
+ lines.add(" " + ChatColor.YELLOW + ChatColor.ITALIC + permission.getNode() + nodePermsString);
// Addendum to the line to specify whether the sender has permission or not when default is OP_ONLY
- final DefaultPermission defaultPermission = permissions.getDefaultPermission();
+ final DefaultPermission defaultPermission = permission.getDefaultPermission();
String addendum = "";
if (DefaultPermission.OP_ONLY.equals(defaultPermission)) {
- addendum = PermissionsManager.evaluateDefaultPermission(defaultPermission, sender)
+ addendum = defaultPermission.evaluate(sender)
? " (You have permission)"
: " (No permission)";
}
@@ -156,7 +174,7 @@ public class HelpProvider {
+ defaultPermission.getTitle() + addendum);
// Evaluate if the sender has permission to the command
- if (permissionsManager.hasPermission(sender, command)) {
+ if (permissionsManager.hasPermission(sender, command.getPermission())) {
lines.add(ChatColor.GOLD + " Result: " + ChatColor.GREEN + ChatColor.ITALIC + "You have permission");
} else {
lines.add(ChatColor.GOLD + " Result: " + ChatColor.DARK_RED + ChatColor.ITALIC + "No permission");
diff --git a/src/main/java/fr/xephi/authme/converter/Converter.java b/src/main/java/fr/xephi/authme/converter/Converter.java
index 9068f02f..28f18fd9 100644
--- a/src/main/java/fr/xephi/authme/converter/Converter.java
+++ b/src/main/java/fr/xephi/authme/converter/Converter.java
@@ -1,7 +1,16 @@
package fr.xephi.authme.converter;
+import org.bukkit.command.CommandSender;
+
/**
- * Common supertype for AuthMe converters.
+ * Interface for AuthMe converters.
*/
-public interface Converter extends Runnable {
+public interface Converter {
+
+ /**
+ * Execute the conversion.
+ *
+ * @param sender the sender who initialized the conversion
+ */
+ void execute(CommandSender sender);
}
diff --git a/src/main/java/fr/xephi/authme/converter/CrazyLoginConverter.java b/src/main/java/fr/xephi/authme/converter/CrazyLoginConverter.java
index c617ccad..5a8c547a 100644
--- a/src/main/java/fr/xephi/authme/converter/CrazyLoginConverter.java
+++ b/src/main/java/fr/xephi/authme/converter/CrazyLoginConverter.java
@@ -1,47 +1,46 @@
package fr.xephi.authme.converter;
-import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.initialization.DataFolder;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.properties.ConverterSettings;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
/**
- * @author Xephi59
+ * Converter for CrazyLogin to AuthMe.
*/
public class CrazyLoginConverter implements Converter {
private final DataSource database;
- private final CommandSender sender;
+ private final NewSetting settings;
+ private final File dataFolder;
- /**
- * Constructor for CrazyLoginConverter.
- *
- * @param instance AuthMe
- * @param sender CommandSender
- */
- public CrazyLoginConverter(AuthMe instance, CommandSender sender) {
- this.database = instance.getDataSource();
- this.sender = sender;
+ @Inject
+ CrazyLoginConverter(@DataFolder File dataFolder, DataSource dataSource, NewSetting settings) {
+ this.dataFolder = dataFolder;
+ this.database = dataSource;
+ this.settings = settings;
}
@Override
- public void run() {
- String fileName = Settings.crazyloginFileName;
- try {
- File source = new File(AuthMe.getInstance().getDataFolder() + File.separator + fileName);
- if (!source.exists()) {
- sender.sendMessage("Error while trying to import data, please put " + fileName + " in AuthMe folder!");
- return;
- }
- String line;
- BufferedReader users = new BufferedReader(new FileReader(source));
+ public void execute(CommandSender sender) {
+ String fileName = settings.getProperty(ConverterSettings.CRAZYLOGIN_FILE_NAME);
+ File source = new File(dataFolder, fileName);
+ if (!source.exists()) {
+ sender.sendMessage("CrazyLogin file not found, please put " + fileName + " in AuthMe folder!");
+ return;
+ }
+
+ String line;
+ try (BufferedReader users = new BufferedReader(new FileReader(source))) {
while ((line = users.readLine()) != null) {
if (line.contains("|")) {
String[] args = line.split("\\|");
@@ -49,22 +48,21 @@ public class CrazyLoginConverter implements Converter {
continue;
}
String playerName = args[0];
- String psw = args[1];
- if (psw != null) {
+ String password = args[1];
+ if (password != null) {
PlayerAuth auth = PlayerAuth.builder()
.name(playerName.toLowerCase())
.realName(playerName)
- .password(psw, null)
+ .password(password, null)
.build();
database.saveAuth(auth);
}
}
}
- users.close();
ConsoleLogger.info("CrazyLogin database has been imported correctly");
} catch (IOException ex) {
- ConsoleLogger.showError(ex.getMessage());
ConsoleLogger.showError("Can't open the crazylogin database file! Does it exist?");
+ ConsoleLogger.logException("Encountered", ex);
}
}
diff --git a/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java b/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java
index 7919f6a0..82b2540d 100644
--- a/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java
+++ b/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java
@@ -12,7 +12,7 @@ import java.util.List;
/**
* Mandatory migration from the deprecated flat file datasource to SQLite.
*/
-public class ForceFlatToSqlite implements Converter {
+public class ForceFlatToSqlite {
private final DataSource source;
private final DataSource destination;
@@ -31,7 +31,6 @@ public class ForceFlatToSqlite implements Converter {
/**
* Perform the conversion.
*/
- @Override
public void run() {
List skippedPlayers = new ArrayList<>();
for (PlayerAuth auth : source.getAllAuths()) {
diff --git a/src/main/java/fr/xephi/authme/converter/RakamakConverter.java b/src/main/java/fr/xephi/authme/converter/RakamakConverter.java
index f1acf300..e568bb8b 100644
--- a/src/main/java/fr/xephi/authme/converter/RakamakConverter.java
+++ b/src/main/java/fr/xephi/authme/converter/RakamakConverter.java
@@ -1,14 +1,16 @@
package fr.xephi.authme.converter;
-import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
-import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.properties.ConverterSettings;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@@ -21,24 +23,26 @@ import java.util.Map.Entry;
*/
public class RakamakConverter implements Converter {
- private final AuthMe instance;
private final DataSource database;
- private final CommandSender sender;
+ private final NewSetting settings;
private final File pluginFolder;
+ private final PasswordSecurity passwordSecurity;
- public RakamakConverter(AuthMe instance, CommandSender sender) {
- this.instance = instance;
- this.database = instance.getDataSource();
- this.sender = sender;
- pluginFolder = instance.getDataFolder();
+ @Inject
+ RakamakConverter(@DataFolder File dataFolder, DataSource dataSource, NewSetting settings,
+ PasswordSecurity passwordSecurity) {
+ this.database = dataSource;
+ this.settings = settings;
+ this.pluginFolder = dataFolder;
+ this.passwordSecurity = passwordSecurity;
}
@Override
// TODO ljacqu 20151229: Restructure this into smaller portions
- public void run() {
- boolean useIP = Settings.rakamakUseIp;
- String fileName = Settings.rakamakUsers;
- String ipFileName = Settings.rakamakUsersIp;
+ public void execute(CommandSender sender) {
+ boolean useIP = settings.getProperty(ConverterSettings.RAKAMAK_USE_IP);
+ String fileName = settings.getProperty(ConverterSettings.RAKAMAK_FILE_NAME);
+ String ipFileName = settings.getProperty(ConverterSettings.RAKAMAK_IP_FILE_NAME);
File source = new File(pluginFolder, fileName);
File ipfiles = new File(pluginFolder, ipFileName);
HashMap playerIP = new HashMap<>();
@@ -60,7 +64,6 @@ public class RakamakConverter implements Converter {
ipFile.close();
users = new BufferedReader(new FileReader(source));
- PasswordSecurity passwordSecurity = instance.getPasswordSecurity();
while ((line = users.readLine()) != null) {
if (line.contains("=")) {
String[] arguments = line.split("=");
diff --git a/src/main/java/fr/xephi/authme/converter/RoyalAuthConverter.java b/src/main/java/fr/xephi/authme/converter/RoyalAuthConverter.java
index b79657e2..49cde259 100644
--- a/src/main/java/fr/xephi/authme/converter/RoyalAuthConverter.java
+++ b/src/main/java/fr/xephi/authme/converter/RoyalAuthConverter.java
@@ -5,9 +5,11 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import org.bukkit.OfflinePlayer;
+import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
+import javax.inject.Inject;
import java.io.File;
import static fr.xephi.authme.util.StringUtils.makePath;
@@ -19,13 +21,14 @@ public class RoyalAuthConverter implements Converter {
private final AuthMe plugin;
private final DataSource dataSource;
- public RoyalAuthConverter(AuthMe plugin) {
+ @Inject
+ RoyalAuthConverter(AuthMe plugin, DataSource dataSource) {
this.plugin = plugin;
- this.dataSource = plugin.getDataSource();
+ this.dataSource = dataSource;
}
@Override
- public void run() {
+ public void execute(CommandSender sender) {
for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) {
try {
String name = player.getName().toLowerCase();
diff --git a/src/main/java/fr/xephi/authme/converter/SqliteToSql.java b/src/main/java/fr/xephi/authme/converter/SqliteToSql.java
index 0791613e..61168480 100644
--- a/src/main/java/fr/xephi/authme/converter/SqliteToSql.java
+++ b/src/main/java/fr/xephi/authme/converter/SqliteToSql.java
@@ -1,40 +1,43 @@
package fr.xephi.authme.converter;
-import fr.xephi.authme.settings.NewSetting;
-import org.bukkit.command.CommandSender;
-
-import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
+import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType;
import fr.xephi.authme.datasource.SQLite;
import fr.xephi.authme.output.MessageKey;
+import fr.xephi.authme.output.Messages;
+import fr.xephi.authme.settings.NewSetting;
+import org.bukkit.command.CommandSender;
+
+import javax.inject.Inject;
public class SqliteToSql implements Converter {
- private final AuthMe plugin;
- private final CommandSender sender;
private final NewSetting settings;
+ private final DataSource dataSource;
+ private final Messages messages;
- public SqliteToSql(AuthMe plugin, CommandSender sender, NewSetting settings) {
- this.plugin = plugin;
- this.sender = sender;
+ @Inject
+ SqliteToSql(NewSetting settings, DataSource dataSource, Messages messages) {
this.settings = settings;
+ this.dataSource = dataSource;
+ this.messages = messages;
}
@Override
- public void run() {
- if (plugin.getDataSource().getType() != DataSourceType.MYSQL) {
+ public void execute(CommandSender sender) {
+ if (dataSource.getType() != DataSourceType.MYSQL) {
sender.sendMessage("Please configure your mySQL connection and re-run this command");
return;
}
try {
SQLite data = new SQLite(settings);
for (PlayerAuth auth : data.getAllAuths()) {
- plugin.getDataSource().saveAuth(auth);
+ dataSource.saveAuth(auth);
}
} catch (Exception e) {
- plugin.getMessages().send(sender, MessageKey.ERROR);
+ messages.send(sender, MessageKey.ERROR);
ConsoleLogger.logException("Problem during SQLite to SQL conversion:", e);
}
}
diff --git a/src/main/java/fr/xephi/authme/converter/vAuthConverter.java b/src/main/java/fr/xephi/authme/converter/vAuthConverter.java
index 2e3d9746..7c6f3ea5 100644
--- a/src/main/java/fr/xephi/authme/converter/vAuthConverter.java
+++ b/src/main/java/fr/xephi/authme/converter/vAuthConverter.java
@@ -4,18 +4,19 @@ import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
+
public class vAuthConverter implements Converter {
private final AuthMe plugin;
- private final CommandSender sender;
- public vAuthConverter(AuthMe plugin, CommandSender sender) {
+ @Inject
+ vAuthConverter(AuthMe plugin) {
this.plugin = plugin;
- this.sender = sender;
}
@Override
- public void run() {
+ public void execute(CommandSender sender) {
try {
new vAuthFileReader(plugin).convert();
} catch (Exception e) {
diff --git a/src/main/java/fr/xephi/authme/converter/xAuthConverter.java b/src/main/java/fr/xephi/authme/converter/xAuthConverter.java
index 696f86fd..6fdddbf7 100644
--- a/src/main/java/fr/xephi/authme/converter/xAuthConverter.java
+++ b/src/main/java/fr/xephi/authme/converter/xAuthConverter.java
@@ -3,18 +3,19 @@ package fr.xephi.authme.converter;
import fr.xephi.authme.AuthMe;
import org.bukkit.command.CommandSender;
+import javax.inject.Inject;
+
public class xAuthConverter implements Converter {
private final AuthMe plugin;
- private final CommandSender sender;
- public xAuthConverter(AuthMe plugin, CommandSender sender) {
+ @Inject
+ xAuthConverter(AuthMe plugin) {
this.plugin = plugin;
- this.sender = sender;
}
@Override
- public void run() {
+ public void execute(CommandSender sender) {
try {
Class.forName("de.luricos.bukkit.xAuth.xAuth");
xAuthToFlat converter = new xAuthToFlat(plugin, sender);
diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
index 6aad92b2..12d45d20 100644
--- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
+++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
@@ -8,6 +8,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
@@ -15,12 +16,11 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-/**
- */
public class CacheDataSource implements DataSource {
private final DataSource source;
@@ -41,7 +41,8 @@ public class CacheDataSource implements DataSource {
.build())
);
cachedAuths = CacheBuilder.newBuilder()
- .refreshAfterWrite(8, TimeUnit.MINUTES)
+ .refreshAfterWrite(5, TimeUnit.MINUTES)
+ .expireAfterAccess(15, TimeUnit.MINUTES)
.build(new CacheLoader>() {
@Override
public Optional load(String key) {
@@ -53,6 +54,7 @@ public class CacheDataSource implements DataSource {
return executorService.submit(new Callable>() {
@Override
public Optional call() {
+ ConsoleLogger.debug("REFRESH " + key);
return load(key);
}
});
@@ -70,7 +72,7 @@ public class CacheDataSource implements DataSource {
}
@Override
- public synchronized boolean isAuthAvailable(String user) {
+ public boolean isAuthAvailable(String user) {
return getAuth(user) != null;
}
@@ -85,13 +87,13 @@ public class CacheDataSource implements DataSource {
}
@Override
- public synchronized PlayerAuth getAuth(String user) {
+ public PlayerAuth getAuth(String user) {
user = user.toLowerCase();
return cachedAuths.getUnchecked(user).orNull();
}
@Override
- public synchronized boolean saveAuth(PlayerAuth auth) {
+ public boolean saveAuth(PlayerAuth auth) {
boolean result = source.saveAuth(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
@@ -100,7 +102,7 @@ public class CacheDataSource implements DataSource {
}
@Override
- public synchronized boolean updatePassword(PlayerAuth auth) {
+ public boolean updatePassword(PlayerAuth auth) {
boolean result = source.updatePassword(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
@@ -137,16 +139,17 @@ public class CacheDataSource implements DataSource {
}
@Override
- public List autoPurgeDatabase(long until) {
- List cleared = source.autoPurgeDatabase(until);
+ public Set autoPurgeDatabase(long until) {
+ Set cleared = source.autoPurgeDatabase(until);
for (String name : cleared) {
cachedAuths.invalidate(name);
}
+
return cleared;
}
@Override
- public synchronized boolean removeAuth(String name) {
+ public boolean removeAuth(String name) {
name = name.toLowerCase();
boolean result = source.removeAuth(name);
if (result) {
@@ -156,7 +159,7 @@ public class CacheDataSource implements DataSource {
}
@Override
- public synchronized void close() {
+ public void close() {
source.close();
cachedAuths.invalidateAll();
executorService.shutdown();
@@ -168,7 +171,7 @@ public class CacheDataSource implements DataSource {
}
@Override
- public synchronized boolean updateEmail(final PlayerAuth auth) {
+ public boolean updateEmail(final PlayerAuth auth) {
boolean result = source.updateEmail(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
@@ -177,17 +180,17 @@ public class CacheDataSource implements DataSource {
}
@Override
- public synchronized List getAllAuthsByIp(final String ip) {
+ public List getAllAuthsByIp(final String ip) {
return source.getAllAuthsByIp(ip);
}
@Override
- public synchronized int countAuthsByEmail(final String email) {
+ public int countAuthsByEmail(final String email) {
return source.countAuthsByEmail(email);
}
@Override
- public synchronized void purgeBanned(final List banned) {
+ public void purgeBanned(final Set banned) {
source.purgeBanned(banned);
cachedAuths.invalidateAll(banned);
}
diff --git a/src/main/java/fr/xephi/authme/datasource/DataSource.java b/src/main/java/fr/xephi/authme/datasource/DataSource.java
index 4c844a83..dd80bc76 100644
--- a/src/main/java/fr/xephi/authme/datasource/DataSource.java
+++ b/src/main/java/fr/xephi/authme/datasource/DataSource.java
@@ -1,14 +1,16 @@
package fr.xephi.authme.datasource;
import fr.xephi.authme.cache.auth.PlayerAuth;
+import fr.xephi.authme.initialization.Reloadable;
import fr.xephi.authme.security.crypts.HashedPassword;
import java.util.List;
+import java.util.Set;
/**
* Interface for manipulating {@link PlayerAuth} objects from a data source.
*/
-public interface DataSource {
+public interface DataSource extends Reloadable {
/**
* Return whether there is a record for the given username.
@@ -74,7 +76,7 @@ public interface DataSource {
* @param until The minimum last login
* @return The account names that have been removed
*/
- List autoPurgeDatabase(long until);
+ Set autoPurgeDatabase(long until);
/**
* Remove a user record from the database.
@@ -126,7 +128,7 @@ public interface DataSource {
*
* @param banned the list of players to delete
*/
- void purgeBanned(List banned);
+ void purgeBanned(Set banned);
/**
* Return the data source type.
@@ -204,6 +206,7 @@ public interface DataSource {
/**
* Reload the data source.
*/
+ @Override
void reload();
}
diff --git a/src/main/java/fr/xephi/authme/datasource/FlatFile.java b/src/main/java/fr/xephi/authme/datasource/FlatFile.java
index b36fa279..fa9d291e 100644
--- a/src/main/java/fr/xephi/authme/datasource/FlatFile.java
+++ b/src/main/java/fr/xephi/authme/datasource/FlatFile.java
@@ -17,7 +17,9 @@ import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Deprecated flat file datasource. The only method guaranteed to work is {@link FlatFile#getAllAuths()}
@@ -227,11 +229,11 @@ public class FlatFile implements DataSource {
}
@Override
- public List autoPurgeDatabase(long until) {
+ public Set autoPurgeDatabase(long until) {
BufferedReader br = null;
BufferedWriter bw = null;
ArrayList lines = new ArrayList<>();
- List cleared = new ArrayList<>();
+ Set cleared = new HashSet<>();
try {
br = new BufferedReader(new FileReader(source));
String line;
@@ -256,6 +258,7 @@ public class FlatFile implements DataSource {
silentClose(br);
silentClose(bw);
}
+
return cleared;
}
@@ -414,7 +417,7 @@ public class FlatFile implements DataSource {
}
@Override
- public void purgeBanned(List banned) {
+ public void purgeBanned(Set banned) {
BufferedReader br = null;
BufferedWriter bw = null;
ArrayList lines = new ArrayList<>();
diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java
index 5182b859..94e43e00 100644
--- a/src/main/java/fr/xephi/authme/datasource/MySQL.java
+++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java
@@ -3,6 +3,7 @@ package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
+
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.HashAlgorithm;
@@ -24,10 +25,10 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
-/**
- */
public class MySQL implements DataSource {
private final String host;
@@ -105,34 +106,36 @@ public class MySQL implements DataSource {
ds = hikariDataSource;
}
- private synchronized void setConnectionArguments() throws RuntimeException {
+ private void setConnectionArguments() throws RuntimeException {
ds = new HikariDataSource();
ds.setPoolName("AuthMeMYSQLPool");
- ds.setDriverClassName("com.mysql.jdbc.Driver");
- ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
- ds.addDataSourceProperty("rewriteBatchedStatements", "true");
- ds.addDataSourceProperty("jdbcCompliantTruncation", "false");
- ds.addDataSourceProperty("cachePrepStmts", "true");
- ds.addDataSourceProperty("prepStmtCacheSize", "250");
- ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
- //set utf-8 as default encoding
+ // Database URL
+ ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
+
+ // Auth
+ ds.setUsername(this.username);
+ ds.setPassword(this.password);
+
+ // Encoding
ds.addDataSourceProperty("characterEncoding", "utf8");
ds.addDataSourceProperty("encoding","UTF-8");
ds.addDataSourceProperty("useUnicode", "true");
- ds.setUsername(this.username);
- ds.setPassword(this.password);
- ds.setInitializationFailFast(true); // Don't start the plugin if the database is unavailable
- ds.setMaxLifetime(180000); // 3 Min
- ds.setIdleTimeout(60000); // 1 Min
- ds.setMinimumIdle(2);
- ds.setMaximumPoolSize((Runtime.getRuntime().availableProcessors() * 2) + 1);
+ // Random stuff
+ ds.addDataSourceProperty("rewriteBatchedStatements", "true");
+ ds.addDataSourceProperty("jdbcCompliantTruncation", "false");
+
+ // Caching
+ ds.addDataSourceProperty("cachePrepStmts", "true");
+ ds.addDataSourceProperty("prepStmtCacheSize", "250");
+ ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
+
ConsoleLogger.info("Connection arguments loaded, Hikari ConnectionPool ready!");
}
@Override
- public synchronized void reload() throws RuntimeException {
+ public void reload() throws RuntimeException {
if (ds != null) {
ds.close();
}
@@ -140,11 +143,11 @@ public class MySQL implements DataSource {
ConsoleLogger.info("Hikari ConnectionPool arguments reloaded!");
}
- private synchronized Connection getConnection() throws SQLException {
+ private Connection getConnection() throws SQLException {
return ds.getConnection();
}
- private synchronized void setupConnection() throws SQLException {
+ private void setupConnection() throws SQLException {
try (Connection con = getConnection()) {
Statement st = con.createStatement();
DatabaseMetaData md = con.getMetaData();
@@ -257,7 +260,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized boolean isAuthAvailable(String user) {
+ public boolean isAuthAvailable(String user) {
String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
ResultSet rs = null;
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
@@ -293,7 +296,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized PlayerAuth getAuth(String user) {
+ public PlayerAuth getAuth(String user) {
String sql = "SELECT * FROM " + tableName + " WHERE " + col.NAME + "=?;";
PlayerAuth auth;
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
@@ -327,7 +330,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized boolean saveAuth(PlayerAuth auth) {
+ public boolean saveAuth(PlayerAuth auth) {
try (Connection con = getConnection()) {
PreparedStatement pst;
PreparedStatement pst2;
@@ -424,6 +427,7 @@ public class MySQL implements DataSource {
rs.close();
pst.close();
} else if (hashAlgorithm == HashAlgorithm.WORDPRESS) {
+ // NOTE: Eclipse says pst should be closed HERE, but it's a bug, we already close it above. -sgdc3
pst = con.prepareStatement("SELECT " + col.ID + " FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, auth.getNickname());
rs = pst.executeQuery();
@@ -500,6 +504,7 @@ public class MySQL implements DataSource {
rs.close();
pst.close();
} else if (hashAlgorithm == HashAlgorithm.XFBCRYPT) {
+ // NOTE: Eclipse says pst should be closed HERE, but it's a bug, we already close it above. -sgdc3
pst = con.prepareStatement("SELECT " + col.ID + " FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, auth.getNickname());
rs = pst.executeQuery();
@@ -528,7 +533,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized boolean updatePassword(PlayerAuth auth) {
+ public boolean updatePassword(PlayerAuth auth) {
return updatePassword(auth.getNickname(), auth.getPassword());
}
@@ -591,7 +596,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized boolean updateSession(PlayerAuth auth) {
+ public boolean updateSession(PlayerAuth auth) {
String sql = "UPDATE " + tableName + " SET "
+ col.IP + "=?, " + col.LAST_LOGIN + "=?, " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
@@ -608,8 +613,8 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized List autoPurgeDatabase(long until) {
- List list = new ArrayList<>();
+ public Set autoPurgeDatabase(long until) {
+ Set list = new HashSet<>();
String select = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.LAST_LOGIN + ";";
String delete = "DELETE FROM " + tableName + " WHERE " + col.LAST_LOGIN + ";";
try (Connection con = getConnection();
@@ -626,11 +631,12 @@ public class MySQL implements DataSource {
} catch (SQLException ex) {
logSqlException(ex);
}
+
return list;
}
@Override
- public synchronized boolean removeAuth(String user) {
+ public boolean removeAuth(String user) {
user = user.toLowerCase();
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
PreparedStatement xfSelect = null;
@@ -663,7 +669,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized boolean updateQuitLoc(PlayerAuth auth) {
+ public boolean updateQuitLoc(PlayerAuth auth) {
String sql = "UPDATE " + tableName
+ " SET " + col.LASTLOC_X + " =?, " + col.LASTLOC_Y + "=?, " + col.LASTLOC_Z + "=?, " + col.LASTLOC_WORLD + "=?"
+ " WHERE " + col.NAME + "=?;";
@@ -682,7 +688,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized boolean updateEmail(PlayerAuth auth) {
+ public boolean updateEmail(PlayerAuth auth) {
String sql = "UPDATE " + tableName + " SET " + col.EMAIL + " =? WHERE " + col.NAME + "=?;";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, auth.getEmail());
@@ -696,14 +702,14 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized void close() {
+ public void close() {
if (ds != null && !ds.isClosed()) {
ds.close();
}
}
@Override
- public synchronized List getAllAuthsByIp(String ip) {
+ public List getAllAuthsByIp(String ip) {
List result = new ArrayList<>();
String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.IP + "=?;";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
@@ -720,7 +726,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized int countAuthsByEmail(String email) {
+ public int countAuthsByEmail(String email) {
String sql = "SELECT COUNT(1) FROM " + tableName + " WHERE UPPER(" + col.EMAIL + ") = UPPER(?)";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, email);
@@ -736,7 +742,7 @@ public class MySQL implements DataSource {
}
@Override
- public synchronized void purgeBanned(List banned) {
+ public void purgeBanned(Set banned) {
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
for (String name : banned) {
diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java
index dfc74740..8072d58f 100644
--- a/src/main/java/fr/xephi/authme/datasource/SQLite.java
+++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java
@@ -1,14 +1,5 @@
package fr.xephi.authme.datasource;
-import com.google.common.annotations.VisibleForTesting;
-import fr.xephi.authme.ConsoleLogger;
-import fr.xephi.authme.cache.auth.PlayerAuth;
-import fr.xephi.authme.security.crypts.HashedPassword;
-import fr.xephi.authme.settings.NewSetting;
-import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.settings.properties.DatabaseSettings;
-import fr.xephi.authme.util.StringUtils;
-
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@@ -16,7 +7,19 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import fr.xephi.authme.ConsoleLogger;
+import fr.xephi.authme.cache.auth.PlayerAuth;
+import fr.xephi.authme.security.crypts.HashedPassword;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.properties.DatabaseSettings;
+import fr.xephi.authme.util.StringUtils;
/**
*/
@@ -61,14 +64,13 @@ public class SQLite implements DataSource {
ConsoleLogger.logException("Error while executing SQL statement:", e);
}
- private synchronized void connect() throws ClassNotFoundException, SQLException {
+ private void connect() throws ClassNotFoundException, SQLException {
Class.forName("org.sqlite.JDBC");
ConsoleLogger.info("SQLite driver loaded");
this.con = DriverManager.getConnection("jdbc:sqlite:plugins/AuthMe/" + database + ".db");
-
}
- private synchronized void setup() throws SQLException {
+ private void setup() throws SQLException {
Statement st = null;
ResultSet rs = null;
try {
@@ -131,11 +133,17 @@ public class SQLite implements DataSource {
@Override
public void reload() {
- // TODO 20160309: Implement reloading
+ close(con);
+ try {
+ this.connect();
+ this.setup();
+ } catch (ClassNotFoundException | SQLException ex) {
+ ConsoleLogger.logException("Error during SQLite initialization:", ex);
+ }
}
@Override
- public synchronized boolean isAuthAvailable(String user) {
+ public boolean isAuthAvailable(String user) {
PreparedStatement pst = null;
ResultSet rs = null;
try {
@@ -173,7 +181,7 @@ public class SQLite implements DataSource {
}
@Override
- public synchronized PlayerAuth getAuth(String user) {
+ public PlayerAuth getAuth(String user) {
PreparedStatement pst = null;
ResultSet rs = null;
try {
@@ -193,7 +201,7 @@ public class SQLite implements DataSource {
}
@Override
- public synchronized boolean saveAuth(PlayerAuth auth) {
+ public boolean saveAuth(PlayerAuth auth) {
PreparedStatement pst = null;
try {
HashedPassword password = auth.getPassword();
@@ -234,7 +242,7 @@ public class SQLite implements DataSource {
}
@Override
- public synchronized boolean updatePassword(PlayerAuth auth) {
+ public boolean updatePassword(PlayerAuth auth) {
return updatePassword(auth.getNickname(), auth.getPassword());
}
@@ -285,8 +293,8 @@ public class SQLite implements DataSource {
}
@Override
- public List autoPurgeDatabase(long until) {
- List list = new ArrayList<>();
+ public Set autoPurgeDatabase(long until) {
+ Set list = new HashSet<>();
String select = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.LAST_LOGIN + ";";
String delete = "DELETE FROM " + tableName + " WHERE " + col.LAST_LOGIN + ";";
try (PreparedStatement selectPst = con.prepareStatement(select);
@@ -302,11 +310,12 @@ public class SQLite implements DataSource {
} catch (SQLException ex) {
logSqlException(ex);
}
+
return list;
}
@Override
- public synchronized boolean removeAuth(String user) {
+ public boolean removeAuth(String user) {
PreparedStatement pst = null;
try {
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;");
@@ -356,7 +365,7 @@ public class SQLite implements DataSource {
}
@Override
- public synchronized void close() {
+ public void close() {
try {
if (con != null && !con.isClosed()) {
con.close();
@@ -376,6 +385,16 @@ public class SQLite implements DataSource {
}
}
+ private void close(Connection con) {
+ if (con != null) {
+ try {
+ con.close();
+ } catch (SQLException ex) {
+ logSqlException(ex);
+ }
+ }
+ }
+
private void close(ResultSet rs) {
if (rs != null) {
try {
@@ -425,7 +444,7 @@ public class SQLite implements DataSource {
}
@Override
- public void purgeBanned(List banned) {
+ public void purgeBanned(Set banned) {
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
try (PreparedStatement pst = con.prepareStatement(sql)) {
for (String name : banned) {
diff --git a/src/main/java/fr/xephi/authme/events/AbstractTeleportEvent.java b/src/main/java/fr/xephi/authme/events/AbstractTeleportEvent.java
index 57a456b6..51d366d9 100644
--- a/src/main/java/fr/xephi/authme/events/AbstractTeleportEvent.java
+++ b/src/main/java/fr/xephi/authme/events/AbstractTeleportEvent.java
@@ -19,25 +19,13 @@ public abstract class AbstractTeleportEvent extends CustomEvent implements Cance
*
* @param isAsync Whether to fire the event asynchronously or not
* @param player The player
- * @param from The location the player is being teleported away from
- * @param to The teleport destination
- */
- public AbstractTeleportEvent(boolean isAsync, Player player, Location from, Location to) {
- super(isAsync);
- this.player = player;
- this.from = from;
- this.to = to;
- }
-
- /**
- * Constructor, using the player's current location as "from" location.
- *
- * @param isAsync Whether to fire the event asynchronously or not
- * @param player The player
* @param to The teleport destination
*/
public AbstractTeleportEvent(boolean isAsync, Player player, Location to) {
- this(isAsync, player, player.getLocation(), to);
+ super(isAsync);
+ this.player = player;
+ this.from = player.getLocation();
+ this.to = to;
}
/**
diff --git a/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java b/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java
index b2a5819a..843cfaf2 100644
--- a/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java
+++ b/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java
@@ -5,7 +5,8 @@ import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
/**
- * This event is called when a player uses the /login command with correct credentials.
+ * This event is called when a player uses the login command,
+ * it's fired even when a user does a /login with invalid password.
* {@link #setCanLogin(boolean) event.setCanLogin(false)} prevents the player from logging in.
*/
public class AuthMeAsyncPreLoginEvent extends CustomEvent {
diff --git a/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java b/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java
index 28532b39..e5e6868d 100644
--- a/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java
+++ b/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java
@@ -17,11 +17,10 @@ public class FirstSpawnTeleportEvent extends AbstractTeleportEvent {
* Constructor.
*
* @param player The player
- * @param from The location the player is being teleported away from
* @param to The teleport destination
*/
- public FirstSpawnTeleportEvent(Player player, Location from, Location to) {
- super(true, player, from, to);
+ public FirstSpawnTeleportEvent(Player player, Location to) {
+ super(false, player, to);
}
/**
diff --git a/src/main/java/fr/xephi/authme/events/LoginEvent.java b/src/main/java/fr/xephi/authme/events/LoginEvent.java
index 6c2647fd..eb38d626 100644
--- a/src/main/java/fr/xephi/authme/events/LoginEvent.java
+++ b/src/main/java/fr/xephi/authme/events/LoginEvent.java
@@ -30,6 +30,17 @@ public class LoginEvent extends CustomEvent {
return player;
}
+ /**
+ * Ensures compatibility with plugins like GuiRules.
+ *
+ * @return true
+ * @deprecated this will always return true because this event is only called if it was successful
+ */
+ @Deprecated
+ public boolean isLogin() {
+ return true;
+ }
+
/**
* Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link Event}.
*
diff --git a/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java b/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java
index 3a429bc3..a1a85d84 100644
--- a/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java
+++ b/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java
@@ -17,12 +17,11 @@ public class SpawnTeleportEvent extends AbstractTeleportEvent {
* Constructor.
*
* @param player The player
- * @param from The location the player is being teleported away from
* @param to The teleport destination
* @param isAuthenticated Whether or not the player is logged in
*/
- public SpawnTeleportEvent(Player player, Location from, Location to, boolean isAuthenticated) {
- super(false, player, from, to);
+ public SpawnTeleportEvent(Player player, Location to, boolean isAuthenticated) {
+ super(false, player, to);
this.isAuthenticated = isAuthenticated;
}
diff --git a/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java b/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java
index ed089b8a..47e7d17d 100644
--- a/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java
+++ b/src/main/java/fr/xephi/authme/hooks/BungeeCordMessage.java
@@ -2,29 +2,37 @@ package fr.xephi.authme.hooks;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
+
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.security.crypts.HashedPassword;
+import fr.xephi.authme.settings.properties.SecuritySettings;
+import fr.xephi.authme.util.BukkitService;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
-/**
- */
+import javax.inject.Inject;
+
+
public class BungeeCordMessage implements PluginMessageListener {
- private final AuthMe plugin;
+ @Inject
+ private DataSource dataSource;
+
+ @Inject
+ private BukkitService bukkitService;
+
+ @Inject
+ private PlayerCache playerCache;
+
+ @Inject
+ private AuthMe plugin;
+
+ BungeeCordMessage() { }
- /**
- * Constructor for BungeeCordMessage.
- *
- * @param plugin The plugin instance
- */
- public BungeeCordMessage(AuthMe plugin) {
- this.plugin = plugin;
- }
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
@@ -38,8 +46,7 @@ public class BungeeCordMessage implements PluginMessageListener {
final String[] args = str.split(";");
final String act = args[0];
final String name = args[1];
- final DataSource dataSource = plugin.getDataSource();
- plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
+ bukkitService.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
PlayerAuth auth = dataSource.getAuth(name);
@@ -47,23 +54,33 @@ public class BungeeCordMessage implements PluginMessageListener {
return;
}
if ("login".equals(act)) {
- PlayerCache.getInstance().updatePlayer(auth);
+ playerCache.updatePlayer(auth);
dataSource.setLogged(name);
- ConsoleLogger.info("Player " + auth.getNickname()
- + " has logged in from one of your server!");
+ //START 03062016 sgdc3: should fix #731 but we need to recode this mess
+ if (plugin.sessions.containsKey(name)) {
+ plugin.sessions.get(name).cancel();
+ plugin.sessions.remove(name);
+ }
+ //END
+
+ if (!plugin.getSettings().getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
+ ConsoleLogger.info("Player " + auth.getNickname() + " has logged in from one of your server!");
+ }
} else if ("logout".equals(act)) {
- PlayerCache.getInstance().removePlayer(name);
+ playerCache.removePlayer(name);
dataSource.setUnlogged(name);
- ConsoleLogger.info("Player " + auth.getNickname()
- + " has logged out from one of your server!");
+ if (!plugin.getSettings().getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
+ ConsoleLogger.info("Player " + auth.getNickname() + " has logged out from one of your server!");
+ }
} else if ("register".equals(act)) {
- ConsoleLogger.info("Player " + auth.getNickname()
- + " has registered out from one of your server!");
+ if (!plugin.getSettings().getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
+ ConsoleLogger.info("Player " + auth.getNickname() + " has registered out from one of your server!");
+ }
} else if ("changepassword".equals(act)) {
final String password = args[2];
final String salt = args.length >= 4 ? args[3] : null;
auth.setPassword(new HashedPassword(password, salt));
- PlayerCache.getInstance().updatePlayer(auth);
+ playerCache.updatePlayer(auth);
dataSource.updatePassword(auth);
}
diff --git a/src/main/java/fr/xephi/authme/hooks/PluginHooks.java b/src/main/java/fr/xephi/authme/hooks/PluginHooks.java
index fd455bb1..76f8e034 100644
--- a/src/main/java/fr/xephi/authme/hooks/PluginHooks.java
+++ b/src/main/java/fr/xephi/authme/hooks/PluginHooks.java
@@ -1,19 +1,18 @@
package fr.xephi.authme.hooks;
-import java.io.File;
-
+import com.earth2me.essentials.Essentials;
+import com.onarandombox.MultiverseCore.MultiverseCore;
+import com.onarandombox.MultiverseCore.api.MVWorldManager;
+import fr.xephi.authme.ConsoleLogger;
+import net.minelink.ctplus.CombatTagPlus;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
-import com.earth2me.essentials.Essentials;
-import com.onarandombox.MultiverseCore.MultiverseCore;
-import com.onarandombox.MultiverseCore.api.MVWorldManager;
-
-import fr.xephi.authme.ConsoleLogger;
-import net.minelink.ctplus.CombatTagPlus;
+import javax.inject.Inject;
+import java.io.File;
/**
* Hooks into third-party plugins and allows to perform actions on them.
@@ -30,6 +29,7 @@ public class PluginHooks {
*
* @param pluginManager The server's plugin manager
*/
+ @Inject
public PluginHooks(PluginManager pluginManager) {
this.pluginManager = pluginManager;
tryHookToCombatPlus();
@@ -77,13 +77,23 @@ public class PluginHooks {
return null;
}
+ /**
+ * Checks whether the player is an NPC.
+ *
+ * @param player The player to process
+ * @return True if player is NPC, false otherwise
+ */
+ public boolean isNpc(Player player) {
+ return player.hasMetadata("NPC") || isNpcInCombatTagPlus(player);
+ }
+
/**
* Query the CombatTagPlus plugin whether the given player is an NPC.
*
* @param player The player to verify
* @return True if the player is an NPC according to CombatTagPlus, false if not or if the plugin is unavailable
*/
- public boolean isNpcInCombatTagPlus(Player player) {
+ private boolean isNpcInCombatTagPlus(Player player) {
return combatTagPlus != null && combatTagPlus.getNpcPlayerHelper().isNpc(player);
}
diff --git a/src/main/java/fr/xephi/authme/initialization/AuthMeServiceInitializer.java b/src/main/java/fr/xephi/authme/initialization/AuthMeServiceInitializer.java
new file mode 100644
index 00000000..29e5adcf
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/initialization/AuthMeServiceInitializer.java
@@ -0,0 +1,324 @@
+package fr.xephi.authme.initialization;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import fr.xephi.authme.settings.NewSetting;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Provider;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Dependency injector of AuthMe: initializes and injects services and tasks.
+ *
+ * Only constructor and field injection are supported, indicated with the JSR330
+ * {@link javax.inject.Inject @Inject} annotation.
+ *
+ * {@link PostConstruct @PostConstruct} methods are recognized and invoked upon
+ * instantiation. Note that the parent classes are not scanned for such methods.
+ */
+public class AuthMeServiceInitializer {
+
+ private final Set ALLOWED_PACKAGES;
+ private final Map, Object> objects;
+
+ /**
+ * Constructor.
+ *
+ * @param allowedPackages list of allowed packages. Only classes whose package
+ * starts with any of the given entries will be instantiated
+ */
+ public AuthMeServiceInitializer(String... allowedPackages) {
+ ALLOWED_PACKAGES = ImmutableSet.copyOf(allowedPackages);
+ objects = new HashMap<>();
+ objects.put(getClass(), this);
+ }
+
+ /**
+ * Retrieves or instantiates an object of the given type.
+ *
+ * @param clazz the class to retrieve the value for
+ * @param the class' type
+ * @return object of the class' type
+ */
+ public T get(Class clazz) {
+ return get(clazz, new HashSet>());
+ }
+
+ /**
+ * Register an object with a custom class (supertype). Use this for example to specify a
+ * concrete implementation of an interface or an abstract class.
+ *
+ * @param clazz the class to register the object for
+ * @param object the object
+ * @param the class' type
+ */
+ public void register(Class super T> clazz, T object) {
+ if (objects.containsKey(clazz)) {
+ throw new IllegalStateException("There is already an object present for " + clazz);
+ }
+ Preconditions.checkNotNull(object);
+ objects.put(clazz, object);
+ }
+
+ /**
+ * Associate an annotation with a value.
+ *
+ * @param annotation the annotation
+ * @param value the value
+ */
+ public void provide(Class extends Annotation> annotation, Object value) {
+ if (objects.containsKey(annotation)) {
+ throw new IllegalStateException("Annotation @" + annotation.getClass().getSimpleName()
+ + " already registered");
+ }
+ Preconditions.checkNotNull(value);
+ objects.put(annotation, value);
+ }
+
+ /**
+ * Creates a new instance of the given class and does not keep track of it afterwards,
+ * unlike {@link #get(Class)} (singleton scope).
+ *
+ * @param clazz the class to instantiate
+ * @param the class' type
+ * @return new instance of class T
+ */
+ public T newInstance(Class clazz) {
+ return instantiate(clazz, new HashSet>());
+ }
+
+ /**
+ * Returns an instance of the given class if available. This simply returns the instance if present and
+ * otherwise {@code null}. Calling this method will not instantiate anything.
+ *
+ * @param clazz the class to retrieve the instance for
+ * @param the class' type
+ * @return instance or null if none available
+ */
+ public T getIfAvailable(Class clazz) {
+ if (Annotation.class.isAssignableFrom(clazz)) {
+ throw new UnsupportedOperationException("Annotations may not be retrieved in this way!");
+ }
+ return clazz.cast(objects.get(clazz));
+ }
+
+ /**
+ * Returns an instance of the given class by retrieving it or by instantiating it if not yet present.
+ *
+ * @param clazz the class to retrieve a value for
+ * @param traversedClasses the list of traversed classes
+ * @param the class' type
+ * @return instance or associated value (for annotations)
+ */
+ private T get(Class clazz, Set> traversedClasses) {
+ if (Annotation.class.isAssignableFrom(clazz)) {
+ throw new UnsupportedOperationException("Cannot retrieve annotated elements in this way!");
+ } else if (objects.containsKey(clazz)) {
+ return clazz.cast(objects.get(clazz));
+ }
+
+ // First time we come across clazz, need to instantiate it. Validate that we can do so
+ validatePackage(clazz);
+ validateInstantiable(clazz);
+
+ // Add the clazz to the list of traversed classes in a new Set, so each path we take has its own Set.
+ traversedClasses = new HashSet<>(traversedClasses);
+ traversedClasses.add(clazz);
+ T object = instantiate(clazz, traversedClasses);
+ storeObject(object);
+ return object;
+ }
+
+ /**
+ * Performs a reload on all applicable instances which are registered.
+ * Requires that the {@link NewSetting settings} instance be registered.
+ *
+ * Note that the order in which these classes are reloaded is not guaranteed.
+ */
+ public void performReloadOnServices() {
+ NewSetting settings = (NewSetting) objects.get(NewSetting.class);
+ if (settings == null) {
+ throw new IllegalStateException("Settings instance is null");
+ }
+ for (Object object : objects.values()) {
+ if (object instanceof Reloadable) {
+ ((Reloadable) object).reload();
+ } else if (object instanceof SettingsDependent) {
+ ((SettingsDependent) object).loadSettings(settings);
+ }
+ }
+ }
+
+ /**
+ * Instantiates the given class by locating its @Inject elements and retrieving
+ * or instantiating the required instances.
+ *
+ * @param clazz the class to instantiate
+ * @param traversedClasses collection of classes already traversed
+ * @param the class' type
+ * @return the instantiated object
+ */
+ private T instantiate(Class clazz, Set> traversedClasses) {
+ Injection injection = firstNotNull(
+ ConstructorInjection.provide(clazz), FieldInjection.provide(clazz), InstantiationFallback.provide(clazz));
+ if (injection == null) {
+ throw new IllegalStateException("Did not find injection method for " + clazz + ". Make sure you have "
+ + "a constructor with @Inject or fields with @Inject. Fields with @Inject require "
+ + "the default constructor");
+ }
+
+ validateInjectionHasNoCircularDependencies(injection.getDependencies(), traversedClasses);
+ Object[] dependencies = resolveDependencies(injection, traversedClasses);
+ T object = injection.instantiateWith(dependencies);
+ executePostConstructMethod(object);
+ return object;
+ }
+
+ /**
+ * Resolves the dependencies for the given class instantiation, i.e. returns a collection that satisfy
+ * the class' dependencies by retrieving elements or instantiating them where necessary.
+ *
+ * @param injection the injection parameters
+ * @param traversedClasses collection of traversed classes
+ * @return array with the parameters to use in the constructor
+ */
+ private Object[] resolveDependencies(Injection> injection, Set> traversedClasses) {
+ Class>[] dependencies = injection.getDependencies();
+ Class>[] annotations = injection.getDependencyAnnotations();
+ Object[] values = new Object[dependencies.length];
+ for (int i = 0; i < dependencies.length; ++i) {
+ if (annotations[i] == null) {
+ values[i] = get(dependencies[i], traversedClasses);
+ } else {
+ Object value = objects.get(annotations[i]);
+ if (value == null) {
+ throw new IllegalStateException("Value for field with @" + annotations[i].getSimpleName()
+ + " must be registered beforehand");
+ }
+ values[i] = value;
+ }
+ }
+ return values;
+ }
+
+ /**
+ * Stores the given object with its class as key. Throws an exception if the key already has
+ * a value associated to it.
+ *
+ * @param object the object to store
+ */
+ private void storeObject(Object object) {
+ if (objects.containsKey(object.getClass())) {
+ throw new IllegalStateException("There is already an object present for " + object.getClass());
+ }
+ Preconditions.checkNotNull(object);
+ objects.put(object.getClass(), object);
+ }
+
+ /**
+ * Validates that none of the dependencies' types are present in the given collection
+ * of traversed classes. This prevents circular dependencies.
+ *
+ * @param dependencies the dependencies of the class
+ * @param traversedClasses the collection of traversed classes
+ */
+ private static void validateInjectionHasNoCircularDependencies(Class>[] dependencies,
+ Set> traversedClasses) {
+ for (Class> clazz : dependencies) {
+ if (traversedClasses.contains(clazz)) {
+ throw new IllegalStateException("Found cyclic dependency - already traversed '" + clazz
+ + "' (full traversal list: " + traversedClasses + ")");
+ }
+ }
+ }
+
+ /**
+ * Validates the package of a parameter type to ensure that it is part of the allowed packages.
+ * This ensures that we don't try to instantiate things that are beyond our reach in case some
+ * external parameter type has not been registered.
+ *
+ * @param clazz the class to validate
+ */
+ private void validatePackage(Class> clazz) {
+ if (clazz.getPackage() == null) {
+ throw new IllegalStateException("Primitive types must be provided explicitly (or use an annotation).");
+ }
+ String packageName = clazz.getPackage().getName();
+ for (String allowedPackage : ALLOWED_PACKAGES) {
+ if (packageName.startsWith(allowedPackage)) {
+ return;
+ }
+ }
+ throw new IllegalStateException("Class " + clazz + " with package " + packageName + " is outside of the "
+ + "allowed packages. It must be provided explicitly or the package must be passed to the constructor.");
+ }
+
+ /**
+ * Executes an object's method annotated with {@link PostConstruct} if present.
+ * Throws an exception if there are multiple such methods, or if the method is static.
+ *
+ * @param object the object to execute the post construct method for
+ */
+ private static void executePostConstructMethod(Object object) {
+ Method postConstructMethod = getAndValidatePostConstructMethod(object.getClass());
+ if (postConstructMethod != null) {
+ try {
+ postConstructMethod.setAccessible(true);
+ postConstructMethod.invoke(object);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new UnsupportedOperationException("Error executing @PostConstruct method", e);
+ }
+ }
+ }
+
+ private static void validateInstantiable(Class> clazz) {
+ if (clazz.isEnum() || clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
+ throw new IllegalStateException("Class " + clazz.getSimpleName() + " cannot be instantiated");
+ }
+ }
+
+ /**
+ * Validate and locate the given class' post construct method. Returns {@code null} if none present.
+ *
+ * @param clazz the class to search
+ * @return post construct method, or null
+ */
+ private static Method getAndValidatePostConstructMethod(Class> clazz) {
+ Method postConstructMethod = null;
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(PostConstruct.class)) {
+ if (postConstructMethod != null) {
+ throw new IllegalStateException("Multiple methods with @PostConstruct on " + clazz);
+ } else if (method.getParameterTypes().length > 0 || Modifier.isStatic(method.getModifiers())) {
+ throw new IllegalStateException("@PostConstruct method may not be static or have any parameters. "
+ + "Invalid method in " + clazz);
+ } else if (method.getReturnType() != void.class) {
+ throw new IllegalStateException("@PostConstruct method must have return type void. "
+ + "Offending class: " + clazz);
+ } else {
+ postConstructMethod = method;
+ }
+ }
+ }
+ return postConstructMethod;
+ }
+
+ @SafeVarargs
+ private static Injection firstNotNull(Provider extends Injection>... providers) {
+ for (Provider extends Injection> provider : providers) {
+ Injection object = provider.get();
+ if (object != null) {
+ return object;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/initialization/ConstructorInjection.java b/src/main/java/fr/xephi/authme/initialization/ConstructorInjection.java
new file mode 100644
index 00000000..74ea28b2
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/initialization/ConstructorInjection.java
@@ -0,0 +1,86 @@
+package fr.xephi.authme.initialization;
+
+import com.google.common.base.Preconditions;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Functionality for constructor injection.
+ */
+public class ConstructorInjection implements Injection {
+
+ private final Constructor constructor;
+
+ private ConstructorInjection(Constructor constructor) {
+ this.constructor = constructor;
+ }
+
+ @Override
+ public Class>[] getDependencies() {
+ return constructor.getParameterTypes();
+ }
+
+ @Override
+ public Class>[] getDependencyAnnotations() {
+ Annotation[][] parameterAnnotations = constructor.getParameterAnnotations();
+ Class>[] annotations = new Class>[parameterAnnotations.length];
+ for (int i = 0; i < parameterAnnotations.length; ++i) {
+ annotations[i] = parameterAnnotations[i].length > 0
+ ? parameterAnnotations[i][0].annotationType()
+ : null;
+ }
+ return annotations;
+ }
+
+ @Override
+ public T instantiateWith(Object... values) {
+ validateNoNullValues(values);
+ try {
+ return constructor.newInstance(values);
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ }
+
+ public static Provider> provide(final Class clazz) {
+ return new Provider>() {
+ @Override
+ public ConstructorInjection get() {
+ Constructor constructor = getInjectionConstructor(clazz);
+ return constructor == null ? null : new ConstructorInjection<>(constructor);
+ }
+ };
+ }
+
+
+ /**
+ * Gets the first found constructor annotated with {@link Inject} of the given class
+ * and marks it as accessible.
+ *
+ * @param clazz the class to process
+ * @param the class' type
+ * @return injection constructor for the class, null if not applicable
+ */
+ @SuppressWarnings("unchecked")
+ private static Constructor getInjectionConstructor(Class