This commit is contained in:
Gabriele C 2020-02-02 19:05:12 +01:00
parent 3a00e290bb
commit c95443fda7
33 changed files with 203 additions and 150 deletions

View File

@ -31,6 +31,7 @@ import fr.xephi.authme.settings.SettingsWarner;
import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.CleanupTask; import fr.xephi.authme.task.CleanupTask;
import fr.xephi.authme.task.purge.PurgeService; import fr.xephi.authme.task.purge.PurgeService;
import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.util.ExceptionUtils; import fr.xephi.authme.util.ExceptionUtils;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.command.Command; import org.bukkit.command.Command;
@ -172,7 +173,9 @@ public class AuthMe extends JavaPlugin {
// Successful message // Successful message
logger.info("AuthMe " + getPluginVersion() + " build n." + getPluginBuildNumber() + " successfully enabled!"); logger.info("AuthMe " + getPluginVersion() + " build n." + getPluginBuildNumber() + " successfully enabled!");
// Start catching wrong sync/async calls // Start catching wrong sync/async calls
ThreadSafety.setEnabled(true); if(System.getProperty("authme.disableThreadSafetyChecks") == null) {
BukkitThreadSafety.setEnabled(true);
}
// Purge on start if enabled // Purge on start if enabled
PurgeService purgeService = injector.getSingleton(PurgeService.class); PurgeService purgeService = injector.getSingleton(PurgeService.class);

View File

@ -6,6 +6,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.SOURCE)
public @interface MightBeAsync { public @interface MightBeAsync {
} }

View File

@ -6,6 +6,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.SOURCE)
public @interface ShouldBeAsync { public @interface ShouldBeAsync {
} }

View File

