From 8ca3374c1619c23b37d1d44e117f31fb9581e8d3 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sat, 27 Jun 2020 03:37:22 +0200 Subject: [PATCH 1/4] WIP cleanup (1/?) --- .checkstyle.xml | 2 +- .codeclimate.yml | 1 - .gitignore | 1 + .idea/misc.xml | 25 + README.md | 39 +- pom.xml | 6 + samples/NewConfig.yml | 570 ------------------ samples/NewPlugin.yml | 199 ------ src/main/java/fr/xephi/authme/AuthMe.java | 21 +- .../java/fr/xephi/authme/ConsoleLogger.java | 63 +- .../authme/command/CommandInitializer.java | 2 +- .../executable/authme/ConverterCommand.java | 2 - .../executable/authme/GetIpCommand.java | 2 +- .../authme/PurgeBannedPlayersCommand.java | 5 +- .../executable/authme/PurgeCommand.java | 6 +- .../authme/debug/HasPermissionChecker.java | 8 +- .../fr/xephi/authme/data/auth/PlayerAuth.java | 2 + .../data/limbo/LimboPlayerTaskManager.java | 1 + .../DistributedFilesPersistenceHandler.java | 4 +- .../IndividualFilesPersistenceHandler.java | 9 +- .../persistence/LimboPlayerSerializer.java | 3 +- .../authme/datasource/CacheDataSource.java | 7 +- .../authme/datasource/SqLiteMigrater.java | 5 +- .../converter/RoyalAuthConverter.java | 3 + .../datasource/converter/XAuthConverter.java | 148 ----- .../events/AuthMeAsyncPreLoginEvent.java | 2 + .../events/AuthMeAsyncPreRegisterEvent.java | 2 + .../authme/events/AuthMeTeleportEvent.java | 2 + .../authme/events/EmailChangedEvent.java | 2 + .../xephi/authme/events/FailedLoginEvent.java | 2 + .../events/FirstSpawnTeleportEvent.java | 2 + .../fr/xephi/authme/events/LoginEvent.java | 2 + .../fr/xephi/authme/events/LogoutEvent.java | 2 + .../events/PasswordEncryptionEvent.java | 31 +- .../authme/events/ProtectInventoryEvent.java | 2 + .../fr/xephi/authme/events/RegisterEvent.java | 2 + .../authme/events/RestoreInventoryEvent.java | 2 + .../authme/events/RestoreSessionEvent.java | 3 + .../authme/events/SpawnTeleportEvent.java | 2 + .../authme/events/UnregisterByAdminEvent.java | 3 + .../events/UnregisterByPlayerEvent.java | 3 + .../xephi/authme/listener/PlayerListener.java | 1 + .../message/updater/MessageUpdater.java | 13 +- .../permission/handlers/VaultHandler.java | 7 +- .../authme/process/join/AsynchronousJoin.java | 6 +- .../xephi/authme/security/HashAlgorithm.java | 4 +- .../fr/xephi/authme/security/HashUtils.java | 2 +- .../authme/security/PasswordSecurity.java | 1 + .../xephi/authme/security/crypts/Pbkdf2.java | 7 +- .../authme/security/crypts/Pbkdf2Django.java | 7 +- .../xephi/authme/security/crypts/PhpBB.java | 17 +- .../authme/security/crypts/PhpFusion.java | 7 +- .../authme/security/crypts/TwoFactor.java | 23 +- .../authme/security/crypts/Whirlpool.java | 399 ------------ .../authme/security/crypts/Wordpress.java | 12 +- .../xephi/authme/security/crypts/XAuth.java | 43 -- .../security/totp/TotpAuthenticator.java | 7 +- .../service/HelpTranslationGenerator.java | 3 +- .../authme/service/MigrationService.java | 1 + .../authme/service/TeleportationService.java | 2 +- .../authme/service/ValidationService.java | 3 +- .../service/bungeecord/BungeeReceiver.java | 9 +- .../fr/xephi/authme/settings/Settings.java | 5 +- .../settings/SettingsMigrationService.java | 1 + .../fr/xephi/authme/settings/SpawnLoader.java | 33 +- .../commandconfig/OnLoginCommand.java | 2 +- .../settings/properties/SecuritySettings.java | 2 +- .../authme/util/AtomicIntervalCounter.java | 2 + .../fr/xephi/authme/util/ExceptionUtils.java | 28 +- .../java/fr/xephi/authme/util/FileUtils.java | 44 +- .../authme/util/InternetProtocolUtils.java | 13 +- .../fr/xephi/authme/util/PlayerUtils.java | 11 +- .../fr/xephi/authme/util/StringUtils.java | 6 +- src/main/java/fr/xephi/authme/util/Utils.java | 13 +- .../java/fr/xephi/authme/util/UuidUtils.java | 1 + .../xephi/authme/util/expiring/Duration.java | 10 +- .../authme/util/expiring/ExpiringMap.java | 20 +- .../authme/util/expiring/ExpiringSet.java | 18 +- .../authme/util/expiring/TimedCounter.java | 12 +- .../authme/util/lazytags/DependentTag.java | 11 +- .../xephi/authme/util/lazytags/SimpleTag.java | 9 +- .../fr/xephi/authme/util/lazytags/Tag.java | 5 + .../authme/util/lazytags/TagBuilder.java | 9 +- .../authme/util/lazytags/TagReplacer.java | 21 +- .../util/lazytags/WrappedTagReplacer.java | 17 +- src/main/resources/email.html | 3 +- src/main/resources/recovery_code_email.html | 1 + .../resources/verification_code_email.html | 1 + .../authme/AuthMeInitializationTest.java | 6 +- .../xephi/authme/ClassesConsistencyTest.java | 2 - .../fr/xephi/authme/ReflectionTestUtils.java | 1 - .../command/CommandConsistencyTest.java | 2 + .../authme/debug/DataStatisticsTest.java | 8 +- .../debug/HasPermissionCheckerTest.java | 1 + .../help/HelpMessagesConsistencyTest.java | 3 +- .../command/help/HelpMessagesServiceTest.java | 9 +- .../RegistrationCaptchaManagerTest.java | 1 - .../data/limbo/LimboPlayerMatchers.java | 18 +- ...istributedFilesPersistenceHandlerTest.java | 13 +- ...IndividualFilesPersistenceHandlerTest.java | 3 +- .../datasource/MySqlIntegrationTest.java | 3 +- .../datasource/PostgreSqlIntegrationTest.java | 3 +- .../datasource/SQLiteIntegrationTest.java | 3 +- .../SqLiteMigraterIntegrationTest.java | 10 +- .../converter/LoginSecurityConverterTest.java | 3 +- .../authme/listener/ListenerServiceTest.java | 4 +- .../authme/listener/OnJoinVerifierTest.java | 12 +- .../authme/listener/PlayerListenerTest.java | 6 +- .../message/MessageFilePlaceholderTest.java | 3 +- .../message/MessagesIntegrationTest.java | 11 +- .../message/updater/MessageUpdaterTest.java | 17 +- .../updater/MigraterYamlFileResourceTest.java | 6 +- .../permission/PermissionConsistencyTest.java | 6 +- .../permission/PermissionsManagerTest.java | 2 + .../HashAlgorithmIntegrationTest.java | 2 + .../authme/security/PasswordSecurityTest.java | 2 +- .../authme/security/crypts/WhirlpoolTest.java | 16 - .../authme/security/crypts/XAuthTest.java | 16 - ...lpTranslationGeneratorIntegrationTest.java | 9 +- .../authme/service/MigrationServiceTest.java | 1 + .../service/TeleportationServiceTest.java | 5 +- .../authme/service/ValidationServiceTest.java | 3 +- .../settings/SettingsIntegrationTest.java | 9 +- .../SettingsMigrationServiceTest.java | 13 +- .../xephi/authme/settings/SettingsTest.java | 7 +- .../authme/settings/SpawnLoaderTest.java | 7 +- .../WelcomeMessageConfigurationTest.java | 3 +- .../commandconfig/CommandManagerTest.java | 6 +- .../CommandMigrationServiceTest.java | 7 +- .../fr/xephi/authme/util/FileUtilsTest.java | 10 +- .../fr/xephi/authme/util/StringUtilsTest.java | 1 + .../java/fr/xephi/authme/util/UtilsTest.java | 2 + .../tools/dependencygraph/DrawDependency.java | 3 +- .../HelpTranslationVerifier.java | 2 + .../messages/AddJavaDocToMessageEnumTask.java | 3 +- .../tools/messages/CheckMessageKeyUsages.java | 10 +- src/test/java/tools/utils/FileIoUtils.java | 4 +- src/test/resources/simplelogger.properties | 1 + 138 files changed, 650 insertions(+), 1718 deletions(-) create mode 100644 .idea/misc.xml delete mode 100644 samples/NewConfig.yml delete mode 100644 samples/NewPlugin.yml delete mode 100644 src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java delete mode 100644 src/main/java/fr/xephi/authme/security/crypts/Whirlpool.java delete mode 100644 src/main/java/fr/xephi/authme/security/crypts/XAuth.java delete mode 100644 src/test/java/fr/xephi/authme/security/crypts/WhirlpoolTest.java delete mode 100644 src/test/java/fr/xephi/authme/security/crypts/XAuthTest.java diff --git a/.checkstyle.xml b/.checkstyle.xml index b92fc345c..d0f579dcc 100644 --- a/.checkstyle.xml +++ b/.checkstyle.xml @@ -1,7 +1,7 @@ + "https://checkstyle.org/dtds/configuration_1_3.dtd"> diff --git a/.codeclimate.yml b/.codeclimate.yml index 536899863..217a1b6b8 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -38,7 +38,6 @@ exclude_patterns: - 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClient.java' - 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClientFactory.java' - 'src/main/java/fr/xephi/authme/security/crypts/PhpBB.java' - - 'src/main/java/fr/xephi/authme/security/crypts/Whirlpool.java' - 'src/main/java/fr/xephi/authme/security/crypts/Wordpress.java' # Don't check test classes - 'src/test/java/**/*Test.java' diff --git a/.gitignore b/.gitignore index 9a8a9ebf9..1df043b94 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ hs_err_pid* # Include the project's code style settings file !.idea/codeStyleSettings.xml +!.idea/misc.xml # File-based project format: *.ipr diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..b45dc4b5c --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 863ffc7c2..c8e9e84a6 100644 --- a/README.md +++ b/README.md @@ -90,23 +90,28 @@ You can also create your own translation file and, if you want, you can share it - **Dev resources:** - JavaDocs - Maven Repository - ```xml - - - codemc-repo - https://repo.codemc.org/repository/maven-public/ - - - - - - fr.xephi - authme - 5.6.0-SNAPSHOT - provided - - - ``` + - Maven dependency usage: + ```xml + + ... + + + codemc-repo + https://repo.codemc.org/repository/maven-public/ + + + ... + + + fr.xephi + authme + 5.6.0-SNAPSHOT + provided + + + ... + + ``` - **Statistics:** ![Graph](https://bstats.org/signatures/bukkit/AuthMe.svg) diff --git a/pom.xml b/pom.xml index 314ee62e1..9c2442a1b 100644 --- a/pom.xml +++ b/pom.xml @@ -622,6 +622,12 @@ + + org.jetbrains + annotations + 17.0.0 + provided + com.google.guava diff --git a/samples/NewConfig.yml b/samples/NewConfig.yml deleted file mode 100644 index c0b392c4b..000000000 --- a/samples/NewConfig.yml +++ /dev/null @@ -1,570 +0,0 @@ -# ======================================================================================================= -# _____ __ .__ _____ __________ .__ .___ .___ -# / _ \ __ ___/ |_| |__ / \ ____\______ \ ____ | | _________ __| _/____ __| _/ -# / /_\ \| | \ __| | \ / \ / \_/ __ \| __/ __ \| | / _ \__ \ / __ _/ __ \ / __ | -# / | | | /| | | Y / Y \ ___/| | \ ___/| |_( <_> / __ \/ /_/ \ ___// /_/ | -# \____|__ |____/ |__| |___| \____|__ /\___ |____|_ /\___ |____/\____(____ \____ |\___ \____ | -# \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ -# -# ======================================================================================================= -# -# Authme Main Configuration File. -# -# ======================================================================================================= - -# Plugin infos (overwritten on start, just a simple way to find out your plugin version). -authors: ${pluginAuthors} -version: ${project.version} -buildNumber: ${buildNumber} - -# Set this setting to true when you have configured the plugin, -# when false the server will be stopped with a warning message. -enabled: false - -# Database settings. -data_source: - # =========================== - # Database general settings. - # =========================== - - # Database backend (sqlite, mysql). - backend: sqlite - # Enable database queries caching, should improve performance. - caching: true - - # =========================== - # SqLite db parameters. - # =========================== - - sqlite: - # The name of the database storage file. - filename: 'authme.db' - - # =========================== - # MySql db parameters. - # =========================== - - mysql: - # Connection parameters. - host: '127.0.0.1' - port: 3306 - username: 'change_me' - password: 'change_me' - database: 'my_minecraft_server' - tablename: 'authme' - - # Column names. - column_names: - id: id - # Column for storing nicknames (ignore case nickname). - name: username - # Column for storing the realname (case sensitive nickname). - real_name: realname - # Column for storing passwords. - password: password - # Column for storing email addresses. - email: email - # Column for storing the authentication status (logged or not). - login_status: isLogged - # Column for storing player IPs. - ip: ip - # Column for storing lastlogins date and time. - last_login_timestamp: lastlogin - # Latest logout location of the players. - last_location: - world: world - x: x - y: y - z: z - # Enabled only if the bungeecord integration is activated. - server: world - - # Support for registrations via WebInterfaces/CSM. - # Disable some backend caching parameters. - disableAggressiveCaching: false - -# Main settings -settings: - - # =========================== - # Bungeecord integration - # =========================== - - bungeecord: - # Enable bungeecord integration features - enabled: true - - # Server name (must be unique, please use the name in the bungeecord configuration). - # Use 'auto' for auto configuration (requires the bungeecord module). - serverName: LoginLobby1 - # Keep the auth status when the player moves between servers. - # Required if you're using the bungeecord module. - keepAuthBetweenServers: true - - # Target server after login - send_after_login: - enabled: false - message: '' - delay: 5 - # Server name ("ServerName") or group ("G:GroupName") - # Groups are avariable only when the bungeecord module is avariable. - # If the server change fails the player will be kicked. - target: Lobby1 - failKickMessage: 'Failed to connect to the lobby! Please try to join the server again!' - # Target server after logout - send_after_logout: - enabled: false - message: '' - delay: 5 - # Server name ("ServerName") or group ("G:GroupName") - # Groups are avariable only when the bungeecord module is avariable. - # If the server change fails the player will be kicked. - target: LoginLobby1 - failKickMessage: 'Failed to connect to the lobby! Please try to join the server again!' - - # Variables: - # %p playername - bungee_commands: - player_command_after_register: - enabled: false - cmd: '' - console_command_after_register: - enabled: false - cmd: 'alert %p joined for the first time the network!' - player_command_after_login: - enabled: false - cmd: 'glist' - console_command_after_login: - enabled: false - cmd: 'alert %p logged in correctly!' - player_command_after_join: - enabled: false - cmd: '' - console_command_after_join: - enabled: false - cmd: 'alert %p joined the network!' - player_command_first_join: - enabled: false - cmd: '' - console_command_first_join: - enabled: false - cmd: 'alert %p joined for the first time the network!' - - # =========================== - # Sessions configuration. - # =========================== - - sessions: - # Enable sessions. - # When a player is authenticated, his IP and his nickname is saved. - # The next time the player will join the server, if his IP is the same - # of the last time, and the timeout time hasn't expired, he will be - # automatically authenticated. - enabled: false - # Session timeout. - # 0 for unlimited time (Very dangerous, use it at your own risk!) - # Consider that if player's ip has changed but the timeout hasn't - # expired, player will be kicked out of the sever! - timeout: 10 - # When enabled a player's session will expire if someone tries to - # login with a different IP Address. - expire_on_ip_change: true - - # =========================== - # Registration settings. - # =========================== - - registration: - # After how many time unregistered players should be kicked? - # Set to 0 to disable. (default: 30) - timeout: 30 - - nickname: - min_length: 4 - max_lenght: 16 - # Regex syntax. - allowed_characters: '[a-zA-Z0-9_]*' - - password: - # Enable double check of password on registration: - # /register - double_check: true - # Minimum password lenght. - min_length: 5 - # Regex syntax. - allowed_characters: '[\x21-\x7E]*' - # Denied unsafe passwords. - unsafePasswords: - - '123456' - - 'password' - - 'qwerty' - - '12345' - - '54321' - - # =========================== - # Login settings. - # =========================== - - login: - # After how many time unlogged players should be kicked? - # Set to 0 to disable. (default: 30) - timeout: 30 - - - - # =========================== - # Encryption parameters. - # =========================== - - password_encryption: - # The hashing algorithm. - # Possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB, MYBB, IPB3, - # PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5, - # PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (developpers only). - encryption_algorithm: SHA256 - # The salt length for the SALTED2MD5 and MD5(MD5(password)+salt) algorithms. - md5_salt_length: 8 - # If password check fails try all the other hash algorithm. - # AuthMe will update the password to the new passwordHash. - enable_convertion: false - - # =========================== - # Unlogged user restrictions. - # =========================== - - unlogged_restrictions: - # Deny chat messages send for unlogged users. - deny_chat: true - # Hide chat to unlogged users. - # Only player messages, plugins will be able to send messages to the player anyway. - hide_chat: false - - # Deny any command message not in the whitelist below. - deny_commands: true - command_whitelist: - - /login - - /register - - /l - - /reg - - /email - - /captcha - - movements: - # Restrict player movements. - restrict: true - # Allowed radius. - allowed_radius: 0 - # Should unlogged players have speed = 0? - # After the login the walking/flying speeed will be reset to the default value. - removeSpeed: true - - # End is there atm xD - - # This option will save the quit location of the players. - SaveQuitLocation: false - # Should not logged in players be teleported to the spawn? - # After the authentication, if SaveQuitLocation is enabled, - # they will be teleported back to their normal position. - teleportUnAuthedToSpawn: false - - # If enabled, after the login, if the ForceSpawnOnTheseWorlds setting contains - # the player's world, he will be teleported to the world spawnpoint. - # The quit location of the player will be overwritten. - # This is different from "teleportUnAuthedToSpawn" that teleports player - # back to his quit location after the authentication. - ForceSpawnLocOnJoinEnabled: false - # WorldNames where we need to force the spawn location - # Warning: This setting is Case Sensitive! - ForceSpawnOnTheseWorlds: - - world - - world_nether - - world_the_end - - # this is very important options, - # every time player join the server, - # if they are registered, AuthMe will switch him - # to unLoggedInGroup, this - # should prevent all major exploit. - # So you can set up on your Permission Plugin - # this special group with 0 permissions, or permissions to chat, - # or permission to - # send private message or all other perms that you want, - # the better way is to set up - # this group with few permissions, - # so if player try to exploit some account, - # they can - # do anything except what you set in perm Group. - # After a correct logged-in player will be - # moved to his correct permissions group! - # Pay attention group name is case sensitive, - # so Admin is different from admin, - # otherwise your group will be wiped, - # and player join in default group []! - # Example unLoggedinGroup: NotLogged - unLoggedinGroup: unLoggedinGroup - - # =========================== - # Address restrictions - # =========================== - - # Max number of registrations per IP (default: 1) - maxRegPerIp: 1 - # Maximum allowed number of Logins per IP, 0 to disable (default: 0) - maxLoginPerIp: 0 - # Maximum allowed number of Joins per IP, 0 to disable (default: 0) - maxJoinPerIp: 0 - - # When this setting is enabled, online players can't be kicked out - # due to "Logged in from another Location" - # This setting will prevent potential security exploits. - ForceSingleSession: true - - # To activate the restricted user feature you need - # to enable this option and configure the - # AllowedRestrictedUser field. - AllowRestrictedUser: false - # The restricted user feature will kick players listed below - # if they dont match of the defined ip address. - # Example: - # AllowedRestrictedUser: - # - playername;127.0.0.1 - AllowedRestrictedUser: - - playername;127.0.0. - # Ban ip when the ip is not the ip registered in database - banUnsafedIP: false - - - - # =============================== - # Other restrictions - # =============================== - - # Should we protect the player inventory before logging in? - # Warning: Requires the latest version of ProtocolLib! - ProtectInventoryBeforeLogIn: true - - # Should unregistered players be kicked immediately? - kickNonRegistered: false - # Should players be kicked on wrong password? - kickOnWrongPassword: false - - # Should we display all other accounts of a player when he joins? - # Required permission: authme.admin.accounts - displayOtherAccounts: true - - # =============================== - # Restrictions compatibility - # =============================== - - # Spawn Priority. Avariable values : authme, essentials, multiverse, default - spawnPriority: authme,essentials,multiverse,default - # AuthMe will NEVER teleport players! - noTeleport: false - - GameMode: - # Do you want to set player's gamemode to survival when he joins? - # This enables also the settings below. - ForceSurvivalMode: false - # Do you want to reset player's inventory if player joins with creative mode? - ResetInventoryIfCreative: false - # Do you want to force the survival mode ONLY after the /login process? - ForceOnlyAfterLogin: false - - # sgdc3: Ok, our configuration is shit.... xD Today I will stop there - - - registration: - # enable registration on the server? - enabled: true - # Send every X seconds a message to a player to - # remind him that he has to login/register - messageInterval: 5 - # Only registered and logged in players can play. - # See restrictions for exceptions - force: true - # Does we replace password registration by an Email registration method ? - enableEmailRegistrationSystem: false - # Enable double check of email when you register - # when it's true, registration require that kind of command: - # /register - doubleEmailCheck: false - # Do we force kicking player after a successful registration ? - # Do not use with login feature below - forceKickAfterRegister: false - # Does AuthMe need to enforce a /login after a successful registration ? - forceLoginAfterRegister: false - unrestrictions: - # below you can list all your account name, that - # AuthMe will ignore for registration or login, configure it - # at your own risk!! Remember that if you are going to add - # nickname with [], you have to delimit name with ' '. - # this option add compatibility with BuildCraft and some - # other mods. - # It is CaseSensitive! - UnrestrictedName: [] - # Message language, available : en, de, br, cz, pl, fr, ru, hu, sk, es, zhtw, fi, zhcn, lt, it, ko, pt - messagesLanguage: en - # Force these commands after /login, without any '/', use %p for replace with player name - forceCommands: [] - # Force these commands after /login as a server console, without any '/', use %p for replace with player name - forceCommandsAsConsole: [] - # Force these commands after /register, without any '/', use %p for replace with player name - forceRegisterCommands: [] - # Force these commands after /register as a server console, without any '/', use %p for replace with player name - forceRegisterCommandsAsConsole: [] - # Do we need to display the welcome message (welcome.txt) after a register or a login? - # You can use colors in this welcome.txt + some replaced strings : - # {PLAYER} : player name, {ONLINE} : display number of online players, {MAXPLAYERS} : display server slots, - # {IP} : player ip, {LOGINS} : number of players logged, {WORLD} : player current world, {SERVER} : server name - # {VERSION} : get current bukkit version, {COUNTRY} : player country - useWelcomeMessage: true - # Do we need to broadcast the welcome message to all server or only to the player? set true for server or false for player - broadcastWelcomeMessage: false - # Do we need to delay the join/leave message to be displayed only when the player is authenticated ? - delayJoinMessage: false - removeJoinMessage: false - removeLeaveMessage: false - # Do we need to add potion effect Blinding before login/register ? - applyBlindEffect: false -ExternalBoardOptions: - # MySQL column for the salt , needed for some forum/cms support - mySQLColumnSalt: '' - # MySQL column for the group, needed for some forum/cms support - mySQLColumnGroup: '' - # -1 mean disabled. If u want that only - # activated player can login in your server - # u can put in this options the group number - # of unactivated user, needed for some forum/cms support - nonActivedUserGroup: -1 - # Other MySQL columns where we need to put the Username (case sensitive) - mySQLOtherUsernameColumns: [] - # How much Log to Round needed in BCrypt(do not change it if you do not know what's your doing) - bCryptLog2Round: 10 - # phpBB prefix defined during phpbb installation process - phpbbTablePrefix: 'phpbb_' - # phpBB activated group id , 2 is default registered group defined by phpbb - phpbbActivatedGroupId: 2 - # WordPress prefix defined during WordPress installation process - wordpressTablePrefix: 'wp_' -permission: - # Take care with this options, if you dont want - # to use Vault and Group Switching of - # AuthMe for unloggedIn players put true - # below, default is false. - EnablePermissionCheck: false -BackupSystem: - # Enable or Disable Automatic Backup - ActivateBackup: false - # set Backup at every start of Server - OnServerStart: false - # set Backup at every stop of Server - OnServerStop: true - # Windows only mysql installation Path - MysqlWindowsPath: 'C:\\Program Files\\MySQL\\MySQL Server 5.1\\' -Security: - SQLProblem: - # Stop the server if we can't contact the sql database - # Take care with this, if you set that to false, - # AuthMe automatically disable and the server is not protected! - stopServer: true - ReloadCommand: - # /reload support - useReloadCommandSupport: true - console: - # Remove spam console - noConsoleSpam: false - captcha: - # Player need to put a captcha when he fails too lot the password - useCaptcha: false - # Max allowed tries before request a captcha - maxLoginTry: 5 - # Captcha length - captchaLength: 5 -Converter: - Rakamak: - # Rakamak file name - fileName: users.rak - # Rakamak use ip ? - useIP: false - # IP file name for rakamak - ipFileName: UsersIp.rak - CrazyLogin: - # CrazyLogin database file - fileName: accounts.db -Email: - # Email SMTP server host - mailSMTP: smtp.gmail.com - # Email SMTP server port - mailPort: 465 - # Email account that send the mail - mailAccount: '' - # Email account password - mailPassword: '' - # Custom SenderName, that replace the mailAccount name in the email - mailSenderName: '' - # Random password length - RecoveryPasswordLength: 8 - # Email subject of password get - mailSubject: 'Your new AuthMe Password' - # Email text here - mailText: 'Dear ,

This is your new AuthMe password for the server

:



Do not forget to change password after login!
/changepassword newPassword' - # Like maxRegPerIp but with email - maxRegPerEmail: 1 - # Recall players to add an email ? - recallPlayers: false - # Delay in minute for the recall scheduler - delayRecall: 5 - # Blacklist these domains for emails - emailBlacklisted: - - 10minutemail.com - # WhiteList only these domains for emails - emailWhitelisted: [] - # Do we need to send new password draw in an image ? - generateImage: false -Hooks: - # Do we need to hook with multiverse for spawn checking? - multiverse: true - # Do we need to hook with BungeeCord for get the real Player ip ? - bungeecord: false - # Do we need to disable Essentials SocialSpy on join ? - disableSocialSpy: true - # Do we need to force /motd Essentials command on join ? - useEssentialsMotd: false - # Do we need to cache custom Attributes ? - customAttributes: false -Purge: - # On Enable , does AuthMe need to purge automatically old accounts unused ? - useAutoPurge: false - # Number of Days an account become Unused - daysBeforeRemovePlayer: 60 - # Do we need to remove the player.dat file during purge process ? - removePlayerDat: false - # Do we need to remove the Essentials/users/player.yml file during purge process ? - removeEssentialsFile: false - # World where are players.dat stores - defaultWorld: 'world' - # Do we need to remove LimitedCreative/inventories/player.yml , player_creative.yml files during purge process ? - removeLimitedCreativesInventories: false - # Do we need to remove the AntiXRayData/PlayerData/player file during purge process ? - removeAntiXRayFile: false - # Do we need to remove permissions ? - removePermissions: false -Protection: - # Enable some servers protection ( country based login, antibot ) - enableProtection: false - # Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes - countries: - - US - - GB - # Countries blacklisted automatically ( without any needed to enable protection ) - countriesBlacklist: - - A1 - # Do we need to enable automatic antibot system? - enableAntiBot: false - # Max number of player allowed to login in 5 secs before enable AntiBot system automatically - antiBotSensibility: 5 - # Duration in minutes of the antibot automatic system - antiBotDuration: 10 -VeryGames: - # These features are only available on VeryGames Server Provider - enableIpCheck: false diff --git a/samples/NewPlugin.yml b/samples/NewPlugin.yml deleted file mode 100644 index f403da60b..000000000 --- a/samples/NewPlugin.yml +++ /dev/null @@ -1,199 +0,0 @@ -name: ${pluginName} -authors: [${pluginAuthors}] -website: ${project.url} -description: ${project.description} -main: ${mainClass} -version: ${project.version}-b${buildNumber} -softdepend: - - Vault - - PermissionsBukkit - - PermissionsEX - - EssentialsGroupManager - - Multiverse-Core - - Essentials - - EssentialsSpawn - - ProtocolLib -commands: - authme: - description: AuthMe admin commands - usage: '/authme reload|register playername password|changepassword playername password|unregister playername|version|converter datatype' - permission: authme.admin - register: - description: Register an account - usage: /register password confirmpassword - aliases: [reg] - permission: authme.player.register - login: - description: Login into a account - usage: /login password - aliases: [l,log] - permission: authme.player.login - changepassword: - description: Change password of a account - usage: /changepassword oldPassword newPassword - permission: authme.player.changepassword - logout: - description: Logout from the server - usage: /logout - permission: authme.player.logout - unregister: - description: unregister your account - usage: /unregister password - permission: authme.player.unregister - email: - description: Add Email or recover password - usage: '/email add your@email.com your@email.com|change oldEmail newEmail|recovery your@email.com' - permission: authme.player.email - captcha: - description: Captcha command - usage: /captcha theCaptcha - permission: authme.player.captcha -permissions: - authme.canbeforced: - description: Allow the user to be forced-logged via API - default: true - authme.player: - description: Gives access to all authme player commands - default: true - children: - authme.player.login: true - authme.player.logout: true - authme.player.register: true - authme.player.unregister: true - authme.player.changepassword: true - authme.player.captcha: true - authme.player.email: true - authme.player.register: - description: Register your account - default: false - authme.player.unregister: - description: Unregister your account - default: false - authme.player.login: - description: Login into your account - default: false - authme.player.logout: - description: Logout from your account - default: false - authme.player.changepassword: - description: Change password of your account - default: false - authme.player.email: - description: Gives access to player's email commands - default: false - children: - authme.player.email.add: true - authme.player.email.change: true - authme.player.email.recover: true - authme.player.email.add: - description: Add an email to your account - default: false - authme.player.email.change: - description: Change email of your account - default: false - authme.player.email.recover: - description: Recover your account - default: false - authme.player.captcha: - description: Captcha command - default: false - authme.admin: - description: Gives access to all authme admin commands - default: op - children: - authme.admin.forcelogin: true - authme.admin.forcelogout: true - authme.admin.register: true - authme.admin.unregister: true - authme.admin.changemail: true - authme.admin.changepassword: true - authme.admin.lastlogin: true - authme.admin.accounts: true - authme.admin.getemail: true - authme.admin.getip: true - authme.admin.setspawn: true - authme.admin.spawn: true - authme.admin.setfirstspawn: true - authme.admin.firstspawn: true - authme.admin.purge: true - authme.admin.purgebannedplayers: true - authme.admin.purgelastpos: true - authme.admin.converter: true - authme.admin.reload: true - authme.admin.switchantibot: true - authme.admin.seeotheraccounts: true - authme.admin.register: - description: Register an account - default: false - authme.admin.unregister: - description: Unregister an account - default: false - authme.admin.forcelogin: - description: Force login for that player - default: false - authme.admin.forcelogout: - description: Force logout for that player - default: false - authme.admin.changepassword: - description: Change the password of an account - default: false - authme.admin.getemail: - description: Get last email about a player - default: false - authme.admin.changeemail: - description: Change a player email - default: false - authme.admin.accounts: - description: Display Players Accounts - default: false - authme.admin.seeotheraccounts: - description: Display other accounts about a player when he logs in - default: false - authme.admin.lastlogin: - description: Get last login date about a player - default: false - authme.admin.getip: - description: Get IP from a player (fake and real) - default: false - authme.admin.setspawn: - description: Set the AuthMe spawn point - default: false - authme.admin.spawn: - description: Teleport to AuthMe spawn point - default: false - authme.admin.setfirstspawn: - description: Set the AuthMe First Spawn Point - default: false - authme.admin.firstspawn: - description: Teleport to AuthMe First Spawn Point - default: false - authme.admin.switchantibot: - description: Switch AntiBot mode on/off - default: false - authme.admin.purge: - description: Database purge command - default: false - authme.admin.purgebannedplayers: - description: Purge banned players - default: false - authme.admin.purgelastpos: - description: Purge last position of a player/players - default: false - authme.admin.converter: - description: Allow the /authme converter command - default: false - authme.admin.reload: - description: Reload the plugin - default: false - authme.vip: - description: Allow vip slot when the server is full - default: false - authme.bypassantibot: - description: Bypass the AntiBot check - default: false - authme.allowmultipleaccounts: - description: Allow more accounts for same ip - default: false - authme.bypassforcesurvival: - description: Bypass all ForceSurvival features - default: false diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 045d1ee97..3984a2abf 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -2,7 +2,6 @@ import ch.jalu.injector.Injector; import ch.jalu.injector.InjectorBuilder; -import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.api.v3.AuthMeApi; import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.datasource.DataSource; @@ -32,6 +31,7 @@ import fr.xephi.authme.task.CleanupTask; import fr.xephi.authme.task.purge.PurgeService; import fr.xephi.authme.util.ExceptionUtils; +import fr.xephi.authme.util.FileUtils; import org.bukkit.Server; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -40,6 +40,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPluginLoader; import org.bukkit.scheduler.BukkitScheduler; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.function.Consumer; @@ -79,7 +80,6 @@ public AuthMe() { /* * Constructor for unit testing. */ - @VisibleForTesting AuthMe(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) { super(loader, description, dataFolder, file); } @@ -89,6 +89,7 @@ public AuthMe() { * * @return The plugin's name. */ + @NotNull public static String getPluginName() { return PLUGIN_NAME; } @@ -98,6 +99,7 @@ public static String getPluginName() { * * @return The plugin's version. */ + @NotNull public static String getPluginVersion() { return pluginVersion; } @@ -107,6 +109,7 @@ public static String getPluginVersion() { * * @return The plugin's build number. */ + @NotNull public static String getPluginBuildNumber() { return pluginBuildNumber; } @@ -182,7 +185,7 @@ public void onEnable() { * * @param versionRaw the version as given by the plugin description file */ - private static void loadPluginInfo(String versionRaw) { + private static void loadPluginInfo(@NotNull String versionRaw) { int index = versionRaw.lastIndexOf("-"); if (index != -1) { pluginVersion = versionRaw.substring(0, index); @@ -198,7 +201,7 @@ private static void loadPluginInfo(String versionRaw) { */ private void initialize() { // Create plugin folder - getDataFolder().mkdir(); + FileUtils.createDirectoryOrFail(getDataFolder()); // Create injector, provide elements from the Bukkit environment and register providers injector = new InjectorBuilder() @@ -241,7 +244,7 @@ private void initialize() { * * @param injector the injector */ - void instantiateServices(Injector injector) { + void instantiateServices(@NotNull Injector injector) { database = injector.getSingleton(DataSource.class); bukkitService = injector.getSingleton(BukkitService.class); commandHandler = injector.getSingleton(CommandHandler.class); @@ -259,7 +262,7 @@ void instantiateServices(Injector injector) { * * @param injector the injector */ - void registerEventListeners(Injector injector) { + void registerEventListeners(@NotNull Injector injector) { // Get the plugin manager instance PluginManager pluginManager = getServer().getPluginManager(); @@ -332,8 +335,8 @@ public void onDisable() { * @return True if the command was executed, false otherwise. */ @Override - public boolean onCommand(CommandSender sender, Command cmd, - String commandLabel, String[] args) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, + @NotNull String commandLabel, String[] args) { // Make sure the command handler has been initialized if (commandHandler == null) { getLogger().severe("AuthMe command handler is not available"); @@ -344,6 +347,7 @@ public boolean onCommand(CommandSender sender, Command cmd, return commandHandler.processCommand(sender, commandLabel, args); } + @NotNull private String getServerNameVersionSafe() { try { Server server = getServer(); @@ -352,4 +356,5 @@ private String getServerNameVersionSafe() { return "-"; } } + } diff --git a/src/main/java/fr/xephi/authme/ConsoleLogger.java b/src/main/java/fr/xephi/authme/ConsoleLogger.java index 88798ced0..ed78f002f 100644 --- a/src/main/java/fr/xephi/authme/ConsoleLogger.java +++ b/src/main/java/fr/xephi/authme/ConsoleLogger.java @@ -1,11 +1,11 @@ package fr.xephi.authme; -import com.google.common.base.Throwables; import fr.xephi.authme.output.LogLevel; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.util.ExceptionUtils; +import org.jetbrains.annotations.NotNull; import java.io.Closeable; import java.io.File; @@ -42,7 +42,9 @@ public final class ConsoleLogger { private static OutputStreamWriter fileWriter; // Individual state + @NotNull private final String name; + @NotNull private LogLevel logLevel = LogLevel.INFO; /** @@ -50,7 +52,7 @@ public final class ConsoleLogger { * * @param name the name of this logger (the fully qualified class name using it) */ - public ConsoleLogger(String name) { + public ConsoleLogger(@NotNull String name) { this.name = name; } @@ -58,7 +60,7 @@ public ConsoleLogger(String name) { // Configurations // -------- - public static void initialize(Logger logger, File logFile) { + public static void initialize(@NotNull Logger logger, @NotNull File logFile) { ConsoleLogger.logger = logger; ConsoleLogger.logFile = logFile; } @@ -68,7 +70,7 @@ public static void initialize(Logger logger, File logFile) { * * @param settings the settings to read from */ - public static void initializeSharedSettings(Settings settings) { + public static void initializeSharedSettings(@NotNull Settings settings) { boolean useLogging = settings.getProperty(SecuritySettings.USE_LOGGING); if (useLogging) { initializeFileWriter(); @@ -82,14 +84,16 @@ public static void initializeSharedSettings(Settings settings) { * * @param settings the settings to read from */ - public void initializeSettings(Settings settings) { + public void initializeSettings(@NotNull Settings settings) { this.logLevel = settings.getProperty(PluginSettings.LOG_LEVEL); } + @NotNull public LogLevel getLogLevel() { return logLevel; } + @NotNull public String getName() { return name; } @@ -104,8 +108,12 @@ public String getName() { * * @param message The message to log */ - public void warning(String message) { - logger.warning(message); + public void warning(@NotNull String message) { + if (logger != null) { + logger.warning(message); + } else { + System.err.println("[WARN] " + message); + } writeLog("[WARN] " + message); } @@ -116,9 +124,9 @@ public void warning(String message) { * @param message The message to accompany the exception * @param th The Throwable to log */ - public void logException(String message, Throwable th) { + public void logException(@NotNull String message, @NotNull Throwable th) { warning(message + " " + ExceptionUtils.formatException(th)); - writeLog(Throwables.getStackTraceAsString(th)); + writeLog(ExceptionUtils.getStackTraceAsString(th)); } /** @@ -126,8 +134,12 @@ public void logException(String message, Throwable th) { * * @param message The message to log */ - public void info(String message) { - logger.info(message); + public void info(@NotNull String message) { + if (logger != null) { + logger.info(message); + } else { + System.out.println("[INFO] " + message); + } writeLog("[INFO] " + message); } @@ -139,9 +151,13 @@ public void info(String message) { * * @param message The message to log */ - public void fine(String message) { + public void fine(@NotNull String message) { if (logLevel.includes(LogLevel.FINE)) { - logger.info(message); + if (logger != null) { + logger.info(message); + } else { + System.err.println("[FINE] " + message); + } writeLog("[FINE] " + message); } } @@ -158,7 +174,7 @@ public void fine(String message) { * * @param message The message to log */ - public void debug(String message) { + public void debug(@NotNull String message) { if (logLevel.includes(LogLevel.DEBUG)) { logAndWriteWithDebugPrefix(message); } @@ -171,7 +187,7 @@ public void debug(String message) { * @param param1 parameter to replace in the message */ // Avoids array creation if DEBUG level is disabled - public void debug(String message, Object param1) { + public void debug(@NotNull String message, Object param1) { if (logLevel.includes(LogLevel.DEBUG)) { debug(message, new Object[]{param1}); } @@ -185,7 +201,7 @@ public void debug(String message, Object param1) { * @param param2 second param to replace in message */ // Avoids array creation if DEBUG level is disabled - public void debug(String message, Object param1, Object param2) { + public void debug(@NotNull String message, Object param1, Object param2) { if (logLevel.includes(LogLevel.DEBUG)) { debug(message, new Object[]{param1, param2}); } @@ -197,7 +213,7 @@ public void debug(String message, Object param1, Object param2) { * @param message the message * @param params the params to replace in the message */ - public void debug(String message, Object... params) { + public void debug(@NotNull String message, Object... params) { if (logLevel.includes(LogLevel.DEBUG)) { logAndWriteWithDebugPrefix(MessageFormat.format(message, params)); } @@ -208,15 +224,19 @@ public void debug(String message, Object... params) { * * @param msgSupplier the message supplier */ - public void debug(Supplier msgSupplier) { + public void debug(@NotNull Supplier msgSupplier) { if (logLevel.includes(LogLevel.DEBUG)) { logAndWriteWithDebugPrefix(msgSupplier.get()); } } - private void logAndWriteWithDebugPrefix(String message) { + private void logAndWriteWithDebugPrefix(@NotNull String message) { String debugMessage = "[DEBUG] " + message; - logger.info(debugMessage); + if (logger != null) { + logger.info(debugMessage); + } else { + System.err.println(debugMessage); + } writeLog(debugMessage); } @@ -244,7 +264,7 @@ public static void closeFileWriter() { * * @param message The message to write to the log */ - private static void writeLog(String message) { + private static void writeLog(@NotNull String message) { if (fileWriter != null) { String dateTime = DATE_FORMAT.format(LocalDateTime.now()); try { @@ -284,4 +304,5 @@ private static void initializeFileWriter() { } } } + } diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index fcc3ce611..4429a0541 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -445,7 +445,7 @@ private CommandDescription buildAuthMeBaseCommand() { .labels("converter", "convert", "conv") .description("Converter command") .detailedDescription("Converter command for AuthMeReloaded.") - .withArgument("job", "Conversion job: xauth / crazylogin / rakamak / " + .withArgument("job", "Conversion job: crazylogin / rakamak / " + "royalauth / vauth / sqliteToSql / mysqlToSqlite / loginsecurity", OPTIONAL) .permission(AdminPermission.CONVERTER) .executableCommand(ConverterCommand.class) 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 fd0a73513..1467b2ac0 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 @@ -13,7 +13,6 @@ import fr.xephi.authme.datasource.converter.RoyalAuthConverter; import fr.xephi.authme.datasource.converter.SqliteToSql; import fr.xephi.authme.datasource.converter.VAuthConverter; -import fr.xephi.authme.datasource.converter.XAuthConverter; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.service.BukkitService; @@ -81,7 +80,6 @@ private static Class getConverterClassFromArgs(List */ private static Map> getConverters() { return ImmutableSortedMap.>naturalOrder() - .put("xauth", XAuthConverter.class) .put("crazylogin", CrazyLoginConverter.class) .put("rakamak", RakamakConverter.class) .put("royalauth", RoyalAuthConverter.class) 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 2e00c65e9..3aedeb933 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 @@ -25,7 +25,7 @@ public void executeCommand(CommandSender sender, List arguments) { Player player = bukkitService.getPlayerExact(playerName); PlayerAuth auth = dataSource.getAuth(playerName); - if (player != null) { + if (player != null && player.getAddress() != null) { sender.sendMessage("Current IP of " + player.getName() + " is " + PlayerUtils.getPlayerIp(player) + ":" + player.getAddress().getPort()); } 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 82b109cc3..fa3ae58f6 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 @@ -29,9 +29,12 @@ public void executeCommand(CommandSender sender, List arguments) { Set bannedPlayers = bukkitService.getBannedPlayers(); Set namedBanned = new HashSet<>(bannedPlayers.size()); for (OfflinePlayer offlinePlayer : bannedPlayers) { + if (offlinePlayer.getName() == null) { + continue; + } namedBanned.add(offlinePlayer.getName().toLowerCase()); } - purgeService.purgePlayers(sender, namedBanned, bannedPlayers.toArray(new OfflinePlayer[bannedPlayers.size()])); + purgeService.purgePlayers(sender, namedBanned, bannedPlayers.toArray(new OfflinePlayer[0])); } } 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 1538061e9..edc86a1de 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 @@ -27,8 +27,10 @@ public void executeCommand(CommandSender sender, List arguments) { String daysStr = arguments.get(0); // Convert the days string to an integer value, and make sure it's valid - Integer days = Ints.tryParse(daysStr); - if (days == null) { + int days; + try { + days = Integer.parseInt(daysStr); + } catch (NumberFormatException e) { sender.sendMessage(ChatColor.RED + "The value you've entered is invalid!"); return; } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java index e8a15b795..d2764d65e 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java @@ -61,12 +61,8 @@ public void execute(CommandSender sender, List arguments) { Player player = bukkitService.getPlayerExact(playerName); if (player == null) { OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName); - if (offlinePlayer == null) { - sender.sendMessage(ChatColor.DARK_RED + "Player '" + playerName + "' does not exist"); - } else { - sender.sendMessage("Player '" + playerName + "' not online; checking with offline player"); - performPermissionCheck(offlinePlayer, permissionNode, permissionsManager::hasPermissionOffline, sender); - } + sender.sendMessage("Player '" + playerName + "' not online; checking with offline player"); + performPermissionCheck(offlinePlayer, permissionNode, permissionsManager::hasPermissionOffline, sender); } else { performPermissionCheck(player, permissionNode, permissionsManager::hasPermission, sender); } diff --git a/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java b/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java index 23aa8116d..916ff7347 100644 --- a/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java +++ b/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java @@ -74,6 +74,7 @@ public int getGroupId() { } public void setQuitLocation(Location location) { + Objects.requireNonNull(location.getWorld(), "world not loaded!"); x = location.getBlockX(); y = location.getBlockY(); z = location.getBlockZ(); @@ -300,6 +301,7 @@ public Builder lastIp(String lastIp) { * @return this builder instance */ public Builder location(Location location) { + Objects.requireNonNull(location.getWorld(), "world not loaded!"); this.x = location.getX(); this.y = location.getY(); this.z = location.getZ(); diff --git a/src/main/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManager.java b/src/main/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManager.java index 3612e6797..e9708aea9 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManager.java +++ b/src/main/java/fr/xephi/authme/data/limbo/LimboPlayerTaskManager.java @@ -66,6 +66,7 @@ void registerMessageTask(Player player, LimboPlayer limbo, LimboMessageType mess */ void registerTimeoutTask(Player player, LimboPlayer limbo) { final int timeout = settings.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND; + //noinspection ConstantConditions Inspection error! if (timeout > 0) { String message = messages.retrieveSingle(player, MessageKey.LOGIN_TIMEOUT_ERROR); BukkitTask task = bukkitService.runTaskLater(new TimeoutTask(player, message, playerCache), timeout); diff --git a/src/main/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandler.java b/src/main/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandler.java index 9708ce884..025dd005a 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandler.java +++ b/src/main/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandler.java @@ -1,6 +1,5 @@ package fr.xephi.authme.data.limbo.persistence; -import com.google.common.io.Files; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -19,6 +18,7 @@ import java.io.FileWriter; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -115,7 +115,7 @@ private Map readLimboPlayers(File file) { } try { - return gson.fromJson(Files.asCharSource(file, StandardCharsets.UTF_8).read(), LIMBO_MAP_TYPE); + return gson.fromJson(new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8), LIMBO_MAP_TYPE); } catch (Exception e) { logger.logException("Failed reading '" + file + "':", e); } diff --git a/src/main/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandler.java b/src/main/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandler.java index 9772ec064..205b887ab 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandler.java +++ b/src/main/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandler.java @@ -1,6 +1,5 @@ package fr.xephi.authme.data.limbo.persistence; -import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import fr.xephi.authme.ConsoleLogger; @@ -15,6 +14,7 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; /** * Saves LimboPlayer objects as JSON into individual files. @@ -48,7 +48,7 @@ public LimboPlayer getLimboPlayer(Player player) { } try { - String str = Files.asCharSource(file, StandardCharsets.UTF_8).read(); + String str = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); return gson.fromJson(str, LimboPlayer.class); } catch (IOException e) { logger.logException("Could not read player data on disk for '" + player.getName() + "'", e); @@ -61,9 +61,8 @@ public void saveLimboPlayer(Player player, LimboPlayer limboPlayer) { String id = player.getUniqueId().toString(); try { File file = new File(cacheDir, id + File.separator + "data.json"); - Files.createParentDirs(file); - Files.touch(file); - Files.write(gson.toJson(limboPlayer), file, StandardCharsets.UTF_8); + FileUtils.createDirectoryOrFail(file); + Files.write(file.toPath(), gson.toJson(limboPlayer).getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { logger.logException("Failed to write " + player.getName() + " data:", e); } diff --git a/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java b/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java index 5f9b40ede..1f8bac434 100644 --- a/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java +++ b/src/main/java/fr/xephi/authme/data/limbo/persistence/LimboPlayerSerializer.java @@ -9,6 +9,7 @@ import org.bukkit.Location; import java.lang.reflect.Type; +import java.util.Objects; /** * Converts a LimboPlayer to a JsonElement. @@ -36,7 +37,7 @@ class LimboPlayerSerializer implements JsonSerializer { public JsonElement serialize(LimboPlayer limboPlayer, Type type, JsonSerializationContext context) { Location loc = limboPlayer.getLocation(); JsonObject locationObject = new JsonObject(); - locationObject.addProperty(LOC_WORLD, loc.getWorld().getName()); + locationObject.addProperty(LOC_WORLD, Objects.requireNonNull(loc.getWorld()).getName()); locationObject.addProperty(LOC_X, loc.getX()); locationObject.addProperty(LOC_Y, loc.getY()); locationObject.addProperty(LOC_Z, loc.getZ()); diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index e1418dcaf..b40948f5f 100644 --- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java +++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java @@ -18,6 +18,7 @@ import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.Executors; @@ -65,8 +66,8 @@ public ListenableFuture> reload(final String key, Optional< }); } - public LoadingCache> getCachedAuths() { - return cachedAuths; + public Map> getCachedAuths() { + return cachedAuths.asMap(); } @Override @@ -292,8 +293,10 @@ public void invalidateCache(String playerName) { cachedAuths.invalidate(playerName); } + @SuppressWarnings("OptionalAssignedToNull") @Override public void refreshCache(String playerName) { + // We are actually checking if the entry is cached if (cachedAuths.getIfPresent(playerName) != null) { cachedAuths.refresh(playerName); } diff --git a/src/main/java/fr/xephi/authme/datasource/SqLiteMigrater.java b/src/main/java/fr/xephi/authme/datasource/SqLiteMigrater.java index b4a2a577b..d2fb50e36 100644 --- a/src/main/java/fr/xephi/authme/datasource/SqLiteMigrater.java +++ b/src/main/java/fr/xephi/authme/datasource/SqLiteMigrater.java @@ -1,6 +1,5 @@ package fr.xephi.authme.datasource; -import com.google.common.io.Files; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.settings.Settings; @@ -10,6 +9,8 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -72,7 +73,7 @@ private String createBackup() { String backupName = "backup-" + databaseName + FileUtils.createCurrentTimeString() + ".db"; File backup = new File(backupDirectory, backupName); try { - Files.copy(sqLite, backup); + Files.copy(sqLite.toPath(), backup.toPath(), StandardCopyOption.REPLACE_EXISTING); return backupName; } catch (IOException e) { throw new IllegalStateException("Failed to create SQLite backup before migration", e); diff --git a/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java index 7c45aebfa..394586a1c 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java @@ -34,6 +34,9 @@ public class RoyalAuthConverter implements Converter { @Override public void execute(CommandSender sender) { for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) { + if (player.getName() == null) { + continue; + } try { String name = player.getName().toLowerCase(); File file = new File(makePath(".", "plugins", "RoyalAuth", "userdata", name + ".yml")); diff --git a/src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java deleted file mode 100644 index 928566583..000000000 --- a/src/main/java/fr/xephi/authme/datasource/converter/XAuthConverter.java +++ /dev/null @@ -1,148 +0,0 @@ -package fr.xephi.authme.datasource.converter; - -import de.luricos.bukkit.xAuth.database.DatabaseTables; -import de.luricos.bukkit.xAuth.utils.xAuthLog; -import de.luricos.bukkit.xAuth.xAuth; -import fr.xephi.authme.data.auth.PlayerAuth; -import fr.xephi.authme.datasource.DataSource; -import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.util.Utils; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.PluginManager; - -import javax.inject.Inject; -import java.io.File; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import static fr.xephi.authme.util.FileUtils.makePath; - -public class XAuthConverter implements Converter { - - @Inject - @DataFolder - private File dataFolder; - @Inject - private DataSource database; - @Inject - private PluginManager pluginManager; - - XAuthConverter() { - } - - @Override - public void execute(CommandSender sender) { - try { - Class.forName("de.luricos.bukkit.xAuth.xAuth"); - convert(sender); - } catch (ClassNotFoundException ce) { - sender.sendMessage("xAuth has not been found, please put xAuth.jar in your plugin folder and restart!"); - } - } - - private void convert(CommandSender sender) { - if (pluginManager.getPlugin("xAuth") == null) { - sender.sendMessage("[AuthMe] xAuth plugin not found"); - return; - } - //TODO ljacqu 20160702: xAuthDb is not used except for the existence check -- is this intended? - File xAuthDb = new File(dataFolder.getParent(), makePath("xAuth", "xAuth.h2.db")); - if (!xAuthDb.exists()) { - sender.sendMessage("[AuthMe] xAuth H2 database not found, checking for MySQL or SQLite data..."); - } - List players = getXAuthPlayers(); - if (Utils.isCollectionEmpty(players)) { - sender.sendMessage("[AuthMe] Error while importing xAuthPlayers: did not find any players"); - return; - } - sender.sendMessage("[AuthMe] Starting import..."); - - for (int id : players) { - String pl = getIdPlayer(id); - String psw = getPassword(id); - if (psw != null && !psw.isEmpty() && pl != null) { - PlayerAuth auth = PlayerAuth.builder() - .name(pl.toLowerCase()) - .realName(pl) - .password(psw, null).build(); - database.saveAuth(auth); - } - } - sender.sendMessage("[AuthMe] Successfully converted from xAuth database"); - } - - private String getIdPlayer(int id) { - String realPass = ""; - Connection conn = xAuth.getPlugin().getDatabaseController().getConnection(); - PreparedStatement ps = null; - ResultSet rs = null; - try { - String sql = String.format("SELECT `playername` FROM `%s` WHERE `id` = ?", - xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT)); - ps = conn.prepareStatement(sql); - ps.setInt(1, id); - rs = ps.executeQuery(); - if (!rs.next()) { - return null; - } - realPass = rs.getString("playername").toLowerCase(); - } catch (SQLException e) { - xAuthLog.severe("Failed to retrieve name for account: " + id, e); - return null; - } finally { - xAuth.getPlugin().getDatabaseController().close(conn, ps, rs); - } - return realPass; - } - - private List getXAuthPlayers() { - List xP = new ArrayList<>(); - Connection conn = xAuth.getPlugin().getDatabaseController().getConnection(); - PreparedStatement ps = null; - ResultSet rs = null; - try { - String sql = String.format("SELECT * FROM `%s`", - xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT)); - ps = conn.prepareStatement(sql); - rs = ps.executeQuery(); - while (rs.next()) { - xP.add(rs.getInt("id")); - } - } catch (SQLException e) { - xAuthLog.severe("Cannot import xAuthPlayers", e); - return new ArrayList<>(); - } finally { - xAuth.getPlugin().getDatabaseController().close(conn, ps, rs); - } - return xP; - } - - private String getPassword(int accountId) { - String realPass = ""; - Connection conn = xAuth.getPlugin().getDatabaseController().getConnection(); - PreparedStatement ps = null; - ResultSet rs = null; - try { - String sql = String.format("SELECT `password`, `pwtype` FROM `%s` WHERE `id` = ?", - xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT)); - ps = conn.prepareStatement(sql); - ps.setInt(1, accountId); - rs = ps.executeQuery(); - if (!rs.next()) { - return null; - } - realPass = rs.getString("password"); - } catch (SQLException e) { - xAuthLog.severe("Failed to retrieve password hash for account: " + accountId, e); - return null; - } finally { - xAuth.getPlugin().getDatabaseController().close(conn, ps, rs); - } - return realPass; - } - -} diff --git a/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java b/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java index dd2e21c3d..7808507ce 100644 --- a/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java +++ b/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreLoginEvent.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * This event is called when a player uses the login command, @@ -63,6 +64,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreRegisterEvent.java b/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreRegisterEvent.java index af26ad518..4014c4bba 100644 --- a/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreRegisterEvent.java +++ b/src/main/java/fr/xephi/authme/events/AuthMeAsyncPreRegisterEvent.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * This event is called when a player uses the register command, @@ -63,6 +64,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/AuthMeTeleportEvent.java b/src/main/java/fr/xephi/authme/events/AuthMeTeleportEvent.java index ed8a08d35..6a226044b 100644 --- a/src/main/java/fr/xephi/authme/events/AuthMeTeleportEvent.java +++ b/src/main/java/fr/xephi/authme/events/AuthMeTeleportEvent.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * This event is fired before AuthMe teleports a player for general purposes. @@ -32,6 +33,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/EmailChangedEvent.java b/src/main/java/fr/xephi/authme/events/EmailChangedEvent.java index e489c2028..252d6ccad 100644 --- a/src/main/java/fr/xephi/authme/events/EmailChangedEvent.java +++ b/src/main/java/fr/xephi/authme/events/EmailChangedEvent.java @@ -4,6 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * This event is called when a player adds or changes his email address. @@ -70,6 +71,7 @@ public void setCancelled(boolean cancelled) { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/FailedLoginEvent.java b/src/main/java/fr/xephi/authme/events/FailedLoginEvent.java index c80ce65b8..23501213f 100644 --- a/src/main/java/fr/xephi/authme/events/FailedLoginEvent.java +++ b/src/main/java/fr/xephi/authme/events/FailedLoginEvent.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Event fired when a player enters a wrong password. @@ -40,6 +41,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java b/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java index e5e6868d8..f7fdccdb0 100644 --- a/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java +++ b/src/main/java/fr/xephi/authme/events/FirstSpawnTeleportEvent.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Event that is called if a player is teleported to the AuthMe first spawn, i.e. to the @@ -33,6 +34,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/LoginEvent.java b/src/main/java/fr/xephi/authme/events/LoginEvent.java index eb38d6266..35edce698 100644 --- a/src/main/java/fr/xephi/authme/events/LoginEvent.java +++ b/src/main/java/fr/xephi/authme/events/LoginEvent.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Event fired when a player has successfully logged in or registered. @@ -51,6 +52,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/LogoutEvent.java b/src/main/java/fr/xephi/authme/events/LogoutEvent.java index 70fae0967..0f71d987c 100644 --- a/src/main/java/fr/xephi/authme/events/LogoutEvent.java +++ b/src/main/java/fr/xephi/authme/events/LogoutEvent.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * This event is called when a player logs out through AuthMe, i.e. only when the player @@ -42,6 +43,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/PasswordEncryptionEvent.java b/src/main/java/fr/xephi/authme/events/PasswordEncryptionEvent.java index 2ad872262..be0b3f85a 100644 --- a/src/main/java/fr/xephi/authme/events/PasswordEncryptionEvent.java +++ b/src/main/java/fr/xephi/authme/events/PasswordEncryptionEvent.java @@ -2,6 +2,7 @@ import fr.xephi.authme.security.crypts.EncryptionMethod; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * This event is called when we need to compare or hash a password for a player and allows @@ -23,20 +24,6 @@ public PasswordEncryptionEvent(EncryptionMethod method) { this.method = method; } - /** - * Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link org.bukkit.event.Event}. - * - * @return The list of handlers - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - /** * Return the encryption method used to hash the password. * @@ -54,4 +41,20 @@ public EncryptionMethod getMethod() { public void setMethod(EncryptionMethod method) { this.method = method; } + + /** + * Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link org.bukkit.event.Event}. + * + * @return The list of handlers + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + @NotNull + public HandlerList getHandlers() { + return handlers; + } + } diff --git a/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java b/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java index f2fba487d..6797bb0a8 100644 --- a/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java +++ b/src/main/java/fr/xephi/authme/events/ProtectInventoryEvent.java @@ -5,6 +5,7 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; /** * This event is called before the inventory data of a player is suppressed, @@ -78,6 +79,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/RegisterEvent.java b/src/main/java/fr/xephi/authme/events/RegisterEvent.java index 2a98d0544..ac189df80 100644 --- a/src/main/java/fr/xephi/authme/events/RegisterEvent.java +++ b/src/main/java/fr/xephi/authme/events/RegisterEvent.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Event fired when a player has successfully registered. @@ -40,6 +41,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java b/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java index eb9bf71d8..b0ce76e0d 100644 --- a/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java +++ b/src/main/java/fr/xephi/authme/events/RestoreInventoryEvent.java @@ -4,6 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * This event is fired when the inventory of a player is restored @@ -53,6 +54,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/RestoreSessionEvent.java b/src/main/java/fr/xephi/authme/events/RestoreSessionEvent.java index abfffaa9c..79aaaf9d6 100644 --- a/src/main/java/fr/xephi/authme/events/RestoreSessionEvent.java +++ b/src/main/java/fr/xephi/authme/events/RestoreSessionEvent.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Event fired before a session is restored. @@ -45,7 +46,9 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } + } diff --git a/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java b/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java index a1a85d846..5045bfb78 100644 --- a/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java +++ b/src/main/java/fr/xephi/authme/events/SpawnTeleportEvent.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Called if a player is teleported to a specific spawn upon joining or logging in. @@ -44,6 +45,7 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/fr/xephi/authme/events/UnregisterByAdminEvent.java b/src/main/java/fr/xephi/authme/events/UnregisterByAdminEvent.java index f12e51160..cf5e5eecc 100644 --- a/src/main/java/fr/xephi/authme/events/UnregisterByAdminEvent.java +++ b/src/main/java/fr/xephi/authme/events/UnregisterByAdminEvent.java @@ -3,6 +3,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Event fired after a player has been unregistered from an external source (by an admin or via the API). @@ -61,7 +62,9 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } + } diff --git a/src/main/java/fr/xephi/authme/events/UnregisterByPlayerEvent.java b/src/main/java/fr/xephi/authme/events/UnregisterByPlayerEvent.java index cd96cd91d..cb48ed66e 100644 --- a/src/main/java/fr/xephi/authme/events/UnregisterByPlayerEvent.java +++ b/src/main/java/fr/xephi/authme/events/UnregisterByPlayerEvent.java @@ -2,6 +2,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; /** * Event fired after a player has unregistered himself. @@ -30,7 +31,9 @@ public static HandlerList getHandlerList() { } @Override + @NotNull public HandlerList getHandlers() { return handlers; } + } diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index 33d875edd..dade7498b 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -100,6 +100,7 @@ public void onAsyncPlayerPreLoginEventLowest(AsyncPlayerPreLoginEvent event) { final String name = event.getName(); // NOTE: getAddress() sometimes returning null, we don't want to handle this race condition + //noinspection ConstantConditions if (event.getAddress() == null) { event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, messages.retrieveSingle(name, MessageKey.KICK_UNRESOLVED_HOSTNAME)); diff --git a/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java b/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java index a4f9767f8..82dcf75bc 100644 --- a/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java +++ b/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java @@ -7,7 +7,6 @@ import ch.jalu.configme.resource.PropertyReader; import ch.jalu.configme.resource.PropertyResource; import com.google.common.collect.ImmutableMap; -import com.google.common.io.Files; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.message.MessageKey; @@ -15,6 +14,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -30,7 +31,7 @@ */ public class MessageUpdater { - private ConsoleLogger logger = ConsoleLoggerFactory.get(MessageUpdater.class); + private final ConsoleLogger logger = ConsoleLoggerFactory.get(MessageUpdater.class); /** * Applies any necessary migrations to the user's messages file and saves it if it has been modified. @@ -120,7 +121,7 @@ private static void backupMessagesFile(File messagesFile) { String backupName = FileUtils.createBackupFilePath(messagesFile); File backupFile = new File(backupName); try { - Files.copy(messagesFile, backupFile); + Files.copy(messagesFile.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { throw new IllegalStateException("Could not back up '" + messagesFile + "' to '" + backupFile + "'", e); } @@ -166,7 +167,7 @@ public static MessageKeyConfigurationData createConfigurationData() { // Create ConfigurationData instance Map> commentsMap = comments.entrySet().stream() - .collect(Collectors.toMap(e -> e.getKey(), e -> singletonList(e.getValue()))); + .collect(Collectors.toMap(Map.Entry::getKey, e -> singletonList(e.getValue()))); return new MessageKeyConfigurationData(builder, commentsMap); } @@ -184,13 +185,13 @@ protected String getFromReader(PropertyReader reader) { static final class MessageKeyPropertyListBuilder { - private PropertyListBuilder propertyListBuilder = new PropertyListBuilder(); + private final PropertyListBuilder propertyListBuilder = new PropertyListBuilder(); void addMessageKey(MessageKey key) { propertyListBuilder.add(new MessageKeyProperty(key)); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) List getAllProperties() { return (List) propertyListBuilder.create(); } diff --git a/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java index dad2fba50..31bac025f 100644 --- a/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java +++ b/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java @@ -42,12 +42,7 @@ Permission getVaultPermission(Server server) throws PermissionHandlerException { throw new PermissionHandlerException("Could not load permissions provider service"); } - // Get the Vault provider and make sure it's valid - Permission vaultPerms = permissionProvider.getProvider(); - if (vaultPerms == null) { - throw new PermissionHandlerException("Could not load Vault permissions provider"); - } - return vaultPerms; + return permissionProvider.getProvider(); } @Override diff --git a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java index 3db023118..deb3691ff 100644 --- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java +++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java @@ -130,9 +130,8 @@ public void processJoin(final Player player) { return; } } else if (!service.getProperty(RegistrationSettings.FORCE)) { - bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> { - welcomeMessageConfiguration.sendWelcomeMessage(player); - }); + bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> + welcomeMessageConfiguration.sendWelcomeMessage(player)); // Skip if registration is optional return; @@ -169,6 +168,7 @@ private void processJoinSync(Player player, boolean isAuthAvailable) { } if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) { // Allow infinite blindness effect + //noinspection ConstantConditions Inspection error! int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout; player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2)); } diff --git a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java index 7a684a3da..8f75e0b75 100644 --- a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java +++ b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java @@ -30,7 +30,6 @@ public enum HashAlgorithm { WBB3(fr.xephi.authme.security.crypts.Wbb3.class), WBB4(fr.xephi.authme.security.crypts.Wbb4.class), WORDPRESS(fr.xephi.authme.security.crypts.Wordpress.class), - XAUTH(fr.xephi.authme.security.crypts.XAuth.class), XFBCRYPT(fr.xephi.authme.security.crypts.XfBCrypt.class), CUSTOM(null), @@ -38,8 +37,7 @@ public enum HashAlgorithm { @Deprecated MD5(fr.xephi.authme.security.crypts.Md5.class), @Deprecated PLAINTEXT(null), @Deprecated SHA1(fr.xephi.authme.security.crypts.Sha1.class), - @Deprecated SHA512(fr.xephi.authme.security.crypts.Sha512.class), - @Deprecated WHIRLPOOL(fr.xephi.authme.security.crypts.Whirlpool.class); + @Deprecated SHA512(fr.xephi.authme.security.crypts.Sha512.class); private final Class clazz; diff --git a/src/main/java/fr/xephi/authme/security/HashUtils.java b/src/main/java/fr/xephi/authme/security/HashUtils.java index e80880784..33ba11363 100644 --- a/src/main/java/fr/xephi/authme/security/HashUtils.java +++ b/src/main/java/fr/xephi/authme/security/HashUtils.java @@ -76,7 +76,7 @@ public static MessageDigest getDigest(MessageDigestAlgorithm algorithm) { * @return True if the salt is valid, false otherwise */ public static boolean isValidBcryptHash(String hash) { - return hash.length() == 60 && hash.substring(0, 2).equals("$2"); + return hash.length() == 60 && hash.startsWith("$2"); } /** diff --git a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java index d6cb6e71c..1fc5d1753 100644 --- a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java +++ b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java @@ -148,6 +148,7 @@ private EncryptionMethod initializeEncryptionMethodWithEvent(HashAlgorithm algor * * @return The associated encryption method, or null if CUSTOM / deprecated */ + @SuppressWarnings("deprecation") private EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm) { if (HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)) { return null; diff --git a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java index c79647ab7..7c007d044 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java @@ -41,8 +41,11 @@ public boolean comparePassword(String password, HashedPassword hashedPassword, S if (line.length != 4) { return false; } - Integer iterations = Ints.tryParse(line[1]); - if (iterations == null) { + + int iterations; + try { + iterations = Integer.parseInt(line[1]); + } catch (NumberFormatException e) { logger.warning("Cannot read number of rounds for Pbkdf2: '" + line[1] + "'"); return false; } diff --git a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java index a0877cd4b..50e3ec8fc 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java @@ -30,8 +30,11 @@ public boolean comparePassword(String password, HashedPassword hashedPassword, S if (line.length != 4) { return false; } - Integer iterations = Ints.tryParse(line[1]); - if (iterations == null) { + + int iterations; + try { + iterations = Integer.parseInt(line[1]); + } catch (NumberFormatException e) { logger.warning("Cannot read number of rounds for Pbkdf2Django: '" + line[1] + "'"); return false; } diff --git a/src/main/java/fr/xephi/authme/security/crypts/PhpBB.java b/src/main/java/fr/xephi/authme/security/crypts/PhpBB.java index c4e27e9d7..c3bc50abb 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/PhpBB.java +++ b/src/main/java/fr/xephi/authme/security/crypts/PhpBB.java @@ -8,6 +8,7 @@ import fr.xephi.authme.security.crypts.description.Usage; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import static fr.xephi.authme.security.HashUtils.isEqual; @@ -72,14 +73,10 @@ private static final class PhpassSaltedMd5 { private static final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; private static String md5(String data) { - try { - byte[] bytes = data.getBytes("ISO-8859-1"); - MessageDigest md5er = HashUtils.getDigest(MessageDigestAlgorithm.MD5); - byte[] hash = md5er.digest(bytes); - return bytes2hex(hash); - } catch (UnsupportedEncodingException e) { - throw new UnsupportedOperationException(e); - } + byte[] bytes = data.getBytes(StandardCharsets.ISO_8859_1); + MessageDigest md5er = HashUtils.getDigest(MessageDigestAlgorithm.MD5); + byte[] hash = md5er.digest(bytes); + return bytes2hex(hash); } private static int hexToInt(char ch) { @@ -136,15 +133,13 @@ private static String _hash_encode64(String input, int count) { private static String _hash_crypt_private(String password, String setting) { String output = "*"; - if (!setting.substring(0, 3).equals("$H$")) + if (!setting.startsWith("$H$")) return output; int count_log2 = itoa64.indexOf(setting.charAt(3)); if (count_log2 < 7 || count_log2 > 30) return output; int count = 1 << count_log2; String salt = setting.substring(4, 12); - if (salt.length() != 8) - return output; String m1 = md5(salt + password); String hash = pack(m1); do { diff --git a/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java b/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java index b97441171..4859e49c3 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java +++ b/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java @@ -9,6 +9,7 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -21,10 +22,10 @@ public String computeHash(String password, String salt, String name) { String algo = "HmacSHA256"; String keyString = HashUtils.sha1(salt); try { - SecretKeySpec key = new SecretKeySpec(keyString.getBytes("UTF-8"), algo); + SecretKeySpec key = new SecretKeySpec(keyString.getBytes(StandardCharsets.UTF_8), algo); Mac mac = Mac.getInstance(algo); mac.init(key); - byte[] bytes = mac.doFinal(password.getBytes("ASCII")); + byte[] bytes = mac.doFinal(password.getBytes(StandardCharsets.US_ASCII)); StringBuilder hash = new StringBuilder(); for (byte aByte : bytes) { String hex = Integer.toHexString(0xFF & aByte); @@ -34,7 +35,7 @@ public String computeHash(String password, String salt, String name) { hash.append(hex); } return hash.toString(); - } catch (UnsupportedEncodingException | InvalidKeyException | NoSuchAlgorithmException e) { + } catch (InvalidKeyException | NoSuchAlgorithmException e) { throw new UnsupportedOperationException("Cannot create PHPFUSION hash for " + name, e); } } diff --git a/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java b/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java index 67b22c780..60cfa493c 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java +++ b/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java @@ -1,9 +1,6 @@ package fr.xephi.authme.security.crypts; -import com.google.common.escape.Escaper; import com.google.common.io.BaseEncoding; -import com.google.common.net.UrlEscapers; -import com.google.common.primitives.Ints; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.security.crypts.description.HasSalt; @@ -13,6 +10,9 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -50,8 +50,15 @@ public static String getQrBarcodeUrl(String user, String host, String secret) { String format = "https://www.google.com/chart?chs=130x130&chld=M%%7C0&cht=qr&chl=" + "otpauth://totp/" + "%s@%s%%3Fsecret%%3D%s"; - Escaper urlEscaper = UrlEscapers.urlFragmentEscaper(); - return String.format(format, urlEscaper.escape(user), urlEscaper.escape(host), secret); + + try { + user = URLEncoder.encode(user, StandardCharsets.UTF_8.toString()); + host = URLEncoder.encode(host, StandardCharsets.UTF_8.toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + return String.format(format, user, host, secret); } @Override @@ -81,8 +88,10 @@ public boolean comparePassword(String password, HashedPassword hashedPassword, S private boolean checkPassword(String secretKey, String userInput) throws NoSuchAlgorithmException, InvalidKeyException { - Integer code = Ints.tryParse(userInput); - if (code == null) { + int code; + try { + code = Integer.parseInt(userInput); + } catch (NumberFormatException e) { //code is not an integer return false; } diff --git a/src/main/java/fr/xephi/authme/security/crypts/Whirlpool.java b/src/main/java/fr/xephi/authme/security/crypts/Whirlpool.java deleted file mode 100644 index 7c62b2619..000000000 --- a/src/main/java/fr/xephi/authme/security/crypts/Whirlpool.java +++ /dev/null @@ -1,399 +0,0 @@ -package fr.xephi.authme.security.crypts; - -/** - * The Whirlpool hashing function. - *

- *

- * References - *

- *

- * The Whirlpool algorithm was developed by Paulo S. L. M. Barreto and Vincent Rijmen. - *

- * See P.S.L.M. Barreto, V. Rijmen, ``The Whirlpool hashing function,'' First - * NESSIE workshop, 2000 (tweaked version, 2003), - * - * - * @author Paulo S.L.M. Barreto - * @author Vincent Rijmen. - * @version 3.0 (2003.03.12) - *

- * ==================================================================== - * ========= - *

- * Differences from version 2.1: - *

- * - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, - * 9). - *

- * ==================================================================== - * ========= - *

- * Differences from version 2.0: - *

- * - Generation of ISO/IEC 10118-3 test vectors. - Bug fix: nonzero - * carry was ignored when tallying the data length (this bug apparently - * only manifested itself when feeding data in pieces rather than in a - * single chunk at once). - *

- * Differences from version 1.0: - *

- * - Original S-box replaced by the tweaked, hardware-efficient - * version. - *

- * ==================================================================== - * ========= - *

- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import fr.xephi.authme.security.crypts.description.Recommendation; -import fr.xephi.authme.security.crypts.description.Usage; - -import java.util.Arrays; - -@Deprecated -@Recommendation(Usage.DEPRECATED) -public class Whirlpool extends UnsaltedMethod { - - /** - * The message digest size (in bits) - */ - public static final int DIGESTBITS = 512; - - /** - * The message digest size (in bytes) - */ - public static final int DIGESTBYTES = DIGESTBITS >>> 3; - - /** - * The number of rounds of the internal dedicated block cipher. - */ - protected static final int R = 10; - - /** - * The substitution box. - */ - private static final String sbox = "\u1823\uc6E8\u87B8\u014F\u36A6\ud2F5\u796F\u9152" + "\u60Bc\u9B8E\uA30c\u7B35\u1dE0\ud7c2\u2E4B\uFE57" + "\u1577\u37E5\u9FF0\u4AdA\u58c9\u290A\uB1A0\u6B85" + "\uBd5d\u10F4\ucB3E\u0567\uE427\u418B\uA77d\u95d8" + "\uFBEE\u7c66\udd17\u479E\ucA2d\uBF07\uAd5A\u8333" + "\u6302\uAA71\uc819\u49d9\uF2E3\u5B88\u9A26\u32B0" + "\uE90F\ud580\uBEcd\u3448\uFF7A\u905F\u2068\u1AAE" + "\uB454\u9322\u64F1\u7312\u4008\uc3Ec\udBA1\u8d3d" + "\u9700\ucF2B\u7682\ud61B\uB5AF\u6A50\u45F3\u30EF" + "\u3F55\uA2EA\u65BA\u2Fc0\udE1c\uFd4d\u9275\u068A" + "\uB2E6\u0E1F\u62d4\uA896\uF9c5\u2559\u8472\u394c" + "\u5E78\u388c\ud1A5\uE261\uB321\u9c1E\u43c7\uFc04" + "\u5199\u6d0d\uFAdF\u7E24\u3BAB\ucE11\u8F4E\uB7EB" + "\u3c81\u94F7\uB913\u2cd3\uE76E\uc403\u5644\u7FA9" + "\u2ABB\uc153\udc0B\u9d6c\u3174\uF646\uAc89\u14E1" + "\u163A\u6909\u70B6\ud0Ed\ucc42\u98A4\u285c\uF886"; - - private static final long[][] C = new long[8][256]; - private static final long[] rc = new long[R + 1]; - - static { - for (int x = 0; x < 256; x++) { - char c = sbox.charAt(x / 2); - long v1 = ((x & 1) == 0) ? c >>> 8 : c & 0xff; - long v2 = v1 << 1; - if (v2 >= 0x100L) { - v2 ^= 0x11dL; - } - long v4 = v2 << 1; - if (v4 >= 0x100L) { - v4 ^= 0x11dL; - } - long v5 = v4 ^ v1; - long v8 = v4 << 1; - if (v8 >= 0x100L) { - v8 ^= 0x11dL; - } - long v9 = v8 ^ v1; - /* - * build the circulant table C[0][x] = S[x].[1, 1, 4, 1, 8, 5, 2, - * 9]: - */ - C[0][x] = (v1 << 56) | (v1 << 48) | (v4 << 40) | (v1 << 32) | (v8 << 24) | (v5 << 16) | (v2 << 8) | (v9); - /* - * build the remaining circulant tables C[t][x] = C[0][x] rotr t - */ - for (int t = 1; t < 8; t++) { - C[t][x] = (C[t - 1][x] >>> 8) | ((C[t - 1][x] << 56)); - } - } - /* - * build the round constants: - */ - rc[0] = 0L; /* - * not used (assigment kept only to properly initialize all - * variables) - */ - for (int r = 1; r <= R; r++) { - int i = 8 * (r - 1); - rc[r] = (C[0][i] & 0xff00000000000000L) ^ (C[1][i + 1] & 0x00ff000000000000L) ^ (C[2][i + 2] & 0x0000ff0000000000L) ^ (C[3][i + 3] & 0x000000ff00000000L) ^ (C[4][i + 4] & 0x00000000ff000000L) ^ (C[5][i + 5] & 0x0000000000ff0000L) ^ (C[6][i + 6] & 0x000000000000ff00L) ^ (C[7][i + 7] & 0x00000000000000ffL); - } - } - - /** - * Global number of hashed bits (256-bit counter). - */ - protected final byte[] bitLength = new byte[32]; - - /** - * Buffer of data to hash. - */ - protected final byte[] buffer = new byte[64]; - - /** - * Current number of bits on the buffer. - */ - protected int bufferBits = 0; - - /** - * Current (possibly incomplete) byte slot on the buffer. - */ - protected int bufferPos = 0; - - /** - * The hashing state. - */ - protected final long[] hash = new long[8]; - protected final long[] K = new long[8]; - protected final long[] L = new long[8]; - protected final long[] block = new long[8]; - protected final long[] state = new long[8]; - - public Whirlpool() { - } - - protected static String display(byte[] array) { - char[] val = new char[2 * array.length]; - String hex = "0123456789ABCDEF"; - for (int i = 0; i < array.length; i++) { - int b = array[i] & 0xff; - val[2 * i] = hex.charAt(b >>> 4); - val[2 * i + 1] = hex.charAt(b & 15); - } - return String.valueOf(val); - } - - /** - * The core Whirlpool transform. - */ - protected void processBuffer() { - /* - * map the buffer to a block: - */ - for (int i = 0, j = 0; i < 8; i++, j += 8) { - block[i] = (((long) buffer[j]) << 56) ^ (((long) buffer[j + 1] & 0xffL) << 48) ^ (((long) buffer[j + 2] & 0xffL) << 40) ^ (((long) buffer[j + 3] & 0xffL) << 32) ^ (((long) buffer[j + 4] & 0xffL) << 24) ^ (((long) buffer[j + 5] & 0xffL) << 16) ^ (((long) buffer[j + 6] & 0xffL) << 8) ^ (((long) buffer[j + 7] & 0xffL)); - } - /* - * compute and apply K^0 to the cipher state: - */ - for (int i = 0; i < 8; i++) { - state[i] = block[i] ^ (K[i] = hash[i]); - } - /* - * iterate over all rounds: - */ - for (int r = 1; r <= R; r++) { - /* - * compute K^r from K^{r-1}: - */ - for (int i = 0; i < 8; i++) { - L[i] = 0L; - for (int t = 0, s = 56; t < 8; t++, s -= 8) { - L[i] ^= C[t][(int) (K[(i - t) & 7] >>> s) & 0xff]; - } - } - for (int i = 0; i < 8; i++) { - K[i] = L[i]; - } - K[0] ^= rc[r]; - /* - * apply the r-th round transformation: - */ - for (int i = 0; i < 8; i++) { - L[i] = K[i]; - for (int t = 0, s = 56; t < 8; t++, s -= 8) { - L[i] ^= C[t][(int) (state[(i - t) & 7] >>> s) & 0xff]; - } - } - for (int i = 0; i < 8; i++) { - state[i] = L[i]; - } - } - /* - * apply the Miyaguchi-Preneel compression function: - */ - for (int i = 0; i < 8; i++) { - hash[i] ^= state[i] ^ block[i]; - } - } - - /** - * Initialize the hashing state. - */ - public void NESSIEinit() { - Arrays.fill(bitLength, (byte) 0); - bufferBits = bufferPos = 0; - buffer[0] = 0; - Arrays.fill(hash, 0L); - } - - /** - * Delivers input data to the hashing algorithm. - * - * @param source plaintext data to hash. - * @param sourceBits how many bits of plaintext to process. - *

- * This method maintains the invariant: bufferBits < 512 - *

- */ - public void NESSIEadd(byte[] source, long sourceBits) { - /* - * sourcePos | +-------+-------+------- ||||||||||||||||||||| source - * +-------+-------+------- - * +-------+-------+-------+-------+-------+------- - * |||||||||||||||||||||| buffer - * +-------+-------+-------+-------+-------+------- | bufferPos - */ - int sourcePos = 0; // index of leftmost source byte containing data (1 - // to 8 bits). - int sourceGap = (8 - ((int) sourceBits & 7)) & 7; // space on - // source[sourcePos]. - int bufferRem = bufferBits & 7; // occupied bits on buffer[bufferPos]. - int b; - // tally the length of the added data: - long value = sourceBits; - for (int i = 31, carry = 0; i >= 0; i--) { - carry += (bitLength[i] & 0xff) + ((int) value & 0xff); - bitLength[i] = (byte) carry; - carry >>>= 8; - value >>>= 8; - } - // process data in chunks of 8 bits: - while (sourceBits > 8) { // at least source[sourcePos] and - // source[sourcePos+1] contain data. - // take a byte from the source: - b = ((source[sourcePos] << sourceGap) & 0xff) | ((source[sourcePos + 1] & 0xff) >>> (8 - sourceGap)); - if (b < 0 || b >= 256) { - throw new RuntimeException("LOGIC ERROR"); - } - // process this byte: - buffer[bufferPos++] |= b >>> bufferRem; - bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos; - if (bufferBits == 512) { - // process data block: - processBuffer(); - // reset buffer: - bufferBits = bufferPos = 0; - } - buffer[bufferPos] = (byte) ((b << (8 - bufferRem)) & 0xff); - bufferBits += bufferRem; - // proceed to remaining data: - sourceBits -= 8; - sourcePos++; - } - // now 0 <= sourceBits <= 8; - // furthermore, all data (if any is left) is in source[sourcePos]. - if (sourceBits > 0) { - b = (source[sourcePos] << sourceGap) & 0xff; // bits are - // left-justified on b. - // process the remaining bits: - buffer[bufferPos] |= b >>> bufferRem; - } else { - b = 0; - } - if (bufferRem + sourceBits < 8) { - // all remaining data fits on buffer[bufferPos], and there still - // remains some space. - bufferBits += sourceBits; - } else { - // buffer[bufferPos] is full: - bufferPos++; - bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos; - sourceBits -= 8 - bufferRem; - // now 0 <= sourceBits < 8; furthermore, all data is in - // source[sourcePos]. - if (bufferBits == 512) { - // process data block: - processBuffer(); - // reset buffer: - bufferBits = bufferPos = 0; - } - buffer[bufferPos] = (byte) ((b << (8 - bufferRem)) & 0xff); - bufferBits += (int) sourceBits; - } - } - - /** - *

- * Get the hash value from the hashing state. - *

- *

- * This method uses the invariant: bufferBits < 512 - *

- * @param digest byte[] - */ - public void NESSIEfinalize(byte[] digest) { - // append a '1'-bit: - buffer[bufferPos] |= 0x80 >>> (bufferBits & 7); - bufferPos++; // all remaining bits on the current byte are set to zero. - // pad with zero bits to complete 512N + 256 bits: - if (bufferPos > 32) { - while (bufferPos < 64) { - buffer[bufferPos++] = 0; - } - // process data block: - processBuffer(); - // reset buffer: - bufferPos = 0; - } - while (bufferPos < 32) { - buffer[bufferPos++] = 0; - } - // append bit length of hashed data: - System.arraycopy(bitLength, 0, buffer, 32, 32); - // process data block: - processBuffer(); - // return the completed message digest: - for (int i = 0, j = 0; i < 8; i++, j += 8) { - long h = hash[i]; - digest[j] = (byte) (h >>> 56); - digest[j + 1] = (byte) (h >>> 48); - digest[j + 2] = (byte) (h >>> 40); - digest[j + 3] = (byte) (h >>> 32); - digest[j + 4] = (byte) (h >>> 24); - digest[j + 5] = (byte) (h >>> 16); - digest[j + 6] = (byte) (h >>> 8); - digest[j + 7] = (byte) (h); - } - } - - /** - * Delivers string input data to the hashing algorithm. - * - * @param source plaintext data to hash (ASCII text string). - * This method maintains the invariant: bufferBits < 512 - */ - public void NESSIEadd(String source) { - if (source.length() > 0) { - byte[] data = new byte[source.length()]; - for (int i = 0; i < source.length(); i++) { - data[i] = (byte) source.charAt(i); - } - NESSIEadd(data, 8 * data.length); - } - } - - @Override - public String computeHash(String password) { - byte[] digest = new byte[DIGESTBYTES]; - NESSIEinit(); - NESSIEadd(password); - NESSIEfinalize(digest); - return display(digest); - } - -} diff --git a/src/main/java/fr/xephi/authme/security/crypts/Wordpress.java b/src/main/java/fr/xephi/authme/security/crypts/Wordpress.java index f70c09496..a9ac88a6e 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/Wordpress.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Wordpress.java @@ -8,6 +8,7 @@ import fr.xephi.authme.security.crypts.description.Usage; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Arrays; @@ -73,9 +74,6 @@ private String crypt(String password, String setting) { } int count = 1 << countLog2; String salt = setting.substring(4, 4 + 8); - if (salt.length() != 8) { - return output; - } MessageDigest md = HashUtils.getDigest(MessageDigestAlgorithm.MD5); byte[] pass = stringToUtf8(password); byte[] hash = md.digest(stringToUtf8(salt + password)); @@ -99,16 +97,12 @@ private String gensaltPrivate(byte[] input) { } private byte[] stringToUtf8(String string) { - try { - return string.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new UnsupportedOperationException("This system doesn't support UTF-8!", e); - } + return string.getBytes(StandardCharsets.UTF_8); } @Override public String computeHash(String password) { - byte random[] = new byte[6]; + byte[] random = new byte[6]; randomGen.nextBytes(random); return crypt(password, gensaltPrivate(stringToUtf8(new String(random)))); } diff --git a/src/main/java/fr/xephi/authme/security/crypts/XAuth.java b/src/main/java/fr/xephi/authme/security/crypts/XAuth.java deleted file mode 100644 index 62f2e0d71..000000000 --- a/src/main/java/fr/xephi/authme/security/crypts/XAuth.java +++ /dev/null @@ -1,43 +0,0 @@ -package fr.xephi.authme.security.crypts; - -import fr.xephi.authme.security.crypts.description.Recommendation; -import fr.xephi.authme.security.crypts.description.Usage; - -import static fr.xephi.authme.security.HashUtils.isEqual; - -@Recommendation(Usage.RECOMMENDED) -public class XAuth extends HexSaltedMethod { - - private static String getWhirlpool(String message) { - Whirlpool w = new Whirlpool(); - byte[] digest = new byte[Whirlpool.DIGESTBYTES]; - w.NESSIEinit(); - w.NESSIEadd(message); - w.NESSIEfinalize(digest); - return Whirlpool.display(digest); - } - - @Override - public String computeHash(String password, String salt, String name) { - String hash = getWhirlpool(salt + password).toLowerCase(); - int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length(); - return hash.substring(0, saltPos) + salt + hash.substring(saltPos); - } - - @Override - public boolean comparePassword(String password, HashedPassword hashedPassword, String name) { - String hash = hashedPassword.getHash(); - int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length(); - if (saltPos + 12 > hash.length()) { - return false; - } - String salt = hash.substring(saltPos, saltPos + 12); - return isEqual(hash, computeHash(password, salt, name)); - } - - @Override - public int getSaltLength() { - return 12; - } - -} diff --git a/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java b/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java index e26b136f4..434473171 100644 --- a/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java +++ b/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java @@ -55,7 +55,12 @@ public boolean checkCode(PlayerAuth auth, String totpCode) { */ public boolean checkCode(String playerName, String totpKey, String inputCode) { String nameLower = playerName.toLowerCase(); - Integer totpCode = Ints.tryParse(inputCode); + Integer totpCode; + try { + totpCode = Integer.parseInt(inputCode); + } catch (NumberFormatException e) { + totpCode = null; + } if (totpCode != null && !usedCodes.contains(nameLower, totpCode) && authenticator.authorize(totpKey, totpCode)) { usedCodes.put(nameLower, totpCode, System.currentTimeMillis()); diff --git a/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java b/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java index e1c8c5ba7..893e7e411 100644 --- a/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java +++ b/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java @@ -18,6 +18,7 @@ import javax.inject.Inject; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.util.LinkedHashMap; @@ -54,7 +55,7 @@ public File updateHelpFile() throws IOException { Map helpEntries = generateHelpMessageEntries(); String helpEntriesYaml = exportToYaml(helpEntries); - Files.write(helpFile.toPath(), helpEntriesYaml.getBytes(), StandardOpenOption.TRUNCATE_EXISTING); + Files.write(helpFile.toPath(), helpEntriesYaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING); return helpFile; } diff --git a/src/main/java/fr/xephi/authme/service/MigrationService.java b/src/main/java/fr/xephi/authme/service/MigrationService.java index de8d88a78..b46b5bbf9 100644 --- a/src/main/java/fr/xephi/authme/service/MigrationService.java +++ b/src/main/java/fr/xephi/authme/service/MigrationService.java @@ -29,6 +29,7 @@ private MigrationService() { * @param dataSource The data source * @param authmeSha256 Instance to the AuthMe Sha256 encryption method implementation */ + @SuppressWarnings("deprecation") public static void changePlainTextToSha256(Settings settings, DataSource dataSource, Sha256 authmeSha256) { if (HashAlgorithm.PLAINTEXT == settings.getProperty(SecuritySettings.PASSWORD_HASH)) { diff --git a/src/main/java/fr/xephi/authme/service/TeleportationService.java b/src/main/java/fr/xephi/authme/service/TeleportationService.java index f0eb7f851..39a1907ef 100644 --- a/src/main/java/fr/xephi/authme/service/TeleportationService.java +++ b/src/main/java/fr/xephi/authme/service/TeleportationService.java @@ -131,7 +131,7 @@ public void teleportOnLogin(final Player player, PlayerAuth auth, LimboPlayer li } // #856: If LimboPlayer comes from a persisted file, the Location might be null - String worldName = (limbo != null && limbo.getLocation() != null) + String worldName = (limbo != null && limbo.getLocation() != null && limbo.getLocation().getWorld() != null) ? limbo.getLocation().getWorld().getName() : null; diff --git a/src/main/java/fr/xephi/authme/service/ValidationService.java b/src/main/java/fr/xephi/authme/service/ValidationService.java index 183a3b4a6..1380f08f5 100644 --- a/src/main/java/fr/xephi/authme/service/ValidationService.java +++ b/src/main/java/fr/xephi/authme/service/ValidationService.java @@ -25,6 +25,7 @@ import javax.inject.Inject; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -155,7 +156,7 @@ public boolean fulfillsNameRestrictions(Player player) { } String ip = PlayerUtils.getPlayerIp(player); - String domain = player.getAddress().getHostName(); + String domain = Objects.requireNonNull(player.getAddress()).getHostName(); for (String restriction : restrictions) { if (restriction.startsWith("regex:")) { restriction = restriction.replace("regex:", ""); diff --git a/src/main/java/fr/xephi/authme/service/bungeecord/BungeeReceiver.java b/src/main/java/fr/xephi/authme/service/bungeecord/BungeeReceiver.java index ae1b79cd9..ccf49b644 100644 --- a/src/main/java/fr/xephi/authme/service/bungeecord/BungeeReceiver.java +++ b/src/main/java/fr/xephi/authme/service/bungeecord/BungeeReceiver.java @@ -14,6 +14,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.Messenger; import org.bukkit.plugin.messaging.PluginMessageListener; +import org.jetbrains.annotations.NotNull; import javax.inject.Inject; import java.util.Optional; @@ -40,7 +41,7 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent } @Override - public void reload(final Settings settings) { + public void reload(Settings settings) { this.isEnabled = settings.getProperty(HooksSettings.BUNGEECORD); if (this.isEnabled) { @@ -56,7 +57,7 @@ public void reload(final Settings settings) { * * @param in the input to handle */ - private void handleBroadcast(final ByteArrayDataInput in) { + private void handleBroadcast(ByteArrayDataInput in) { // Read data byte array final short dataLength = in.readShort(); final byte[] dataBytes = new byte[dataLength]; @@ -130,7 +131,7 @@ private void handle(ByteArrayDataInput in) { } @Override - public void onPluginMessageReceived(final String channel, final Player player, final byte[] data) { + public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte[] data) { if (!isEnabled) { return; } @@ -146,7 +147,7 @@ public void onPluginMessageReceived(final String channel, final Player player, f } } - private void performLogin(final String name) { + private void performLogin(String name) { Player player = bukkitService.getPlayerExact(name); if (player != null && player.isOnline()) { management.forceLogin(player); diff --git a/src/main/java/fr/xephi/authme/settings/Settings.java b/src/main/java/fr/xephi/authme/settings/Settings.java index ab33a7e8d..78d540734 100644 --- a/src/main/java/fr/xephi/authme/settings/Settings.java +++ b/src/main/java/fr/xephi/authme/settings/Settings.java @@ -4,13 +4,13 @@ import ch.jalu.configme.configurationdata.ConfigurationData; import ch.jalu.configme.migration.MigrationService; import ch.jalu.configme.resource.PropertyResource; -import com.google.common.io.Files; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.output.ConsoleLoggerFactory; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import static fr.xephi.authme.util.FileUtils.copyFileFromResource; @@ -89,7 +89,7 @@ private String readFile(String filename) { final File file = new File(pluginFolder, filename); if (copyFileFromResource(file, filename)) { try { - return Files.asCharSource(file, StandardCharsets.UTF_8).read(); + return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); } catch (IOException e) { logger.logException("Failed to read file '" + filename + "':", e); } @@ -98,4 +98,5 @@ private String readFile(String filename) { } return ""; } + } diff --git a/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java index 23168d530..46a45552e 100644 --- a/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java +++ b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java @@ -309,6 +309,7 @@ private static boolean mergeAndMovePermissionGroupSettings(PropertyReader reader * @param configData Configuration data * @return True if the configuration has changed, false otherwise */ + @SuppressWarnings("deprecation") private static boolean moveDeprecatedHashAlgorithmIntoLegacySection(PropertyReader reader, ConfigurationData configData) { HashAlgorithm currentHash = SecuritySettings.PASSWORD_HASH.determineValue(reader); diff --git a/src/main/java/fr/xephi/authme/settings/SpawnLoader.java b/src/main/java/fr/xephi/authme/settings/SpawnLoader.java index 7b3fc1385..ff39efa31 100644 --- a/src/main/java/fr/xephi/authme/settings/SpawnLoader.java +++ b/src/main/java/fr/xephi/authme/settings/SpawnLoader.java @@ -19,6 +19,7 @@ import javax.inject.Inject; import java.io.File; import java.io.IOException; +import java.util.Objects; /** * Manager for spawn points. It loads spawn definitions from AuthMe and third-party plugins @@ -170,8 +171,10 @@ public void unloadCmiSpawn() { * @see RestrictionSettings#SPAWN_PRIORITY */ public Location getSpawnLocation(Player player) { - if (player == null || player.getWorld() == null) { + if (player == null) { return null; + } else { + player.getWorld(); } World world = player.getWorld(); @@ -179,19 +182,18 @@ public Location getSpawnLocation(Player player) { for (String priority : spawnPriority) { switch (priority.toLowerCase().trim()) { case "default": - if (world.getSpawnLocation() != null) { - if (!isValidSpawnPoint(world.getSpawnLocation())) { - for (World spawnWorld : Bukkit.getWorlds()) { - if (isValidSpawnPoint(spawnWorld.getSpawnLocation())) { - world = spawnWorld; - break; - } + world.getSpawnLocation(); + if (!isValidSpawnPoint(world.getSpawnLocation())) { + for (World spawnWorld : Bukkit.getWorlds()) { + if (isValidSpawnPoint(spawnWorld.getSpawnLocation())) { + world = spawnWorld; + break; } - logger.warning("Seems like AuthMe is unable to find a proper spawn location. " - + "Set a location with the command '/authme setspawn'"); } - spawnLoc = world.getSpawnLocation(); + logger.warning("Seems like AuthMe is unable to find a proper spawn location. " + + "Set a location with the command '/authme setspawn'"); } + spawnLoc = world.getSpawnLocation(); break; case "multiverse": if (settings.getProperty(HooksSettings.MULTIVERSE)) { @@ -228,10 +230,7 @@ public Location getSpawnLocation(Player player) { * @return True upon success, false otherwise */ private boolean isValidSpawnPoint(Location location) { - if (location.getX() == 0 && location.getY() == 0 && location.getZ() == 0) { - return false; - } - return true; + return location.getX() != 0 || location.getY() != 0 || location.getZ() != 0; } /** @@ -290,7 +289,7 @@ public Location getPlayerLocationOrSpawn(Player player) { private static Location getLocationFromConfiguration(FileConfiguration configuration, String pathPrefix) { if (containsAllSpawnFields(configuration, pathPrefix)) { String prefix = pathPrefix + "."; - String worldName = configuration.getString(prefix + "world"); + String worldName = Objects.requireNonNull(configuration.getString(prefix + "world")); World world = Bukkit.getWorld(worldName); if (!StringUtils.isEmpty(worldName) && world != null) { return new Location(world, configuration.getDouble(prefix + "x"), @@ -312,7 +311,7 @@ private static Location getLocationFromCmiConfiguration(FileConfiguration config final String pathPrefix = "Spawn.Main"; if (isLocationCompleteInCmiConfig(configuration, pathPrefix)) { String prefix = pathPrefix + "."; - String worldName = configuration.getString(prefix + "World"); + String worldName = Objects.requireNonNull(configuration.getString(prefix + "World")); World world = Bukkit.getWorld(worldName); if (!StringUtils.isEmpty(worldName) && world != null) { return new Location(world, configuration.getDouble(prefix + "X"), diff --git a/src/main/java/fr/xephi/authme/settings/commandconfig/OnLoginCommand.java b/src/main/java/fr/xephi/authme/settings/commandconfig/OnLoginCommand.java index 13cc30fca..77aa50ffa 100644 --- a/src/main/java/fr/xephi/authme/settings/commandconfig/OnLoginCommand.java +++ b/src/main/java/fr/xephi/authme/settings/commandconfig/OnLoginCommand.java @@ -17,7 +17,7 @@ public OnLoginCommand() { } /** - * Creates a copy of this object, using the given command as new {@link Command#command command}. + * Creates a copy of this object, using the given command. * * @param command the command text to use in the copy * @return copy of the source with the new command diff --git a/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java index 0cffd2804..b69f06253 100644 --- a/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java +++ b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java @@ -53,7 +53,7 @@ public final class SecuritySettings implements SettingsHolder { @Comment({ "Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512,", - "MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,", + "MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, JOOMLA, WBB3, WBB4, MD5VB,", "PBKDF2DJANGO, WORDPRESS, ROYALAUTH, ARGON2, CUSTOM (for developers only). See full list at", "https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md", "If you use ARGON2, check that you have the argon2 c library on your system" diff --git a/src/main/java/fr/xephi/authme/util/AtomicIntervalCounter.java b/src/main/java/fr/xephi/authme/util/AtomicIntervalCounter.java index 2a50e660a..b0ff14fa7 100644 --- a/src/main/java/fr/xephi/authme/util/AtomicIntervalCounter.java +++ b/src/main/java/fr/xephi/authme/util/AtomicIntervalCounter.java @@ -5,6 +5,7 @@ * in the given 'interval'. */ public class AtomicIntervalCounter { + private final int threshold; private final int interval; private int count; @@ -50,4 +51,5 @@ public synchronized boolean handle() { lastInsert = now; return false; } + } diff --git a/src/main/java/fr/xephi/authme/util/ExceptionUtils.java b/src/main/java/fr/xephi/authme/util/ExceptionUtils.java index fd5ae8852..daca03780 100644 --- a/src/main/java/fr/xephi/authme/util/ExceptionUtils.java +++ b/src/main/java/fr/xephi/authme/util/ExceptionUtils.java @@ -1,7 +1,11 @@ package fr.xephi.authme.util; -import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Collections; +import java.util.IdentityHashMap; import java.util.Set; /** @@ -21,8 +25,9 @@ private ExceptionUtils() { * @param the desired throwable subtype * @return the first throwable found of the given type, or null if none found */ - public static T findThrowableInCause(Class wantedThrowableType, Throwable throwable) { - Set visitedObjects = Sets.newIdentityHashSet(); + public static T findThrowableInCause(@NotNull Class wantedThrowableType, + @NotNull Throwable throwable) { + Set visitedObjects = Collections.newSetFromMap(new IdentityHashMap<>()); Throwable currentThrowable = throwable; while (currentThrowable != null && !visitedObjects.contains(currentThrowable)) { if (wantedThrowableType.isInstance(currentThrowable)) { @@ -40,7 +45,22 @@ public static T findThrowableInCause(Class wantedThrowa * @param th the throwable to process * @return string with the type of the Throwable and its message, e.g. "[IOException]: Could not open stream" */ - public static String formatException(Throwable th) { + @NotNull + public static String formatException(@NotNull Throwable th) { return "[" + th.getClass().getSimpleName() + "]: " + th.getMessage(); } + + /** + * Returns a string containing the result of {@link Throwable#toString()}, followed by the full, recursive + * stack trace of {@code throwable}. + * + * @param throwable the throwable to precess + * @return string containing the stacktrace + */ + public static String getStackTraceAsString(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString(); + } + } diff --git a/src/main/java/fr/xephi/authme/util/FileUtils.java b/src/main/java/fr/xephi/authme/util/FileUtils.java index 7f7ee4aaa..0fae165c5 100644 --- a/src/main/java/fr/xephi/authme/util/FileUtils.java +++ b/src/main/java/fr/xephi/authme/util/FileUtils.java @@ -1,13 +1,14 @@ package fr.xephi.authme.util; -import com.google.common.io.Files; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.output.ConsoleLoggerFactory; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -21,7 +22,7 @@ public final class FileUtils { private static final DateTimeFormatter CURRENT_DATE_STRING_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd_HHmm"); - private static ConsoleLogger logger = ConsoleLoggerFactory.get(FileUtils.class); + private static final ConsoleLogger logger = ConsoleLoggerFactory.get(FileUtils.class); // Utility class private FileUtils() { @@ -35,7 +36,7 @@ private FileUtils() { * * @return False if the file does not exist and could not be copied, true otherwise */ - public static boolean copyFileFromResource(File destinationFile, String resourcePath) { + public static boolean copyFileFromResource(@NotNull File destinationFile, @NotNull String resourcePath) { if (destinationFile.exists()) { return true; } else if (!createDirectory(destinationFile.getParentFile())) { @@ -48,7 +49,7 @@ public static boolean copyFileFromResource(File destinationFile, String resource logger.warning(format("Cannot copy resource '%s' to file '%s': cannot load resource", resourcePath, destinationFile.getPath())); } else { - java.nio.file.Files.copy(is, destinationFile.toPath()); + Files.copy(is, destinationFile.toPath()); return true; } } catch (IOException e) { @@ -64,7 +65,7 @@ public static boolean copyFileFromResource(File destinationFile, String resource * @param dir the directory to create * @return true upon success, false otherwise */ - public static boolean createDirectory(File dir) { + public static boolean createDirectory(@NotNull File dir) { if (!dir.exists() && !dir.mkdirs()) { logger.warning("Could not create directory '" + dir + "'"); return false; @@ -72,6 +73,34 @@ public static boolean createDirectory(File dir) { return dir.isDirectory(); } + /** + * Creates the given directory, throws a runtime exception on fail. + * + * @param dir the directory to create + * @throws IllegalStateException when unable to create the directory + */ + public static void createDirectoryOrFail(@NotNull File dir) { + if (!dir.exists() && !dir.mkdirs() || !dir.isDirectory()) { + throw new IllegalStateException("Could not create directory '" + dir + "'"); + } + } + + /** + * Creates the given file, throws a runtime exception on fail. + * + * @param file the file to create + * @throws IllegalStateException when unable to create the file + */ + public static void createFileOrFail(@NotNull File file) { + try { + if (!file.exists() && !file.createNewFile() || !file.isFile()) { + throw new IllegalStateException("Could not create file '" + file + "'"); + } + } catch (IOException e) { + throw new IllegalStateException("Could not create file '" + file + "'", e); + } + } + /** * Returns a JAR file as stream. Returns null if it doesn't exist. * @@ -165,9 +194,10 @@ public static String createCurrentTimeString() { * @return path to a file suitably named for storing a backup */ public static String createBackupFilePath(File file) { - String filename = "backup_" + Files.getNameWithoutExtension(file.getName()) + String filename = "backup_" + com.google.common.io.Files.getNameWithoutExtension(file.getName()) + "_" + createCurrentTimeString() - + "." + Files.getFileExtension(file.getName()); + + "." + com.google.common.io.Files.getFileExtension(file.getName()); return makePath(file.getParent(), filename); } + } diff --git a/src/main/java/fr/xephi/authme/util/InternetProtocolUtils.java b/src/main/java/fr/xephi/authme/util/InternetProtocolUtils.java index 039421548..34203f3e8 100644 --- a/src/main/java/fr/xephi/authme/util/InternetProtocolUtils.java +++ b/src/main/java/fr/xephi/authme/util/InternetProtocolUtils.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util; +import org.jetbrains.annotations.NotNull; + import java.net.InetAddress; import java.net.UnknownHostException; @@ -18,7 +20,7 @@ private InternetProtocolUtils() { * @param address address to check * @return true if the address is a local (site and link) or loopback address, false otherwise */ - public static boolean isLocalAddress(String address) { + public static boolean isLocalAddress(@NotNull String address) { try { InetAddress inetAddress = InetAddress.getByName(address); @@ -48,7 +50,7 @@ public static boolean isLocalAddress(String address) { * @param address address to check * @return true if the address is a loopback one */ - public static boolean isLoopbackAddress(String address) { + public static boolean isLoopbackAddress(@NotNull String address) { try { InetAddress inetAddress = InetAddress.getByName(address); return inetAddress.isLoopbackAddress(); @@ -57,11 +59,7 @@ public static boolean isLoopbackAddress(String address) { } } - private static boolean isLoopbackAddress(InetAddress address) { - return address.isLoopbackAddress(); - } - - private static boolean isIPv6UniqueSiteLocal(InetAddress address) { + private static boolean isIPv6UniqueSiteLocal(@NotNull InetAddress address) { // ref: https://en.wikipedia.org/wiki/Unique_local_address // currently undefined but could be used in the near future fc00::/8 @@ -69,4 +67,5 @@ private static boolean isIPv6UniqueSiteLocal(InetAddress address) { // in use for unique site-local fd00::/8 || (address.getAddress()[0] & 0xFF) == 0xFD; } + } diff --git a/src/main/java/fr/xephi/authme/util/PlayerUtils.java b/src/main/java/fr/xephi/authme/util/PlayerUtils.java index 04216933c..ffed6469d 100644 --- a/src/main/java/fr/xephi/authme/util/PlayerUtils.java +++ b/src/main/java/fr/xephi/authme/util/PlayerUtils.java @@ -1,6 +1,9 @@ package fr.xephi.authme.util; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; /** * Player utilities. @@ -15,9 +18,12 @@ private PlayerUtils() { * Returns the IP of the given player. * * @param player The player to return the IP address for + * * @return The player's IP address */ - public static String getPlayerIp(Player player) { + @NotNull + public static String getPlayerIp(@NotNull Player player) { + Objects.requireNonNull(player.getAddress(), "address"); return player.getAddress().getAddress().getHostAddress(); } @@ -25,9 +31,10 @@ public static String getPlayerIp(Player player) { * Returns if the player is an NPC or not. * * @param player The player to check + * * @return True if the player is an NPC, false otherwise */ - public static boolean isNpc(Player player) { + public static boolean isNpc(@NotNull Player player) { return player.hasMetadata("NPC"); } diff --git a/src/main/java/fr/xephi/authme/util/StringUtils.java b/src/main/java/fr/xephi/authme/util/StringUtils.java index 5c8613005..49ae5c85c 100644 --- a/src/main/java/fr/xephi/authme/util/StringUtils.java +++ b/src/main/java/fr/xephi/authme/util/StringUtils.java @@ -3,6 +3,7 @@ import net.ricecode.similarity.LevenshteinDistanceStrategy; import net.ricecode.similarity.StringSimilarityService; import net.ricecode.similarity.StringSimilarityServiceImpl; +import org.jetbrains.annotations.NotNull; /** * Utility class for String operations. @@ -42,7 +43,7 @@ public static double getDifference(String first, String second) { * * @return True if the string contains at least one of the items */ - public static boolean containsAny(String str, Iterable pieces) { + public static boolean containsAny(String str, @NotNull Iterable pieces) { if (str == null) { return false; } @@ -77,8 +78,9 @@ public static boolean isEmpty(String str) { */ // Note ljacqu 20170314: `needle` is restricted to char type intentionally because something like // isInsideString("11", "2211") would unexpectedly return true... - public static boolean isInsideString(char needle, String haystack) { + public static boolean isInsideString(char needle, @NotNull String haystack) { int index = haystack.indexOf(needle); return index > 0 && index < haystack.length() - 1; } + } diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java index 74c3088e3..3caadb5e8 100644 --- a/src/main/java/fr/xephi/authme/util/Utils.java +++ b/src/main/java/fr/xephi/authme/util/Utils.java @@ -5,6 +5,7 @@ import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; +import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.regex.Pattern; @@ -17,7 +18,7 @@ public final class Utils { /** Number of milliseconds in a minute. */ public static final long MILLIS_PER_MINUTE = 60_000L; - private static ConsoleLogger logger = ConsoleLoggerFactory.get(Utils.class); + private static final ConsoleLogger logger = ConsoleLoggerFactory.get(Utils.class); // Utility class private Utils() { @@ -30,7 +31,8 @@ private Utils() { * * @return the given regex compiled into Pattern object. */ - public static Pattern safePatternCompile(String pattern) { + @NotNull + public static Pattern safePatternCompile(@NotNull String pattern) { try { return Pattern.compile(pattern); } catch (Exception e) { @@ -46,7 +48,7 @@ public static Pattern safePatternCompile(String pattern) { * * @return true if the class is loaded, false otherwise */ - public static boolean isClassLoaded(String className) { + public static boolean isClassLoaded(@NotNull String className) { try { Class.forName(className); return true; @@ -63,7 +65,7 @@ public static boolean isClassLoaded(String className) { * @param sender the sender to inform * @param message the message to log and send */ - public static void logAndSendMessage(CommandSender sender, String message) { + public static void logAndSendMessage(CommandSender sender, @NotNull String message) { logger.info(message); // Make sure sender is not console user, which will see the message from ConsoleLogger already if (sender != null && !(sender instanceof ConsoleCommandSender)) { @@ -79,7 +81,7 @@ public static void logAndSendMessage(CommandSender sender, String message) { * @param sender the sender to inform * @param message the warning to log and send */ - public static void logAndSendWarning(CommandSender sender, String message) { + public static void logAndSendWarning(CommandSender sender, @NotNull String message) { logger.warning(message); // Make sure sender is not console user, which will see the message from ConsoleLogger already if (sender != null && !(sender instanceof ConsoleCommandSender)) { @@ -107,4 +109,5 @@ public static boolean isCollectionEmpty(Collection coll) { public static boolean isEmailEmpty(String email) { return StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email); } + } diff --git a/src/main/java/fr/xephi/authme/util/UuidUtils.java b/src/main/java/fr/xephi/authme/util/UuidUtils.java index be35a9351..ec91703b4 100644 --- a/src/main/java/fr/xephi/authme/util/UuidUtils.java +++ b/src/main/java/fr/xephi/authme/util/UuidUtils.java @@ -24,4 +24,5 @@ public static UUID parseUuidSafely(String string) { return null; } } + } diff --git a/src/main/java/fr/xephi/authme/util/expiring/Duration.java b/src/main/java/fr/xephi/authme/util/expiring/Duration.java index ecc86299e..e216d8cb6 100644 --- a/src/main/java/fr/xephi/authme/util/expiring/Duration.java +++ b/src/main/java/fr/xephi/authme/util/expiring/Duration.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.expiring; +import org.jetbrains.annotations.NotNull; + import java.util.concurrent.TimeUnit; /** @@ -8,6 +10,7 @@ public class Duration { private final long duration; + @NotNull private final TimeUnit unit; /** @@ -16,7 +19,7 @@ public class Duration { * @param duration the duration * @param unit the time unit in which {@code duration} is expressed */ - public Duration(long duration, TimeUnit unit) { + public Duration(long duration, @NotNull TimeUnit unit) { this.duration = duration; this.unit = unit; } @@ -38,7 +41,8 @@ public Duration(long duration, TimeUnit unit) { * @param sourceUnit the time unit the duration is expressed in * @return Duration object using the most suitable time unit */ - public static Duration createWithSuitableUnit(long sourceDuration, TimeUnit sourceUnit) { + @NotNull + public static Duration createWithSuitableUnit(long sourceDuration, @NotNull TimeUnit sourceUnit) { long durationMillis = Math.abs(TimeUnit.MILLISECONDS.convert(sourceDuration, sourceUnit)); TimeUnit targetUnit; @@ -66,7 +70,9 @@ public long getDuration() { /** * @return the time unit in which the duration is expressed */ + @NotNull public TimeUnit getTimeUnit() { return unit; } + } diff --git a/src/main/java/fr/xephi/authme/util/expiring/ExpiringMap.java b/src/main/java/fr/xephi/authme/util/expiring/ExpiringMap.java index 3bf19351b..a21075383 100644 --- a/src/main/java/fr/xephi/authme/util/expiring/ExpiringMap.java +++ b/src/main/java/fr/xephi/authme/util/expiring/ExpiringMap.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.expiring; +import org.jetbrains.annotations.NotNull; + import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -24,6 +26,7 @@ */ public class ExpiringMap { + @NotNull private final Map> entries = new ConcurrentHashMap<>(); private long expirationMillis; @@ -33,7 +36,7 @@ public class ExpiringMap { * @param duration the duration of time after which entries expire * @param unit the time unit in which {@code duration} is expressed */ - public ExpiringMap(long duration, TimeUnit unit) { + public ExpiringMap(long duration, @NotNull TimeUnit unit) { setExpiration(duration, unit); } @@ -44,7 +47,7 @@ public ExpiringMap(long duration, TimeUnit unit) { * @param key the key to look up * @return the associated value, or {@code null} if not available */ - public V get(K key) { + public V get(@NotNull K key) { ExpiringEntry value = entries.get(key); if (value == null) { return null; @@ -62,7 +65,7 @@ public V get(K key) { * @param key the key to insert a value for * @param value the value to insert */ - public void put(K key, V value) { + public void put(@NotNull K key, @NotNull V value) { long expiration = System.currentTimeMillis() + expirationMillis; entries.put(key, new ExpiringEntry<>(value, expiration)); } @@ -72,7 +75,7 @@ public void put(K key, V value) { * * @param key the key to remove the value for */ - public void remove(K key) { + public void remove(@NotNull K key) { entries.remove(key); } @@ -90,7 +93,7 @@ public void removeExpiredEntries() { * @param duration the duration of time after which entries expire * @param unit the time unit in which {@code duration} is expressed */ - public void setExpiration(long duration, TimeUnit unit) { + public void setExpiration(long duration, @NotNull TimeUnit unit) { this.expirationMillis = unit.toMillis(duration); } @@ -108,6 +111,7 @@ public boolean isEmpty() { /** * @return the internal map */ + @NotNull protected Map> getEntries() { return entries; } @@ -119,15 +123,16 @@ protected Map> getEntries() { */ protected static final class ExpiringEntry { + @NotNull private final V value; private final long expiration; - ExpiringEntry(V value, long expiration) { + ExpiringEntry(@NotNull V value, long expiration) { this.value = value; this.expiration = expiration; } - V getValue() { + @NotNull V getValue() { return value; } @@ -135,4 +140,5 @@ long getExpiration() { return expiration; } } + } diff --git a/src/main/java/fr/xephi/authme/util/expiring/ExpiringSet.java b/src/main/java/fr/xephi/authme/util/expiring/ExpiringSet.java index fea8fb313..e547fd5be 100644 --- a/src/main/java/fr/xephi/authme/util/expiring/ExpiringSet.java +++ b/src/main/java/fr/xephi/authme/util/expiring/ExpiringSet.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.expiring; +import org.jetbrains.annotations.NotNull; + import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -18,7 +20,8 @@ */ public class ExpiringSet { - private Map entries = new ConcurrentHashMap<>(); + @NotNull + private final Map entries = new ConcurrentHashMap<>(); private long expirationMillis; /** @@ -27,7 +30,7 @@ public class ExpiringSet { * @param duration the duration of time after which entries expire * @param unit the time unit in which {@code duration} is expressed */ - public ExpiringSet(long duration, TimeUnit unit) { + public ExpiringSet(long duration, @NotNull TimeUnit unit) { setExpiration(duration, unit); } @@ -36,7 +39,7 @@ public ExpiringSet(long duration, TimeUnit unit) { * * @param entry the entry to add */ - public void add(E entry) { + public void add(@NotNull E entry) { entries.put(entry, System.currentTimeMillis() + expirationMillis); } @@ -46,7 +49,7 @@ public void add(E entry) { * @param entry the entry to check * @return true if the entry is present and not expired, false otherwise */ - public boolean contains(E entry) { + public boolean contains(@NotNull E entry) { Long expiration = entries.get(entry); if (expiration == null) { return false; @@ -63,7 +66,7 @@ public boolean contains(E entry) { * * @param entry the entry to remove */ - public void remove(E entry) { + public void remove(@NotNull E entry) { entries.remove(entry); } @@ -88,7 +91,8 @@ public void removeExpiredEntries() { * @param entry the entry whose duration before it expires should be returned * @return duration the entry will remain in the set (if there are not modifications) */ - public Duration getExpiration(E entry) { + @NotNull + public Duration getExpiration(@NotNull E entry) { Long expiration = entries.get(entry); if (expiration == null) { return new Duration(-1, TimeUnit.SECONDS); @@ -108,7 +112,7 @@ public Duration getExpiration(E entry) { * @param duration the duration of time after which entries expire * @param unit the time unit in which {@code duration} is expressed */ - public void setExpiration(long duration, TimeUnit unit) { + public void setExpiration(long duration, @NotNull TimeUnit unit) { this.expirationMillis = unit.toMillis(duration); } diff --git a/src/main/java/fr/xephi/authme/util/expiring/TimedCounter.java b/src/main/java/fr/xephi/authme/util/expiring/TimedCounter.java index d6d8bba1d..84e332b9d 100644 --- a/src/main/java/fr/xephi/authme/util/expiring/TimedCounter.java +++ b/src/main/java/fr/xephi/authme/util/expiring/TimedCounter.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.expiring; +import org.jetbrains.annotations.NotNull; + import java.util.concurrent.TimeUnit; /** @@ -18,12 +20,13 @@ public class TimedCounter extends ExpiringMap { * @param duration the duration of time after which entries expire * @param unit the time unit in which {@code duration} is expressed */ - public TimedCounter(long duration, TimeUnit unit) { + public TimedCounter(long duration, @NotNull TimeUnit unit) { super(duration, unit); } @Override - public Integer get(K key) { + @NotNull + public Integer get(@NotNull K key) { Integer value = super.get(key); return value == null ? 0 : value; } @@ -33,7 +36,7 @@ public Integer get(K key) { * * @param key the key to increment the counter for */ - public void increment(K key) { + public void increment(@NotNull K key) { put(key, get(key) + 1); } @@ -43,7 +46,7 @@ public void increment(K key) { * * @param key the key to increment the counter for */ - public void decrement(K key) { + public void decrement(@NotNull K key) { ExpiringEntry e = getEntries().get(key); if (e != null) { @@ -67,4 +70,5 @@ public int total() { .map(ExpiringEntry::getValue) .reduce(0, Integer::sum); } + } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java b/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java index 5fb0cd3d3..bad772989 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.lazytags; +import org.jetbrains.annotations.NotNull; + import java.util.function.Function; /** @@ -9,7 +11,9 @@ */ public class DependentTag implements Tag { + @NotNull private final String name; + @NotNull private final Function replacementFunction; /** @@ -18,18 +22,21 @@ public class DependentTag implements Tag { * @param name the tag (placeholder) that will be replaced * @param replacementFunction the function producing the replacement */ - public DependentTag(String name, Function replacementFunction) { + public DependentTag(@NotNull String name,@NotNull Function replacementFunction) { this.name = name; this.replacementFunction = replacementFunction; } @Override + @NotNull public String getName() { return name; } @Override - public String getValue(A argument) { + @NotNull + public String getValue(@NotNull A argument) { return replacementFunction.apply(argument); } + } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java b/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java index a5bb58a26..b6c86e556 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/SimpleTag.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.lazytags; +import org.jetbrains.annotations.NotNull; + import java.util.function.Supplier; /** @@ -9,21 +11,26 @@ */ public class SimpleTag implements Tag { + @NotNull private final String name; + @NotNull private final Supplier replacementFunction; - public SimpleTag(String name, Supplier replacementFunction) { + public SimpleTag(@NotNull String name, @NotNull Supplier replacementFunction) { this.name = name; this.replacementFunction = replacementFunction; } @Override + @NotNull public String getName() { return name; } @Override + @NotNull public String getValue(A argument) { return replacementFunction.get(); } + } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/Tag.java b/src/main/java/fr/xephi/authme/util/lazytags/Tag.java index 2c7c6ba53..4722133b3 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/Tag.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/Tag.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.lazytags; +import org.jetbrains.annotations.NotNull; + /** * Represents a tag in a text to be replaced with a value (which may depend on some argument). * @@ -10,6 +12,7 @@ public interface Tag { /** * @return the tag to replace */ + @NotNull String getName(); /** @@ -18,5 +21,7 @@ public interface Tag { * @param argument the argument to evaluate the replacement for * @return the replacement */ + @NotNull String getValue(A argument); + } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java b/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java index 677b30e2f..84d330b80 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/TagBuilder.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.lazytags; +import org.jetbrains.annotations.NotNull; + import java.util.function.Function; import java.util.function.Supplier; @@ -11,11 +13,14 @@ public final class TagBuilder { private TagBuilder() { } - public static Tag createTag(String name, Function replacementFunction) { + @NotNull + public static Tag createTag(@NotNull String name, @NotNull Function replacementFunction) { return new DependentTag<>(name, replacementFunction); } - public static Tag createTag(String name, Supplier replacementFunction) { + @NotNull + public static Tag createTag(@NotNull String name, @NotNull Supplier replacementFunction) { return new SimpleTag<>(name, replacementFunction); } + } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java b/src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java index a9d193199..5812754b7 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/TagReplacer.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.lazytags; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -13,7 +15,9 @@ */ public final class TagReplacer { + @NotNull private final List> tags; + @NotNull private final Collection messages; /** @@ -22,7 +26,7 @@ public final class TagReplacer { * @param tags the tags that are being used in the messages * @param messages the messages */ - private TagReplacer(List> tags, Collection messages) { + private TagReplacer(@NotNull List> tags, @NotNull Collection messages) { this.tags = tags; this.messages = messages; } @@ -36,7 +40,9 @@ private TagReplacer(List> tags, Collection messages) { * @param the argument type * @return new tag replacer instance */ - public static TagReplacer newReplacer(Collection> allTags, Collection messages) { + @NotNull + public static TagReplacer newReplacer(@NotNull Collection> allTags, + @NotNull Collection messages) { List> usedTags = determineUsedTags(allTags, messages); return new TagReplacer<>(usedTags, messages); } @@ -47,7 +53,8 @@ public static TagReplacer newReplacer(Collection> allTags, Collect * @param argument the argument to get the messages for * @return the adapted messages */ - public List getAdaptedMessages(A argument) { + @NotNull + public List getAdaptedMessages(@NotNull A argument) { // Note ljacqu 20170121: Using a Map might seem more natural here but we avoid doing so for performance // Although the performance gain here is probably minimal... List tagValues = new LinkedList<>(); @@ -74,7 +81,9 @@ public List getAdaptedMessages(A argument) { * @param argument type * @return tags used at least once */ - private static List> determineUsedTags(Collection> allTags, Collection messages) { + @NotNull + private static List> determineUsedTags(@NotNull Collection> allTags, + @NotNull Collection messages) { return allTags.stream() .filter(tag -> messages.stream().anyMatch(msg -> msg.contains(tag.getName()))) .collect(Collectors.toList()); @@ -84,11 +93,13 @@ private static List> determineUsedTags(Collection> allTags, Co private static final class TagValue { /** The tag to replace. */ + @NotNull private final String tag; /** The value to replace with. */ + @NotNull private final String value; - TagValue(String tag, String value) { + TagValue(@NotNull String tag, @NotNull String value) { this.tag = tag; this.value = value; } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java b/src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java index ce9487e21..4003cacf9 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/WrappedTagReplacer.java @@ -1,5 +1,7 @@ package fr.xephi.authme.util.lazytags; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; @@ -18,8 +20,11 @@ */ public class WrappedTagReplacer { + @NotNull private final Collection items; + @NotNull private final BiFunction itemCreator; + @NotNull private final TagReplacer tagReplacer; /** @@ -30,10 +35,10 @@ public class WrappedTagReplacer { * @param stringGetter getter of the String property to adapt on the items * @param itemCreator a function taking (T, String): the original item and the adapted String, returning a new item */ - public WrappedTagReplacer(Collection> allTags, - Collection items, - Function stringGetter, - BiFunction itemCreator) { + public WrappedTagReplacer(@NotNull Collection> allTags, + @NotNull Collection items, + @NotNull Function stringGetter, + @NotNull BiFunction itemCreator) { this.items = items; this.itemCreator = itemCreator; @@ -47,7 +52,8 @@ public WrappedTagReplacer(Collection> allTags, * @param argument the argument to adapt the items for * @return the adapted items */ - public List getAdaptedItems(A argument) { + @NotNull + public List getAdaptedItems(@NotNull A argument) { List adaptedStrings = tagReplacer.getAdaptedMessages(argument); List adaptedItems = new LinkedList<>(); @@ -58,4 +64,5 @@ public List getAdaptedItems(A argument) { } return adaptedItems; } + } diff --git a/src/main/resources/email.html b/src/main/resources/email.html index a2a7ed060..fd60c2ff2 100644 --- a/src/main/resources/email.html +++ b/src/main/resources/email.html @@ -1,3 +1,4 @@ +

Dear ,

@@ -15,4 +16,4 @@

See you on ! -

\ No newline at end of file +

diff --git a/src/main/resources/recovery_code_email.html b/src/main/resources/recovery_code_email.html index fc7327a1e..e08439572 100644 --- a/src/main/resources/recovery_code_email.html +++ b/src/main/resources/recovery_code_email.html @@ -1,3 +1,4 @@ +

Dear ,

diff --git a/src/main/resources/verification_code_email.html b/src/main/resources/verification_code_email.html index c12ae946c..2140fbe2b 100644 --- a/src/main/resources/verification_code_email.html +++ b/src/main/resources/verification_code_email.html @@ -1,3 +1,4 @@ +

Dear ,

diff --git a/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java b/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java index 5fa11f6da..cc4144de2 100644 --- a/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java +++ b/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java @@ -4,7 +4,6 @@ import ch.jalu.configme.resource.PropertyResource; import ch.jalu.injector.Injector; import ch.jalu.injector.InjectorBuilder; -import com.google.common.io.Files; import fr.xephi.authme.api.v3.AuthMeApi; import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.datasource.DataSource; @@ -35,6 +34,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Collections; import java.util.logging.Logger; @@ -72,7 +73,8 @@ public void initAuthMe() throws IOException { dataFolder = temporaryFolder.newFolder(); File settingsFile = new File(dataFolder, "config.yml"); JavaPluginLoader pluginLoader = new JavaPluginLoader(server); - Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "config.test.yml"), settingsFile); + Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "config.test.yml").toPath(), + settingsFile.toPath(), StandardCopyOption.REPLACE_EXISTING); // Mock / wire various Bukkit components given(server.getLogger()).willReturn(Logger.getAnonymousLogger()); diff --git a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java index f02b5dc9b..919d1eeb1 100644 --- a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java @@ -12,7 +12,6 @@ import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension; import fr.xephi.authme.initialization.HasCleanup; import fr.xephi.authme.process.register.executors.RegistrationMethod; -import fr.xephi.authme.security.crypts.Whirlpool; import fr.xephi.authme.util.expiring.ExpiringMap; import fr.xephi.authme.util.expiring.ExpiringSet; import fr.xephi.authme.util.expiring.TimedCounter; @@ -61,7 +60,6 @@ int.class, long.class, float.class, String.class, File.class, Enum.class, collec /** Classes excluded from the field visibility test. */ private static final Set> CLASSES_EXCLUDED_FROM_VISIBILITY_TEST = ImmutableSet.of( - Whirlpool.class, // not our implementation, so we don't touch it MySqlExtension.class, // has immutable protected fields used by all children AbstractSqlDataSource.class, // protected members for inheritance Columns.class // uses non-static String constants, which is safe diff --git a/src/test/java/fr/xephi/authme/ReflectionTestUtils.java b/src/test/java/fr/xephi/authme/ReflectionTestUtils.java index 69a1e1d99..cfa093146 100644 --- a/src/test/java/fr/xephi/authme/ReflectionTestUtils.java +++ b/src/test/java/fr/xephi/authme/ReflectionTestUtils.java @@ -61,7 +61,6 @@ private static Field getField(Class clazz, String fieldName) { } } - @SuppressWarnings("unchecked") public static V getFieldValue(Class clazz, T instance, String fieldName) { Field field = getField(clazz, fieldName); return getFieldValue(field, instance); diff --git a/src/test/java/fr/xephi/authme/command/CommandConsistencyTest.java b/src/test/java/fr/xephi/authme/command/CommandConsistencyTest.java index d2033d1bc..9772fe1d6 100644 --- a/src/test/java/fr/xephi/authme/command/CommandConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandConsistencyTest.java @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import static fr.xephi.authme.TestHelper.getJarFile; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -68,6 +69,7 @@ private static Collection> initializeCommands() { private static Map> getLabelsFromPluginFile() { FileConfiguration pluginFile = YamlConfiguration.loadConfiguration(getJarFile("/plugin.yml")); MemorySection commandList = (MemorySection) pluginFile.get("commands"); + Objects.requireNonNull(commandList); Map commandDefinitions = commandList.getValues(false); Map> commandLabels = new HashMap<>(); diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/debug/DataStatisticsTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/debug/DataStatisticsTest.java index fe50d8370..3b67201af 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/debug/DataStatisticsTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/debug/DataStatisticsTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme.debug; import ch.jalu.injector.factory.SingletonStore; -import com.google.common.cache.LoadingCache; import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerCache; @@ -40,6 +39,7 @@ /** * Test for {@link DataStatistics}. */ +@SuppressWarnings({"rawtypes", "unchecked"}) @RunWith(MockitoJUnitRunner.class) public class DataStatisticsTest { @@ -99,9 +99,9 @@ public void shouldOutputStatistics() { public void shouldOutputCachedDataSourceStatistics() { // given CacheDataSource cacheDataSource = mock(CacheDataSource.class); - LoadingCache> cache = mock(LoadingCache.class); - given(cache.size()).willReturn(11L); - given(cacheDataSource.getCachedAuths()).willReturn(cache); + Map> cacheValues = mock(Map.class); + given(cacheValues.size()).willReturn(11); + given(cacheDataSource.getCachedAuths()).willReturn(cacheValues); ReflectionTestUtils.setField(DataStatistics.class, dataStatistics, "dataSource", cacheDataSource); CommandSender sender = mock(CommandSender.class); diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionCheckerTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionCheckerTest.java index 4bd8eab19..6f669a22d 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionCheckerTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionCheckerTest.java @@ -45,6 +45,7 @@ public class HasPermissionCheckerTest { @Mock private BukkitService bukkitService; + @SuppressWarnings("FuseStreamOperations") @Test public void shouldListAllPermissionNodeClasses() { // given diff --git a/src/test/java/fr/xephi/authme/command/help/HelpMessagesConsistencyTest.java b/src/test/java/fr/xephi/authme/command/help/HelpMessagesConsistencyTest.java index 019e6c863..0641ff4fb 100644 --- a/src/test/java/fr/xephi/authme/command/help/HelpMessagesConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/command/help/HelpMessagesConsistencyTest.java @@ -14,6 +14,7 @@ import java.io.File; import java.util.Collection; import java.util.List; +import java.util.Objects; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; @@ -55,7 +56,7 @@ public void shouldOnlyHaveDescriptionForOneCommand() { FileConfiguration configuration = YamlConfiguration.loadConfiguration(DEFAULT_MESSAGES_FILE); // when - Object commands = configuration.get("commands"); + Object commands = Objects.requireNonNull(configuration.get("commands")); // then assertThat(commands, instanceOf(MemorySection.class)); diff --git a/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java b/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java index 514724a97..3443a1b88 100644 --- a/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java +++ b/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.help; -import com.google.common.io.Files; import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.TestHelper; import fr.xephi.authme.command.CommandDescription; @@ -11,6 +10,7 @@ import fr.xephi.authme.permission.DefaultPermission; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; +import fr.xephi.authme.util.FileUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -18,6 +18,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Collection; import static fr.xephi.authme.command.TestCommandsUtil.getCommandWithLabel; @@ -45,9 +47,10 @@ public class HelpMessagesServiceTest { @Before public void initializeHandler() throws IOException { dataFolder = temporaryFolder.newFolder(); - new File(dataFolder, "messages").mkdirs(); + FileUtils.createDirectoryOrFail(new File(dataFolder, "messages")); File messagesFile = new File(dataFolder, MessagePathHelper.createHelpMessageFilePath("test")); - Files.copy(TestHelper.getJarFile(TEST_FILE), messagesFile); + Files.copy(TestHelper.getJarFile(TEST_FILE).toPath(), messagesFile.toPath(), + StandardCopyOption.REPLACE_EXISTING); HelpMessagesFileHandler helpMessagesFileHandler = createMessagesFileHandler(); helpMessagesService = new HelpMessagesService(helpMessagesFileHandler); diff --git a/src/test/java/fr/xephi/authme/data/captcha/RegistrationCaptchaManagerTest.java b/src/test/java/fr/xephi/authme/data/captcha/RegistrationCaptchaManagerTest.java index 4a71ab2ca..d640aabef 100644 --- a/src/test/java/fr/xephi/authme/data/captcha/RegistrationCaptchaManagerTest.java +++ b/src/test/java/fr/xephi/authme/data/captcha/RegistrationCaptchaManagerTest.java @@ -84,7 +84,6 @@ public void shouldGenerateAndRetrieveCode() { assertThat(captchaManager.checkCode(player, captcha1), equalTo(true)); } - @SuppressWarnings("unchecked") private static ExpiringMap getCodeMap(RegistrationCaptchaManager captchaManager) { CaptchaCodeStorage captchaStorage = ReflectionTestUtils.getFieldValue( RegistrationCaptchaManager.class, captchaManager, "captchaCodeStorage"); diff --git a/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java b/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java index 78386e2d3..88c21392e 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java +++ b/src/test/java/fr/xephi/authme/data/limbo/LimboPlayerMatchers.java @@ -21,7 +21,7 @@ private LimboPlayerMatchers() { } public static Matcher isLimbo(LimboPlayer limbo) { - String[] groups = limbo.getGroups().toArray(new String[limbo.getGroups().size()]); + String[] groups = limbo.getGroups().toArray(new String[0]); return isLimbo(limbo.isOperator(), limbo.isCanFly(), limbo.getWalkSpeed(), limbo.getFlySpeed(), groups); } @@ -57,7 +57,7 @@ public static Matcher hasLocation(String world, double x, double y, @Override protected boolean matchesSafely(LimboPlayer item) { Location location = item.getLocation(); - return location.getWorld().getName().equals(world) + return location.getWorld() != null && location.getWorld().getName().equals(world) && location.getX() == x && location.getY() == y && location.getZ() == z; } @@ -74,7 +74,8 @@ public void describeMismatchSafely(LimboPlayer item, Description description) { description.appendText("Limbo with location = null"); } else { description.appendText(format("Limbo with location: world=%s, x=%f, y=%f, z=%f", - location.getWorld().getName(), location.getX(), location.getY(), location.getZ())); + location.getWorld() != null ? location.getWorld().getName() : "N/D", + location.getX(), location.getY(), location.getZ())); } } }; @@ -89,7 +90,8 @@ public static Matcher hasLocation(String world, double x, double y, @Override protected boolean matchesSafely(LimboPlayer item) { Location location = item.getLocation(); - return hasLocation(location.getWorld(), location.getX(), location.getY(), location.getZ()).matches(item) + return location.getWorld() != null + && hasLocation(location.getWorld(), location.getX(), location.getY(), location.getZ()).matches(item) && location.getYaw() == yaw && location.getPitch() == pitch; } @@ -106,16 +108,16 @@ public void describeMismatchSafely(LimboPlayer item, Description description) { description.appendText("Limbo with location = null"); } else { description.appendText(format("Limbo with location: world=%s, x=%f, y=%f, z=%f, yaw=%f, pitch=%f", - location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), - location.getYaw(), location.getPitch())); + location.getWorld() != null ? location.getWorld().getName() : "N/D", + location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch())); } } }; } public static Matcher hasLocation(Location location) { - return hasLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), - location.getYaw(), location.getPitch()); + return hasLocation(location.getWorld() != null ? location.getWorld().getName() : null, + location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); } // Hamcrest's contains() doesn't like it when there are no items, so we need to check for the empty case explicitly diff --git a/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java b/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java index fd41134a1..d4ef8e01d 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java @@ -3,13 +3,13 @@ import ch.jalu.injector.testing.BeforeInjecting; import ch.jalu.injector.testing.DelayedInjectionRunner; import ch.jalu.injector.testing.InjectDelayed; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.data.limbo.LimboPlayer; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.LimboSettings; +import fr.xephi.authme.util.FileUtils; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; @@ -23,6 +23,9 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Collections; import java.util.UUID; @@ -72,6 +75,7 @@ public class DistributedFilesPersistenceHandlerTest { private static final UUID UNKNOWN_UUID2 = fromString("84d1cc0b-8f12-d04a-e7ba-a067d05cdc39"); + @SuppressWarnings("unused") @InjectDelayed private DistributedFilesPersistenceHandler persistenceHandler; @@ -79,6 +83,7 @@ public class DistributedFilesPersistenceHandlerTest { private Settings settings; @Mock private BukkitService bukkitService; + @SuppressWarnings("FieldCanBeLocal") @DataFolder private File dataFolder; private File playerDataFolder; @@ -96,12 +101,12 @@ public void setUpClasses() throws IOException { given(settings.getProperty(LimboSettings.DISTRIBUTION_SIZE)).willReturn(SegmentSize.SIXTEEN); dataFolder = temporaryFolder.newFolder(); playerDataFolder = new File(dataFolder, "playerdata"); - playerDataFolder.mkdir(); + FileUtils.createDirectoryOrFail(playerDataFolder); File limboFilesFolder = new File(TEST_RESOURCES_FOLDER + PROJECT_ROOT + "data/limbo"); for (File file : limboFilesFolder.listFiles()) { File from = new File(playerDataFolder, file.getName()); - Files.copy(file, from); + Files.copy(file.toPath(), from.toPath(), StandardCopyOption.REPLACE_EXISTING); } given(bukkitService.getWorld(anyString())) @@ -185,7 +190,7 @@ public void shouldHandleReadErrorGracefully() throws IOException { // assumption File invalidFile = new File(playerDataFolder, "seg16-4-limbo.json"); assertThat(invalidFile.exists(), equalTo(false)); - Files.write("not valid json".getBytes(), invalidFile); + Files.write(invalidFile.toPath(), "not valid json".getBytes(StandardCharsets.UTF_8)); // when LimboPlayer result = persistenceHandler.getLimboPlayer(mockPlayerWithUuid(UNKNOWN_UUID)); diff --git a/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java b/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java index 06df57bf0..0e54e6939 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/persistence/IndividualFilesPersistenceHandlerTest.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Collections; import java.util.UUID; @@ -60,7 +61,7 @@ public void copyTestFiles() throws IOException { throw new IllegalStateException("Cannot create '" + playerFolder.getAbsolutePath() + "'"); } Files.copy(TestHelper.getJarPath(FileUtils.makePath(SOURCE_FOLDER, "sample-folder", "data.json")), - new File(playerFolder, "data.json").toPath()); + new File(playerFolder, "data.json").toPath(), StandardCopyOption.REPLACE_EXISTING); } @Test diff --git a/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java index 027608230..7ff33d6c1 100644 --- a/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java @@ -11,6 +11,7 @@ import org.junit.BeforeClass; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.sql.Connection; @@ -47,7 +48,7 @@ public static void initializeSettings() throws IOException, ClassNotFoundExcepti TestHelper.setRealLogger(); Path sqlInitFile = TestHelper.getJarPath(TestHelper.PROJECT_ROOT + "datasource/sql-initialize.sql"); - sqlInitialize = new String(Files.readAllBytes(sqlInitFile)); + sqlInitialize = new String(Files.readAllBytes(sqlInitFile), StandardCharsets.UTF_8); } @Before diff --git a/src/test/java/fr/xephi/authme/datasource/PostgreSqlIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/PostgreSqlIntegrationTest.java index 54a00bf40..d50c4d4e1 100644 --- a/src/test/java/fr/xephi/authme/datasource/PostgreSqlIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/datasource/PostgreSqlIntegrationTest.java @@ -11,6 +11,7 @@ import org.junit.BeforeClass; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.sql.Connection; @@ -47,7 +48,7 @@ public static void initializeSettings() throws IOException, ClassNotFoundExcepti TestHelper.setRealLogger(); Path sqlInitFile = TestHelper.getJarPath(TestHelper.PROJECT_ROOT + "datasource/sql-initialize.sql"); - sqlInitialize = new String(Files.readAllBytes(sqlInitFile)); + sqlInitialize = new String(Files.readAllBytes(sqlInitFile), StandardCharsets.UTF_8); } @Before diff --git a/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java index 06e60eeb6..db7b03649 100644 --- a/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/datasource/SQLiteIntegrationTest.java @@ -11,6 +11,7 @@ import org.junit.Test; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.sql.Connection; @@ -52,7 +53,7 @@ public static void initializeSettings() throws IOException, ClassNotFoundExcepti Path sqlInitFile = TestHelper.getJarPath(TestHelper.PROJECT_ROOT + "datasource/sql-initialize.sql"); // Note ljacqu 20160221: It appears that we can only run one statement per Statement.execute() so we split // the SQL file by ";\n" as to get the individual statements - sqlInitialize = new String(Files.readAllBytes(sqlInitFile)).split(";(\\r?)\\n"); + sqlInitialize = new String(Files.readAllBytes(sqlInitFile), StandardCharsets.UTF_8).split(";(\\r?)\\n"); } @Before diff --git a/src/test/java/fr/xephi/authme/datasource/SqLiteMigraterIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/SqLiteMigraterIntegrationTest.java index b95a0b814..e1151466a 100644 --- a/src/test/java/fr/xephi/authme/datasource/SqLiteMigraterIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/datasource/SqLiteMigraterIntegrationTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.datasource; import com.google.common.collect.Lists; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.settings.Settings; @@ -12,6 +11,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; @@ -39,7 +40,7 @@ public class SqLiteMigraterIntegrationTest { public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Before - public void setup() throws SQLException, IOException, NoSuchMethodException { + public void setup() throws SQLException, IOException { TestHelper.setupLogger(); Settings settings = mock(Settings.class); @@ -48,15 +49,16 @@ public void setup() throws SQLException, IOException, NoSuchMethodException { File sqliteDbFile = TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "datasource/sqlite.april2016.db"); dataFolder = temporaryFolder.newFolder(); File tempFile = new File(dataFolder, "authme.db"); - Files.copy(sqliteDbFile, tempFile); + Files.copy(sqliteDbFile.toPath(), tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); Connection con = DriverManager.getConnection("jdbc:sqlite:" + tempFile.getPath()); sqLite = createSqlite(settings, dataFolder, con); } + @SuppressWarnings("unchecked") @Test - public void shouldRun() throws ClassNotFoundException, SQLException { + public void shouldRun() throws SQLException { // given / when sqLite.setup(); sqLite.migrateIfNeeded(); diff --git a/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java b/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java index 54201fb71..9584d7100 100644 --- a/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java +++ b/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java @@ -19,6 +19,7 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.sql.Connection; import java.sql.SQLException; @@ -123,7 +124,7 @@ public void shouldConvertFromMySql() throws IOException, SQLException { private Connection initializeMySqlTable() throws IOException, SQLException { File sqlInitFile = TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "datasource/converter/loginsecurity.sql"); - String initStatement = new String(Files.readAllBytes(sqlInitFile.toPath())); + String initStatement = new String(Files.readAllBytes(sqlInitFile.toPath()), StandardCharsets.UTF_8); HikariConfig config = new HikariConfig(); config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource"); diff --git a/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java b/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java index 76877fcac..dc7d6abcc 100644 --- a/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java +++ b/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java @@ -13,6 +13,7 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.entity.EntityEvent; import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -228,8 +229,9 @@ public TestPlayerEvent(Player player) { } @Override + @NotNull public HandlerList getHandlers() { - return null; + throw new UnsupportedOperationException(); } } } diff --git a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java index 3667e1bea..e21e5747d 100644 --- a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java +++ b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java @@ -29,6 +29,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import java.net.InetAddress; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -96,7 +97,7 @@ public void shouldNotDoAnythingForNormalEvent() { public void shouldRefuseNonVipPlayerForFullServer() { // given Player player = mock(Player.class); - PlayerLoginEvent event = new PlayerLoginEvent(player, "hostname", null); + PlayerLoginEvent event = new PlayerLoginEvent(player, "hostname", mock(InetAddress.class)); event.setResult(PlayerLoginEvent.Result.KICK_FULL); given(permissionsManager.hasPermission(player, PlayerStatePermission.IS_VIP)).willReturn(false); String serverFullMessage = "server is full"; @@ -116,7 +117,7 @@ public void shouldRefuseNonVipPlayerForFullServer() { public void shouldKickNonVipForJoiningVipPlayer() { // given Player player = mock(Player.class); - PlayerLoginEvent event = new PlayerLoginEvent(player, "hostname", null); + PlayerLoginEvent event = new PlayerLoginEvent(player, "hostname", mock(InetAddress.class)); event.setResult(PlayerLoginEvent.Result.KICK_FULL); given(permissionsManager.hasPermission(player, PlayerStatePermission.IS_VIP)).willReturn(true); List onlinePlayers = Arrays.asList(mock(Player.class), mock(Player.class)); @@ -141,7 +142,7 @@ public void shouldKickNonVipForJoiningVipPlayer() { public void shouldKickVipPlayerIfNoPlayerCanBeKicked() { // given Player player = mock(Player.class); - PlayerLoginEvent event = new PlayerLoginEvent(player, "hostname", null); + PlayerLoginEvent event = new PlayerLoginEvent(player, "hostname", mock(InetAddress.class)); event.setResult(PlayerLoginEvent.Result.KICK_FULL); given(permissionsManager.hasPermission(player, PlayerStatePermission.IS_VIP)).willReturn(true); List onlinePlayers = Collections.singletonList(mock(Player.class)); @@ -314,6 +315,7 @@ public void shouldAcceptCasingMismatchForDisabledSetting() throws FailedVerifica verifyNoInteractions(dataSource); } + @SuppressWarnings("ConstantConditions") @Test public void shouldAcceptNameForUnregisteredAccount() throws FailedVerificationException { // given @@ -371,6 +373,7 @@ public void shouldAcceptAlreadyOnlineNameForDisabledSetting() throws FailedVerif verifyNoInteractions(bukkitService); } + @SuppressWarnings("ConstantConditions") @Test public void shouldAllowUser() throws FailedVerificationException { // given @@ -387,6 +390,7 @@ public void shouldAllowUser() throws FailedVerificationException { verify(antiBotService).shouldKick(); } + @SuppressWarnings("ConstantConditions") @Test public void shouldAllowUserWithAuth() throws FailedVerificationException { // given @@ -400,6 +404,7 @@ public void shouldAllowUserWithAuth() throws FailedVerificationException { verifyNoInteractions(permissionsManager, antiBotService); } + @SuppressWarnings("ConstantConditions") @Test public void shouldAllowUserWithBypassPermission() throws FailedVerificationException { // given @@ -415,6 +420,7 @@ public void shouldAllowUserWithBypassPermission() throws FailedVerificationExcep verifyNoInteractions(antiBotService); } + @SuppressWarnings("ConstantConditions") @Test public void shouldKickUserForFailedAntibotCheck() { // given diff --git a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java index c2459a652..be02ac1cc 100644 --- a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java +++ b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java @@ -650,7 +650,7 @@ public void shouldNotInterfereWithUnrestrictedUser() throws FailedVerificationEx // given String name = "Player01"; Player player = mockPlayerWithName(name); - PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", null)); + PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", mock(InetAddress.class))); given(validationService.isUnrestricted(name)).willReturn(true); // when @@ -668,7 +668,7 @@ public void shouldStopHandlingForFullServer() throws FailedVerificationException // given String name = "someone"; Player player = mockPlayerWithName(name); - PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", null)); + PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", mock(InetAddress.class))); given(validationService.isUnrestricted(name)).willReturn(false); given(onJoinVerifier.refusePlayerForFullServer(event)).willReturn(true); @@ -688,7 +688,7 @@ public void shouldStopHandlingEventForBadResult() throws FailedVerificationExcep // given String name = "someone"; Player player = mockPlayerWithName(name); - PlayerLoginEvent event = new PlayerLoginEvent(player, "", null); + PlayerLoginEvent event = new PlayerLoginEvent(player, "", mock(InetAddress.class)); event.setResult(PlayerLoginEvent.Result.KICK_BANNED); event = spy(event); given(validationService.isUnrestricted(name)).willReturn(false); diff --git a/src/test/java/fr/xephi/authme/message/MessageFilePlaceholderTest.java b/src/test/java/fr/xephi/authme/message/MessageFilePlaceholderTest.java index 0966902ba..c6209f3fb 100644 --- a/src/test/java/fr/xephi/authme/message/MessageFilePlaceholderTest.java +++ b/src/test/java/fr/xephi/authme/message/MessageFilePlaceholderTest.java @@ -14,6 +14,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import static fr.xephi.authme.message.MessagePathHelper.MESSAGES_FOLDER; @@ -64,7 +65,7 @@ public void shouldHaveAllPlaceholders() { private List findMissingTags(MessageKey key, PropertyReader reader) { if (key.getTags().length > 0 && reader.contains(key.getKey())) { - String message = reader.getString(key.getKey()); + String message = Objects.requireNonNull(reader.getString(key.getKey())); return Arrays.stream(key.getTags()) .filter(tag -> !EXCLUSIONS.get(key).contains(tag) && !message.contains(tag)) .collect(Collectors.toList()); diff --git a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java index bc1e9769d..8cf1f3082 100644 --- a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.message; import com.google.common.collect.ImmutableMap; -import com.google.common.io.Files; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.TestHelper; @@ -23,6 +22,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; @@ -71,9 +72,10 @@ public static void setup() { public void setUpMessages() throws IOException { dataFolder = temporaryFolder.newFolder(); File testFile = new File(dataFolder, MessagePathHelper.createMessageFilePath("test")); - new File(dataFolder, MessagePathHelper.MESSAGES_FOLDER).mkdirs(); + FileUtils.createDirectoryOrFail(new File(dataFolder, MessagePathHelper.MESSAGES_FOLDER)); FileUtils.create(testFile); - Files.copy(TestHelper.getJarFile(YML_TEST_FILE), testFile); + Files.copy(TestHelper.getJarFile(YML_TEST_FILE).toPath(), testFile.toPath(), + StandardCopyOption.REPLACE_EXISTING); messagesFileHandler = createMessagesFileHandler(); messages = new Messages(messagesFileHandler); @@ -284,7 +286,8 @@ public void shouldFormatDurationObjects() throws IOException { // given // Use the JAR's messages_en.yml file for this, so copy to the file we're using and reload the file handler File testFile = new File(dataFolder, MessagePathHelper.createMessageFilePath("test")); - Files.copy(TestHelper.getJarFile("/" + MessagePathHelper.DEFAULT_MESSAGES_FILE), testFile); + Files.copy(TestHelper.getJarFile("/" + MessagePathHelper.DEFAULT_MESSAGES_FILE).toPath(), + testFile.toPath(), StandardCopyOption.REPLACE_EXISTING); messagesFileHandler.reload(); Map expectedTexts = ImmutableMap.builder() diff --git a/src/test/java/fr/xephi/authme/message/updater/MessageUpdaterTest.java b/src/test/java/fr/xephi/authme/message/updater/MessageUpdaterTest.java index eac3b67e3..aa485a40d 100644 --- a/src/test/java/fr/xephi/authme/message/updater/MessageUpdaterTest.java +++ b/src/test/java/fr/xephi/authme/message/updater/MessageUpdaterTest.java @@ -3,7 +3,6 @@ import ch.jalu.configme.properties.Property; import ch.jalu.configme.resource.PropertyReader; import ch.jalu.configme.resource.YamlFileReader; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.message.MessageKey; import org.junit.BeforeClass; @@ -13,6 +12,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -28,7 +29,7 @@ */ public class MessageUpdaterTest { - private MessageUpdater messageUpdater = new MessageUpdater(); + private final MessageUpdater messageUpdater = new MessageUpdater(); @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @@ -43,7 +44,8 @@ public void shouldNotUpdateDefaultFile() throws IOException { // given String messagesFilePath = DEFAULT_MESSAGES_FILE; File messagesFile = temporaryFolder.newFile(); - Files.copy(TestHelper.getJarFile("/" + messagesFilePath), messagesFile); + Files.copy(TestHelper.getJarFile("/" + messagesFilePath).toPath(), messagesFile.toPath(), + StandardCopyOption.REPLACE_EXISTING); long modifiedDate = messagesFile.lastModified(); // when @@ -58,7 +60,8 @@ public void shouldNotUpdateDefaultFile() throws IOException { public void shouldAddMissingKeys() throws IOException { // given File messagesFile = temporaryFolder.newFile(); - Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/messages_test.yml"), messagesFile); + Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/messages_test.yml").toPath(), + messagesFile.toPath(), StandardCopyOption.REPLACE_EXISTING); // when boolean wasChanged = messageUpdater.migrateAndSave(messagesFile, "does-not-exist", DEFAULT_MESSAGES_FILE); @@ -78,7 +81,8 @@ public void shouldAddMissingKeys() throws IOException { public void shouldMigrateOldEntries() throws IOException { // given File messagesFile = temporaryFolder.newFile(); - Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/messages_en_old.yml"), messagesFile); + Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/messages_en_old.yml").toPath(), + messagesFile.toPath(), StandardCopyOption.REPLACE_EXISTING); // when boolean wasChanged = messageUpdater.migrateAndSave(messagesFile, DEFAULT_MESSAGES_FILE, DEFAULT_MESSAGES_FILE); @@ -104,7 +108,8 @@ public void shouldMigrateOldEntries() throws IOException { public void shouldPerformNewerMigrations() throws IOException { // given File messagesFile = temporaryFolder.newFile(); - Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/messages_test2.yml"), messagesFile); + Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/messages_test2.yml").toPath(), + messagesFile.toPath(), StandardCopyOption.REPLACE_EXISTING); // when boolean wasChanged = messageUpdater.migrateAndSave(messagesFile, DEFAULT_MESSAGES_FILE, DEFAULT_MESSAGES_FILE); diff --git a/src/test/java/fr/xephi/authme/message/updater/MigraterYamlFileResourceTest.java b/src/test/java/fr/xephi/authme/message/updater/MigraterYamlFileResourceTest.java index 03d79e71f..a4eda4ee8 100644 --- a/src/test/java/fr/xephi/authme/message/updater/MigraterYamlFileResourceTest.java +++ b/src/test/java/fr/xephi/authme/message/updater/MigraterYamlFileResourceTest.java @@ -5,7 +5,6 @@ import ch.jalu.configme.properties.Property; import ch.jalu.configme.properties.StringProperty; import ch.jalu.configme.resource.PropertyReader; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import org.junit.Rule; import org.junit.Test; @@ -13,6 +12,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.List; @@ -48,7 +49,8 @@ public void shouldReadChineseFile() { public void shouldWriteWithCorrectCharset() throws IOException { // given File file = temporaryFolder.newFile(); - Files.copy(TestHelper.getJarFile(CHINESE_MESSAGES_FILE), file); + Files.copy(TestHelper.getJarFile(CHINESE_MESSAGES_FILE).toPath(), file.toPath(), + StandardCopyOption.REPLACE_EXISTING); MigraterYamlFileResource resource = new MigraterYamlFileResource(file); ConfigurationData configurationData = buildConfigurationData(); configurationData.initializeValues(resource.createReader()); diff --git a/src/test/java/fr/xephi/authme/permission/PermissionConsistencyTest.java b/src/test/java/fr/xephi/authme/permission/PermissionConsistencyTest.java index 6d7a37e2f..2ab78b078 100644 --- a/src/test/java/fr/xephi/authme/permission/PermissionConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/permission/PermissionConsistencyTest.java @@ -18,6 +18,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -131,6 +132,7 @@ private static List getPermissionsFromClasses() { private static Map getPermissionsFromPluginYmlFile() { FileConfiguration pluginFile = YamlConfiguration.loadConfiguration(getJarFile("/plugin.yml")); MemorySection permsList = (MemorySection) pluginFile.get("permissions"); + Objects.requireNonNull(permsList); Map permissions = new HashMap<>(); addChildren(permsList, permissions); @@ -148,7 +150,7 @@ private static void addChildren(MemorySection node, Map children = new ArrayList<>(); - collectChildren((MemorySection) memorySection.get("children"), children); + collectChildren((MemorySection) Objects.requireNonNull(memorySection.get("children")), children); this.children = removeStart(memorySection.getCurrentPath() + ".children.", children); } else { this.children = Collections.emptySet(); diff --git a/src/test/java/fr/xephi/authme/permission/PermissionsManagerTest.java b/src/test/java/fr/xephi/authme/permission/PermissionsManagerTest.java index 6c7efb452..78d769943 100644 --- a/src/test/java/fr/xephi/authme/permission/PermissionsManagerTest.java +++ b/src/test/java/fr/xephi/authme/permission/PermissionsManagerTest.java @@ -123,6 +123,7 @@ public void shouldDenyEvenForOpPlayer() { assertThat(result, equalTo(false)); } + @SuppressWarnings("ConstantConditions") @Test public void shouldHandleNullPermissionForCommandSender() { // given @@ -136,6 +137,7 @@ public void shouldHandleNullPermissionForCommandSender() { assertThat(result, equalTo(true)); } + @SuppressWarnings("ConstantConditions") @Test public void shouldHandleNullPermissionForPlayer() { // given diff --git a/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java b/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java index e59dae647..c016a3045 100644 --- a/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java @@ -59,6 +59,7 @@ public void shouldHaveUniqueClassForEntries() { } } + @SuppressWarnings("deprecation") @Test public void shouldBeAbleToInstantiateEncryptionAlgorithms() { // given / when / then @@ -81,6 +82,7 @@ public void shouldBeAbleToInstantiateEncryptionAlgorithms() { } } + @SuppressWarnings("deprecation") @Test public void shouldBeDeprecatedIfEncryptionClassIsDeprecated() throws NoSuchFieldException { // given diff --git a/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java b/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java index 520ae8ddc..914df7c75 100644 --- a/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java +++ b/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java @@ -253,7 +253,7 @@ public void shouldSkipCheckIfMandatorySaltIsUnavailable() { String username = "someone12"; HashedPassword hashedPassword = new HashedPassword("~T!est#Hash"); given(method.hasSeparateSalt()).willReturn(true); - given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.XAUTH); + given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.SMF); passwordSecurity.reload(); // when diff --git a/src/test/java/fr/xephi/authme/security/crypts/WhirlpoolTest.java b/src/test/java/fr/xephi/authme/security/crypts/WhirlpoolTest.java deleted file mode 100644 index 76cef4b05..000000000 --- a/src/test/java/fr/xephi/authme/security/crypts/WhirlpoolTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.xephi.authme.security.crypts; - -/** - * Test for {@link Whirlpool}. - */ -public class WhirlpoolTest extends AbstractEncryptionMethodTest { - - public WhirlpoolTest() { - super(new Whirlpool(), - "74DFC2B27ACFA364DA55F93A5CAEE29CCAD3557247EDA238831B3E9BD931B01D77FE994E4F12B9D4CFA92A124461D2065197D8CF7F33FC88566DA2DB2A4D6EAE", // password - "819B4CBD26508E39EA76BFE102DCF2ACC87A446747CAB0BD88522B0822A724583E81B6A4BD2CE255DB694E530B659F47D434EEB50344A02F50B64414C9671583", // PassWord1 - "71ECB0E5AEAB006F5336348076AA6A8E46075AEC9E010C7055BA1334B57746F2A9D8A8799BDD9B7EB4AB7544A59D25F469C8BCA2067508ACBA62A929260A1E17", // &^%te$t?Pw@_ - "CBFEFB3DD7FC6D7F88E006955CFFE07758C74216A825A355D67AE352DA99D8F17FA00CB5CB6875A90BAB4992121E786F57E7B3602232002752925E4DC545C414"); // âË_3(íù* - } - -} diff --git a/src/test/java/fr/xephi/authme/security/crypts/XAuthTest.java b/src/test/java/fr/xephi/authme/security/crypts/XAuthTest.java deleted file mode 100644 index 877a81ee1..000000000 --- a/src/test/java/fr/xephi/authme/security/crypts/XAuthTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.xephi.authme.security.crypts; - -/** - * Test for {@link XAuth}. - */ -public class XAuthTest extends AbstractEncryptionMethodTest { - - public XAuthTest() { - super(new XAuth(), - "e54d4916577410d26d2f6e9362445463dab9ffdff9a67ed3b74d3f2312bc8fab84f653fcb88ad8338793ef8a6d0a1162105e46ec24f0dcb52355c634e3e6439f45444b09c715", // password - "d54489a4fd4732ee03d56810ab92944096e3d49335266adeecfbc12567abb3ff744761b33a1fcc4d04739e377775c788e4baace3caf35c7b9176b82b1fe3472e4cbdc5a43214", // PassWord1 - "ce6404c1092fb5abf0a72f9c4327bfe8f4cdc4b8dc90ee6ca35c42b8ae9481b89c2559bb60b99ff2b57a102cfced40b8e2f5ef481400c9e6f79445017fc763b1cc27f4c2df36", // &^%te$t?Pw@_ - "73074fe3f5503677ab9c5a1885b46a8b6fb249453317da08d86312c20e7b326e84f615e1b594c71129d2d1020400a89838e44653dc02d1799886e522a2789fbe1df6e70b7ffb"); // âË_3(íù* - } - -} diff --git a/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java b/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java index 3e094cc2b..c33f10ac4 100644 --- a/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java @@ -3,7 +3,6 @@ import ch.jalu.injector.testing.BeforeInjecting; import ch.jalu.injector.testing.DelayedInjectionRunner; import ch.jalu.injector.testing.InjectDelayed; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.command.CommandInitializer; import fr.xephi.authme.command.help.HelpMessage; @@ -13,6 +12,7 @@ import fr.xephi.authme.message.HelpMessagesFileHandler; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; +import fr.xephi.authme.util.FileUtils; import org.bukkit.configuration.MemorySection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -25,6 +25,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -67,9 +69,10 @@ public static void setUpLogger() { public void setUpClasses() throws IOException { dataFolder = temporaryFolder.newFolder(); File messagesFolder = new File(dataFolder, "messages"); - messagesFolder.mkdir(); + FileUtils.createDirectoryOrFail(messagesFolder); helpMessagesFile = new File(messagesFolder, "help_test.yml"); - Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/help_test.yml"), helpMessagesFile); + Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/help_test.yml").toPath(), + helpMessagesFile.toPath(), StandardCopyOption.REPLACE_EXISTING); given(settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)).willReturn("test"); } diff --git a/src/test/java/fr/xephi/authme/service/MigrationServiceTest.java b/src/test/java/fr/xephi/authme/service/MigrationServiceTest.java index e1579710c..68c1e5256 100644 --- a/src/test/java/fr/xephi/authme/service/MigrationServiceTest.java +++ b/src/test/java/fr/xephi/authme/service/MigrationServiceTest.java @@ -30,6 +30,7 @@ /** * Test for {@link MigrationService}. */ +@SuppressWarnings("deprecation") @RunWith(MockitoJUnitRunner.class) public class MigrationServiceTest { diff --git a/src/test/java/fr/xephi/authme/service/TeleportationServiceTest.java b/src/test/java/fr/xephi/authme/service/TeleportationServiceTest.java index 46db5e05c..9c9261af3 100644 --- a/src/test/java/fr/xephi/authme/service/TeleportationServiceTest.java +++ b/src/test/java/fr/xephi/authme/service/TeleportationServiceTest.java @@ -20,6 +20,7 @@ import org.mockito.junit.MockitoJUnitRunner; import java.util.Arrays; +import java.util.Objects; import static fr.xephi.authme.service.BukkitServiceTestHelper.setBukkitServiceToScheduleSyncTaskFromOptionallyAsyncTask; import static org.hamcrest.Matchers.equalTo; @@ -240,7 +241,7 @@ public void shouldTeleportPlayerToSpawnAfterLogin() { PlayerAuth auth = mock(PlayerAuth.class); LimboPlayer limbo = mock(LimboPlayer.class); Location limboLocation = mockLocation(); - given(limboLocation.getWorld().getName()).willReturn("forced1"); + given(Objects.requireNonNull(limboLocation.getWorld()).getName()).willReturn("forced1"); given(limbo.getLocation()).willReturn(limboLocation); setBukkitServiceToScheduleSyncTaskFromOptionallyAsyncTask(bukkitService); @@ -262,7 +263,7 @@ public void shouldNotTeleportToSpawnForOtherCaseInWorld() { PlayerAuth auth = mock(PlayerAuth.class); LimboPlayer limbo = mock(LimboPlayer.class); Location limboLocation = mockLocation(); - given(limboLocation.getWorld().getName()).willReturn("Forced1"); // different case + given(Objects.requireNonNull(limboLocation.getWorld()).getName()).willReturn("Forced1"); // different case given(limbo.getLocation()).willReturn(limboLocation); // when diff --git a/src/test/java/fr/xephi/authme/service/ValidationServiceTest.java b/src/test/java/fr/xephi/authme/service/ValidationServiceTest.java index dafc8c3dc..a854d54b3 100644 --- a/src/test/java/fr/xephi/authme/service/ValidationServiceTest.java +++ b/src/test/java/fr/xephi/authme/service/ValidationServiceTest.java @@ -23,6 +23,7 @@ import org.mockito.Mock; import java.util.Collections; +import java.util.Objects; import java.util.logging.Logger; import static com.google.common.collect.Sets.newHashSet; @@ -403,7 +404,7 @@ private static Player mockPlayer(String name, String ip) { Player player = mock(Player.class); given(player.getName()).willReturn(name); TestHelper.mockPlayerIp(player, ip); - given(player.getAddress().getHostName()).willReturn("--"); + given(Objects.requireNonNull(player.getAddress()).getHostName()).willReturn("--"); return player; } diff --git a/src/test/java/fr/xephi/authme/settings/SettingsIntegrationTest.java b/src/test/java/fr/xephi/authme/settings/SettingsIntegrationTest.java index e9a58c677..ff77f9ffe 100644 --- a/src/test/java/fr/xephi/authme/settings/SettingsIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/settings/SettingsIntegrationTest.java @@ -7,7 +7,6 @@ import ch.jalu.configme.resource.PropertyResource; import ch.jalu.configme.resource.YamlFileResource; import com.google.common.collect.ImmutableMap; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.settings.properties.TestConfiguration; import fr.xephi.authme.settings.properties.TestEnum; @@ -19,6 +18,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -37,7 +38,7 @@ public class SettingsIntegrationTest { /** File name of the sample config missing certain {@link TestConfiguration} values. */ private static final String INCOMPLETE_FILE = TestHelper.PROJECT_ROOT + "settings/config-incomplete-sample.yml"; - private static ConfigurationData CONFIG_DATA = + private static final ConfigurationData CONFIG_DATA = ConfigurationDataBuilder.createConfiguration(TestConfiguration.class); @Rule @@ -125,7 +126,7 @@ public void shouldReloadSettings() throws IOException { // when assertThat(settings.getProperty(TestConfiguration.RATIO_ORDER), equalTo(TestEnum.SECOND)); // default value - Files.copy(getJarFile(COMPLETE_FILE), configFile); + Files.copy(getJarFile(COMPLETE_FILE).toPath(), configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); settings.reload(); // then @@ -136,7 +137,7 @@ private File copyFileFromResources(String path) { try { File source = getJarFile(path); File destination = temporaryFolder.newFile(); - Files.copy(source, destination); + Files.copy(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); return destination; } catch (IOException e) { throw new IllegalStateException("Could not copy test file", e); diff --git a/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java b/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java index 021bfb93b..656d7132a 100644 --- a/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java +++ b/src/test/java/fr/xephi/authme/settings/SettingsMigrationServiceTest.java @@ -4,7 +4,6 @@ import ch.jalu.configme.resource.PropertyReader; import ch.jalu.configme.resource.PropertyResource; import ch.jalu.configme.resource.YamlFileResource; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.output.LogLevel; @@ -20,6 +19,8 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; @@ -62,7 +63,7 @@ public void shouldPerformMigrationsInMemory() throws IOException { // given File dataFolder = temporaryFolder.newFolder(); File configFile = new File(dataFolder, "config.yml"); - Files.copy(getJarFile(OLD_CONFIG_FILE), configFile); + Files.copy(getJarFile(OLD_CONFIG_FILE).toPath(), configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); PropertyResource resource = new YamlFileResource(configFile); SettingsMigrationService migrationService = new SettingsMigrationService(dataFolder); @@ -83,7 +84,7 @@ public void shouldPerformMigrationsAndPersistToDisk() throws IOException { // given File dataFolder = temporaryFolder.newFolder(); File configFile = new File(dataFolder, "config.yml"); - Files.copy(getJarFile(OLD_CONFIG_FILE), configFile); + Files.copy(getJarFile(OLD_CONFIG_FILE).toPath(), configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); PropertyResource resource = new YamlFileResource(configFile); TestMigrationServiceExtension migrationService = new TestMigrationServiceExtension(dataFolder); ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData(); @@ -103,7 +104,7 @@ public void shouldKeepOldOtherAccountsSettings() throws IOException { // given File dataFolder = temporaryFolder.newFolder(); File configFile = new File(dataFolder, "config.yml"); - Files.copy(getJarFile(OLD_CONFIG_FILE), configFile); + Files.copy(getJarFile(OLD_CONFIG_FILE).toPath(), configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); PropertyResource resource = new YamlFileResource(configFile); SettingsMigrationService migrationService = new SettingsMigrationService(dataFolder); @@ -132,14 +133,14 @@ private void verifyHasUpToDateSettings(Settings settings, File dataFolder) throw assertThat(settings.getProperty(MYSQL_COL_SALT), equalTo("salt_col_name")); // Check migration of old setting to email.html - assertThat(Files.readLines(new File(dataFolder, "email.html"), StandardCharsets.UTF_8), + assertThat(Files.readAllLines(new File(dataFolder, "email.html").toPath(), StandardCharsets.UTF_8), contains("Dear ,

This is your new AuthMe password for the server " + "

:



Do not forget to " + "change password after login!
/changepassword newPassword")); } private static class TestMigrationServiceExtension extends SettingsMigrationService { - private List returnedValues = new ArrayList<>(); + private final List returnedValues = new ArrayList<>(); TestMigrationServiceExtension(@DataFolder File pluginFolder) { super(pluginFolder); diff --git a/src/test/java/fr/xephi/authme/settings/SettingsTest.java b/src/test/java/fr/xephi/authme/settings/SettingsTest.java index 73d3cc8d6..d9e2b6baf 100644 --- a/src/test/java/fr/xephi/authme/settings/SettingsTest.java +++ b/src/test/java/fr/xephi/authme/settings/SettingsTest.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Collections; @@ -52,7 +53,7 @@ public void shouldLoadEmailMessage() throws IOException { String emailMessage = "Sample email message\nThat's all!"; File emailFile = new File(testPluginFolder, "email.html"); createFile(emailFile); - Files.write(emailFile.toPath(), emailMessage.getBytes()); + Files.write(emailFile.toPath(), emailMessage.getBytes(StandardCharsets.UTF_8)); PropertyResource resource = mockPropertyResourceAndReader(); Settings settings = new Settings(testPluginFolder, resource, null, CONFIG_DATA); @@ -70,7 +71,7 @@ public void shouldLoadRecoveryCodeMessage() throws IOException { String emailMessage = "Your recovery code is %code."; File emailFile = new File(testPluginFolder, "recovery_code_email.html"); createFile(emailFile); - Files.write(emailFile.toPath(), emailMessage.getBytes()); + Files.write(emailFile.toPath(), emailMessage.getBytes(StandardCharsets.UTF_8)); PropertyResource resource = mockPropertyResourceAndReader(); Settings settings = new Settings(testPluginFolder, resource, null, CONFIG_DATA); @@ -88,7 +89,7 @@ public void shouldLoadVerificationMessage() throws IOException { String emailMessage = "Please verify your identity with ."; File emailFile = new File(testPluginFolder, "verification_code_email.html"); createFile(emailFile); - Files.write(emailFile.toPath(), emailMessage.getBytes()); + Files.write(emailFile.toPath(), emailMessage.getBytes(StandardCharsets.UTF_8)); PropertyResource resource = mockPropertyResourceAndReader(); Settings settings = new Settings(testPluginFolder, resource, null, CONFIG_DATA); diff --git a/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java b/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java index edd561925..1dbe0db24 100644 --- a/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java +++ b/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java @@ -3,7 +3,6 @@ import ch.jalu.injector.testing.BeforeInjecting; import ch.jalu.injector.testing.DelayedInjectionRunner; import ch.jalu.injector.testing.InjectDelayed; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.service.PluginHookService; @@ -19,6 +18,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -31,12 +32,14 @@ @RunWith(DelayedInjectionRunner.class) public class SpawnLoaderTest { + @SuppressWarnings("unused") @InjectDelayed private SpawnLoader spawnLoader; @Mock private Settings settings; + @SuppressWarnings("unused") @Mock private PluginHookService pluginHookService; @@ -52,7 +55,7 @@ public void setup() throws IOException { testFolder = temporaryFolder.newFolder(); File source = TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "settings/spawn-firstspawn.yml"); File destination = new File(testFolder, "spawn.yml"); - Files.copy(source, destination); + Files.copy(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); // Create a settings mock with default values given(settings.getProperty(RestrictionSettings.SPAWN_PRIORITY)) diff --git a/src/test/java/fr/xephi/authme/settings/WelcomeMessageConfigurationTest.java b/src/test/java/fr/xephi/authme/settings/WelcomeMessageConfigurationTest.java index 0be553d7b..37909476c 100644 --- a/src/test/java/fr/xephi/authme/settings/WelcomeMessageConfigurationTest.java +++ b/src/test/java/fr/xephi/authme/settings/WelcomeMessageConfigurationTest.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; import java.util.List; @@ -135,7 +136,7 @@ public void shouldApplyOtherReplacements() { private void setWelcomeMessageAndReload(String welcomeMessage) { try { - Files.write(welcomeFile.toPath(), welcomeMessage.getBytes()); + Files.write(welcomeFile.toPath(), welcomeMessage.getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { throw new IllegalStateException("Could not write to '" + welcomeFile + "'", e); } diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java index a42a83a37..ef492b7bc 100644 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java +++ b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.settings.commandconfig; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.service.BukkitServiceTestHelper; @@ -18,6 +17,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collections; @@ -49,6 +50,7 @@ public class CommandManagerTest { private BukkitService bukkitService; @Mock private GeoIpService geoIpService; + @SuppressWarnings("unused") @Mock private SettingsMigrationService settingsMigrationService; @@ -302,7 +304,7 @@ private void copyJarFileAsCommandsYml(String path) { File source = TestHelper.getJarFile(path); File destination = new File(testFolder, "commands.yml"); try { - Files.copy(source, destination); + Files.copy(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java index 800bcc052..de4b00009 100644 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java +++ b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandMigrationServiceTest.java @@ -18,6 +18,7 @@ import java.io.File; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -120,12 +121,14 @@ public void shouldMigrateOldOtherAccountsCommand() { resource.createReader(), configurationData); // then - Map onLoginCommands = configurationData.getValue(CommandSettingsHolder.COMMANDS).getOnLogin(); + CommandConfig commandConfig = configurationData.getValue(CommandSettingsHolder.COMMANDS); + Objects.requireNonNull(commandConfig); + Map onLoginCommands = commandConfig.getOnLogin(); assertThat(onLoginCommands, aMapWithSize(6)); // 5 in the file + the newly migrated on OnLoginCommand newCommand = getUnknownOnLoginCommand(onLoginCommands); assertThat(newCommand.getCommand(), equalTo("helpop %p (%ip) has other accounts!")); assertThat(newCommand.getExecutor(), equalTo(Executor.CONSOLE)); - assertThat(newCommand.getIfNumberOfAccountsAtLeast().get(), equalTo(3)); + assertThat(newCommand.getIfNumberOfAccountsAtLeast().orElse(null), equalTo(3)); assertThat(newCommand.getIfNumberOfAccountsLessThan().isPresent(), equalTo(false)); } diff --git a/src/test/java/fr/xephi/authme/util/FileUtilsTest.java b/src/test/java/fr/xephi/authme/util/FileUtilsTest.java index 36af67242..8983ccfbe 100644 --- a/src/test/java/fr/xephi/authme/util/FileUtilsTest.java +++ b/src/test/java/fr/xephi/authme/util/FileUtilsTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.util; -import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import org.junit.BeforeClass; import org.junit.Rule; @@ -9,6 +8,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.matchesPattern; @@ -39,7 +40,7 @@ public void shouldNotCopyFile() throws IOException { File file = new File(folder, "config.yml"); // purposely don't copy config.yml to verify that config.yml isn't copied by the method File emailJarFile = TestHelper.getJarFile("/email.html"); - Files.copy(emailJarFile, file); + Files.copy(emailJarFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); // when boolean result = FileUtils.copyFileFromResource(file, "config.yml"); @@ -83,7 +84,7 @@ public void shouldReturnFalseForInvalidJarFile() throws IOException { public void shouldReturnFalseForParentInvalidParentFolders() throws IOException { // given File folder = temporaryFolder.newFolder(); - new File(folder, "hello").createNewFile(); + FileUtils.createFileOrFail(new File(folder, "hello")); File fileToCreate = new File(folder, "hello/test"); // when @@ -127,6 +128,7 @@ public void shouldDeleteFile() throws IOException { assertThat(file.exists(), equalTo(false)); } + @SuppressWarnings("ConstantConditions") @Test public void shouldDoNothingForNullFile() { // given @@ -175,7 +177,7 @@ public void shouldReturnFalseOnDirectoryCreateFail() throws IOException { // given File root = temporaryFolder.newFolder(); File dirAsFile = new File(root, "file"); - dirAsFile.createNewFile(); + FileUtils.createFileOrFail(dirAsFile); // when boolean result = FileUtils.createDirectory(dirAsFile); diff --git a/src/test/java/fr/xephi/authme/util/StringUtilsTest.java b/src/test/java/fr/xephi/authme/util/StringUtilsTest.java index 39a3eb934..85aaa1541 100644 --- a/src/test/java/fr/xephi/authme/util/StringUtilsTest.java +++ b/src/test/java/fr/xephi/authme/util/StringUtilsTest.java @@ -39,6 +39,7 @@ public void shouldReturnFalseIfNoneFound() { assertThat(result, equalTo(false)); } + @SuppressWarnings("ConstantConditions") @Test public void shouldReturnFalseForNullString() { // given/when diff --git a/src/test/java/fr/xephi/authme/util/UtilsTest.java b/src/test/java/fr/xephi/authme/util/UtilsTest.java index 37d52163d..48de908f4 100644 --- a/src/test/java/fr/xephi/authme/util/UtilsTest.java +++ b/src/test/java/fr/xephi/authme/util/UtilsTest.java @@ -98,6 +98,7 @@ public void shouldNotSendToCommandSenderTwice() { verifyNoInteractions(sender); } + @SuppressWarnings("ConstantConditions") @Test public void shouldCheckIfCollectionIsEmpty() { // given @@ -140,6 +141,7 @@ public void shouldLogWarningAndNotSendToConsoleSender() { verifyNoInteractions(sender); } + @SuppressWarnings("ConstantConditions") @Test public void shouldLogWarningAndHandleNullCommandSender() { // given diff --git a/src/test/java/tools/dependencygraph/DrawDependency.java b/src/test/java/tools/dependencygraph/DrawDependency.java index 40a3b6b23..ff3f890d4 100644 --- a/src/test/java/tools/dependencygraph/DrawDependency.java +++ b/src/test/java/tools/dependencygraph/DrawDependency.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; @@ -93,7 +94,7 @@ public void execute(Scanner scanner) { // Write dot file try { - Files.write(Paths.get(DOT_FILE), ("digraph G {\n" + dotFile + "\n}").getBytes()); + Files.write(Paths.get(DOT_FILE), ("digraph G {\n" + dotFile + "\n}").getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/src/test/java/tools/helptranslation/HelpTranslationVerifier.java b/src/test/java/tools/helptranslation/HelpTranslationVerifier.java index 08a446ded..fc35142ed 100644 --- a/src/test/java/tools/helptranslation/HelpTranslationVerifier.java +++ b/src/test/java/tools/helptranslation/HelpTranslationVerifier.java @@ -17,6 +17,7 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -150,6 +151,7 @@ private Set getLeafKeys(String path) { return Collections.emptySet(); } MemorySection memorySection = (MemorySection) configuration.get(path); + Objects.requireNonNull(memorySection); // MemorySection#getKeys(true) returns all keys on all levels, e.g. if the configuration has // 'commands.authme.register' then it also has 'commands.authme' and 'commands'. We can traverse each node and diff --git a/src/test/java/tools/messages/AddJavaDocToMessageEnumTask.java b/src/test/java/tools/messages/AddJavaDocToMessageEnumTask.java index 383a3e965..50cf269d8 100644 --- a/src/test/java/tools/messages/AddJavaDocToMessageEnumTask.java +++ b/src/test/java/tools/messages/AddJavaDocToMessageEnumTask.java @@ -10,6 +10,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Task to add English messages as javadoc comment to each MessageKey enum entry. @@ -44,7 +45,7 @@ public String getTaskName() { } private String getMessageForJavaDoc(MessageKey key) { - return configuration.getString(key.getKey()) + return Objects.requireNonNull(configuration.getString(key.getKey())) .replaceAll("&[0-9a-f]", "") .replace("&", "&") .replace("<", "<") diff --git a/src/test/java/tools/messages/CheckMessageKeyUsages.java b/src/test/java/tools/messages/CheckMessageKeyUsages.java index 7387f0023..12067d19e 100644 --- a/src/test/java/tools/messages/CheckMessageKeyUsages.java +++ b/src/test/java/tools/messages/CheckMessageKeyUsages.java @@ -1,6 +1,5 @@ package tools.messages; -import com.google.common.collect.Lists; import fr.xephi.authme.message.MessageKey; import tools.utils.AutoToolTask; import tools.utils.FileIoUtils; @@ -9,8 +8,10 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.stream.Collectors; import static java.util.Arrays.asList; @@ -33,8 +34,11 @@ public void executeDefault() { if (unusedKeys.isEmpty()) { System.out.println("No unused MessageKey entries found :)"); } else { - System.out.println("Did not find usages for keys:\n- " - + String.join("\n- ", Lists.transform(unusedKeys, MessageKey::name))); + System.out.println("Did not find usages for keys:\n- " + unusedKeys.stream() + .filter(Objects::nonNull) + .map(Enum::name) + .collect(Collectors.joining("\n- ")) + ); } } diff --git a/src/test/java/tools/utils/FileIoUtils.java b/src/test/java/tools/utils/FileIoUtils.java index 995c71a01..54377a2fc 100644 --- a/src/test/java/tools/utils/FileIoUtils.java +++ b/src/test/java/tools/utils/FileIoUtils.java @@ -35,7 +35,7 @@ public static void writeToFile(String outputFile, String contents) { */ public static void writeToFile(Path path, String contents) { try { - Files.write(path, contents.getBytes()); + Files.write(path, contents.getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { throw new UnsupportedOperationException("Failed to write to file '" + path + "'", e); } @@ -49,7 +49,7 @@ public static void writeToFile(Path path, String contents) { */ public static void appendToFile(String outputFile, String contents) { try { - Files.write(Paths.get(outputFile), contents.getBytes(), StandardOpenOption.APPEND); + Files.write(Paths.get(outputFile), contents.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); } catch (IOException e) { throw new UnsupportedOperationException("Failed to append to file '" + outputFile + "'", e); } diff --git a/src/test/resources/simplelogger.properties b/src/test/resources/simplelogger.properties index 56bab2197..d61e702eb 100644 --- a/src/test/resources/simplelogger.properties +++ b/src/test/resources/simplelogger.properties @@ -1,2 +1,3 @@ +# suppress inspection "UnusedProperty" for whole file # Suppress INFO statements when a new Hikari pool is being created org.slf4j.simpleLogger.log.com.zaxxer.hikari=WARN From 5271e76b75b56c6aaa2b642fefd1f025a1eff350 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sat, 27 Jun 2020 03:45:11 +0200 Subject: [PATCH 2/4] Cleanup (2/?) --- .idea/misc.xml | 3 ++- .../persistence/DistributedFilesPersistenceHandlerTest.java | 2 -- src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java | 2 -- .../authme/settings/commandconfig/CommandManagerTest.java | 3 ++- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index b45dc4b5c..b9cd73845 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,9 +1,10 @@ - + + diff --git a/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java b/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java index d4ef8e01d..bd55d5cd4 100644 --- a/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java +++ b/src/test/java/fr/xephi/authme/data/limbo/persistence/DistributedFilesPersistenceHandlerTest.java @@ -74,8 +74,6 @@ public class DistributedFilesPersistenceHandlerTest { /** UUID for which no data is stored (belongs to an existing segment file: seg16-8). */ private static final UUID UNKNOWN_UUID2 = fromString("84d1cc0b-8f12-d04a-e7ba-a067d05cdc39"); - - @SuppressWarnings("unused") @InjectDelayed private DistributedFilesPersistenceHandler persistenceHandler; diff --git a/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java b/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java index 1dbe0db24..dbec4e444 100644 --- a/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java +++ b/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java @@ -32,14 +32,12 @@ @RunWith(DelayedInjectionRunner.class) public class SpawnLoaderTest { - @SuppressWarnings("unused") @InjectDelayed private SpawnLoader spawnLoader; @Mock private Settings settings; - @SuppressWarnings("unused") @Mock private PluginHookService pluginHookService; diff --git a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java index ef492b7bc..0731b486b 100644 --- a/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java +++ b/src/test/java/fr/xephi/authme/settings/commandconfig/CommandManagerTest.java @@ -48,9 +48,10 @@ public class CommandManagerTest { @Mock private BukkitService bukkitService; + @Mock private GeoIpService geoIpService; - @SuppressWarnings("unused") + @Mock private SettingsMigrationService settingsMigrationService; From 5a37643562a7b15d5b27a901ae498512a266e2bc Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sat, 27 Jun 2020 03:52:54 +0200 Subject: [PATCH 3/4] Codestyle cleanup (codeclimate) --- .../xephi/authme/command/executable/authme/PurgeCommand.java | 1 - src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java | 5 +++++ src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java | 1 - .../java/fr/xephi/authme/security/crypts/Pbkdf2Django.java | 1 - src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java | 1 - .../fr/xephi/authme/security/totp/TotpAuthenticator.java | 1 - .../fr/xephi/authme/service/HelpTranslationGenerator.java | 3 ++- .../java/fr/xephi/authme/util/lazytags/DependentTag.java | 2 +- 8 files changed, 8 insertions(+), 7 deletions(-) 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 edc86a1de..735a9fd8a 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,6 +1,5 @@ package fr.xephi.authme.command.executable.authme; -import com.google.common.primitives.Ints; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.task.purge.PurgeService; import org.bukkit.ChatColor; diff --git a/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java b/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java index 916ff7347..661d2ba62 100644 --- a/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java +++ b/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java @@ -73,6 +73,11 @@ public int getGroupId() { return groupId; } + /** + * Sets the player's auth quit location. + * + * @param location the quit location + */ public void setQuitLocation(Location location) { Objects.requireNonNull(location.getWorld(), "world not loaded!"); x = location.getBlockX(); diff --git a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java index 7c007d044..d8cc5b6b2 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java @@ -1,6 +1,5 @@ package fr.xephi.authme.security.crypts; -import com.google.common.primitives.Ints; import de.rtner.misc.BinTools; import de.rtner.security.auth.spi.PBKDF2Engine; import de.rtner.security.auth.spi.PBKDF2Parameters; diff --git a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java index 50e3ec8fc..87cc70da8 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java @@ -1,6 +1,5 @@ package fr.xephi.authme.security.crypts; -import com.google.common.primitives.Ints; import de.rtner.security.auth.spi.PBKDF2Engine; import de.rtner.security.auth.spi.PBKDF2Parameters; import fr.xephi.authme.ConsoleLogger; diff --git a/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java b/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java index 4859e49c3..25124421b 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java +++ b/src/main/java/fr/xephi/authme/security/crypts/PhpFusion.java @@ -8,7 +8,6 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; diff --git a/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java b/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java index 434473171..4d96bb042 100644 --- a/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java +++ b/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java @@ -2,7 +2,6 @@ import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; -import com.google.common.primitives.Ints; import com.warrenstrange.googleauth.GoogleAuthenticator; import com.warrenstrange.googleauth.GoogleAuthenticatorKey; import com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator; diff --git a/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java b/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java index 893e7e411..4f1c8fb07 100644 --- a/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java +++ b/src/main/java/fr/xephi/authme/service/HelpTranslationGenerator.java @@ -55,7 +55,8 @@ public File updateHelpFile() throws IOException { Map helpEntries = generateHelpMessageEntries(); String helpEntriesYaml = exportToYaml(helpEntries); - Files.write(helpFile.toPath(), helpEntriesYaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING); + Files.write(helpFile.toPath(), helpEntriesYaml.getBytes(StandardCharsets.UTF_8), + StandardOpenOption.TRUNCATE_EXISTING); return helpFile; } diff --git a/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java b/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java index bad772989..f9fc8bce2 100644 --- a/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java +++ b/src/main/java/fr/xephi/authme/util/lazytags/DependentTag.java @@ -22,7 +22,7 @@ public class DependentTag
implements Tag { * @param name the tag (placeholder) that will be replaced * @param replacementFunction the function producing the replacement */ - public DependentTag(@NotNull String name,@NotNull Function replacementFunction) { + public DependentTag(@NotNull String name, @NotNull Function replacementFunction) { this.name = name; this.replacementFunction = replacementFunction; } From dc9ba02607cea33d543f69acc32060ba53bb1815 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sat, 27 Jun 2020 21:42:10 +0200 Subject: [PATCH 4/4] Cleanup (3/?) --- .../java/fr/xephi/authme/ConsoleLogger.java | 59 ++++++---- .../executable/authme/PurgeCommand.java | 7 +- .../executable/authme/ReloadCommand.java | 5 +- .../AbstractDataSourceConverter.java | 9 +- .../converter/LoginSecurityConverter.java | 7 +- .../converter/RakamakConverter.java | 2 +- .../xephi/authme/listener/OnJoinVerifier.java | 5 +- .../xephi/authme/security/crypts/Pbkdf2.java | 7 +- .../authme/security/crypts/Pbkdf2Django.java | 7 +- .../authme/security/crypts/TwoFactor.java | 7 +- .../security/totp/TotpAuthenticator.java | 8 +- .../xephi/authme/service/BackupService.java | 9 +- .../xephi/authme/service/BukkitService.java | 11 +- .../authme/service/ValidationService.java | 6 +- .../xephi/authme/settings/SettingsWarner.java | 6 +- .../fr/xephi/authme/settings/SpawnLoader.java | 20 ++-- .../settings/WelcomeMessageConfiguration.java | 5 +- .../fr/xephi/authme/task/MessageTask.java | 5 +- .../fr/xephi/authme/task/TimeoutTask.java | 7 +- .../authme/task/purge/PurgeExecutor.java | 16 +-- .../xephi/authme/task/purge/PurgeService.java | 12 +- .../fr/xephi/authme/task/purge/PurgeTask.java | 13 ++- src/main/java/fr/xephi/authme/util/Utils.java | 59 ++++------ .../xephi/authme/ClassesConsistencyTest.java | 3 +- .../fr/xephi/authme/ConsoleLoggerTest.java | 106 ++++++++++++++++++ .../authme/settings/SettingsWarnerTest.java | 4 +- .../java/fr/xephi/authme/util/UtilsTest.java | 93 +-------------- .../tools/dependencygraph/DrawDependency.java | 8 +- 28 files changed, 271 insertions(+), 235 deletions(-) diff --git a/src/main/java/fr/xephi/authme/ConsoleLogger.java b/src/main/java/fr/xephi/authme/ConsoleLogger.java index ed78f002f..afdb8f4a1 100644 --- a/src/main/java/fr/xephi/authme/ConsoleLogger.java +++ b/src/main/java/fr/xephi/authme/ConsoleLogger.java @@ -5,6 +5,9 @@ import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.util.ExceptionUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; import org.jetbrains.annotations.NotNull; import java.io.Closeable; @@ -109,11 +112,7 @@ public String getName() { * @param message The message to log */ public void warning(@NotNull String message) { - if (logger != null) { - logger.warning(message); - } else { - System.err.println("[WARN] " + message); - } + logger.warning(message); writeLog("[WARN] " + message); } @@ -135,11 +134,7 @@ public void logException(@NotNull String message, @NotNull Throwable th) { * @param message The message to log */ public void info(@NotNull String message) { - if (logger != null) { - logger.info(message); - } else { - System.out.println("[INFO] " + message); - } + logger.info(message); writeLog("[INFO] " + message); } @@ -153,15 +148,43 @@ public void info(@NotNull String message) { */ public void fine(@NotNull String message) { if (logLevel.includes(LogLevel.FINE)) { - if (logger != null) { - logger.info(message); - } else { - System.err.println("[FINE] " + message); - } + logger.info(message); writeLog("[FINE] " + message); } } + /** + * Sends a message to the given sender (null safe), and logs the message to the console. + * This method is aware that the command sender might be the console sender and avoids + * displaying the message twice in this case. + * + * @param sender the sender to inform + * @param message the message to log and send + */ + public void logAndSendMessage(CommandSender sender, @NotNull String message) { + info(message); + // Make sure sender is not console user, which will see the message from ConsoleLogger already + if (sender != null && !(sender instanceof ConsoleCommandSender)) { + sender.sendMessage(message); + } + } + + /** + * Sends a warning to the given sender (null safe), and logs the warning to the console. + * This method is aware that the command sender might be the console sender and avoids + * displaying the message twice in this case. + * + * @param sender the sender to inform + * @param message the warning to log and send + */ + public void logAndSendWarning(CommandSender sender, @NotNull String message) { + warning(message); + // Make sure sender is not console user, which will see the message from ConsoleLogger already + if (sender != null && !(sender instanceof ConsoleCommandSender)) { + sender.sendMessage(ChatColor.RED + message); + } + } + // -------- // Debug log methods // -------- @@ -232,11 +255,7 @@ public void debug(@NotNull Supplier msgSupplier) { private void logAndWriteWithDebugPrefix(@NotNull String message) { String debugMessage = "[DEBUG] " + message; - if (logger != null) { - logger.info(debugMessage); - } else { - System.err.println(debugMessage); - } + logger.info(debugMessage); writeLog(debugMessage); } 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 735a9fd8a..d77e4fcb5 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 @@ -2,6 +2,7 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.task.purge.PurgeService; +import fr.xephi.authme.util.Utils; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -26,10 +27,8 @@ public void executeCommand(CommandSender sender, List arguments) { String daysStr = arguments.get(0); // Convert the days string to an integer value, and make sure it's valid - int days; - try { - days = Integer.parseInt(daysStr); - } catch (NumberFormatException e) { + Integer days = Utils.tryInteger(daysStr); + if (days == null) { sender.sendMessage(ChatColor.RED + "The value you've entered is invalid!"); return; } 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 84de195c5..9ae7fda80 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 @@ -56,7 +56,7 @@ public void executeCommand(CommandSender sender, List arguments) { // 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())) { - Utils.logAndSendMessage(sender, "Note: cannot change database type during /authme reload"); + logger.logAndSendMessage(sender, "Note: cannot change database type during /authme reload"); } performReloadOnServices(); commonService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS); @@ -69,9 +69,10 @@ public void executeCommand(CommandSender sender, List arguments) { private void performReloadOnServices() { reloadableStore.retrieveAllOfType() - .forEach(r -> r.reload()); + .forEach(Reloadable::reload); settingsDependentStore.retrieveAllOfType() .forEach(s -> s.reload(settings)); } + } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java index fdced2fa4..1e898f530 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java @@ -10,8 +10,6 @@ import java.util.ArrayList; import java.util.List; -import static fr.xephi.authme.util.Utils.logAndSendMessage; - /** * Converts from one AuthMe data source type to another. * @@ -53,7 +51,7 @@ public void execute(CommandSender sender) { try { source = getSource(); } catch (Exception e) { - logAndSendMessage(sender, "The data source to convert from could not be initialized"); + logger.logAndSendMessage(sender, "The data source to convert from could not be initialized"); logger.logException("Could not initialize source:", e); return; } @@ -70,10 +68,10 @@ public void execute(CommandSender sender) { } if (!skippedPlayers.isEmpty()) { - logAndSendMessage(sender, "Skipped conversion for players which were already in " + logger.logAndSendMessage(sender, "Skipped conversion for players which were already in " + destinationType + ": " + String.join(", ", skippedPlayers)); } - logAndSendMessage(sender, "Database successfully converted from " + source.getType() + logger.logAndSendMessage(sender, "Database successfully converted from " + source.getType() + " to " + destinationType); } @@ -82,4 +80,5 @@ public void execute(CommandSender sender) { * @throws Exception during initialization of source */ protected abstract S getSource() throws Exception; + } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java index 5f74ec1e8..04789b1f7 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java @@ -25,8 +25,6 @@ import java.util.Optional; import java.util.UUID; -import static fr.xephi.authme.util.Utils.logAndSendMessage; - /** * Converts data from LoginSecurity to AuthMe. */ @@ -104,9 +102,9 @@ private void migrateData(CommandSender sender, ResultSet resultSet) throws SQLEx } } - logAndSendMessage(sender, "Migrated " + successfulSaves + " accounts successfully from LoginSecurity"); + logger.logAndSendMessage(sender, "Migrated " + successfulSaves + " accounts successfully from LoginSecurity"); if (!skippedPlayers.isEmpty()) { - logAndSendMessage(sender, "Skipped conversion for players which were already in AuthMe: " + logger.logAndSendMessage(sender, "Skipped conversion for players which were already in AuthMe: " + String.join(", ", skippedPlayers)); } } @@ -205,4 +203,5 @@ private Connection createMySqlConnection() { return null; } } + } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java index b69fe688d..38631eb19 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java @@ -88,7 +88,7 @@ public void execute(CommandSender sender) { database.saveAuth(auth); database.updateSession(auth); } - Utils.logAndSendMessage(sender, "Rakamak database has been imported successfully"); + logger.logAndSendMessage(sender, "Rakamak database has been imported successfully"); } catch (IOException ex) { logger.logException("Can't open the rakamak database file! Does it exist?", ex); } diff --git a/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java b/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java index ce61b8f2b..249c3f4fe 100644 --- a/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java +++ b/src/main/java/fr/xephi/authme/listener/OnJoinVerifier.java @@ -61,7 +61,10 @@ public class OnJoinVerifier implements Reloadable { @Override public void reload() { String nickRegEx = settings.getProperty(RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS); - nicknamePattern = Utils.safePatternCompile(nickRegEx); + nicknamePattern = Utils.safePatternCompile(nickRegEx, patternString -> { + logger.warning("Failed to compile pattern '" + patternString + "' - defaulting to allowing everything"); + return Utils.MATCH_ANYTHING_PATTERN; + }); } /** diff --git a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java index d8cc5b6b2..09f3db140 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java @@ -9,6 +9,7 @@ import fr.xephi.authme.security.crypts.description.Usage; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.SecuritySettings; +import fr.xephi.authme.util.Utils; import javax.inject.Inject; @@ -41,10 +42,8 @@ public boolean comparePassword(String password, HashedPassword hashedPassword, S return false; } - int iterations; - try { - iterations = Integer.parseInt(line[1]); - } catch (NumberFormatException e) { + Integer iterations = Utils.tryInteger(line[1]); + if (iterations == null) { logger.warning("Cannot read number of rounds for Pbkdf2: '" + line[1] + "'"); return false; } diff --git a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java index 87cc70da8..d48367e52 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java @@ -5,6 +5,7 @@ import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.security.crypts.description.AsciiRestricted; +import fr.xephi.authme.util.Utils; import java.util.Base64; @@ -30,10 +31,8 @@ public boolean comparePassword(String password, HashedPassword hashedPassword, S return false; } - int iterations; - try { - iterations = Integer.parseInt(line[1]); - } catch (NumberFormatException e) { + Integer iterations = Utils.tryInteger(line[1]); + if (iterations == null) { logger.warning("Cannot read number of rounds for Pbkdf2Django: '" + line[1] + "'"); return false; } diff --git a/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java b/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java index 60cfa493c..03dfc5fde 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java +++ b/src/main/java/fr/xephi/authme/security/crypts/TwoFactor.java @@ -7,6 +7,7 @@ import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.SaltType; import fr.xephi.authme.security.crypts.description.Usage; +import fr.xephi.authme.util.Utils; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -88,10 +89,8 @@ public boolean comparePassword(String password, HashedPassword hashedPassword, S private boolean checkPassword(String secretKey, String userInput) throws NoSuchAlgorithmException, InvalidKeyException { - int code; - try { - code = Integer.parseInt(userInput); - } catch (NumberFormatException e) { + Integer code = Utils.tryInteger(userInput); + if (code == null) { //code is not an integer return false; } diff --git a/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java b/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java index 4d96bb042..bdafdf6c4 100644 --- a/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java +++ b/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java @@ -10,6 +10,7 @@ import fr.xephi.authme.initialization.HasCleanup; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; +import fr.xephi.authme.util.Utils; import org.bukkit.entity.Player; import javax.inject.Inject; @@ -54,12 +55,7 @@ public boolean checkCode(PlayerAuth auth, String totpCode) { */ public boolean checkCode(String playerName, String totpKey, String inputCode) { String nameLower = playerName.toLowerCase(); - Integer totpCode; - try { - totpCode = Integer.parseInt(inputCode); - } catch (NumberFormatException e) { - totpCode = null; - } + Integer totpCode = Utils.tryInteger(inputCode); if (totpCode != null && !usedCodes.contains(nameLower, totpCode) && authenticator.authorize(totpKey, totpCode)) { usedCodes.put(nameLower, totpCode, System.currentTimeMillis()); diff --git a/src/main/java/fr/xephi/authme/service/BackupService.java b/src/main/java/fr/xephi/authme/service/BackupService.java index 2e72a7b0c..e7ecca408 100644 --- a/src/main/java/fr/xephi/authme/service/BackupService.java +++ b/src/main/java/fr/xephi/authme/service/BackupService.java @@ -19,9 +19,6 @@ import java.io.InputStream; import java.io.OutputStream; -import static fr.xephi.authme.util.Utils.logAndSendMessage; -import static fr.xephi.authme.util.Utils.logAndSendWarning; - /** * Performs a backup of the data source. */ @@ -66,7 +63,7 @@ public void doBackup(BackupCause cause, CommandSender sender) { if (!settings.getProperty(BackupSettings.ENABLED)) { // Print a warning if the backup was requested via command or by another plugin if (cause == BackupCause.COMMAND || cause == BackupCause.OTHER) { - logAndSendWarning(sender, + logger.logAndSendWarning(sender, "Can't perform a backup: disabled in configuration. Cause of the backup: " + cause.name()); } return; @@ -78,10 +75,10 @@ public void doBackup(BackupCause cause, CommandSender sender) { // Do backup and check return value! if (doBackup()) { - logAndSendMessage(sender, + logger.logAndSendMessage(sender, "A backup has been performed successfully. Cause of the backup: " + cause.name()); } else { - logAndSendWarning(sender, "Error while performing a backup! Cause of the backup: " + cause.name()); + logger.logAndSendWarning(sender, "Error while performing a backup! Cause of the backup: " + cause.name()); } } diff --git a/src/main/java/fr/xephi/authme/service/BukkitService.java b/src/main/java/fr/xephi/authme/service/BukkitService.java index a6af581ab..97b48cfac 100644 --- a/src/main/java/fr/xephi/authme/service/BukkitService.java +++ b/src/main/java/fr/xephi/authme/service/BukkitService.java @@ -328,17 +328,16 @@ public BanEntry banIp(String ip, String reason, Date expires, String source) { } /** - * Returns an optional with a boolean indicating whether bungeecord is enabled or not if the - * server implementation is Spigot. Otherwise returns an empty optional. + * Returns a boolean indicating whether bungeecord support is enabled or not. * - * @return Optional with configuration value for Spigot, empty optional otherwise + * @return boolean with configuration value for Spigot */ - public Optional isBungeeCordConfiguredForSpigot() { + public boolean isBungeeCordConfiguredForSpigot() { try { YamlConfiguration spigotConfig = Bukkit.spigot().getConfig(); - return Optional.of(spigotConfig.getBoolean("settings.bungeecord")); + return spigotConfig.getBoolean("settings.bungeecord"); } catch (NoSuchMethodError e) { - return Optional.empty(); + return false; } } diff --git a/src/main/java/fr/xephi/authme/service/ValidationService.java b/src/main/java/fr/xephi/authme/service/ValidationService.java index 1380f08f5..e6be431bd 100644 --- a/src/main/java/fr/xephi/authme/service/ValidationService.java +++ b/src/main/java/fr/xephi/authme/service/ValidationService.java @@ -56,7 +56,11 @@ public class ValidationService implements Reloadable { @PostConstruct @Override public void reload() { - passwordRegex = Utils.safePatternCompile(settings.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX)); + passwordRegex = Utils.safePatternCompile(settings.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX), + patternString -> { + logger.warning("Failed to compile pattern '" + patternString + "' - defaulting to allowing everything"); + return Utils.MATCH_ANYTHING_PATTERN; + }); restrictedNames = settings.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS) ? loadNameRestrictions(settings.getProperty(RestrictionSettings.RESTRICTED_USERS)) : HashMultimap.create(); diff --git a/src/main/java/fr/xephi/authme/settings/SettingsWarner.java b/src/main/java/fr/xephi/authme/settings/SettingsWarner.java index c51bdf6b3..c7cabd57f 100644 --- a/src/main/java/fr/xephi/authme/settings/SettingsWarner.java +++ b/src/main/java/fr/xephi/authme/settings/SettingsWarner.java @@ -13,7 +13,6 @@ import fr.xephi.authme.settings.properties.SecuritySettings; import javax.inject.Inject; -import java.util.Optional; /** * Logs warning messages in cases where the configured values suggest a misconfiguration. @@ -60,7 +59,7 @@ public void logWarningsForMisconfigurations() { } // Warn if spigot.yml has settings.bungeecord set to true but config.yml has Hooks.bungeecord set to false - if (isTrue(bukkitService.isBungeeCordConfiguredForSpigot()) + if (bukkitService.isBungeeCordConfiguredForSpigot() && !settings.getProperty(HooksSettings.BUNGEECORD)) { logger.warning("Note: Hooks.bungeecord is set to false but your server appears to be running in" + " bungeecord mode (see your spigot.yml). In order to allow the datasource caching and the" @@ -76,7 +75,4 @@ public void logWarningsForMisconfigurations() { } } - private static boolean isTrue(Optional value) { - return value.isPresent() && value.get(); - } } diff --git a/src/main/java/fr/xephi/authme/settings/SpawnLoader.java b/src/main/java/fr/xephi/authme/settings/SpawnLoader.java index ff39efa31..b9dcf1669 100644 --- a/src/main/java/fr/xephi/authme/settings/SpawnLoader.java +++ b/src/main/java/fr/xephi/authme/settings/SpawnLoader.java @@ -15,6 +15,7 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import javax.inject.Inject; import java.io.File; @@ -229,7 +230,7 @@ public Location getSpawnLocation(Player player) { * * @return True upon success, false otherwise */ - private boolean isValidSpawnPoint(Location location) { + private boolean isValidSpawnPoint(@NotNull Location location) { return location.getX() != 0 || location.getY() != 0 || location.getZ() != 0; } @@ -241,7 +242,7 @@ private boolean isValidSpawnPoint(Location location) { * * @return True upon success, false otherwise */ - private boolean setLocation(String prefix, Location location) { + private boolean setLocation(@NotNull String prefix, Location location) { if (location != null && location.getWorld() != null) { authMeConfiguration.set(prefix + ".world", location.getWorld().getName()); authMeConfiguration.set(prefix + ".x", location.getX()); @@ -271,7 +272,7 @@ private boolean saveAuthMeConfig() { * * @return location of the given player if alive, spawn location if dead. */ - public Location getPlayerLocationOrSpawn(Player player) { + public Location getPlayerLocationOrSpawn(@NotNull Player player) { if (player.isOnline() && player.isDead()) { return getSpawnLocation(player); } @@ -286,7 +287,8 @@ public Location getPlayerLocationOrSpawn(Player player) { * * @return Location corresponding to the values in the path */ - private static Location getLocationFromConfiguration(FileConfiguration configuration, String pathPrefix) { + private static Location getLocationFromConfiguration(@NotNull FileConfiguration configuration, + @NotNull String pathPrefix) { if (containsAllSpawnFields(configuration, pathPrefix)) { String prefix = pathPrefix + "."; String worldName = Objects.requireNonNull(configuration.getString(prefix + "world")); @@ -307,7 +309,7 @@ private static Location getLocationFromConfiguration(FileConfiguration configura * * @return Location corresponding to the values in the path */ - private static Location getLocationFromCmiConfiguration(FileConfiguration configuration) { + private static Location getLocationFromCmiConfiguration(@NotNull FileConfiguration configuration) { final String pathPrefix = "Spawn.Main"; if (isLocationCompleteInCmiConfig(configuration, pathPrefix)) { String prefix = pathPrefix + "."; @@ -331,7 +333,8 @@ private static Location getLocationFromCmiConfiguration(FileConfiguration config * * @return True if all spawn fields are present, false otherwise */ - private static boolean containsAllSpawnFields(FileConfiguration configuration, String pathPrefix) { + private static boolean containsAllSpawnFields(@NotNull FileConfiguration configuration, + @NotNull String pathPrefix) { String[] fields = {"world", "x", "y", "z", "yaw", "pitch"}; for (String field : fields) { if (!configuration.contains(pathPrefix + "." + field)) { @@ -349,7 +352,8 @@ private static boolean containsAllSpawnFields(FileConfiguration configuration, S * * @return True if all spawn fields are present, false otherwise */ - private static boolean isLocationCompleteInCmiConfig(FileConfiguration cmiConfiguration, String pathPrefix) { + private static boolean isLocationCompleteInCmiConfig(@NotNull FileConfiguration cmiConfiguration, + @NotNull String pathPrefix) { String[] fields = {"World", "X", "Y", "Z", "Yaw", "Pitch"}; for (String field : fields) { if (!cmiConfiguration.contains(pathPrefix + "." + field)) { @@ -367,7 +371,7 @@ private static boolean isLocationCompleteInCmiConfig(FileConfiguration cmiConfig * * @return The float */ - private static float getFloat(FileConfiguration configuration, String path) { + private static float getFloat(@NotNull FileConfiguration configuration, @NotNull String path) { Object value = configuration.get(path); // This behavior is consistent with FileConfiguration#getDouble return (value instanceof Number) ? ((Number) value).floatValue() : 0; diff --git a/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java b/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java index 36cdff015..7cb46dd20 100644 --- a/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java +++ b/src/main/java/fr/xephi/authme/settings/WelcomeMessageConfiguration.java @@ -17,6 +17,7 @@ import org.bukkit.Server; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import javax.annotation.PostConstruct; import javax.inject.Inject; @@ -95,6 +96,7 @@ public void reload() { * @param player the player for whom the welcome message should be prepared * @return the welcome message */ + @NotNull public List getWelcomeMessage(Player player) { return messageSupplier.getAdaptedMessages(player); } @@ -104,7 +106,7 @@ public List getWelcomeMessage(Player player) { * * @param player the player for whom the welcome message should be prepared */ - public void sendWelcomeMessage(Player player) { + public void sendWelcomeMessage(@NotNull Player player) { if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) { List welcomeMessage = getWelcomeMessage(player); if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) { @@ -118,6 +120,7 @@ public void sendWelcomeMessage(Player player) { /** * @return the lines of the welcome message file */ + @NotNull private List readWelcomeFile() { if (!(service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE))) { return Collections.emptyList(); diff --git a/src/main/java/fr/xephi/authme/task/MessageTask.java b/src/main/java/fr/xephi/authme/task/MessageTask.java index cf4366d9d..9607cdbe2 100644 --- a/src/main/java/fr/xephi/authme/task/MessageTask.java +++ b/src/main/java/fr/xephi/authme/task/MessageTask.java @@ -2,20 +2,23 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; /** * Message shown to a player in a regular interval as long as he is not logged in. */ public class MessageTask extends BukkitRunnable { + @NotNull private final Player player; + @NotNull private final String[] message; private boolean isMuted; /* * Constructor. */ - public MessageTask(Player player, String[] lines) { + public MessageTask(@NotNull Player player, @NotNull String[] lines) { this.player = player; this.message = lines; isMuted = false; diff --git a/src/main/java/fr/xephi/authme/task/TimeoutTask.java b/src/main/java/fr/xephi/authme/task/TimeoutTask.java index 60aac7414..f71a64d4b 100644 --- a/src/main/java/fr/xephi/authme/task/TimeoutTask.java +++ b/src/main/java/fr/xephi/authme/task/TimeoutTask.java @@ -2,14 +2,18 @@ import fr.xephi.authme.data.auth.PlayerCache; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; /** * Kicks a player if he hasn't logged in (scheduled to run after a configured delay). */ public class TimeoutTask implements Runnable { + @NotNull private final Player player; + @NotNull private final String message; + @NotNull private final PlayerCache playerCache; /** @@ -19,7 +23,7 @@ public class TimeoutTask implements Runnable { * @param message the kick message * @param playerCache player cache instance */ - public TimeoutTask(Player player, String message, PlayerCache playerCache) { + public TimeoutTask(@NotNull Player player, @NotNull String message, @NotNull PlayerCache playerCache) { this.message = message; this.player = player; this.playerCache = playerCache; @@ -31,4 +35,5 @@ public void run() { player.kickPlayer(message); } } + } diff --git a/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java b/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java index 399ff3985..247b433d4 100644 --- a/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java +++ b/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java @@ -11,6 +11,7 @@ import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.Server; +import org.jetbrains.annotations.NotNull; import javax.inject.Inject; import java.io.File; @@ -53,7 +54,7 @@ public class PurgeExecutor { * @param players the players to purge * @param names names to purge */ - public void executePurge(Collection players, Collection names) { + public void executePurge(@NotNull Collection players, @NotNull Collection names) { // Purge other data purgeFromAuthMe(names); purgeEssentials(players); @@ -68,7 +69,7 @@ public void executePurge(Collection players, Collection n * * @param cleared the players whose data should be cleared */ - synchronized void purgeAntiXray(Collection cleared) { + synchronized void purgeAntiXray(@NotNull Collection cleared) { if (!settings.getProperty(PurgeSettings.REMOVE_ANTI_XRAY_FILE)) { return; } @@ -96,7 +97,7 @@ synchronized void purgeAntiXray(Collection cleared) { * * @param names the name of the accounts to delete */ - synchronized void purgeFromAuthMe(Collection names) { + synchronized void purgeFromAuthMe(@NotNull Collection names) { dataSource.purgeRecords(names); //TODO ljacqu 20160717: We shouldn't output namedBanned.size() but the actual total that was deleted logger.info(ChatColor.GOLD + "Deleted " + names.size() + " user accounts"); @@ -107,7 +108,7 @@ synchronized void purgeFromAuthMe(Collection names) { * * @param cleared the players whose data should be cleared */ - synchronized void purgeLimitedCreative(Collection cleared) { + synchronized void purgeLimitedCreative(@NotNull Collection cleared) { if (!settings.getProperty(PurgeSettings.REMOVE_LIMITED_CREATIVE_INVENTORIES)) { return; } @@ -152,7 +153,7 @@ synchronized void purgeLimitedCreative(Collection cleared) { * * @param cleared list of players to clear */ - synchronized void purgeDat(Collection cleared) { + synchronized void purgeDat(@NotNull Collection cleared) { if (!settings.getProperty(PurgeSettings.REMOVE_PLAYER_DAT)) { return; } @@ -176,7 +177,7 @@ synchronized void purgeDat(Collection cleared) { * * @param cleared list of players to clear */ - synchronized void purgeEssentials(Collection cleared) { + synchronized void purgeEssentials(@NotNull Collection cleared) { if (!settings.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES)) { return; } @@ -208,7 +209,7 @@ synchronized void purgeEssentials(Collection cleared) { * * @param cleared the players to remove data for */ - synchronized void purgePermissions(Collection cleared) { + synchronized void purgePermissions(@NotNull Collection cleared) { if (!settings.getProperty(PurgeSettings.REMOVE_PERMISSIONS)) { return; } @@ -223,4 +224,5 @@ synchronized void purgePermissions(Collection cleared) { logger.info("AutoPurge: Removed permissions from " + cleared.size() + " player(s)."); } + } diff --git a/src/main/java/fr/xephi/authme/task/purge/PurgeService.java b/src/main/java/fr/xephi/authme/task/purge/PurgeService.java index 880d51185..4a12733e8 100644 --- a/src/main/java/fr/xephi/authme/task/purge/PurgeService.java +++ b/src/main/java/fr/xephi/authme/task/purge/PurgeService.java @@ -10,14 +10,13 @@ import fr.xephi.authme.util.Utils; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import javax.inject.Inject; import java.util.Calendar; import java.util.Collection; import java.util.Set; -import static fr.xephi.authme.util.Utils.logAndSendMessage; - /** * Initiates purge tasks. */ @@ -77,7 +76,7 @@ public void runPurge(CommandSender sender, long until) { //todo: note this should may run async because it may executes a SQL-Query Set toPurge = dataSource.getRecordsToPurge(until); if (Utils.isCollectionEmpty(toPurge)) { - logAndSendMessage(sender, "No players to purge"); + logger.logAndSendMessage(sender, "No players to purge"); return; } @@ -91,9 +90,9 @@ public void runPurge(CommandSender sender, long until) { * @param names The names to remove * @param players Collection of OfflinePlayers (including those with the given names) */ - public void purgePlayers(CommandSender sender, Set names, OfflinePlayer[] players) { + public void purgePlayers(CommandSender sender, @NotNull Set names, @NotNull OfflinePlayer[] players) { if (isPurging) { - logAndSendMessage(sender, "Purge is already in progress! Aborting purge request"); + logger.logAndSendMessage(sender, "Purge is already in progress! Aborting purge request"); return; } @@ -117,7 +116,8 @@ void setPurging(boolean purging) { * @param players the players (associated with the names) * @param names the lowercase names */ - void executePurge(Collection players, Collection names) { + void executePurge(@NotNull Collection players, @NotNull Collection names) { purgeExecutor.executePurge(players, names); } + } diff --git a/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java b/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java index f29d6f71d..4aabfad9c 100644 --- a/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java +++ b/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java @@ -10,6 +10,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.Set; @@ -21,11 +22,16 @@ class PurgeTask extends BukkitRunnable { private static final int INTERVAL_CHECK = 5; private final ConsoleLogger logger = ConsoleLoggerFactory.get(PurgeTask.class); + + @NotNull private final PurgeService purgeService; + @NotNull private final PermissionsManager permissionsManager; private final UUID sender; + @NotNull private final Set toPurge; + @NotNull private final OfflinePlayer[] offlinePlayers; private final int totalPurgeCount; @@ -40,8 +46,8 @@ class PurgeTask extends BukkitRunnable { * @param toPurge lowercase names to purge * @param offlinePlayers offline players to map to the names */ - PurgeTask(PurgeService service, PermissionsManager permissionsManager, CommandSender sender, - Set toPurge, OfflinePlayer[] offlinePlayers) { + PurgeTask(@NotNull PurgeService service, @NotNull PermissionsManager permissionsManager, CommandSender sender, + @NotNull Set toPurge, OfflinePlayer[] offlinePlayers) { this.purgeService = service; this.permissionsManager = permissionsManager; @@ -116,7 +122,7 @@ private void finish() { purgeService.setPurging(false); } - private void sendMessage(String message) { + private void sendMessage(@NotNull String message) { if (sender == null) { Bukkit.getConsoleSender().sendMessage(message); } else { @@ -126,4 +132,5 @@ private void sendMessage(String message) { } } } + } diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java index 3caadb5e8..fc58e42a8 100644 --- a/src/main/java/fr/xephi/authme/util/Utils.java +++ b/src/main/java/fr/xephi/authme/util/Utils.java @@ -8,6 +8,8 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.function.Function; +import java.util.function.Supplier; import java.util.regex.Pattern; /** @@ -18,7 +20,8 @@ public final class Utils { /** Number of milliseconds in a minute. */ public static final long MILLIS_PER_MINUTE = 60_000L; - private static final ConsoleLogger logger = ConsoleLoggerFactory.get(Utils.class); + /** A pattern that matches anything. */ + public static final Pattern MATCH_ANYTHING_PATTERN = Pattern.compile(".*?"); // Utility class private Utils() { @@ -27,17 +30,16 @@ private Utils() { /** * Compile Pattern sneaky without throwing Exception. * - * @param pattern pattern string to compile + * @param pattern pattern string to compile + * @param fallback the fallback pattern supplier * * @return the given regex compiled into Pattern object. */ - @NotNull - public static Pattern safePatternCompile(@NotNull String pattern) { + public static Pattern safePatternCompile(@NotNull String pattern, @NotNull Function fallback) { try { return Pattern.compile(pattern); } catch (Exception e) { - logger.warning("Failed to compile pattern '" + pattern + "' - defaulting to allowing everything"); - return Pattern.compile(".*?"); + return fallback.apply(pattern); } } @@ -57,38 +59,6 @@ public static boolean isClassLoaded(@NotNull String className) { } } - /** - * Sends a message to the given sender (null safe), and logs the message to the console. - * This method is aware that the command sender might be the console sender and avoids - * displaying the message twice in this case. - * - * @param sender the sender to inform - * @param message the message to log and send - */ - public static void logAndSendMessage(CommandSender sender, @NotNull String message) { - logger.info(message); - // Make sure sender is not console user, which will see the message from ConsoleLogger already - if (sender != null && !(sender instanceof ConsoleCommandSender)) { - sender.sendMessage(message); - } - } - - /** - * Sends a warning to the given sender (null safe), and logs the warning to the console. - * This method is aware that the command sender might be the console sender and avoids - * displaying the message twice in this case. - * - * @param sender the sender to inform - * @param message the warning to log and send - */ - public static void logAndSendWarning(CommandSender sender, @NotNull String message) { - logger.warning(message); - // Make sure sender is not console user, which will see the message from ConsoleLogger already - if (sender != null && !(sender instanceof ConsoleCommandSender)) { - sender.sendMessage(ChatColor.RED + message); - } - } - /** * Null-safe way to check whether a collection is empty or not. * @@ -110,4 +80,17 @@ public static boolean isEmailEmpty(String email) { return StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email); } + /** + * Tries to parse a String as an Integer, returns null on fail. + * + * @return the parsed Integer value + */ + public static Integer tryInteger(@NotNull String string) { + try { + return Integer.parseInt(string); + } catch (NumberFormatException e) { + return null; + } + } + } diff --git a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java index 919d1eeb1..e1e408747 100644 --- a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.hamcrest.Matchers.equalTo; @@ -52,7 +53,7 @@ public class ClassesConsistencyTest { private static final Set> IMMUTABLE_TYPES = ImmutableSet.of( /* JDK */ int.class, long.class, float.class, String.class, File.class, Enum.class, collectionsUnmodifiableList(), - Charset.class, + Charset.class, Pattern.class, /* AuthMe */ Property.class, RegistrationMethod.class, DataSourceColumn.class, PlayerAuthColumn.class, /* Guava */ diff --git a/src/test/java/fr/xephi/authme/ConsoleLoggerTest.java b/src/test/java/fr/xephi/authme/ConsoleLoggerTest.java index 3f334e471..e7d4b1c92 100644 --- a/src/test/java/fr/xephi/authme/ConsoleLoggerTest.java +++ b/src/test/java/fr/xephi/authme/ConsoleLoggerTest.java @@ -4,6 +4,10 @@ import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.SecuritySettings; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -35,6 +39,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; /** @@ -145,6 +150,7 @@ public void shouldLogStackTraceToFile() throws IOException { assertThat(String.join("", loggedLines), containsString(getClass().getCanonicalName())); } + @SuppressWarnings("unchecked") @Test public void shouldSupportVariousDebugMethods() throws IOException { // given @@ -205,6 +211,106 @@ public void shouldHandleExceptionOnFileWriterClose() throws IOException { assertThat(ReflectionTestUtils.getFieldValue(ConsoleLogger.class, null, "fileWriter"), nullValue()); } + @Test + public void shouldLogAndSendMessage() { + // given + Settings settings = newSettings(false, LogLevel.INFO); + ConsoleLogger.initializeSharedSettings(settings); + consoleLogger.initializeSettings(settings); + Player player = mock(Player.class); + String message = "Finished adding foo to the bar"; + + // when + consoleLogger.logAndSendMessage(player, message); + + // then + verify(logger).info(message); + verify(player).sendMessage(message); + } + + @Test + public void shouldHandleNullAsCommandSender() { + // given + Settings settings = newSettings(false, LogLevel.INFO); + ConsoleLogger.initializeSharedSettings(settings); + consoleLogger.initializeSettings(settings); + String message = "Test test, test."; + + // when + consoleLogger.logAndSendMessage(null, message); + + // then + verify(logger).info(message); + } + + @Test + public void shouldNotSendToCommandSenderTwice() { + // given + Settings settings = newSettings(false, LogLevel.INFO); + ConsoleLogger.initializeSharedSettings(settings); + consoleLogger.initializeSettings(settings); + CommandSender sender = mock(ConsoleCommandSender.class); + String message = "Test test, test."; + + // when + consoleLogger.logAndSendMessage(sender, message); + + // then + verify(logger).info(message); + verifyNoInteractions(sender); + } + + @Test + public void shouldLogAndSendWarning() { + // given + Settings settings = newSettings(false, LogLevel.INFO); + ConsoleLogger.initializeSharedSettings(settings); + consoleLogger.initializeSettings(settings); + String message = "Error while performing action"; + CommandSender sender = mock(CommandSender.class); + + // when + consoleLogger.logAndSendWarning(sender, message); + + // then + verify(logger).warning(message); + verify(sender).sendMessage(ChatColor.RED + message); + } + + @Test + public void shouldLogWarningAndNotSendToConsoleSender() { + // given + Settings settings = newSettings(false, LogLevel.INFO); + ConsoleLogger.initializeSharedSettings(settings); + consoleLogger.initializeSettings(settings); + String message = "Error while performing action"; + CommandSender sender = mock(ConsoleCommandSender.class); + + // when + consoleLogger.logAndSendWarning(sender, message); + + // then + verify(logger).warning(message); + verifyNoInteractions(sender); + } + + @SuppressWarnings("ConstantConditions") + @Test + public void shouldLogWarningAndHandleNullCommandSender() { + // given + Settings settings = newSettings(false, LogLevel.INFO); + ConsoleLogger.initializeSharedSettings(settings); + consoleLogger.initializeSettings(settings); + String message = "Error while performing action"; + CommandSender sender = null; + + // when + consoleLogger.logAndSendWarning(sender, message); + + // then + verify(logger).warning(message); + } + private static Settings newSettings(boolean logToFile, LogLevel logLevel) { Settings settings = mock(Settings.class); given(settings.getProperty(SecuritySettings.USE_LOGGING)).willReturn(logToFile); diff --git a/src/test/java/fr/xephi/authme/settings/SettingsWarnerTest.java b/src/test/java/fr/xephi/authme/settings/SettingsWarnerTest.java index cdf4f8ac1..a7e802f02 100644 --- a/src/test/java/fr/xephi/authme/settings/SettingsWarnerTest.java +++ b/src/test/java/fr/xephi/authme/settings/SettingsWarnerTest.java @@ -53,7 +53,7 @@ public void shouldLogWarnings() { given(settings.getProperty(PluginSettings.SESSIONS_TIMEOUT)).willReturn(-5); given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.BCRYPT); given(settings.getProperty(HooksSettings.BUNGEECORD)).willReturn(false); - given(bukkitService.isBungeeCordConfiguredForSpigot()).willReturn(Optional.of(true)); + given(bukkitService.isBungeeCordConfiguredForSpigot()).willReturn(true); // when settingsWarner.logWarningsForMisconfigurations(); @@ -70,7 +70,7 @@ public void shouldNotLogAnyWarning() { given(settings.getProperty(EmailSettings.PORT25_USE_TLS)).willReturn(false); given(settings.getProperty(PluginSettings.SESSIONS_ENABLED)).willReturn(false); given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.MD5); - given(bukkitService.isBungeeCordConfiguredForSpigot()).willReturn(Optional.empty()); + given(bukkitService.isBungeeCordConfiguredForSpigot()).willReturn(false); // when settingsWarner.logWarningsForMisconfigurations(); diff --git a/src/test/java/fr/xephi/authme/util/UtilsTest.java b/src/test/java/fr/xephi/authme/util/UtilsTest.java index 48de908f4..c601097da 100644 --- a/src/test/java/fr/xephi/authme/util/UtilsTest.java +++ b/src/test/java/fr/xephi/authme/util/UtilsTest.java @@ -37,7 +37,7 @@ public void shouldCompilePattern() { String pattern = "gr(a|e)ys?"; // when - Pattern result = Utils.safePatternCompile(pattern); + Pattern result = Utils.safePatternCompile(pattern, patternString -> null); // then assertThat(result.toString(), equalTo(pattern)); @@ -49,55 +49,12 @@ public void shouldDefaultToAllAllowedPattern() { String invalidPattern = "gr(a|eys?"; // missing closing ')' // when - Pattern result = Utils.safePatternCompile(invalidPattern); + Pattern result = Utils.safePatternCompile(invalidPattern, patternString -> Utils.MATCH_ANYTHING_PATTERN); // then assertThat(result.toString(), equalTo(".*?")); } - @Test - public void shouldLogAndSendMessage() { - // given - Logger logger = TestHelper.setupLogger(); - Player player = mock(Player.class); - String message = "Finished adding foo to the bar"; - - // when - Utils.logAndSendMessage(player, message); - - // then - verify(logger).info(message); - verify(player).sendMessage(message); - } - - @Test - public void shouldHandleNullAsCommandSender() { - // given - Logger logger = TestHelper.setupLogger(); - String message = "Test test, test."; - - // when - Utils.logAndSendMessage(null, message); - - // then - verify(logger).info(message); - } - - @Test - public void shouldNotSendToCommandSenderTwice() { - // given - Logger logger = TestHelper.setupLogger(); - CommandSender sender = mock(ConsoleCommandSender.class); - String message = "Test test, test."; - - // when - Utils.logAndSendMessage(sender, message); - - // then - verify(logger).info(message); - verifyNoInteractions(sender); - } - @SuppressWarnings("ConstantConditions") @Test public void shouldCheckIfCollectionIsEmpty() { @@ -111,51 +68,6 @@ public void shouldCheckIfCollectionIsEmpty() { assertThat(Utils.isCollectionEmpty(null), equalTo(true)); } - @Test - public void shouldLogAndSendWarning() { - // given - Logger logger = TestHelper.setupLogger(); - String message = "Error while performing action"; - CommandSender sender = mock(CommandSender.class); - - // when - Utils.logAndSendWarning(sender, message); - - // then - verify(logger).warning(message); - verify(sender).sendMessage(ChatColor.RED + message); - } - - @Test - public void shouldLogWarningAndNotSendToConsoleSender() { - // given - Logger logger = TestHelper.setupLogger(); - String message = "Error while performing action"; - CommandSender sender = mock(ConsoleCommandSender.class); - - // when - Utils.logAndSendWarning(sender, message); - - // then - verify(logger).warning(message); - verifyNoInteractions(sender); - } - - @SuppressWarnings("ConstantConditions") - @Test - public void shouldLogWarningAndHandleNullCommandSender() { - // given - Logger logger = TestHelper.setupLogger(); - String message = "Error while performing action"; - CommandSender sender = null; - - // when - Utils.logAndSendWarning(sender, message); - - // then - verify(logger).warning(message); - } - @Test public void shouldCheckIfClassIsLoaded() { // given / when / then @@ -174,4 +86,5 @@ public void shouldDetectIfEmailIsEmpty() { assertThat(Utils.isEmailEmpty("my@example.org"), equalTo(false)); assertThat(Utils.isEmailEmpty("hey"), equalTo(false)); } + } diff --git a/src/test/java/tools/dependencygraph/DrawDependency.java b/src/test/java/tools/dependencygraph/DrawDependency.java index ff3f890d4..191d05072 100644 --- a/src/test/java/tools/dependencygraph/DrawDependency.java +++ b/src/test/java/tools/dependencygraph/DrawDependency.java @@ -52,7 +52,7 @@ public class DrawDependency implements ToolTask { private boolean mapToSupertype; // Map with the graph's nodes: value is one of the key's dependencies - private Multimap, String> foundDependencies = HashMultimap.create(); + private final Multimap, String> foundDependencies = HashMultimap.create(); @Override public String getTaskName() { @@ -75,7 +75,7 @@ public void execute(Scanner scanner) { System.out.println("Specify the number of times to do this: [0=keep all]"); int stripVerticesCount; try { - stripVerticesCount = Integer.valueOf(scanner.nextLine()); + stripVerticesCount = Integer.parseInt(scanner.nextLine()); } catch (NumberFormatException e) { stripVerticesCount = 0; } @@ -87,9 +87,9 @@ public void execute(Scanner scanner) { // Create dot file content final String pattern = "\t\"%s\" -> \"%s\";"; - String dotFile = ""; + StringBuilder dotFile = new StringBuilder(); for (Map.Entry, String> entry : foundDependencies.entries()) { - dotFile += "\n" + String.format(pattern, entry.getValue(), entry.getKey().getSimpleName()); + dotFile.append("\n").append(String.format(pattern, entry.getValue(), entry.getKey().getSimpleName())); } // Write dot file