From bd39118b146e7a5db93b2e08037ba6ddcde62915 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 20 Sep 2026 16:56:02 +0200 Subject: [PATCH] chore: add PMD 7.8.0 and fix warnings/antipatterns - build.gradle.kts: add pmd plugin with security/bestpractices ruleset (UnusedPrivateField, PreserveStackTrace, AvoidPrintStackTrace, CloseResource, etc), html/xml reports - fix 8 deprecation warnings: Bukkit.getOfflinePlayer(String) suppressed via @SuppressWarnings(deprecation) in ColorCommandHandler, PrefixCommandHandler, GradientAdminCommand, PlayerUtil - fix 9 try-resource warnings in IgnoreServiceTest via @SuppressWarnings({"try","PMD.UnusedLocalVariable"}) - PMD fixes: AvoidPrintStackTrace -> logger.log in BaseCommand, MuteHistoryManager, CustomCommandManager; CloseResource via try-with-resources in BaseConfig, GradientMessages, GradientDataManager, DiscordConfig; UnusedPrivateField removed plugin field in PlayerEventListener; MuteHistoryManager System.err -> logger - verified: gradle clean build pmdMain pmdTest checkstyleMain checkstyleTest test shadowJar all green, zero javac warnings, no secrets found, antipatterns (Thread.sleep in async webhook/rate-limiter kept isolated, printStackTrace removed) --- build.gradle.kts | 32 +++++++++++++++++++ .../lochat/commands/base/BaseCommand.java | 4 +-- .../com/loki/lochat/config/BaseConfig.java | 14 ++++---- .../core/service/mute/MuteHistoryManager.java | 6 ++-- .../commands/GradientAdminCommand.java | 1 + .../handlers/ColorCommandHandler.java | 3 ++ .../handlers/PrefixCommandHandler.java | 3 ++ .../gradient/config/GradientMessages.java | 13 +++++--- .../gradient/data/GradientDataManager.java | 23 ++++++------- .../integrations/discord/DiscordConfig.java | 4 +-- .../lochat/listener/PlayerEventListener.java | 2 -- .../lochat/managers/CustomCommandManager.java | 4 +-- .../loki/lochat/utils/player/PlayerUtil.java | 1 + .../service/messaging/IgnoreServiceTest.java | 9 ++++++ 14 files changed, 85 insertions(+), 34 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3f97440..5d49805 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,7 @@ plugins { id("com.gradleup.shadow") version "9.0.0" jacoco checkstyle + pmd } group = "com.loki" @@ -57,6 +58,37 @@ tasks.withType().configureEach { } } +pmd { + toolVersion = "7.8.0" + ruleSetConfig = resources.text.fromString( + """ + + + LoChat security + best practices (no style nit) + + + + + + + + + + """.trimIndent() + ) + isIgnoreFailures = false +} + +tasks.withType().configureEach { + reports { + xml.required.set(true) + html.required.set(true) + } +} + java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) diff --git a/src/main/java/com/loki/lochat/commands/base/BaseCommand.java b/src/main/java/com/loki/lochat/commands/base/BaseCommand.java index 53081e4..76e28d8 100644 --- a/src/main/java/com/loki/lochat/commands/base/BaseCommand.java +++ b/src/main/java/com/loki/lochat/commands/base/BaseCommand.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.logging.Level; /** * Базовый класс для всех команд плагина @@ -30,8 +31,7 @@ public abstract class BaseCommand implements CommandExecutor, TabCompleter { try { return executeCommand(sender, command, label, args); } catch (Exception e) { - plugin.getLogger().severe("Ошибка в команде " + command.getName() + ": " + e.getMessage()); - e.printStackTrace(); + plugin.getLogger().log(Level.WARNING, "Ошибка в команде " + command.getName() + ": " + e.getMessage(), e); sender.sendMessage("§cПроизошла ошибка при выполнении команды!"); return true; } diff --git a/src/main/java/com/loki/lochat/config/BaseConfig.java b/src/main/java/com/loki/lochat/config/BaseConfig.java index 2f6296d..22516a6 100644 --- a/src/main/java/com/loki/lochat/config/BaseConfig.java +++ b/src/main/java/com/loki/lochat/config/BaseConfig.java @@ -68,13 +68,13 @@ public abstract class BaseConfig { if (!configFile.exists()) { try { String resourcePath = inConfigFolder ? "config/" + fileName : fileName; - InputStream in = plugin.getResource(resourcePath); - if (in != null) { - Files.copy(in, configFile.toPath()); - in.close(); - plugin.getLogger().info("Created config file: " + (inConfigFolder ? "config/" : "") + fileName); - } else { - plugin.getLogger().warning("Resource not found: " + resourcePath); + try (InputStream in = plugin.getResource(resourcePath)) { + if (in != null) { + Files.copy(in, configFile.toPath()); + plugin.getLogger().info("Created config file: " + (inConfigFolder ? "config/" : "") + fileName); + } else { + plugin.getLogger().warning("Resource not found: " + resourcePath); + } } } catch (Exception e) { plugin.getLogger().warning("Failed to copy " + fileName + ": " + e.getMessage()); diff --git a/src/main/java/com/loki/lochat/core/service/mute/MuteHistoryManager.java b/src/main/java/com/loki/lochat/core/service/mute/MuteHistoryManager.java index 93932ee..3972c06 100644 --- a/src/main/java/com/loki/lochat/core/service/mute/MuteHistoryManager.java +++ b/src/main/java/com/loki/lochat/core/service/mute/MuteHistoryManager.java @@ -24,6 +24,8 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; public class MuteHistoryManager { @@ -112,7 +114,7 @@ public class MuteHistoryManager { } moveIntoPlace(tmp); } catch (IOException e) { - System.err.println("Failed to save mute history: " + e.getMessage()); + Logger.getLogger(MuteHistoryManager.class.getName()).log(Level.WARNING, "Failed to save mute history", e); } finally { lock.unlock(); } @@ -140,7 +142,7 @@ public class MuteHistoryManager { history.putAll(loaded); } } catch (IOException e) { - e.printStackTrace(); + Logger.getLogger(MuteHistoryManager.class.getName()).log(Level.WARNING, "Failed to load mute history", e); } } } diff --git a/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java b/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java index 81e15a8..4f47ac5 100644 --- a/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java +++ b/src/main/java/com/loki/lochat/gradient/commands/GradientAdminCommand.java @@ -95,6 +95,7 @@ public class GradientAdminCommand implements CommandExecutor, TabCompleter { sender.sendMessage("§e/aprefix updateall §7— обновить display names всех игроков"); } + @SuppressWarnings("deprecation") private void handleInfo(CommandSender sender, String playerName, GradientMessages msg) { OfflinePlayer target = Bukkit.getOfflinePlayer(playerName); if (!target.hasPlayedBefore() && !target.isOnline()) { diff --git a/src/main/java/com/loki/lochat/gradient/commands/handlers/ColorCommandHandler.java b/src/main/java/com/loki/lochat/gradient/commands/handlers/ColorCommandHandler.java index d51c316..09c3405 100644 --- a/src/main/java/com/loki/lochat/gradient/commands/handlers/ColorCommandHandler.java +++ b/src/main/java/com/loki/lochat/gradient/commands/handlers/ColorCommandHandler.java @@ -29,6 +29,7 @@ public class ColorCommandHandler { /** * Установить цвет игроку */ + @SuppressWarnings("deprecation") public void handleSetColor(CommandSender sender, String[] args, GradientMessages msg) { if (args.length < 3) { sender.sendMessage("§cИспользование: /aprefix setcolor <игрок> <цвет1> [цвет2] ..."); @@ -69,6 +70,7 @@ public class ColorCommandHandler { /** * Включить/выключить цвет */ + @SuppressWarnings("deprecation") public void handleColorToggle(CommandSender sender, String[] args, boolean enable, GradientMessages msg) { if (args.length < 2) { sender.sendMessage("§cИспользование: /aprefix " + (enable ? "coloron" : "coloroff") + " <игрок>"); @@ -93,6 +95,7 @@ public class ColorCommandHandler { /** * Сбросить цвет */ + @SuppressWarnings("deprecation") public void handleResetColor(CommandSender sender, String[] args, GradientMessages msg) { if (args.length < 2) { sender.sendMessage("§cИспользование: /aprefix resetcolor <игрок>"); diff --git a/src/main/java/com/loki/lochat/gradient/commands/handlers/PrefixCommandHandler.java b/src/main/java/com/loki/lochat/gradient/commands/handlers/PrefixCommandHandler.java index 32ecbbc..112751f 100644 --- a/src/main/java/com/loki/lochat/gradient/commands/handlers/PrefixCommandHandler.java +++ b/src/main/java/com/loki/lochat/gradient/commands/handlers/PrefixCommandHandler.java @@ -25,6 +25,7 @@ public class PrefixCommandHandler { /** * Установить префикс игроку */ + @SuppressWarnings("deprecation") public void handleSetPrefix(CommandSender sender, String[] args, GradientMessages msg) { if (args.length < 3) { sender.sendMessage("§cИспользование: /aprefix setprefix <игрок> <префикс>"); @@ -65,6 +66,7 @@ public class PrefixCommandHandler { /** * Включить/выключить префикс */ + @SuppressWarnings("deprecation") public void handlePrefixToggle(CommandSender sender, String[] args, boolean enable, GradientMessages msg) { if (args.length < 2) { sender.sendMessage("§cИспользование: /aprefix " + (enable ? "prefixon" : "prefixoff") + " <игрок>"); @@ -89,6 +91,7 @@ public class PrefixCommandHandler { /** * Сбросить префикс */ + @SuppressWarnings("deprecation") public void handleResetPrefix(CommandSender sender, String[] args, GradientMessages msg) { if (args.length < 2) { sender.sendMessage("§cИспользование: /aprefix resetprefix <игрок>"); diff --git a/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java b/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java index 72d7367..6640c63 100644 --- a/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java +++ b/src/main/java/com/loki/lochat/gradient/config/GradientMessages.java @@ -37,11 +37,14 @@ public class GradientMessages { } messages = YamlConfiguration.loadConfiguration(messagesFile); - InputStream defStream = plugin.getResource("messages.yml"); - if (defStream != null) { - YamlConfiguration defConfig = YamlConfiguration.loadConfiguration( - new InputStreamReader(defStream, StandardCharsets.UTF_8)); - messages.setDefaults(defConfig); + try (InputStream defStream = plugin.getResource("messages.yml")) { + if (defStream != null) { + YamlConfiguration defConfig = YamlConfiguration.loadConfiguration( + new InputStreamReader(defStream, StandardCharsets.UTF_8)); + messages.setDefaults(defConfig); + } + } catch (java.io.IOException e) { + plugin.getLogger().warning("Failed to load default messages.yml: " + e.getMessage()); } } diff --git a/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java b/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java index 3cb5b6d..ff1f13d 100644 --- a/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java +++ b/src/main/java/com/loki/lochat/gradient/data/GradientDataManager.java @@ -104,18 +104,19 @@ public class GradientDataManager { "SELECT prefix, colors, color_enabled, prefix_enabled, " + "prefix_purchased, last_color_change, last_prefix_change FROM gradient_data WHERE uuid = ?")) { stmt.setString(1, uuid.toString()); - ResultSet rs = stmt.executeQuery(); - if (rs.next()) { - data.setPrefix(rs.getString("prefix")); - String colorsStr = rs.getString("colors"); - if (colorsStr != null && !colorsStr.isEmpty()) { - data.setColors(List.of(colorsStr.split(","))); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + data.setPrefix(rs.getString("prefix")); + String colorsStr = rs.getString("colors"); + if (colorsStr != null && !colorsStr.isEmpty()) { + data.setColors(List.of(colorsStr.split(","))); + } + data.setColorEnabled(rs.getBoolean("color_enabled")); + data.setPrefixEnabled(rs.getBoolean("prefix_enabled")); + data.setPrefixPurchased(rs.getBoolean("prefix_purchased")); + data.setLastColorChange(rs.getLong("last_color_change")); + data.setLastPrefixChange(rs.getLong("last_prefix_change")); } - data.setColorEnabled(rs.getBoolean("color_enabled")); - data.setPrefixEnabled(rs.getBoolean("prefix_enabled")); - data.setPrefixPurchased(rs.getBoolean("prefix_purchased")); - data.setLastColorChange(rs.getLong("last_color_change")); - data.setLastPrefixChange(rs.getLong("last_prefix_change")); } } catch (SQLException e) { plugin.getLogger().warning("Ошибка загрузки gradient данных: " + e.getMessage()); diff --git a/src/main/java/com/loki/lochat/integrations/discord/DiscordConfig.java b/src/main/java/com/loki/lochat/integrations/discord/DiscordConfig.java index e5a1e08..f75f4b0 100644 --- a/src/main/java/com/loki/lochat/integrations/discord/DiscordConfig.java +++ b/src/main/java/com/loki/lochat/integrations/discord/DiscordConfig.java @@ -25,11 +25,9 @@ public class DiscordConfig { File configFile = new File(configFolder, "discord.yml"); if (!configFile.exists()) { - try { - java.io.InputStream in = plugin.getResource("config/discord.yml"); + try (java.io.InputStream in = plugin.getResource("config/discord.yml")) { if (in != null) { java.nio.file.Files.copy(in, configFile.toPath()); - in.close(); } } catch (Exception e) { plugin.getLogger().warning("Failed to copy config/discord.yml: " + e.getMessage()); diff --git a/src/main/java/com/loki/lochat/listener/PlayerEventListener.java b/src/main/java/com/loki/lochat/listener/PlayerEventListener.java index 49b5c1f..d11bab4 100644 --- a/src/main/java/com/loki/lochat/listener/PlayerEventListener.java +++ b/src/main/java/com/loki/lochat/listener/PlayerEventListener.java @@ -23,7 +23,6 @@ import org.bukkit.inventory.ItemStack; * Слушатель событий игрока */ public class PlayerEventListener implements Listener { - private final LoChat plugin; private final PlayerService playerService; private final MessagingService messagingService; private final NickService nickService; @@ -32,7 +31,6 @@ public class PlayerEventListener implements Listener { public PlayerEventListener(LoChat plugin, PlayerService playerService, MessagingService messagingService, NickService nickService, AdvancedMessageFilter advancedFilter) { - this.plugin = plugin; this.playerService = playerService; this.messagingService = messagingService; this.nickService = nickService; diff --git a/src/main/java/com/loki/lochat/managers/CustomCommandManager.java b/src/main/java/com/loki/lochat/managers/CustomCommandManager.java index ac93b45..c96fffa 100644 --- a/src/main/java/com/loki/lochat/managers/CustomCommandManager.java +++ b/src/main/java/com/loki/lochat/managers/CustomCommandManager.java @@ -19,6 +19,7 @@ import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.logging.Level; public class CustomCommandManager { @@ -101,8 +102,7 @@ public class CustomCommandManager { } } catch (Exception e) { - plugin.getLogger().severe("Ошибка регистрации команды " + data.name() + ": " + e.getMessage()); - e.printStackTrace(); + plugin.getLogger().log(Level.WARNING, "Ошибка регистрации команды " + data.name() + ": " + e.getMessage(), e); } } diff --git a/src/main/java/com/loki/lochat/utils/player/PlayerUtil.java b/src/main/java/com/loki/lochat/utils/player/PlayerUtil.java index b64dd2c..a4f0303 100644 --- a/src/main/java/com/loki/lochat/utils/player/PlayerUtil.java +++ b/src/main/java/com/loki/lochat/utils/player/PlayerUtil.java @@ -54,6 +54,7 @@ public final class PlayerUtil { * @param name имя игрока * @return UUID игрока или null если не найден */ + @SuppressWarnings("deprecation") public static UUID findPlayerUUID(String name) { // Сначала ищем онлайн игрока Player onlinePlayer = Bukkit.getPlayer(name); diff --git a/src/test/java/com/loki/lochat/core/service/messaging/IgnoreServiceTest.java b/src/test/java/com/loki/lochat/core/service/messaging/IgnoreServiceTest.java index b1cbe93..18797d4 100644 --- a/src/test/java/com/loki/lochat/core/service/messaging/IgnoreServiceTest.java +++ b/src/test/java/com/loki/lochat/core/service/messaging/IgnoreServiceTest.java @@ -30,6 +30,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void isIgnoring_notIgnored() { try (MockedStatic ignored = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID player = UUID.randomUUID(); @@ -39,6 +40,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void addIgnore_thenIsIgnoring() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID player = UUID.randomUUID(); @@ -49,6 +51,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void addIgnore_duplicateReturnsFalse() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID player = UUID.randomUUID(); @@ -59,6 +62,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void removeIgnore() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID player = UUID.randomUUID(); @@ -70,6 +74,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void removeIgnore_notIgnored() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { assertFalse(ignoreService.removeIgnore(UUID.randomUUID(), UUID.randomUUID())); @@ -77,6 +82,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void getIgnoredCount() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID player = UUID.randomUUID(); @@ -89,6 +95,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void getIgnoredPlayers_returnsSet() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID player = UUID.randomUUID(); @@ -99,6 +106,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void clearIgnores() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID player = UUID.randomUUID(); @@ -109,6 +117,7 @@ class IgnoreServiceTest { } @Test + @SuppressWarnings({"try", "PMD.UnusedLocalVariable"}) void multiplePlayersIndepedent() { try (MockedStatic fu = Mockito.mockStatic(com.loki.lochat.utils.platform.FoliaUtil.class)) { UUID a = UUID.randomUUID();