@ -5,7 +5,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMap;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.converter.Converter; import fr.xephi.authme.datasource.converter.AbstractConverter;
import fr.xephi.authme.datasource.converter.CrazyLoginConverter; import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
import fr.xephi.authme.datasource.converter.LoginSecurityConverter; import fr.xephi.authme.datasource.converter.LoginSecurityConverter;
import fr.xephi.authme.datasource.converter.MySqlToSqlite; import fr.xephi.authme.datasource.converter.MySqlToSqlite;
@ -30,7 +30,7 @@ import java.util.Map;
public class ConverterCommand implements ExecutableCommand { public class ConverterCommand implements ExecutableCommand {
@VisibleForTesting @VisibleForTesting
static final Map<String, Class<? extends Converter>> CONVERTERS = getConverters(); static final Map<String, Class<? extends AbstractConverter>> CONVERTERS = getConverters();
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ConverterCommand.class); private final ConsoleLogger logger = ConsoleLoggerFactory.get(ConverterCommand.class);
@ -41,18 +41,18 @@ public class ConverterCommand implements ExecutableCommand {
private BukkitService bukkitService; private BukkitService bukkitService;
@Inject @Inject
private Factory<Converter> converterFactory; private Factory<AbstractConverter> converterFactory;
@Override @Override
public void executeCommand(CommandSender sender, List<String> arguments) { public void executeCommand(CommandSender sender, List<String> arguments) {
Class<? extends Converter> converterClass = getConverterClassFromArgs(arguments); Class<? extends AbstractConverter> converterClass = getConverterClassFromArgs(arguments);
if (converterClass == null) { if (converterClass == null) {
sender.sendMessage("Converters: " + String.join(", ", CONVERTERS.keySet())); sender.sendMessage("Converters: " + String.join(", ", CONVERTERS.keySet()));
return; return;
} }
// Get the proper converter instance // Get the proper converter instance
final Converter converter = converterFactory.newInstance(converterClass); final AbstractConverter converter = converterFactory.newInstance(converterClass);
// Run the convert job // Run the convert job
bukkitService.runTaskAsynchronously(() -> { bukkitService.runTaskAsynchronously(() -> {
@ -68,7 +68,7 @@ public class ConverterCommand implements ExecutableCommand {
sender.sendMessage("[AuthMe] Successfully started " + arguments.get(0)); sender.sendMessage("[AuthMe] Successfully started " + arguments.get(0));
} }
private static Class<? extends Converter> getConverterClassFromArgs(List<String> arguments) { private static Class<? extends AbstractConverter> getConverterClassFromArgs(List<String> arguments) {
return arguments.isEmpty() return arguments.isEmpty()
? null ? null
: CONVERTERS.get(arguments.get(0).toLowerCase()); : CONVERTERS.get(arguments.get(0).toLowerCase());
@ -79,8 +79,8 @@ public class ConverterCommand implements ExecutableCommand {
* *
* @return map with all available converters * @return map with all available converters
*/ */
private static Map<String, Class<? extends Converter>> getConverters() { private static Map<String, Class<? extends AbstractConverter>> getConverters() {
return ImmutableSortedMap.<String, Class<? extends Converter>>naturalOrder() return ImmutableSortedMap.<String, Class<? extends AbstractConverter>>naturalOrder()
.put("xauth", XAuthConverter.class) .put("xauth", XAuthConverter.class)
.put("crazylogin", CrazyLoginConverter.class) .put("crazylogin", CrazyLoginConverter.class)
.put("rakamak", RakamakConverter.class) .put("rakamak", RakamakConverter.class)

View File

@ -1,6 +1,5 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.annotation.MightBeAsync;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;

View File

@ -4,7 +4,7 @@ import ch.jalu.datasourcecolumns.data.DataSourceValue;
import ch.jalu.datasourcecolumns.data.DataSourceValueImpl; import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
import ch.jalu.datasourcecolumns.data.DataSourceValues; import ch.jalu.datasourcecolumns.data.DataSourceValues;
import ch.jalu.datasourcecolumns.predicate.AlwaysTruePredicate; import ch.jalu.datasourcecolumns.predicate.AlwaysTruePredicate;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.columnshandler.AuthMeColumns; import fr.xephi.authme.datasource.columnshandler.AuthMeColumns;
@ -31,7 +31,7 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean isAuthAvailable(String user) { public boolean isAuthAvailable(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
try { try {
return columnsHandler.retrieve(user, AuthMeColumns.NAME).rowExists(); return columnsHandler.retrieve(user, AuthMeColumns.NAME).rowExists();
} catch (SQLException e) { } catch (SQLException e) {
@ -43,7 +43,7 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public HashedPassword getPassword(String user) { public HashedPassword getPassword(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
try { try {
DataSourceValues values = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT); DataSourceValues values = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT);
if (values.rowExists()) { if (values.rowExists()) {
@ -58,7 +58,7 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean saveAuth(PlayerAuth auth) { public boolean saveAuth(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.insert(auth, return columnsHandler.insert(auth,
AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT, AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT,
AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP, AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP,
@ -68,7 +68,7 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean hasSession(String user) { public boolean hasSession(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
try { try {
DataSourceValue<Integer> result = columnsHandler.retrieve(user, AuthMeColumns.HAS_SESSION); DataSourceValue<Integer> result = columnsHandler.retrieve(user, AuthMeColumns.HAS_SESSION);
return result.rowExists() && Integer.valueOf(1).equals(result.getValue()); return result.rowExists() && Integer.valueOf(1).equals(result.getValue());
@ -81,21 +81,21 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateSession(PlayerAuth auth) { public boolean updateSession(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME); return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updatePassword(PlayerAuth auth) { public boolean updatePassword(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return updatePassword(auth.getNickname(), auth.getPassword()); return updatePassword(auth.getNickname(), auth.getPassword());
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updatePassword(String user, HashedPassword password) { public boolean updatePassword(String user, HashedPassword password) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(user, return columnsHandler.update(user,
with(AuthMeColumns.PASSWORD, password.getHash()) with(AuthMeColumns.PASSWORD, password.getHash())
.and(AuthMeColumns.SALT, password.getSalt()).build()); .and(AuthMeColumns.SALT, password.getSalt()).build());
@ -104,7 +104,7 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateQuitLoc(PlayerAuth auth) { public boolean updateQuitLoc(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(auth, return columnsHandler.update(auth,
AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z, AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z,
AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH); AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH);
@ -113,7 +113,7 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public List<String> getAllAuthsByIp(String ip) { public List<String> getAllAuthsByIp(String ip) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
try { try {
return columnsHandler.retrieve(eq(AuthMeColumns.LAST_IP, ip), AuthMeColumns.NAME); return columnsHandler.retrieve(eq(AuthMeColumns.LAST_IP, ip), AuthMeColumns.NAME);
} catch (SQLException e) { } catch (SQLException e) {
@ -125,21 +125,21 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public int countAuthsByEmail(String email) { public int countAuthsByEmail(String email) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.count(eqIgnoreCase(AuthMeColumns.EMAIL, email)); return columnsHandler.count(eqIgnoreCase(AuthMeColumns.EMAIL, email));
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateEmail(PlayerAuth auth) { public boolean updateEmail(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(auth, AuthMeColumns.EMAIL); return columnsHandler.update(auth, AuthMeColumns.EMAIL);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean isLogged(String user) { public boolean isLogged(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
try { try {
DataSourceValue<Integer> result = columnsHandler.retrieve(user, AuthMeColumns.IS_LOGGED); DataSourceValue<Integer> result = columnsHandler.retrieve(user, AuthMeColumns.IS_LOGGED);
return result.rowExists() && Integer.valueOf(1).equals(result.getValue()); return result.rowExists() && Integer.valueOf(1).equals(result.getValue());
@ -152,56 +152,56 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void setLogged(String user) { public void setLogged(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 1); columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 1);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void setUnlogged(String user) { public void setUnlogged(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 0); columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 0);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void grantSession(String user) { public void grantSession(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 1); columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 1);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void revokeSession(String user) { public void revokeSession(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 0); columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 0);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void purgeLogged() { public void purgeLogged() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(eq(AuthMeColumns.IS_LOGGED, 1), AuthMeColumns.IS_LOGGED, 0); columnsHandler.update(eq(AuthMeColumns.IS_LOGGED, 1), AuthMeColumns.IS_LOGGED, 0);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public int getAccountsRegistered() { public int getAccountsRegistered() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.count(new AlwaysTruePredicate<>()); return columnsHandler.count(new AlwaysTruePredicate<>());
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName); return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public DataSourceValue<String> getEmail(String user) { public DataSourceValue<String> getEmail(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
try { try {
return columnsHandler.retrieve(user, AuthMeColumns.EMAIL); return columnsHandler.retrieve(user, AuthMeColumns.EMAIL);
} catch (SQLException e) { } catch (SQLException e) {

View File

@ -10,7 +10,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache; import fr.xephi.authme.data.auth.PlayerCache;
@ -84,14 +84,14 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean isAuthAvailable(String user) { public boolean isAuthAvailable(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return getAuth(user) != null; return getAuth(user) != null;
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public HashedPassword getPassword(String user) { public HashedPassword getPassword(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
user = user.toLowerCase(); user = user.toLowerCase();
Optional<PlayerAuth> pAuthOpt = cachedAuths.getIfPresent(user); Optional<PlayerAuth> pAuthOpt = cachedAuths.getIfPresent(user);
if (pAuthOpt != null && pAuthOpt.isPresent()) { if (pAuthOpt != null && pAuthOpt.isPresent()) {
@ -103,7 +103,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public PlayerAuth getAuth(String user) { public PlayerAuth getAuth(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
user = user.toLowerCase(); user = user.toLowerCase();
return cachedAuths.getUnchecked(user).orElse(null); return cachedAuths.getUnchecked(user).orElse(null);
} }
@ -111,7 +111,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean saveAuth(PlayerAuth auth) { public boolean saveAuth(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
boolean result = source.saveAuth(auth); boolean result = source.saveAuth(auth);
if (result) { if (result) {
cachedAuths.refresh(auth.getNickname()); cachedAuths.refresh(auth.getNickname());
@ -122,7 +122,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updatePassword(PlayerAuth auth) { public boolean updatePassword(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
boolean result = source.updatePassword(auth); boolean result = source.updatePassword(auth);
if (result) { if (result) {
cachedAuths.refresh(auth.getNickname()); cachedAuths.refresh(auth.getNickname());
@ -133,7 +133,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updatePassword(String user, HashedPassword password) { public boolean updatePassword(String user, HashedPassword password) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
user = user.toLowerCase(); user = user.toLowerCase();
boolean result = source.updatePassword(user, password); boolean result = source.updatePassword(user, password);
if (result) { if (result) {
@ -145,7 +145,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateSession(PlayerAuth auth) { public boolean updateSession(PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
boolean result = source.updateSession(auth); boolean result = source.updateSession(auth);
if (result) { if (result) {
cachedAuths.refresh(auth.getNickname()); cachedAuths.refresh(auth.getNickname());
@ -156,7 +156,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateQuitLoc(final PlayerAuth auth) { public boolean updateQuitLoc(final PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
boolean result = source.updateQuitLoc(auth); boolean result = source.updateQuitLoc(auth);
if (result) { if (result) {
cachedAuths.refresh(auth.getNickname()); cachedAuths.refresh(auth.getNickname());
@ -167,14 +167,14 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public Set<String> getRecordsToPurge(long until) { public Set<String> getRecordsToPurge(long until) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.getRecordsToPurge(until); return source.getRecordsToPurge(until);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean removeAuth(String name) { public boolean removeAuth(String name) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
name = name.toLowerCase(); name = name.toLowerCase();
boolean result = source.removeAuth(name); boolean result = source.removeAuth(name);
if (result) { if (result) {
@ -198,7 +198,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateEmail(final PlayerAuth auth) { public boolean updateEmail(final PlayerAuth auth) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
boolean result = source.updateEmail(auth); boolean result = source.updateEmail(auth);
if (result) { if (result) {
cachedAuths.refresh(auth.getNickname()); cachedAuths.refresh(auth.getNickname());
@ -209,77 +209,77 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public List<String> getAllAuthsByIp(String ip) { public List<String> getAllAuthsByIp(String ip) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.getAllAuthsByIp(ip); return source.getAllAuthsByIp(ip);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public int countAuthsByEmail(String email) { public int countAuthsByEmail(String email) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.countAuthsByEmail(email); return source.countAuthsByEmail(email);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void purgeRecords(Collection<String> banned) { public void purgeRecords(Collection<String> banned) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
source.purgeRecords(banned); source.purgeRecords(banned);
cachedAuths.invalidateAll(banned); cachedAuths.invalidateAll(banned);
} }
@Override @Override
public DataSourceType getType() { public DataSourceType getType() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.getType(); return source.getType();
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean isLogged(String user) { public boolean isLogged(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.isLogged(user); return source.isLogged(user);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void setLogged(final String user) { public void setLogged(final String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
source.setLogged(user.toLowerCase()); source.setLogged(user.toLowerCase());
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void setUnlogged(final String user) { public void setUnlogged(final String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
source.setUnlogged(user.toLowerCase()); source.setUnlogged(user.toLowerCase());
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean hasSession(final String user) { public boolean hasSession(final String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.hasSession(user); return source.hasSession(user);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void grantSession(final String user) { public void grantSession(final String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
source.grantSession(user); source.grantSession(user);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void revokeSession(final String user) { public void revokeSession(final String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
source.revokeSession(user); source.revokeSession(user);
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void purgeLogged() { public void purgeLogged() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
source.purgeLogged(); source.purgeLogged();
cachedAuths.invalidateAll(); cachedAuths.invalidateAll();
} }
@ -287,14 +287,14 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public int getAccountsRegistered() { public int getAccountsRegistered() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.getAccountsRegistered(); return source.getAccountsRegistered();
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
boolean result = source.updateRealName(user, realName); boolean result = source.updateRealName(user, realName);
if (result) { if (result) {
cachedAuths.refresh(user); cachedAuths.refresh(user);
@ -305,7 +305,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public DataSourceValue<String> getEmail(String user) { public DataSourceValue<String> getEmail(String user) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return cachedAuths.getUnchecked(user) return cachedAuths.getUnchecked(user)
.map(auth -> DataSourceValueImpl.of(auth.getEmail())) .map(auth -> DataSourceValueImpl.of(auth.getEmail()))
.orElse(DataSourceValueImpl.unknownRow()); .orElse(DataSourceValueImpl.unknownRow());
@ -314,14 +314,14 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public List<PlayerAuth> getAllAuths() { public List<PlayerAuth> getAllAuths() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.getAllAuths(); return source.getAllAuths();
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public List<String> getLoggedPlayersWithEmptyMail() { public List<String> getLoggedPlayersWithEmptyMail() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return playerCache.getCache().values().stream() return playerCache.getCache().values().stream()
.filter(auth -> Utils.isEmailEmpty(auth.getEmail())) .filter(auth -> Utils.isEmailEmpty(auth.getEmail()))
.map(PlayerAuth::getRealName) .map(PlayerAuth::getRealName)
@ -331,14 +331,14 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public List<PlayerAuth> getRecentlyLoggedInPlayers() { public List<PlayerAuth> getRecentlyLoggedInPlayers() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
return source.getRecentlyLoggedInPlayers(); return source.getRecentlyLoggedInPlayers();
} }
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public boolean setTotpKey(String user, String totpKey) { public boolean setTotpKey(String user, String totpKey) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
boolean result = source.setTotpKey(user, totpKey); boolean result = source.setTotpKey(user, totpKey);
if (result) { if (result) {
cachedAuths.refresh(user); cachedAuths.refresh(user);
@ -354,7 +354,7 @@ public class CacheDataSource implements DataSource {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void refreshCache(String playerName) { public void refreshCache(String playerName) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (cachedAuths.getIfPresent(playerName) != null) { if (cachedAuths.getIfPresent(playerName) != null) {
cachedAuths.refresh(playerName); cachedAuths.refresh(playerName);
} }

View File

@ -1,7 +1,7 @@
package fr.xephi.authme.datasource; package fr.xephi.authme.datasource;
import ch.jalu.datasourcecolumns.data.DataSourceValue; import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.initialization.Reloadable;
@ -313,7 +313,7 @@ public interface DataSource extends Reloadable {
*/ */
@ShouldBeAsync @ShouldBeAsync
default void refreshCache(String playerName) { default void refreshCache(String playerName) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
} }
} }

View File

@ -0,0 +1,25 @@
package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.util.BukkitThreadSafety;
import org.bukkit.command.CommandSender;
/**
* Abstract class for AuthMe converters.
*/
public abstract class AbstractConverter {
/**
* Execute the conversion.
*
* @param sender the sender who initialized the conversion
*/
@ShouldBeAsync
public void execute(CommandSender sender) {
BukkitThreadSafety.shouldBeAsync();
executeInternal(sender);
}
@ShouldBeAsync
protected abstract void executeInternal(CommandSender sender);
}

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.datasource.converter; package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.DataSourceType;
@ -17,7 +18,7 @@ import static fr.xephi.authme.util.Utils.logAndSendMessage;
* *
* @param <S> the source type to convert from * @param <S> the source type to convert from
*/ */
public abstract class AbstractDataSourceConverter<S extends DataSource> implements Converter { public abstract class AbstractDataSourceConverter<S extends DataSource> extends AbstractConverter {
private final ConsoleLogger logger = ConsoleLoggerFactory.get(MySqlToSqlite.class); private final ConsoleLogger logger = ConsoleLoggerFactory.get(MySqlToSqlite.class);
@ -40,7 +41,8 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
// Implementation note: Because of ForceFlatToSqlite it is possible that the CommandSender is null, // Implementation note: Because of ForceFlatToSqlite it is possible that the CommandSender is null,
// which is never the case when a converter is launched from the /authme converter command. // which is never the case when a converter is launched from the /authme converter command.
@Override @Override
public void execute(CommandSender sender) { @ShouldBeAsync
public void executeInternal(CommandSender sender) {
if (destinationType != destination.getType()) { if (destinationType != destination.getType()) {
if (sender != null) { if (sender != null) {
sender.sendMessage("Please configure your connection to " sender.sendMessage("Please configure your connection to "

View File

@ -1,19 +0,0 @@
package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.annotation.ShouldBeAsync;
import org.bukkit.command.CommandSender;
/**
* Interface for AuthMe converters.
*/
public interface Converter {
/**
* Execute the conversion.
* TODO: apply the ShouldBeAsync annotation to all the converters
*
* @param sender the sender who initialized the conversion
*/
@ShouldBeAsync
void execute(CommandSender sender);
}

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.datasource.converter; package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
@ -18,7 +19,7 @@ import java.io.IOException;
/** /**
* Converter for CrazyLogin to AuthMe. * Converter for CrazyLogin to AuthMe.
*/ */
public class CrazyLoginConverter implements Converter { public class CrazyLoginConverter extends AbstractConverter {
private final ConsoleLogger logger = ConsoleLoggerFactory.get(CrazyLoginConverter.class); private final ConsoleLogger logger = ConsoleLoggerFactory.get(CrazyLoginConverter.class);
@ -34,7 +35,8 @@ public class CrazyLoginConverter implements Converter {
} }
@Override @Override
public void execute(CommandSender sender) { @ShouldBeAsync
public void executeInternal(CommandSender sender) {
String fileName = settings.getProperty(ConverterSettings.CRAZYLOGIN_FILE_NAME); String fileName = settings.getProperty(ConverterSettings.CRAZYLOGIN_FILE_NAME);
File source = new File(dataFolder, fileName); File source = new File(dataFolder, fileName);
if (!source.exists()) { if (!source.exists()) {

View File

@ -2,6 +2,7 @@ package fr.xephi.authme.datasource.converter;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
@ -30,7 +31,7 @@ import static fr.xephi.authme.util.Utils.logAndSendMessage;
/** /**
* Converts data from LoginSecurity to AuthMe. * Converts data from LoginSecurity to AuthMe.
*/ */
public class LoginSecurityConverter implements Converter { public class LoginSecurityConverter extends AbstractConverter {
private final ConsoleLogger logger = ConsoleLoggerFactory.get(LoginSecurityConverter.class); private final ConsoleLogger logger = ConsoleLoggerFactory.get(LoginSecurityConverter.class);
private final File dataFolder; private final File dataFolder;
@ -55,7 +56,8 @@ public class LoginSecurityConverter implements Converter {
} }
@Override @Override
public void execute(CommandSender sender) { @ShouldBeAsync
public void executeInternal(CommandSender sender) {
try (Connection connection = createConnectionOrInformSender(sender)) { try (Connection connection = createConnectionOrInformSender(sender)) {
if (connection != null) { if (connection != null) {
performConversion(sender, connection); performConversion(sender, connection);

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.datasource.converter; package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
@ -24,7 +25,7 @@ import java.util.Map.Entry;
/** /**
* @author Xephi59 * @author Xephi59
*/ */
public class RakamakConverter implements Converter { public class RakamakConverter extends AbstractConverter {
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RakamakConverter.class); private final ConsoleLogger logger = ConsoleLoggerFactory.get(RakamakConverter.class);
private final DataSource database; private final DataSource database;
@ -41,9 +42,10 @@ public class RakamakConverter implements Converter {
this.passwordSecurity = passwordSecurity; this.passwordSecurity = passwordSecurity;
} }
@Override
//TODO ljacqu 20151229: Restructure this into smaller portions //TODO ljacqu 20151229: Restructure this into smaller portions
public void execute(CommandSender sender) { @Override
@ShouldBeAsync
public void executeInternal(CommandSender sender) {
boolean useIp = settings.getProperty(ConverterSettings.RAKAMAK_USE_IP); boolean useIp = settings.getProperty(ConverterSettings.RAKAMAK_USE_IP);
String fileName = settings.getProperty(ConverterSettings.RAKAMAK_FILE_NAME); String fileName = settings.getProperty(ConverterSettings.RAKAMAK_FILE_NAME);
String ipFileName = settings.getProperty(ConverterSettings.RAKAMAK_IP_FILE_NAME); String ipFileName = settings.getProperty(ConverterSettings.RAKAMAK_IP_FILE_NAME);

View File

@ -2,6 +2,7 @@ package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.output.ConsoleLoggerFactory;
@ -15,7 +16,7 @@ import java.io.File;
import static fr.xephi.authme.util.FileUtils.makePath; import static fr.xephi.authme.util.FileUtils.makePath;
public class RoyalAuthConverter implements Converter { public class RoyalAuthConverter extends AbstractConverter {
private static final String LAST_LOGIN_PATH = "timestamps.quit"; private static final String LAST_LOGIN_PATH = "timestamps.quit";
private static final String PASSWORD_PATH = "login.password"; private static final String PASSWORD_PATH = "login.password";
@ -32,7 +33,8 @@ public class RoyalAuthConverter implements Converter {
} }
@Override @Override
public void execute(CommandSender sender) { @ShouldBeAsync
public void executeInternal(CommandSender sender) {
for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) { for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) {
try { try {
String name = player.getName().toLowerCase(); String name = player.getName().toLowerCase();

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.datasource.converter; package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
@ -17,7 +18,7 @@ import java.util.UUID;
import static fr.xephi.authme.util.FileUtils.makePath; import static fr.xephi.authme.util.FileUtils.makePath;
public class VAuthConverter implements Converter { public class VAuthConverter extends AbstractConverter {
private final ConsoleLogger logger = ConsoleLoggerFactory.get(VAuthConverter.class); private final ConsoleLogger logger = ConsoleLoggerFactory.get(VAuthConverter.class);
private final DataSource dataSource; private final DataSource dataSource;
@ -30,7 +31,8 @@ public class VAuthConverter implements Converter {
} }
@Override @Override
public void execute(CommandSender sender) { @ShouldBeAsync
public void executeInternal(CommandSender sender) {
try (Scanner scanner = new Scanner(vAuthPasswordsFile)) { try (Scanner scanner = new Scanner(vAuthPasswordsFile)) {
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();

View File

@ -3,6 +3,7 @@ package fr.xephi.authme.datasource.converter;
import de.luricos.bukkit.xAuth.database.DatabaseTables; import de.luricos.bukkit.xAuth.database.DatabaseTables;
import de.luricos.bukkit.xAuth.utils.xAuthLog; import de.luricos.bukkit.xAuth.utils.xAuthLog;
import de.luricos.bukkit.xAuth.xAuth; import de.luricos.bukkit.xAuth.xAuth;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
@ -21,7 +22,7 @@ import java.util.List;
import static fr.xephi.authme.util.FileUtils.makePath; import static fr.xephi.authme.util.FileUtils.makePath;
public class XAuthConverter implements Converter { public class XAuthConverter extends AbstractConverter {
@Inject @Inject
@DataFolder @DataFolder
@ -35,7 +36,8 @@ public class XAuthConverter implements Converter {
} }
@Override @Override
public void execute(CommandSender sender) { @ShouldBeAsync
public void executeInternal(CommandSender sender) {
try { try {
Class.forName("de.luricos.bukkit.xAuth.xAuth"); Class.forName("de.luricos.bukkit.xAuth.xAuth");
convert(sender); convert(sender);

View File

@ -1,7 +1,7 @@
package fr.xephi.authme.listener; package fr.xephi.authme.listener;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.MightBeAsync; import fr.xephi.authme.annotation.MightBeAsync;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
@ -76,7 +76,7 @@ public class OnJoinVerifier implements Reloadable {
*/ */
@ShouldBeAsync @ShouldBeAsync
public void checkAntibot(String name, boolean isAuthAvailable) throws FailedVerificationException { public void checkAntibot(String name, boolean isAuthAvailable) throws FailedVerificationException {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (isAuthAvailable || permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)) { if (isAuthAvailable || permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)) {
return; return;
} }
@ -127,7 +127,7 @@ public class OnJoinVerifier implements Reloadable {
* further), false if the player is not refused * further), false if the player is not refused
*/ */
public boolean refusePlayerForFullServer(PlayerLoginEvent event) { public boolean refusePlayerForFullServer(PlayerLoginEvent event) {
ThreadSafety.requireSync(); BukkitThreadSafety.requireSync();
final Player player = event.getPlayer(); final Player player = event.getPlayer();
if (event.getResult() != PlayerLoginEvent.Result.KICK_FULL) { if (event.getResult() != PlayerLoginEvent.Result.KICK_FULL) {
// Server is not full, no need to do anything // Server is not full, no need to do anything
@ -165,7 +165,7 @@ public class OnJoinVerifier implements Reloadable {
*/ */
@ShouldBeAsync @ShouldBeAsync
public void checkNameCasing(String connectingName, PlayerAuth auth) throws FailedVerificationException { public void checkNameCasing(String connectingName, PlayerAuth auth) throws FailedVerificationException {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (auth != null && settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)) { if (auth != null && settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)) {
String realName = auth.getRealName(); // might be null or "Player" String realName = auth.getRealName(); // might be null or "Player"
@ -188,7 +188,7 @@ public class OnJoinVerifier implements Reloadable {
@ShouldBeAsync @ShouldBeAsync
public void checkPlayerCountry(String name, String address, public void checkPlayerCountry(String name, String address,
boolean isAuthAvailable) throws FailedVerificationException { boolean isAuthAvailable) throws FailedVerificationException {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if ((!isAuthAvailable || settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)) if ((!isAuthAvailable || settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED))
&& settings.getProperty(ProtectionSettings.ENABLE_PROTECTION) && settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)
&& !permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_COUNTRY_CHECK) && !permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_COUNTRY_CHECK)
@ -205,7 +205,7 @@ public class OnJoinVerifier implements Reloadable {
* @throws FailedVerificationException if the verification fails * @throws FailedVerificationException if the verification fails
*/ */
public void checkSingleSession(String name) throws FailedVerificationException { public void checkSingleSession(String name) throws FailedVerificationException {
ThreadSafety.requireSync(); BukkitThreadSafety.requireSync();
if (!settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)) { if (!settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)) {
return; return;
} }
@ -224,7 +224,7 @@ public class OnJoinVerifier implements Reloadable {
* @return the player to kick, or null if none applicable * @return the player to kick, or null if none applicable
*/ */
private Player generateKickPlayer(Collection<Player> onlinePlayers) { private Player generateKickPlayer(Collection<Player> onlinePlayers) {
ThreadSafety.requireSync(); BukkitThreadSafety.requireSync();
for (Player player : onlinePlayers) { for (Player player : onlinePlayers) {
if (!permissionsManager.hasPermission(player, PlayerStatePermission.IS_VIP)) { if (!permissionsManager.hasPermission(player, PlayerStatePermission.IS_VIP)) {
return player; return player;

View File

@ -1,7 +1,7 @@
package fr.xephi.authme.mail; package fr.xephi.authme.mail;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.MightBeAsync; import fr.xephi.authme.annotation.MightBeAsync;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
@ -54,7 +54,7 @@ public class EmailService {
*/ */
@ShouldBeAsync @ShouldBeAsync
public boolean sendPasswordMail(String name, String mailAddress, String newPass) { public boolean sendPasswordMail(String name, String mailAddress, String newPass) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (!hasAllInformation()) { if (!hasAllInformation()) {
logger.warning("Cannot perform email registration: not all email settings are complete"); logger.warning("Cannot perform email registration: not all email settings are complete");
return false; return false;
@ -96,7 +96,7 @@ public class EmailService {
*/ */
@ShouldBeAsync @ShouldBeAsync
public boolean sendVerificationMail(String name, String mailAddress, String code) { public boolean sendVerificationMail(String name, String mailAddress, String code) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (!hasAllInformation()) { if (!hasAllInformation()) {
logger.warning("Cannot send verification email: not all email settings are complete"); logger.warning("Cannot send verification email: not all email settings are complete");
return false; return false;
@ -125,7 +125,7 @@ public class EmailService {
*/ */
@ShouldBeAsync @ShouldBeAsync
public boolean sendRecoveryCode(String name, String email, String code) { public boolean sendRecoveryCode(String name, String email, String code) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
HtmlEmail htmlEmail; HtmlEmail htmlEmail;
try { try {
htmlEmail = sendMailSsl.initializeMail(email); htmlEmail = sendMailSsl.initializeMail(email);

View File

@ -4,7 +4,6 @@ import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache; import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.data.limbo.LimboPlayer; import fr.xephi.authme.data.limbo.LimboPlayer;
import fr.xephi.authme.data.limbo.LimboService; import fr.xephi.authme.data.limbo.LimboService;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.events.LoginEvent; import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.RestoreInventoryEvent; import fr.xephi.authme.events.RestoreInventoryEvent;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;

View File

@ -1,6 +1,6 @@
package fr.xephi.authme.service; package fr.xephi.authme.service;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.MightBeAsync; import fr.xephi.authme.annotation.MightBeAsync;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.initialization.SettingsDependent; import fr.xephi.authme.initialization.SettingsDependent;
@ -108,7 +108,7 @@ public class AntiBotService implements SettingsDependent {
* Transitions the anti bot service from active status back to listening. * Transitions the anti bot service from active status back to listening.
*/ */
private void stopProtection() { private void stopProtection() {
ThreadSafety.requireSync(); BukkitThreadSafety.requireSync();
if (antiBotStatus != AntiBotStatus.ACTIVE) { if (antiBotStatus != AntiBotStatus.ACTIVE) {
return; return;
} }
@ -144,7 +144,7 @@ public class AntiBotService implements SettingsDependent {
* @param started the new protection status * @param started the new protection status
*/ */
public void overrideAntiBotStatus(boolean started) { public void overrideAntiBotStatus(boolean started) {
ThreadSafety.requireSync(); BukkitThreadSafety.requireSync();
if (antiBotStatus != AntiBotStatus.DISABLED) { if (antiBotStatus != AntiBotStatus.DISABLED) {
if (started) { if (started) {
startProtection(); startProtection();
@ -161,7 +161,7 @@ public class AntiBotService implements SettingsDependent {
*/ */
@ShouldBeAsync @ShouldBeAsync
public boolean shouldKick() { public boolean shouldKick() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (antiBotStatus == AntiBotStatus.DISABLED) { if (antiBotStatus == AntiBotStatus.DISABLED) {
return false; return false;
} else if (antiBotStatus == AntiBotStatus.ACTIVE) { } else if (antiBotStatus == AntiBotStatus.ACTIVE) {

View File

@ -11,7 +11,7 @@ import com.maxmind.db.cache.CHMCache;
import com.maxmind.db.model.Country; import com.maxmind.db.model.Country;
import com.maxmind.db.model.CountryResponse; import com.maxmind.db.model.CountryResponse;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.output.ConsoleLoggerFactory;
@ -132,7 +132,7 @@ public class GeoIpService {
*/ */
@ShouldBeAsync @ShouldBeAsync
private void updateDatabase() { private void updateDatabase() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
logger.info("Downloading GEO IP database, because the old database is older than " logger.info("Downloading GEO IP database, because the old database is older than "
+ UPDATE_INTERVAL_DAYS + " days or doesn't exist"); + UPDATE_INTERVAL_DAYS + " days or doesn't exist");

View File

@ -1,7 +1,7 @@
package fr.xephi.authme.service; package fr.xephi.authme.service;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.MightBeAsync; import fr.xephi.authme.annotation.MightBeAsync;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
@ -72,7 +72,7 @@ public class PasswordRecoveryService implements Reloadable, HasCleanup {
*/ */
@ShouldBeAsync @ShouldBeAsync
public void createAndSendRecoveryCode(Player player, String email) { public void createAndSendRecoveryCode(Player player, String email) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (!checkEmailCooldown(player)) { if (!checkEmailCooldown(player)) {
return; return;
} }
@ -96,7 +96,7 @@ public class PasswordRecoveryService implements Reloadable, HasCleanup {
*/ */
@ShouldBeAsync @ShouldBeAsync
public void generateAndSendNewPassword(Player player, String email) { public void generateAndSendNewPassword(Player player, String email) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (!checkEmailCooldown(player)) { if (!checkEmailCooldown(player)) {
return; return;
} }

View File

@ -1,7 +1,7 @@
package fr.xephi.authme.task.purge; package fr.xephi.authme.task.purge;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.output.ConsoleLoggerFactory;
@ -57,7 +57,7 @@ public class PurgeExecutor {
*/ */
@ShouldBeAsync @ShouldBeAsync
public void executePurge(Collection<OfflinePlayer> players, Collection<String> names) { public void executePurge(Collection<OfflinePlayer> players, Collection<String> names) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
// Purge other data // Purge other data
purgeFromAuthMe(names); purgeFromAuthMe(names);
purgeEssentials(players); purgeEssentials(players);

View File

@ -1,7 +1,7 @@
package fr.xephi.authme.task.purge; package fr.xephi.authme.task.purge;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.output.ConsoleLoggerFactory;
@ -121,7 +121,7 @@ public class PurgeService {
*/ */
@ShouldBeAsync @ShouldBeAsync
void executePurge(Collection<OfflinePlayer> players, Collection<String> names) { void executePurge(Collection<OfflinePlayer> players, Collection<String> names) {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
purgeExecutor.executePurge(players, names); purgeExecutor.executePurge(players, names);
} }
} }

View File

@ -1,7 +1,7 @@
package fr.xephi.authme.task.purge; package fr.xephi.authme.task.purge;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.ThreadSafety; import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync; import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.output.ConsoleLoggerFactory;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
@ -61,7 +61,7 @@ class PurgeTask extends BukkitRunnable {
@Override @Override
@ShouldBeAsync @ShouldBeAsync
public void run() { public void run() {
ThreadSafety.shouldBeAsync(); BukkitThreadSafety.shouldBeAsync();
if (toPurge.isEmpty()) { if (toPurge.isEmpty()) {
//everything was removed //everything was removed
finish(); finish();

View File

@ -1,22 +1,41 @@
package fr.xephi.authme.util; package fr.xephi.authme.util;
/**
* A thread-safe interval counter, allows to detect if an event happens more than 'threshold' times
* in the given 'interval'.
*/
public class AtomicIntervalCounter { public class AtomicIntervalCounter {
private final int threshold; private final int threshold;
private final int interval; private final int interval;
private int count; private int count;
private long lastInsert; private long lastInsert;
/**
* Constructs a new counter.
*
* @param threshold the threshold value of the counter.
* @param interval the counter interval in milliseconds.
*/
public AtomicIntervalCounter(int threshold, int interval) { public AtomicIntervalCounter(int threshold, int interval) {
this.threshold = threshold; this.threshold = threshold;
this.interval = interval; this.interval = interval;
reset(); reset();
} }
/**
* Resets the counter count.
*/
public synchronized void reset() { public synchronized void reset() {
count = 0; count = 0;
lastInsert = 0; lastInsert = 0;
} }
/**
* Increments the counter and returns true if the current count has reached the threshold value
* in the given interval, this will also reset the count value.
*
* @return true if the count has reached the threshold value.
*/
public synchronized boolean handle() { public synchronized boolean handle() {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (now - lastInsert > interval) { if (now - lastInsert > interval) {

View File

@ -1,18 +1,29 @@
package fr.xephi.authme; package fr.xephi.authme.util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
public final class ThreadSafety { /**
* Utility class that provides static methods to ensure that methods are called from the right thread.
*/
public final class BukkitThreadSafety {
private static boolean enabled = false; private static boolean enabled = false;
private ThreadSafety() { private BukkitThreadSafety() {
} }
/**
* Enables/disables the bukkit thread-safety warnings.
*
* @param enabled true if the warnings should be enabled, false otherwise.
*/
public static void setEnabled(boolean enabled) { public static void setEnabled(boolean enabled) {
ThreadSafety.enabled = enabled; BukkitThreadSafety.enabled = enabled;
} }
/**
* Prints a warning if called by an async thread (not the main server thread).
*/
public static void requireSync() { public static void requireSync() {
if (!enabled || Bukkit.isPrimaryThread()) { if (!enabled || Bukkit.isPrimaryThread()) {
return; return;
@ -21,6 +32,9 @@ public final class ThreadSafety {
new Throwable().printStackTrace(); new Throwable().printStackTrace();
} }
/**
* Prints a warning if called by the main server thread.
*/
public static void shouldBeAsync() { public static void shouldBeAsync() {
if (!enabled || !Bukkit.isPrimaryThread()) { if (!enabled || !Bukkit.isPrimaryThread()) {
return; return;

View File

@ -24,7 +24,6 @@ public final class PlayerUtils {
/** /**
* Returns if the player is an NPC or not. * Returns if the player is an NPC or not.
* TODO: is player metadata thread-safe?
* *
* @param player The player to check * @param player The player to check
* @return True if the player is an NPC, false otherwise * @return True if the player is an NPC, false otherwise

View File

@ -2,7 +2,7 @@ package fr.xephi.authme.command.executable.authme;
import ch.jalu.injector.factory.Factory; import ch.jalu.injector.factory.Factory;
import fr.xephi.authme.TestHelper; import fr.xephi.authme.TestHelper;
import fr.xephi.authme.datasource.converter.Converter; import fr.xephi.authme.datasource.converter.AbstractConverter;
import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.service.CommonService; import fr.xephi.authme.service.CommonService;
@ -49,7 +49,7 @@ public class ConverterCommandTest {
private BukkitService bukkitService; private BukkitService bukkitService;
@Mock @Mock
private Factory<Converter> converterFactory; private Factory<AbstractConverter> converterFactory;
@BeforeClass @BeforeClass
public static void initLogger() { public static void initLogger() {
@ -87,10 +87,10 @@ public class ConverterCommandTest {
@Test @Test
public void shouldHaveUniqueClassForEachConverter() { public void shouldHaveUniqueClassForEachConverter() {
// given // given
Set<Class<? extends Converter>> classes = new HashSet<>(); Set<Class<? extends AbstractConverter>> classes = new HashSet<>();
// when / then // when / then
for (Map.Entry<String, Class<? extends Converter>> entry : ConverterCommand.CONVERTERS.entrySet()) { for (Map.Entry<String, Class<? extends AbstractConverter>> entry : ConverterCommand.CONVERTERS.entrySet()) {
assertThat("Name is not null or empty", assertThat("Name is not null or empty",
StringUtils.isEmpty(entry.getKey()), equalTo(false)); StringUtils.isEmpty(entry.getKey()), equalTo(false));
@ -103,8 +103,8 @@ public class ConverterCommandTest {
public void shouldLaunchConverterForAllTypes() { public void shouldLaunchConverterForAllTypes() {
// given // given
String converterName = "rakamak"; String converterName = "rakamak";
Class<? extends Converter> converterClass = ConverterCommand.CONVERTERS.get(converterName); Class<? extends AbstractConverter> converterClass = ConverterCommand.CONVERTERS.get(converterName);
Converter converter = createMockReturnedByInjector(converterClass); AbstractConverter converter = createMockReturnedByInjector(converterClass);
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
setBukkitServiceToRunTaskAsynchronously(bukkitService); setBukkitServiceToRunTaskAsynchronously(bukkitService);
@ -122,8 +122,8 @@ public class ConverterCommandTest {
public void shouldCatchExceptionInConverterAndInformSender() { public void shouldCatchExceptionInConverterAndInformSender() {
// given // given
String converterName = "vauth"; String converterName = "vauth";
Class<? extends Converter> converterClass = ConverterCommand.CONVERTERS.get(converterName); Class<? extends AbstractConverter> converterClass = ConverterCommand.CONVERTERS.get(converterName);
Converter converter = createMockReturnedByInjector(converterClass); AbstractConverter converter = createMockReturnedByInjector(converterClass);
doThrow(IllegalStateException.class).when(converter).execute(any(CommandSender.class)); doThrow(IllegalStateException.class).when(converter).execute(any(CommandSender.class));
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
setBukkitServiceToRunTaskAsynchronously(bukkitService); setBukkitServiceToRunTaskAsynchronously(bukkitService);
@ -139,7 +139,7 @@ public class ConverterCommandTest {
verify(commonService).send(sender, MessageKey.ERROR); verify(commonService).send(sender, MessageKey.ERROR);
} }
private <T extends Converter> T createMockReturnedByInjector(Class<T> clazz) { private <T extends AbstractConverter> T createMockReturnedByInjector(Class<T> clazz) {
T converter = mock(clazz); T converter = mock(clazz);
given(converterFactory.newInstance(clazz)).willReturn(converter); given(converterFactory.newInstance(clazz)).willReturn(converter);
return converter; return converter;

View File

@ -42,11 +42,11 @@ public class AbstractDataSourceConverterTest {
given(destination.getType()).willReturn(DataSourceType.MYSQL); given(destination.getType()).willReturn(DataSourceType.MYSQL);
DataSourceType destinationType = DataSourceType.SQLITE; DataSourceType destinationType = DataSourceType.SQLITE;
DataSource source = mock(DataSource.class); DataSource source = mock(DataSource.class);
Converter converter = new DataSourceConverterTestImpl<>(source, destination, destinationType); AbstractConverter converter = new DataSourceConverterTestImpl<>(source, destination, destinationType);
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
// when // when
converter.execute(sender); converter.executeInternal(sender);
// then // then
verify(sender).sendMessage(argThat(containsString("Please configure your connection to SQLITE"))); verify(sender).sendMessage(argThat(containsString("Please configure your connection to SQLITE")));
@ -67,7 +67,7 @@ public class AbstractDataSourceConverterTest {
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
// when // when
converter.execute(sender); converter.executeInternal(sender);
// then // then
verify(sender).sendMessage("The data source to convert from could not be initialized"); verify(sender).sendMessage("The data source to convert from could not be initialized");
@ -88,11 +88,11 @@ public class AbstractDataSourceConverterTest {
given(source.getAllAuths()).willReturn(auths); given(source.getAllAuths()).willReturn(auths);
given(destination.isAuthAvailable(auths.get(0).getNickname())).willReturn(true); given(destination.isAuthAvailable(auths.get(0).getNickname())).willReturn(true);
Converter converter = new DataSourceConverterTestImpl<>(source, destination, destinationType); AbstractConverter converter = new DataSourceConverterTestImpl<>(source, destination, destinationType);
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
// when // when
converter.execute(sender); converter.executeInternal(sender);
// then // then
verify(destination).getType(); verify(destination).getType();

View File

@ -59,7 +59,7 @@ public class CrazyLoginConverterTest {
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
// when // when
crazyLoginConverter.execute(sender); crazyLoginConverter.executeInternal(sender);
// then // then
ArgumentCaptor<PlayerAuth> authCaptor = ArgumentCaptor.forClass(PlayerAuth.class); ArgumentCaptor<PlayerAuth> authCaptor = ArgumentCaptor.forClass(PlayerAuth.class);
@ -78,7 +78,7 @@ public class CrazyLoginConverterTest {
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
// when // when
crazyLoginConverter.execute(sender); crazyLoginConverter.executeInternal(sender);
// then // then
verifyNoInteractions(dataSource); verifyNoInteractions(dataSource);

View File

@ -14,7 +14,7 @@ import fr.xephi.authme.TestHelper;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.executable.authme.debug.DebugCommand; import fr.xephi.authme.command.executable.authme.debug.DebugCommand;
import fr.xephi.authme.data.limbo.persistence.LimboPersistence; import fr.xephi.authme.data.limbo.persistence.LimboPersistence;
import fr.xephi.authme.datasource.converter.Converter; import fr.xephi.authme.datasource.converter.AbstractConverter;
import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.process.AsynchronousProcess; import fr.xephi.authme.process.AsynchronousProcess;
import fr.xephi.authme.process.SynchronousProcess; import fr.xephi.authme.process.SynchronousProcess;
@ -204,7 +204,7 @@ public class DrawDependency implements ToolTask {
LimboPersistence.class.getPackage().getName() + ".LimboPersistenceHandler"); LimboPersistence.class.getPackage().getName() + ".LimboPersistenceHandler");
return ImmutableList.of(ExecutableCommand.class, SynchronousProcess.class, AsynchronousProcess.class, return ImmutableList.of(ExecutableCommand.class, SynchronousProcess.class, AsynchronousProcess.class,
EncryptionMethod.class, Converter.class, Listener.class, RegistrationExecutor.class, debugSectionClass, EncryptionMethod.class, AbstractConverter.class, Listener.class, RegistrationExecutor.class, debugSectionClass,
limboPersistenceClass); limboPersistenceClass);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);