From 1ce765ab1e0aadf8d87d7df50757dd43fc9bc97f Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 14 Jun 2026 16:48:28 +0200 Subject: [PATCH] refactor: replace legacy Paths usage with Path.of (#6441) --- .../common/configuration/AppConfig.java | 7 +- .../configuration/ConfigInitializer.java | 7 +- .../configuration/RuntimePathConfig.java | 11 +-- .../software/common/model/FileInfo.java | 3 +- .../common/service/MobileScannerService.java | 3 +- .../common/service/PostHogService.java | 4 +- .../software/common/util/GeneralUtils.java | 16 +-- .../software/common/util/JarPathUtil.java | 9 +- .../model/ApplicationPropertiesLogicTest.java | 9 +- .../software/SPDF/SPDFApplication.java | 5 +- .../SPDF/config/ExternalAppDepConfig.java | 2 +- .../SPDF/controller/api/UIDataController.java | 3 +- .../api/misc/PrintFileController.java | 3 +- .../pipeline/PipelineDirectoryProcessor.java | 5 +- .../api/pipeline/PipelineProcessor.java | 5 +- .../web/ReactRoutingController.java | 5 +- .../service/PdfJsonConversionService.java | 4 +- .../SPDF/service/SharedSignatureService.java | 21 ++-- .../type3/library/Type3FontLibrary.java | 3 +- .../type3/tool/Type3SignatureTool.java | 5 +- .../service/telegram/TelegramPipelineBot.java | 5 +- .../api/misc/PrintFileControllerTest.java | 6 +- .../api/AuditDashboardController.java | 6 +- .../controller/api/AuditRestController.java | 29 ++---- .../controller/api/SignatureController.java | 3 +- .../controller/api/UsageRestController.java | 3 +- .../configuration/ee/LicenseKeyChecker.java | 3 +- .../api/AdminLicenseController.java | 3 +- .../api/AdminSettingsController.java | 6 +- .../controller/api/InviteLinkController.java | 5 +- .../api/UIDataTessdataController.java | 5 +- .../controller/api/UserController.java | 2 +- .../security/service/DatabaseService.java | 24 ++--- .../service/KeyPairCleanupService.java | 3 +- .../service/KeyPersistenceService.java | 26 ++--- .../security/service/LoginAttemptService.java | 3 +- .../service/RefreshRateLimitService.java | 29 ++---- .../proprietary/service/AuditService.java | 3 +- .../service/ServerCertificateService.java | 3 +- .../proprietary/service/SignatureService.java | 19 ++-- .../storage/config/StorageProviderConfig.java | 5 +- .../provider/LocalStorageProvider.java | 3 +- .../storage/provider/S3StorageProvider.java | 6 +- .../storage/service/FileStorageService.java | 15 ++- .../controller/SigningSessionController.java | 2 +- .../service/SigningFinalizationService.java | 97 ++++++------------- .../service/WorkflowSessionService.java | 2 +- .../workflow/util/WorkflowMapper.java | 5 +- scripts/PropSync.java | 2 +- scripts/RestartHelper.java | 4 +- 50 files changed, 178 insertions(+), 279 deletions(-) diff --git a/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java b/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java index 6d5e2507e..ba896b4e3 100644 --- a/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java +++ b/app/common/src/main/java/stirling/software/common/configuration/AppConfig.java @@ -3,7 +3,6 @@ package stirling.software.common.configuration; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.Locale; import java.util.Properties; @@ -122,17 +121,17 @@ public class AppConfig { @Bean(name = "RunningInDocker") public boolean runningInDocker() { - return Files.exists(Paths.get("/.dockerenv")); + return Files.exists(Path.of("/.dockerenv")); } @Bean(name = "configDirMounted") public boolean isRunningInDockerWithConfig() { - Path dockerEnv = Paths.get("/.dockerenv"); + Path dockerEnv = Path.of("/.dockerenv"); // default to true if not docker if (!Files.exists(dockerEnv)) { return true; } - Path mountInfo = Paths.get("/proc/1/mountinfo"); + Path mountInfo = Path.of("/proc/1/mountinfo"); // this should always exist, if not some unknown usecase if (!Files.exists(mountInfo)) { return true; diff --git a/app/common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java b/app/common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java index 4b3c237ec..6d3f366b8 100644 --- a/app/common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java +++ b/app/common/src/main/java/stirling/software/common/configuration/ConfigInitializer.java @@ -7,7 +7,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.List; @@ -27,7 +26,7 @@ public class ConfigInitializer { public void ensureConfigExists() throws IOException, URISyntaxException { // 1) If settings file doesn't exist, create from template - Path destPath = Paths.get(InstallationPathConfig.getSettingsPath()); + Path destPath = Path.of(InstallationPathConfig.getSettingsPath()); boolean settingsFileExists = Files.exists(destPath); @@ -39,7 +38,7 @@ public class ConfigInitializer { if (settingsFileExists) { // move settings.yml to settings.yml.{timestamp}.bak Path backupPath = - Paths.get( + Path.of( InstallationPathConfig.getSettingsPath() + "." + System.currentTimeMillis() @@ -96,7 +95,7 @@ public class ConfigInitializer { } // 3) Ensure custom settings file exists - Path customSettingsPath = Paths.get(InstallationPathConfig.getCustomSettingsPath()); + Path customSettingsPath = Path.of(InstallationPathConfig.getCustomSettingsPath()); if (Files.notExists(customSettingsPath)) { Files.createFile(customSettingsPath); log.info("Created custom_settings file: {}", customSettingsPath); diff --git a/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java b/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java index b1ecc1020..82921c0ba 100644 --- a/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java +++ b/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java @@ -3,7 +3,6 @@ package stirling.software.common.configuration; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; @@ -201,7 +200,7 @@ public class RuntimePathConfig { try { // Normalize to absolute path - Path path = Paths.get(pathStr.trim()).toAbsolutePath().normalize(); + Path path = Path.of(pathStr.trim()).toAbsolutePath().normalize(); String normalizedPath = path.toString(); // Check for duplicates @@ -224,9 +223,9 @@ public class RuntimePathConfig { private void detectOverlappingPaths(List paths) { for (int i = 0; i < paths.size(); i++) { - Path path1 = Paths.get(paths.get(i)); + Path path1 = Path.of(paths.get(i)); for (int j = i + 1; j < paths.size(); j++) { - Path path2 = Paths.get(paths.get(j)); + Path path2 = Path.of(paths.get(j)); // Check if one path is a parent of the other if (path1.startsWith(path2)) { @@ -246,10 +245,10 @@ public class RuntimePathConfig { private void validatePipelinePaths() { try { - Path finishedPath = Paths.get(pipelineFinishedFoldersPath).toAbsolutePath().normalize(); + Path finishedPath = Path.of(pipelineFinishedFoldersPath).toAbsolutePath().normalize(); for (String watchedPathStr : pipelineWatchedFoldersPaths) { - Path watchedPath = Paths.get(watchedPathStr).toAbsolutePath().normalize(); + Path watchedPath = Path.of(watchedPathStr).toAbsolutePath().normalize(); // Check if watched folder is same as finished folder if (watchedPath.equals(finishedPath)) { diff --git a/app/common/src/main/java/stirling/software/common/model/FileInfo.java b/app/common/src/main/java/stirling/software/common/model/FileInfo.java index e89420296..0d2777c43 100644 --- a/app/common/src/main/java/stirling/software/common/model/FileInfo.java +++ b/app/common/src/main/java/stirling/software/common/model/FileInfo.java @@ -1,7 +1,6 @@ package stirling.software.common.model; import java.nio.file.Path; -import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; @@ -24,7 +23,7 @@ public class FileInfo { // Converts the file path string to a Path object. public Path getFilePathAsPath() { - return Paths.get(filePath); + return Path.of(filePath); } // Formats the file size into a human-readable string. diff --git a/app/common/src/main/java/stirling/software/common/service/MobileScannerService.java b/app/common/src/main/java/stirling/software/common/service/MobileScannerService.java index 49512af70..7c544b624 100644 --- a/app/common/src/main/java/stirling/software/common/service/MobileScannerService.java +++ b/app/common/src/main/java/stirling/software/common/service/MobileScannerService.java @@ -3,7 +3,6 @@ package stirling.software.common.service; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,7 +34,7 @@ public class MobileScannerService { public MobileScannerService() throws IOException { // Create temp directory for mobile scanner uploads this.tempDirectory = - Paths.get(System.getProperty("java.io.tmpdir"), "stirling-mobile-scanner"); + Path.of(System.getProperty("java.io.tmpdir"), "stirling-mobile-scanner"); Files.createDirectories(tempDirectory); log.info("Mobile scanner temp directory: {}", tempDirectory); } diff --git a/app/common/src/main/java/stirling/software/common/service/PostHogService.java b/app/common/src/main/java/stirling/software/common/service/PostHogService.java index 92093762f..f6a339ab9 100644 --- a/app/common/src/main/java/stirling/software/common/service/PostHogService.java +++ b/app/common/src/main/java/stirling/software/common/service/PostHogService.java @@ -8,7 +8,7 @@ import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; import java.lang.management.ThreadMXBean; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -160,7 +160,7 @@ public class PostHogService { } private boolean isRunningInDocker() { - return Files.exists(Paths.get("/.dockerenv")); + return Files.exists(Path.of("/.dockerenv")); } private Map getDockerMetrics() { diff --git a/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java b/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java index 61ba8670f..fbcf30fdf 100644 --- a/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java +++ b/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java @@ -255,7 +255,7 @@ public class GeneralUtils { String pattern = locationPattern; if (pattern.startsWith("file:")) { String rawPath = pattern.substring(5).replace("\\*", "").replace("/*", ""); - Path normalizePath = Paths.get(rawPath).normalize(); + Path normalizePath = Path.of(rawPath).normalize(); pattern = "file:" + normalizePath.toString().replace("\\", "/") + "/*"; } return ResourcePatternUtils.getResourcePatternResolver(resourceLoader) @@ -837,7 +837,7 @@ public class GeneralUtils { } public boolean createDir(String path) { - Path folder = Paths.get(path); + Path folder = Path.of(path); if (!Files.exists(folder)) { try { Files.createDirectories(folder); @@ -867,7 +867,7 @@ public class GeneralUtils { public void saveKeyToSettings(String key, Object newValue) throws IOException { String[] keyArray = key.split("\\."); - Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath()); + Path settingsPath = Path.of(InstallationPathConfig.getSettingsPath()); YamlHelper settingsYaml = new YamlHelper(settingsPath); settingsYaml.updateValue(Arrays.asList(keyArray), newValue); settingsYaml.saveOverride(settingsPath); @@ -888,7 +888,7 @@ public class GeneralUtils { return; } - Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath()); + Path settingsPath = Path.of(InstallationPathConfig.getSettingsPath()); YamlHelper settingsYaml = new YamlHelper(settingsPath); // Apply all updates to the same YamlHelper instance @@ -974,11 +974,11 @@ public class GeneralUtils { */ public void extractPipeline() throws IOException { Path pipelineDir = - Paths.get(InstallationPathConfig.getPipelinePath(), DEFAULT_WEBUI_CONFIGS_DIR); + Path.of(InstallationPathConfig.getPipelinePath(), DEFAULT_WEBUI_CONFIGS_DIR); Files.createDirectories(pipelineDir); for (String name : DEFAULT_VALID_PIPELINE) { - if (!Paths.get(name).getFileName().toString().equals(name)) { + if (!Path.of(name).getFileName().toString().equals(name)) { log.error("Invalid pipeline file name: {}", name); throw new IllegalArgumentException("Invalid pipeline file name: " + name); } @@ -1014,7 +1014,7 @@ public class GeneralUtils { throw new IllegalArgumentException( "scriptName must not contain path traversal characters"); } - if (!Paths.get(scriptName).getFileName().toString().equals(scriptName)) { + if (!Path.of(scriptName).getFileName().toString().equals(scriptName)) { throw new IllegalArgumentException( "scriptName must not contain path traversal characters"); } @@ -1024,7 +1024,7 @@ public class GeneralUtils { "scriptName must be either 'png_to_webp.py' or 'split_photos.py'"); } - Path scriptsDir = Paths.get(InstallationPathConfig.getScriptsPath(), PYTHON_SCRIPTS_DIR); + Path scriptsDir = Path.of(InstallationPathConfig.getScriptsPath(), PYTHON_SCRIPTS_DIR); Files.createDirectories(scriptsDir); Path target = scriptsDir.resolve(scriptName); diff --git a/app/common/src/main/java/stirling/software/common/util/JarPathUtil.java b/app/common/src/main/java/stirling/software/common/util/JarPathUtil.java index e5c6488eb..bb0e39491 100644 --- a/app/common/src/main/java/stirling/software/common/util/JarPathUtil.java +++ b/app/common/src/main/java/stirling/software/common/util/JarPathUtil.java @@ -4,7 +4,6 @@ import java.io.File; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import lombok.extern.slf4j.Slf4j; @@ -20,7 +19,7 @@ public class JarPathUtil { public static Path currentJar() { try { Path jar = - Paths.get( + Path.of( JarPathUtil.class .getProtectionDomain() .getCodeSource() @@ -61,14 +60,14 @@ public class JarPathUtil { } // Location 2: ./build/libs/ (development build) - possibleLocations[1] = Paths.get("build", "libs", "restart-helper.jar").toAbsolutePath(); + possibleLocations[1] = Path.of("build", "libs", "restart-helper.jar").toAbsolutePath(); // Location 3: app/common/build/libs/ (multi-module build) possibleLocations[2] = - Paths.get("app", "common", "build", "libs", "restart-helper.jar").toAbsolutePath(); + Path.of("app", "common", "build", "libs", "restart-helper.jar").toAbsolutePath(); // Location 4: Current working directory - possibleLocations[3] = Paths.get("restart-helper.jar").toAbsolutePath(); + possibleLocations[3] = Path.of("restart-helper.jar").toAbsolutePath(); // Check each location for (Path location : possibleLocations) { diff --git a/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java b/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java index f075f1518..ea5f95d77 100644 --- a/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java +++ b/app/common/src/test/java/stirling/software/common/model/ApplicationPropertiesLogicTest.java @@ -2,7 +2,7 @@ package stirling.software.common.model; import static org.junit.jupiter.api.Assertions.*; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -33,16 +33,15 @@ class ApplicationPropertiesLogicTest { @Test void tempFileManagement_defaults_and_overrides() { - Function normalize = s -> Paths.get(s).normalize().toString(); + Function normalize = s -> Path.of(s).normalize().toString(); ApplicationProperties.TempFileManagement tfm = new ApplicationProperties.TempFileManagement(); String expectedBase = - Paths.get(java.lang.System.getProperty("java.io.tmpdir"), "stirling-pdf") - .toString(); + Path.of(java.lang.System.getProperty("java.io.tmpdir"), "stirling-pdf").toString(); assertEquals(expectedBase, tfm.getBaseTmpDir()); - String expectedLibre = Paths.get(expectedBase, "libreoffice").toString(); + String expectedLibre = Path.of(expectedBase, "libreoffice").toString(); assertEquals(expectedLibre, tfm.getLibreofficeDir()); tfm.setBaseTmpDir("/custom/base"); diff --git a/app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java b/app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java index 177d2443a..3cc310075 100644 --- a/app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java +++ b/app/core/src/main/java/stirling/software/SPDF/SPDFApplication.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -75,7 +74,7 @@ public class SPDFApplication { Map propertyFiles = new HashMap<>(); // External config files - Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath()); + Path settingsPath = Path.of(InstallationPathConfig.getSettingsPath()); log.info("Settings file: {}", settingsPath.toString()); if (Files.exists(settingsPath)) { propertyFiles.put( @@ -84,7 +83,7 @@ public class SPDFApplication { log.warn("External configuration file '{}' does not exist.", settingsPath.toString()); } - Path customSettingsPath = Paths.get(InstallationPathConfig.getCustomSettingsPath()); + Path customSettingsPath = Path.of(InstallationPathConfig.getCustomSettingsPath()); log.info("Custom settings file: {}", customSettingsPath.toString()); if (Files.exists(customSettingsPath)) { String existingLocation = diff --git a/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java index c08e53e1a..8755dfe2e 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java @@ -95,7 +95,7 @@ public class ExternalAppDepConfig { checkDependencyAndDisableGroup(cmd); return null; }) - .collect(Collectors.toList()); + .toList(); invokeAllWithTimeout(tasks, DEFAULT_TIMEOUT.plusSeconds(3)); // Python / OpenCV special handling diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java index c1afe8c40..de391c7c3 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java @@ -5,7 +5,6 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.*; import java.util.stream.Stream; @@ -115,7 +114,7 @@ public class UIDataController { if (new java.io.File(runtimePathConfig.getPipelineDefaultWebUiConfigs()).exists()) { try (Stream paths = - Files.walk(Paths.get(runtimePathConfig.getPipelineDefaultWebUiConfigs()))) { + Files.walk(Path.of(runtimePathConfig.getPipelineDefaultWebUiConfigs()))) { List jsonFiles = paths.filter(Files::isRegularFile) .filter(p -> p.toString().endsWith(".json")) diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java index 48a9b5586..e369bbf10 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java @@ -9,7 +9,6 @@ import java.awt.print.PrinterJob; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Locale; @@ -54,7 +53,7 @@ public class PrintFileController { MultipartFile file = request.getFileInput(); String originalFilename = file.getOriginalFilename(); if (originalFilename != null - && (originalFilename.contains("..") || Paths.get(originalFilename).isAbsolute())) { + && (originalFilename.contains("..") || Path.of(originalFilename).isAbsolute())) { throw ExceptionUtils.createIllegalArgumentException( "error.invalid.filepath", "Invalid file path detected: " + originalFilename); } diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java index ef0afce94..79223ddd3 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java @@ -7,7 +7,6 @@ import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; @@ -82,7 +81,7 @@ public class PipelineDirectoryProcessor { try { for (String watchedFoldersDir : watchedFoldersDirs) { - scanWatchedFolder(Paths.get(watchedFoldersDir).toAbsolutePath()); + scanWatchedFolder(Path.of(watchedFoldersDir).toAbsolutePath()); } } finally { // Clean up ThreadLocal to prevent memory leaks @@ -442,7 +441,7 @@ public class PipelineDirectoryProcessor { .replace("{outputFolder}", finishedFoldersDir) .replace("{folderName}", dir.toString())) .replaceAll(""); - return Paths.get(outputDir).isAbsolute() ? Paths.get(outputDir) : Paths.get(".", outputDir); + return Path.of(outputDir).isAbsolute() ? Path.of(outputDir) : Path.of(".", outputDir); } private void deleteOriginalFiles(List filesToProcess, Path processingDir) diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java index fde2cfa90..c57a43f27 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java @@ -5,7 +5,6 @@ import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -326,12 +325,12 @@ public class PipelineProcessor { } List outputFiles = new ArrayList<>(); for (File file : files) { - Path normalizedPath = Paths.get(file.getName()).normalize(); + Path normalizedPath = Path.of(file.getName()).normalize(); if (normalizedPath.startsWith("..")) { throw new SecurityException( "Potential path traversal attempt in file name: " + file.getName()); } - Path path = Paths.get(file.getAbsolutePath()); + Path path = Path.of(file.getAbsolutePath()); // debug statement log.info("Reading file: {}", path); if (Files.exists(path)) { diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java b/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java index d6a95e66d..62ce9dac0 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/web/ReactRoutingController.java @@ -5,7 +5,6 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.regex.Pattern; import org.springframework.beans.factory.annotation.Value; @@ -66,7 +65,7 @@ public class ReactRoutingController { } // Check for external index.html first (customFiles/static/) - Path externalIndexPath = Paths.get(InstallationPathConfig.getStaticPath(), "index.html"); + Path externalIndexPath = Path.of(InstallationPathConfig.getStaticPath(), "index.html"); log.debug("Checking for custom index.html at: {}", externalIndexPath); if (Files.exists(externalIndexPath) && Files.isReadable(externalIndexPath)) { log.info("Using custom index.html from: {}", externalIndexPath); @@ -136,7 +135,7 @@ public class ReactRoutingController { private Resource getIndexHtmlResource() { // Check external location first - Path externalIndexPath = Paths.get(InstallationPathConfig.getStaticPath(), "index.html"); + Path externalIndexPath = Path.of(InstallationPathConfig.getStaticPath(), "index.html"); if (Files.exists(externalIndexPath) && Files.isReadable(externalIndexPath)) { return new FileSystemResource(externalIndexPath.toFile()); } diff --git a/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonConversionService.java b/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonConversionService.java index 1eed1d275..fea3b52fc 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonConversionService.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/PdfJsonConversionService.java @@ -588,7 +588,7 @@ public class PdfJsonConversionService { .replaceAll(""); return String.format("%s (%s)", cleanName, subtype); }) - .collect(java.util.stream.Collectors.toList()); + .toList(); long type3Fonts = responseFonts.stream().filter(f -> "Type3".equals(f.getSubtype())).count(); @@ -1554,7 +1554,7 @@ public class PdfJsonConversionService { .glyphName(outline.getGlyphName()) .unicode(outline.getUnicode()) .build()) - .collect(Collectors.toList()); + .toList(); } } catch (Exception ex) { log.debug( diff --git a/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java b/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java index b1321de3f..3f52dbea2 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/SharedSignatureService.java @@ -4,7 +4,6 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Base64; @@ -41,8 +40,8 @@ public class SharedSignatureService { public boolean hasAccessToFile(String username, String fileName) throws IOException { validateFileName(fileName); // Check if file exists in user's personal folder or ALL_USERS folder - Path userPath = Paths.get(SIGNATURE_BASE_PATH, username, fileName); - Path allUsersPath = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName); + Path userPath = Path.of(SIGNATURE_BASE_PATH, username, fileName); + Path allUsersPath = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName); return Files.exists(userPath) || Files.exists(allUsersPath); } @@ -52,7 +51,7 @@ public class SharedSignatureService { // Get signatures from user's personal folder if (StringUtils.hasText(username)) { - Path userFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path userFolder = Path.of(SIGNATURE_BASE_PATH, username); if (Files.exists(userFolder)) { try { signatures.addAll(getSignaturesFromFolder(userFolder, "Personal")); @@ -63,7 +62,7 @@ public class SharedSignatureService { } // Get signatures from ALL_USERS folder - Path allUsersFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); + Path allUsersFolder = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); if (Files.exists(allUsersFolder)) { try { signatures.addAll(getSignaturesFromFolder(allUsersFolder, "Shared")); @@ -90,7 +89,7 @@ public class SharedSignatureService { */ public byte[] getSharedSignatureBytes(String fileName) throws IOException { validateFileName(fileName); - Path allUsersPath = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName); + Path allUsersPath = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER, fileName); if (!Files.exists(allUsersPath)) { throw new FileNotFoundException("Shared signature file not found"); } @@ -142,7 +141,7 @@ public class SharedSignatureService { } String folderName = "shared".equals(scope) ? ALL_USERS_FOLDER : username; - Path targetFolder = Paths.get(SIGNATURE_BASE_PATH, folderName); + Path targetFolder = Path.of(SIGNATURE_BASE_PATH, folderName); Files.createDirectories(targetFolder); long timestamp = System.currentTimeMillis(); @@ -193,7 +192,7 @@ public class SharedSignatureService { List signatures = new ArrayList<>(); // Load personal signatures - Path personalFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path personalFolder = Path.of(SIGNATURE_BASE_PATH, username); if (Files.exists(personalFolder)) { try (Stream stream = Files.list(personalFolder)) { stream.filter(this::isImageFile) @@ -224,7 +223,7 @@ public class SharedSignatureService { } // Load shared signatures - Path sharedFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); + Path sharedFolder = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); if (Files.exists(sharedFolder)) { try (Stream stream = Files.list(sharedFolder)) { stream.filter(this::isImageFile) @@ -262,7 +261,7 @@ public class SharedSignatureService { validateFileName(signatureId); // Try to find and delete image file in personal folder - Path personalFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path personalFolder = Path.of(SIGNATURE_BASE_PATH, username); boolean deleted = false; if (Files.exists(personalFolder)) { @@ -283,7 +282,7 @@ public class SharedSignatureService { // Try shared folder if not found in personal if (!deleted) { - Path sharedFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); + Path sharedFolder = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); if (Files.exists(sharedFolder)) { try (Stream stream = Files.list(sharedFolder)) { List matchingFiles = diff --git a/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/library/Type3FontLibrary.java b/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/library/Type3FontLibrary.java index 0c885dfb2..457d2c9c8 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/library/Type3FontLibrary.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/library/Type3FontLibrary.java @@ -10,7 +10,6 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.font.PDType3Font; @@ -268,7 +267,7 @@ public class Type3FontLibrary { .filter(Objects::nonNull) .map(String::trim) .filter(s -> !s.isEmpty()) - .collect(Collectors.toList()); + .toList(); } private String normalizeAlias(String alias) { diff --git a/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/tool/Type3SignatureTool.java b/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/tool/Type3SignatureTool.java index ff1836913..10bc39618 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/tool/Type3SignatureTool.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/pdfjson/type3/tool/Type3SignatureTool.java @@ -3,7 +3,6 @@ package stirling.software.SPDF.service.pdfjson.type3.tool; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -285,9 +284,9 @@ public final class Type3SignatureTool { for (int i = 0; i < args.length; i++) { String arg = args[i]; if ("--pdf".equals(arg) && i + 1 < args.length) { - pdf = Paths.get(args[++i]); + pdf = Path.of(args[++i]); } else if ("--output".equals(arg) && i + 1 < args.length) { - output = Paths.get(args[++i]); + output = Path.of(args[++i]); } else if ("--pretty".equals(arg)) { pretty = true; } else if ("--help".equals(arg) || "-h".equals(arg)) { diff --git a/app/core/src/main/java/stirling/software/SPDF/service/telegram/TelegramPipelineBot.java b/app/core/src/main/java/stirling/software/SPDF/service/telegram/TelegramPipelineBot.java index 89910781b..3b8d5cff1 100644 --- a/app/core/src/main/java/stirling/software/SPDF/service/telegram/TelegramPipelineBot.java +++ b/app/core/src/main/java/stirling/software/SPDF/service/telegram/TelegramPipelineBot.java @@ -8,7 +8,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; @@ -411,7 +410,7 @@ public class TelegramPipelineBot extends TelegramLongPollingBot { private Path getInboxFolder(Long chatId) throws IOException { Path baseInbox = - Paths.get( + Path.of( runtimePathConfig.getPipelineWatchedFoldersPath(), telegramProperties.getPipelineInboxFolder()); @@ -445,7 +444,7 @@ public class TelegramPipelineBot extends TelegramLongPollingBot { private List waitForPipelineOutputs(PipelineFileInfo info) throws IOException { - Path finishedDir = Paths.get(runtimePathConfig.getPipelineFinishedFoldersPath()); + Path finishedDir = Path.of(runtimePathConfig.getPipelineFinishedFoldersPath()); Files.createDirectories(finishedDir); Instant start = info.savedAt(); diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/PrintFileControllerTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/PrintFileControllerTest.java index 5fb8d4ce8..7fe102791 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/PrintFileControllerTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/PrintFileControllerTest.java @@ -3,7 +3,7 @@ package stirling.software.SPDF.controller.api.misc; import static org.junit.jupiter.api.Assertions.*; import java.io.IOException; -import java.nio.file.Paths; +import java.nio.file.Path; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -34,9 +34,9 @@ class PrintFileControllerTest { @Test void printFile_absolutePath_throwsException() { PrintFileRequest request = new PrintFileRequest(); - String absPath = Paths.get("/etc/passwd").toString(); + String absPath = Path.of("/etc/passwd").toString(); // Only test on systems where /etc/passwd is absolute - if (Paths.get(absPath).isAbsolute()) { + if (Path.of(absPath).isAbsolute()) { MockMultipartFile file = new MockMultipartFile( "fileInput", absPath, "application/pdf", "data".getBytes()); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditDashboardController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditDashboardController.java index 837c28bf5..6e93ed14e 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditDashboardController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditDashboardController.java @@ -207,16 +207,14 @@ public class AuditDashboardController { // Include standard enum types in case they're not in the database yet List enumTypes = - Arrays.stream(AuditEventType.values()) - .map(AuditEventType::name) - .collect(Collectors.toList()); + Arrays.stream(AuditEventType.values()).map(AuditEventType::name).toList(); // Combine both sources, remove duplicates, and sort Set combinedTypes = new HashSet<>(); combinedTypes.addAll(dbTypes); combinedTypes.addAll(enumTypes); - return combinedTypes.stream().sorted().collect(Collectors.toList()); + return combinedTypes.stream().sorted().toList(); } /** Export audit data as CSV. */ diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditRestController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditRestController.java index a208a46a8..69c940292 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditRestController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/AuditRestController.java @@ -118,7 +118,7 @@ public class AuditRestController { // Convert to response format expected by frontend List eventDtos = - events.getContent().stream().map(this::convertToDto).collect(Collectors.toList()); + events.getContent().stream().map(this::convertToDto).toList(); AuditEventsResponse response = AuditEventsResponse.builder() @@ -191,19 +191,13 @@ public class AuditRestController { ChartData eventsByTypeChart = ChartData.builder() .labels(new ArrayList<>(eventsByType.keySet())) - .values( - eventsByType.values().stream() - .map(Long::intValue) - .collect(Collectors.toList())) + .values(eventsByType.values().stream().map(Long::intValue).toList()) .build(); ChartData eventsByUserChart = ChartData.builder() .labels(new ArrayList<>(eventsByUser.keySet())) - .values( - eventsByUser.values().stream() - .map(Long::intValue) - .collect(Collectors.toList())) + .values(eventsByUser.values().stream().map(Long::intValue).toList()) .build(); // Sort events by day for time series @@ -211,10 +205,7 @@ public class AuditRestController { ChartData eventsOverTimeChart = ChartData.builder() .labels(new ArrayList<>(sortedEventsByDay.keySet())) - .values( - sortedEventsByDay.values().stream() - .map(Long::intValue) - .collect(Collectors.toList())) + .values(sortedEventsByDay.values().stream().map(Long::intValue).toList()) .build(); AuditChartsData chartsData = @@ -239,16 +230,14 @@ public class AuditRestController { // Include standard enum types in case they're not in the database yet List enumTypes = - Arrays.stream(AuditEventType.values()) - .map(AuditEventType::name) - .collect(Collectors.toList()); + Arrays.stream(AuditEventType.values()).map(AuditEventType::name).toList(); // Combine both sources, remove duplicates, and sort Set combinedTypes = new HashSet<>(); combinedTypes.addAll(dbTypes); combinedTypes.addAll(enumTypes); - List result = combinedTypes.stream().sorted().collect(Collectors.toList()); + List result = combinedTypes.stream().sorted().toList(); return ResponseEntity.ok(result); } @@ -263,11 +252,7 @@ public class AuditRestController { // Use the countByPrincipal query to get unique principals List principalCounts = auditRepository.countByPrincipal(); - List users = - principalCounts.stream() - .map(arr -> (String) arr[0]) - .sorted() - .collect(Collectors.toList()); + List users = principalCounts.stream().map(arr -> (String) arr[0]).sorted().toList(); return ResponseEntity.ok(users); } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java index 3295e62ab..5333ff18c 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/SignatureController.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.controller.api; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -183,7 +182,7 @@ public class SignatureController { */ private boolean deleteFromSharedFolder(String signatureId) throws IOException { String signatureBasePath = InstallationPathConfig.getSignaturesPath(); - Path sharedFolder = Paths.get(signatureBasePath, ALL_USERS_FOLDER); + Path sharedFolder = Path.of(signatureBasePath, ALL_USERS_FOLDER); boolean deleted = false; if (Files.exists(sharedFolder)) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/UsageRestController.java b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/UsageRestController.java index 9f4fa470b..1230d928c 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/UsageRestController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/controller/api/UsageRestController.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.controller.api; import java.time.Duration; import java.time.Instant; import java.util.*; -import java.util.stream.Collectors; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -85,7 +84,7 @@ public class UsageRestController { .build(); }) .sorted(Comparator.comparingInt(EndpointStatistic::getVisits).reversed()) - .collect(Collectors.toList()); + .toList(); // Apply limit if specified if (limit != null && limit > 0 && statistics.size() > limit) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/LicenseKeyChecker.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/LicenseKeyChecker.java index af9ac192d..d8dbfc0e0 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/LicenseKeyChecker.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/configuration/ee/LicenseKeyChecker.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.security.configuration.ee; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.annotation.Lazy; @@ -104,7 +103,7 @@ public class LicenseKeyChecker { if (keyOrFilePath.startsWith(FILE_PREFIX)) { String filePath = keyOrFilePath.substring(FILE_PREFIX.length()); try { - Path path = Paths.get(filePath); + Path path = Path.of(filePath); if (!Files.exists(path)) { log.error("License file does not exist: {}", filePath); return null; diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminLicenseController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminLicenseController.java index e9cd65f7c..9e05e9ebb 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminLicenseController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminLicenseController.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.Map; @@ -329,7 +328,7 @@ public class AdminLicenseController { } // Get config directory and target path - Path configPath = Paths.get(InstallationPathConfig.getConfigPath()); + Path configPath = Path.of(InstallationPathConfig.getConfigPath()); Path configPathAbs = configPath.toAbsolutePath().normalize(); Path targetPath = configPathAbs.resolve(filename).normalize(); log.info( diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java index 06fc80c75..14ddde602 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/AdminSettingsController.java @@ -702,7 +702,7 @@ public class AdminSettingsController { if (path != null && !path.trim().isEmpty()) { try { java.nio.file.Path normalized = - java.nio.file.Paths.get(path.trim()).toAbsolutePath().normalize(); + java.nio.file.Path.of(path.trim()).toAbsolutePath().normalize(); String normalizedStr = normalized.toString(); // Check for duplicates @@ -719,9 +719,9 @@ public class AdminSettingsController { // Check for overlapping paths java.util.List pathList = new java.util.ArrayList<>(normalizedPaths); for (int i = 0; i < pathList.size(); i++) { - java.nio.file.Path path1 = java.nio.file.Paths.get(pathList.get(i)); + java.nio.file.Path path1 = java.nio.file.Path.of(pathList.get(i)); for (int j = i + 1; j < pathList.size(); j++) { - java.nio.file.Path path2 = java.nio.file.Paths.get(pathList.get(j)); + java.nio.file.Path path2 = java.nio.file.Path.of(pathList.get(j)); if (path1.startsWith(path2) || path2.startsWith(path1)) { return "Overlapping paths detected: " + path1 + " and " + path2; } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/InviteLinkController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/InviteLinkController.java index 07ec1c973..641216e26 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/InviteLinkController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/InviteLinkController.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.security.controller.api; import java.security.Principal; import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -280,7 +279,7 @@ public class InviteLinkController { "expiresAt", invite.getExpiresAt().toString()); return inviteMap; }) - .collect(Collectors.toList()); + .toList(); return ResponseEntity.ok(Map.of("invites", inviteList)); @@ -331,7 +330,7 @@ public class InviteLinkController { List expiredInvites = inviteTokenRepository.findAll().stream() .filter(invite -> !invite.isValid()) - .collect(Collectors.toList()); + .toList(); int count = expiredInvites.size(); inviteTokenRepository.deleteAll(expiredInvites); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UIDataTessdataController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UIDataTessdataController.java index 743425aec..8212dcfb2 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UIDataTessdataController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UIDataTessdataController.java @@ -6,7 +6,6 @@ import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.*; import java.util.regex.Pattern; @@ -53,7 +52,7 @@ public class UIDataTessdataController { TessdataLanguagesResponse response = new TessdataLanguagesResponse(); response.setInstalled(getAvailableTesseractLanguages()); response.setAvailable(getRemoteTessdataLanguages()); - response.setWritable(isWritableDirectory(Paths.get(runtimePathConfig.getTessDataPath()))); + response.setWritable(isWritableDirectory(Path.of(runtimePathConfig.getTessDataPath()))); return ResponseEntity.ok(response); } @@ -67,7 +66,7 @@ public class UIDataTessdataController { .body(Map.of("message", "No languages provided for download")); } - Path tessdataDir = Paths.get(runtimePathConfig.getTessDataPath()); + Path tessdataDir = Path.of(runtimePathConfig.getTessDataPath()); try { Files.createDirectories(tessdataDir); } catch (IOException e) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index 90abd5f06..295e90029 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -994,7 +994,7 @@ public class UserController { userRepository.findAll().stream() .filter(User::isEnabled) .map(this::toUserSummaryDTO) - .collect(java.util.stream.Collectors.toList()); + .toList(); return ResponseEntity.ok(users); } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java index f120e4e42..2246903d2 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; import java.security.MessageDigest; @@ -23,7 +22,6 @@ import java.util.Comparator; import java.util.List; import java.util.UUID; import java.util.regex.Pattern; -import java.util.stream.Collectors; import javax.sql.DataSource; @@ -100,7 +98,7 @@ public class DatabaseService implements DatabaseServiceInterface { ApplicationProperties.Datasource datasourceProps, DataSource dataSource, DatabaseNotificationServiceInterface backupNotificationService) { - this.BACKUP_DIR = Paths.get(InstallationPathConfig.getBackupPath()).normalize(); + this.BACKUP_DIR = Path.of(InstallationPathConfig.getBackupPath()).normalize(); this.datasourceProps = datasourceProps; this.dataSource = dataSource; this.backupNotificationService = backupNotificationService; @@ -111,7 +109,7 @@ public class DatabaseService implements DatabaseServiceInterface { @Deprecated(since = "2.0.0", forRemoval = true) private void moveBackupFiles() { Path sourceDir = - Paths.get(InstallationPathConfig.getConfigPath(), "db", "backup").normalize(); + Path.of(InstallationPathConfig.getConfigPath(), "db", "backup").normalize(); if (!Files.exists(sourceDir)) { log.info("Source directory does not exist: {}", sourceDir); @@ -217,7 +215,7 @@ public class DatabaseService implements DatabaseServiceInterface { List backupList = this.getBackupList(); backupList.sort(Comparator.comparing(FileInfo::getModificationDate).reversed()); - Path latestExport = Paths.get(backupList.get(0).getFilePath()); + Path latestExport = Path.of(backupList.get(0).getFilePath()); executeDatabaseScript(latestExport); } @@ -258,9 +256,13 @@ public class DatabaseService implements DatabaseServiceInterface { @Override public void exportDatabase() { List filteredBackupList = - this.getBackupList().stream() - .filter(backup -> !backup.getFileName().startsWith(BACKUP_PREFIX + "user_")) - .collect(Collectors.toList()); + new ArrayList<>( + this.getBackupList().stream() + .filter( + backup -> + !backup.getFileName() + .startsWith(BACKUP_PREFIX + "user_")) + .toList()); if (filteredBackupList.size() > 5) { deleteOldestBackup(filteredBackupList); @@ -341,7 +343,7 @@ public class DatabaseService implements DatabaseServiceInterface { for (FileInfo backup : backupList) { try { - Files.deleteIfExists(Paths.get(backup.getFilePath())); + Files.deleteIfExists(Path.of(backup.getFilePath())); deletedFiles.add(Pair.of(backup, true)); } catch (IOException e) { log.error("Error deleting backup file: {}", backup.getFileName(), e); @@ -359,7 +361,7 @@ public class DatabaseService implements DatabaseServiceInterface { if (!backupList.isEmpty()) { FileInfo lastBackup = backupList.get(backupList.size() - 1); try { - Files.deleteIfExists(Paths.get(lastBackup.getFilePath())); + Files.deleteIfExists(Path.of(lastBackup.getFilePath())); deletedFiles.add(Pair.of(lastBackup, true)); } catch (IOException e) { log.error("Error deleting last backup file: {}", lastBackup.getFileName(), e); @@ -381,7 +383,7 @@ public class DatabaseService implements DatabaseServiceInterface { p -> p.getFileName().substring(7, p.getFileName().length() - 4))); FileInfo oldestFile = filteredBackupList.get(0); - Files.deleteIfExists(Paths.get(oldestFile.getFilePath())); + Files.deleteIfExists(Path.of(oldestFile.getFilePath())); log.info("Deleted oldest backup: {}", oldestFile.getFileName()); } catch (IOException e) { log.error("Unable to delete oldest backup, message: {}", e.getMessage(), e); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPairCleanupService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPairCleanupService.java index aec455a92..8745f505f 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPairCleanupService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPairCleanupService.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.security.service; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.time.LocalDateTime; import java.util.List; import java.util.concurrent.TimeUnit; @@ -76,7 +75,7 @@ public class KeyPairCleanupService { return; } - Path privateKeyDirectory = Paths.get(InstallationPathConfig.getPrivateKeyPath()); + Path privateKeyDirectory = Path.of(InstallationPathConfig.getPrivateKeyPath()); Path keyFile = privateKeyDirectory.resolve(keyId + KeyPersistenceService.KEY_SUFFIX); if (Files.exists(keyFile)) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPersistenceService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPersistenceService.java index d0c9f879b..49e66e5c5 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPersistenceService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/KeyPersistenceService.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.security.service; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -20,7 +19,6 @@ import java.time.format.DateTimeFormatter; import java.util.Base64; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; @@ -82,7 +80,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface { */ private void loadExistingKeysFromDisk() { try { - Path keyDirectory = Paths.get(InstallationPathConfig.getPrivateKeyPath()); + Path keyDirectory = Path.of(InstallationPathConfig.getPrivateKeyPath()); if (!Files.exists(keyDirectory)) { log.info("No existing keys found, generating new keypair"); @@ -99,7 +97,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface { b.getFileName().compareTo(a.getFileName())) // Most // recent // first - .collect(Collectors.toList()); + .toList(); } if (keyFiles.isEmpty()) { @@ -275,7 +273,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface { eligible); return eligible; }) - .collect(Collectors.toList()); + .toList(); } private String generateKeyId() { @@ -284,20 +282,17 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface { } private KeyPair generateRSAKeypair() { - KeyPairGenerator keyPairGenerator = null; - try { - keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); + return keyPairGenerator.generateKeyPair(); } catch (NoSuchAlgorithmException e) { - log.error("Failed to initialize RSA key pair generator", e); + throw new IllegalStateException("RSA key pair generator is not available", e); } - - return keyPairGenerator.generateKeyPair(); } private void ensurePrivateKeyDirectoryExists() throws IOException { - Path keyPath = Paths.get(InstallationPathConfig.getPrivateKeyPath()); + Path keyPath = Path.of(InstallationPathConfig.getPrivateKeyPath()); if (!Files.exists(keyPath)) { Files.createDirectories(keyPath); @@ -312,7 +307,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface { *

Public key stored as: keyId.pub */ private void storeKeyPair(String keyId, KeyPair keyPair) throws IOException { - Path keyDirectory = Paths.get(InstallationPathConfig.getPrivateKeyPath()); + Path keyDirectory = Path.of(InstallationPathConfig.getPrivateKeyPath()); // Store private key Path privateKeyFile = keyDirectory.resolve(keyId + KEY_SUFFIX); @@ -346,7 +341,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface { private PrivateKey loadPrivateKey(String keyId) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { Path keyFile = - Paths.get(InstallationPathConfig.getPrivateKeyPath()).resolve(keyId + KEY_SUFFIX); + Path.of(InstallationPathConfig.getPrivateKeyPath()).resolve(keyId + KEY_SUFFIX); if (!Files.exists(keyFile)) { throw new IOException("Private key not found: " + keyFile); @@ -369,8 +364,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface { */ private String loadPublicKey(String keyId) throws IOException { Path publicKeyFile = - Paths.get(InstallationPathConfig.getPrivateKeyPath()) - .resolve(keyId + PUB_KEY_SUFFIX); + Path.of(InstallationPathConfig.getPrivateKeyPath()).resolve(keyId + PUB_KEY_SUFFIX); if (!Files.exists(publicKeyFile)) { throw new IOException("Public key not found: " + publicKeyFile); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java index d715771b5..d3819c35d 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java @@ -5,7 +5,6 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import org.springframework.stereotype.Service; @@ -101,7 +100,7 @@ public class LoginAttemptService { return attemptsCache.entrySet().stream() .filter(entry -> entry.getValue().getAttemptCount() >= MAX_ATTEMPT) .map(Map.Entry::getKey) - .collect(Collectors.toList()); + .toList(); } public int getRemainingAttempts(String key) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/RefreshRateLimitService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/RefreshRateLimitService.java index bb4e45429..6c4321ed7 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/RefreshRateLimitService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/RefreshRateLimitService.java @@ -31,21 +31,14 @@ public class RefreshRateLimitService { this.jwtProperties = applicationProperties.getSecurity().getJwt(); } - private static class RefreshAttempt { - private final AtomicInteger count = new AtomicInteger(0); - private final Instant firstAttempt = Instant.now(); + private record RefreshAttempt(AtomicInteger count, Instant firstAttempt) { + RefreshAttempt() { + this(new AtomicInteger(0), Instant.now()); + } int incrementAndGet() { return count.incrementAndGet(); } - - Instant getFirstAttempt() { - return firstAttempt; - } - - int getCount() { - return count.get(); - } } private final Map attempts = new ConcurrentHashMap<>(); @@ -72,7 +65,7 @@ public class RefreshRateLimitService { // Clean up if outside grace window Instant cutoff = Instant.now().minusMillis(graceWindowMillis); - if (attempt.getFirstAttempt().isBefore(cutoff)) { + if (attempt.firstAttempt().isBefore(cutoff)) { attempts.remove(tokenHash); } @@ -98,15 +91,9 @@ public class RefreshRateLimitService { ? configuredMinutes : JwtConstants.DEFAULT_REFRESH_GRACE_MINUTES; Instant cutoff = Instant.now().minusMillis(graceMinutes * 60000L); - int removed = - attempts.entrySet().stream() - .filter(entry -> entry.getValue().getFirstAttempt().isBefore(cutoff)) - .mapToInt( - entry -> { - attempts.remove(entry.getKey()); - return 1; - }) - .sum(); + int beforeSize = attempts.size(); + attempts.entrySet().removeIf(entry -> entry.getValue().firstAttempt().isBefore(cutoff)); + int removed = beforeSize - attempts.size(); if (removed > 0) { log.debug("Cleaned up {} expired refresh tracking entries", removed); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/service/AuditService.java b/app/proprietary/src/main/java/stirling/software/proprietary/service/AuditService.java index 9f50b9f59..d86ae644e 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/service/AuditService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/service/AuditService.java @@ -11,7 +11,6 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.stream.Collectors; import java.util.stream.IntStream; import org.apache.commons.lang3.StringUtils; @@ -413,7 +412,7 @@ public class AuditService { return m; }) - .collect(Collectors.toList()); + .toList(); data.put("files", fileInfos); } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java b/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java index 01db79a5d..44d750e8e 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/service/ServerCertificateService.java @@ -4,7 +4,6 @@ import java.io.*; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.security.*; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @@ -64,7 +63,7 @@ public class ServerCertificateService implements ServerCertificateServiceInterfa } private Path getKeystorePath() { - return Paths.get(InstallationPathConfig.getConfigPath(), KEYSTORE_FILENAME); + return Path.of(InstallationPathConfig.getConfigPath(), KEYSTORE_FILENAME); } private boolean hasProOrEnterpriseAccess() { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java b/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java index 3b7c0ed5d..8d4dc52a9 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/service/SignatureService.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Base64; @@ -55,7 +54,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { @Override public byte[] getPersonalSignatureBytes(String username, String fileName) throws IOException { validateFileName(fileName); - Path userPath = Paths.get(SIGNATURE_BASE_PATH, username, fileName); + Path userPath = Path.of(SIGNATURE_BASE_PATH, username, fileName); if (!Files.exists(userPath)) { throw new FileNotFoundException("Personal signature not found"); @@ -76,7 +75,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { } String folderName = "shared".equals(scope) ? ALL_USERS_FOLDER : username; - Path targetFolder = Paths.get(SIGNATURE_BASE_PATH, folderName); + Path targetFolder = Path.of(SIGNATURE_BASE_PATH, folderName); // Only enforce limits for personal signatures (not shared) if ("personal".equals(scope)) { @@ -170,13 +169,13 @@ public class SignatureService implements PersonalSignatureServiceInterface { List signatures = new ArrayList<>(); // Load personal signatures - Path personalFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path personalFolder = Path.of(SIGNATURE_BASE_PATH, username); if (Files.exists(personalFolder)) { signatures.addAll(loadSignaturesFromFolder(personalFolder, "personal", true)); } // Load shared signatures - Path sharedFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); + Path sharedFolder = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); if (Files.exists(sharedFolder)) { signatures.addAll(loadSignaturesFromFolder(sharedFolder, "shared", false)); } @@ -189,7 +188,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { validateFileName(signatureId); // Only allow deletion from personal folder - Path personalFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path personalFolder = Path.of(SIGNATURE_BASE_PATH, username); boolean deleted = false; if (Files.exists(personalFolder)) { @@ -227,7 +226,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { validateFileName(signatureId); // Try personal folder first - Path personalFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path personalFolder = Path.of(SIGNATURE_BASE_PATH, username); Path metadataPath = personalFolder.resolve(signatureId + ".json"); if (Files.exists(metadataPath)) { @@ -237,7 +236,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { } // If not found in personal, try shared folder - Path sharedFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); + Path sharedFolder = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); Path sharedMetadataPath = sharedFolder.resolve(signatureId + ".json"); if (Files.exists(sharedMetadataPath)) { @@ -251,7 +250,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { public boolean isSharedSignature(String signatureId) { validateFileName(signatureId); - Path sharedFolder = Paths.get(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); + Path sharedFolder = Path.of(SIGNATURE_BASE_PATH, ALL_USERS_FOLDER); return Files.exists(sharedFolder.resolve(signatureId + ".json")); } @@ -274,7 +273,7 @@ public class SignatureService implements PersonalSignatureServiceInterface { // Private helper methods private void enforceStorageLimits(String username, String dataUrlToAdd) throws IOException { - Path userFolder = Paths.get(SIGNATURE_BASE_PATH, username); + Path userFolder = Path.of(SIGNATURE_BASE_PATH, username); if (!Files.exists(userFolder)) { return; // First signature, no limits to check diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/storage/config/StorageProviderConfig.java b/app/proprietary/src/main/java/stirling/software/proprietary/storage/config/StorageProviderConfig.java index e990fa2ce..db063cda8 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/storage/config/StorageProviderConfig.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/storage/config/StorageProviderConfig.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.storage.config; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Locale; import java.util.Optional; @@ -58,8 +57,8 @@ public class StorageProviderConfig { } basePathValue = InstallationPathConfig.getPath() + "storage"; } - Path basePath = Paths.get(basePathValue).toAbsolutePath().normalize(); - Path installRoot = Paths.get(InstallationPathConfig.getPath()).toAbsolutePath().normalize(); + Path basePath = Path.of(basePathValue).toAbsolutePath().normalize(); + Path installRoot = Path.of(InstallationPathConfig.getPath()).toAbsolutePath().normalize(); if (!basePath.startsWith(installRoot)) { // Warn rather than hard-fail: admins may legitimately point storage at an external // volume, but an unexpected path could indicate a misconfiguration or traversal diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/LocalStorageProvider.java b/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/LocalStorageProvider.java index 75f9eb3fd..b67b66f54 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/LocalStorageProvider.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/LocalStorageProvider.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Optional; import java.util.UUID; @@ -80,7 +79,7 @@ public class LocalStorageProvider implements StorageProvider { if (filename == null || filename.isBlank()) { return "file"; } - String stripped = Paths.get(filename).getFileName().toString().replaceAll("\\p{Cntrl}", ""); + String stripped = Path.of(filename).getFileName().toString().replaceAll("\\p{Cntrl}", ""); return stripped.isBlank() ? "file" : stripped; } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/S3StorageProvider.java b/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/S3StorageProvider.java index a1582458b..2b88d6484 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/S3StorageProvider.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/storage/provider/S3StorageProvider.java @@ -4,7 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; -import java.nio.file.Paths; +import java.nio.file.Path; import java.time.Duration; import java.util.Optional; import java.util.UUID; @@ -150,7 +150,7 @@ public class S3StorageProvider implements StorageProvider, AutoCloseable { if (originalFilename == null || originalFilename.isBlank()) { return null; } - // Strip CR/LF and other control chars before path parsing (Paths.get throws on them on + // Strip CR/LF and other control chars before path parsing (Path.of throws on them on // Windows, and they defeat header parsers). String stripped = originalFilename.replaceAll("\\p{Cntrl}", ""); // Use only the basename to avoid leaking directory structure into the header. @@ -184,7 +184,7 @@ public class S3StorageProvider implements StorageProvider, AutoCloseable { if (filename == null || filename.isBlank()) { return "file"; } - String stripped = Paths.get(filename).getFileName().toString().replaceAll("\\p{Cntrl}", ""); + String stripped = Path.of(filename).getFileName().toString().replaceAll("\\p{Cntrl}", ""); return stripped.isBlank() ? "file" : stripped; } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FileStorageService.java b/app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FileStorageService.java index 03c3a9178..37d1e5fa4 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FileStorageService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/storage/service/FileStorageService.java @@ -14,7 +14,6 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.regex.Pattern; -import java.util.stream.Collectors; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; @@ -361,7 +360,7 @@ public class FileStorageService { return files.stream() .sorted(Comparator.comparing(StoredFile::getCreatedAt).reversed()) .map(file -> buildResponse(file, user, roleByFileId.get(file.getId()))) - .collect(Collectors.toList()); + .toList(); } public StoredFileResponse getAccessibleFileResponse(User user, Long fileId) { @@ -400,7 +399,7 @@ public class FileStorageService { .filter(Objects::nonNull) .map(User::getUsername) .sorted(String.CASE_INSENSITIVE_ORDER) - .collect(Collectors.toList()) + .toList() : List.of(); List shareLinks = ownedByCurrentUser && isShareLinksEnabled() @@ -419,7 +418,7 @@ public class FileStorageService { .expiresAt(share.getExpiresAt()) .build()) .sorted(Comparator.comparing(ShareLinkResponse::getCreatedAt)) - .collect(Collectors.toList()) + .toList() : List.of(); List sharedUsers = ownedByCurrentUser @@ -440,7 +439,7 @@ public class FileStorageService { Comparator.comparing( SharedUserResponse::getUsername, String.CASE_INSENSITIVE_ORDER)) - .collect(Collectors.toList()) + .toList() : List.of(); return StoredFileResponse.builder() .id(file.getId()) @@ -762,7 +761,7 @@ public class FileStorageService { .accessType(access.getAccessType().name()) .accessedAt(access.getAccessedAt()) .build()) - .collect(Collectors.toList()); + .toList(); } public List listAccessedShareLinks(User user) { @@ -818,7 +817,7 @@ public class FileStorageService { .build(); }) .filter(response -> response.getShareToken() != null) - .collect(Collectors.toList()); + .toList(); } public void ensureSharingEnabled() { @@ -1007,7 +1006,7 @@ public class FileStorageService { file.getHistoryStorageKey(), file.getAuditLogStorageKey()) .filter(value -> value != null && !value.isBlank()) - .collect(Collectors.toList()); + .toList(); } private void cleanupStoredObject(StoredObject storedObject) { diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/controller/SigningSessionController.java b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/controller/SigningSessionController.java index 756fba1fe..2464b6ed6 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/controller/SigningSessionController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/controller/SigningSessionController.java @@ -76,7 +76,7 @@ public class SigningSessionController { .map( stirling.software.proprietary.workflow.util.WorkflowMapper ::toResponse) - .collect(java.util.stream.Collectors.toList()); + .toList(); return ResponseEntity.ok(responses); } catch (Exception e) { log.error("Error listing sessions for user {}", principal.getName(), e); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/SigningFinalizationService.java b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/SigningFinalizationService.java index aac9c180f..dc8469dc8 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/SigningFinalizationService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/SigningFinalizationService.java @@ -98,7 +98,7 @@ public class SigningFinalizationService { // Step 1.5: Add summary page BEFORE digital signing (if enabled) // CRITICAL: Must be done before signing to avoid invalidating signatures - if (Boolean.TRUE.equals(settings.includeSummaryPage)) { + if (Boolean.TRUE.equals(settings.includeSummaryPage())) { log.info( "Adding summary page before digital signing for session {}", session.getSessionId()); @@ -108,11 +108,13 @@ public class SigningFinalizationService { // Suppress digital certificate visual block when summary page is enabled // (wet signatures already applied in Step 1 and will still appear) Boolean showVisualSignature = - Boolean.TRUE.equals(settings.includeSummaryPage) ? false : settings.showSignature; + Boolean.TRUE.equals(settings.includeSummaryPage()) + ? false + : settings.showSignature(); log.info( "Finalization settings: includeSummaryPage={}, showVisualSignature={}", - settings.includeSummaryPage, + settings.includeSummaryPage(), showVisualSignature); // Step 2: Apply digital certificates per SIGNED participant @@ -150,8 +152,8 @@ public class SigningFinalizationService { log.info( "Applying signature for {} with reason='{}', location='{}'", fresh.getEmail(), - sigMeta.reason, - sigMeta.location); + sigMeta.reason(), + sigMeta.location()); pdf = applyDigitalSignature( @@ -159,10 +161,10 @@ public class SigningFinalizationService { fresh, submission, showVisualSignature, - settings.pageNumber, - sigMeta.reason, - sigMeta.location, - settings.showLogo); + settings.pageNumber(), + sigMeta.reason(), + sigMeta.location(), + settings.showLogo()); } return pdf; @@ -682,7 +684,7 @@ public class SigningFinalizationService { textDark, textMuted, "Subject:", - certInfo.subjectCN); + certInfo.subjectCN()); rRowY -= LINE_H; drawLabelValue( cs, @@ -693,7 +695,7 @@ public class SigningFinalizationService { textDark, textMuted, "Issuer:", - certInfo.issuerCN); + certInfo.issuerCN()); rRowY -= LINE_H; drawLabelValue( cs, @@ -704,7 +706,7 @@ public class SigningFinalizationService { textDark, textMuted, "Serial:", - certInfo.serialNumber); + certInfo.serialNumber()); rRowY -= LINE_H; drawLabelValue( cs, @@ -715,7 +717,7 @@ public class SigningFinalizationService { textDark, textMuted, "Valid From:", - certInfo.validFrom); + certInfo.validFrom()); rRowY -= LINE_H; drawLabelValue( cs, @@ -726,7 +728,7 @@ public class SigningFinalizationService { textDark, textMuted, "Valid Until:", - certInfo.validUntil); + certInfo.validUntil()); rRowY -= LINE_H; drawLabelValue( cs, @@ -737,7 +739,7 @@ public class SigningFinalizationService { textDark, textMuted, "Algorithm:", - certInfo.algorithm); + certInfo.algorithm()); } yPos -= cardH + 12; @@ -1075,10 +1077,9 @@ public class SigningFinalizationService { } String alias = aliases.nextElement(); Certificate cert = keystore.getCertificate(alias); - if (!(cert instanceof X509Certificate)) { + if (!(cert instanceof X509Certificate x509)) { return null; } - X509Certificate x509 = (X509Certificate) cert; String subjectCN = extractCN(x509.getSubjectX500Principal().getName()); String issuerCN = extractCN(x509.getIssuerX500Principal().getName()); @@ -1256,55 +1257,19 @@ public class SigningFinalizationService { // ===== PRIVATE INNER TYPES ===== - private static class SessionSignatureSettings { - final Boolean showSignature; - final Integer pageNumber; - final Boolean showLogo; - final Boolean includeSummaryPage; + private record SessionSignatureSettings( + Boolean showSignature, + Integer pageNumber, + Boolean showLogo, + Boolean includeSummaryPage) {} - SessionSignatureSettings( - Boolean showSignature, - Integer pageNumber, - Boolean showLogo, - Boolean includeSummaryPage) { - this.showSignature = showSignature; - this.pageNumber = pageNumber; - this.showLogo = showLogo; - this.includeSummaryPage = includeSummaryPage; - } - } + private record ParticipantSignatureMetadata(String reason, String location) {} - private static class ParticipantSignatureMetadata { - final String reason; - final String location; - - ParticipantSignatureMetadata(String reason, String location) { - this.reason = reason; - this.location = location; - } - } - - private static class CertificateInfo { - final String subjectCN; - final String issuerCN; - final String serialNumber; - final String validFrom; - final String validUntil; - final String algorithm; - - CertificateInfo( - String subjectCN, - String issuerCN, - String serialNumber, - String validFrom, - String validUntil, - String algorithm) { - this.subjectCN = subjectCN; - this.issuerCN = issuerCN; - this.serialNumber = serialNumber; - this.validFrom = validFrom; - this.validUntil = validUntil; - this.algorithm = algorithm; - } - } + private record CertificateInfo( + String subjectCN, + String issuerCN, + String serialNumber, + String validFrom, + String validUntil, + String algorithm) {} } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/WorkflowSessionService.java b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/WorkflowSessionService.java index e8887e2f5..dc22c4052 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/WorkflowSessionService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/WorkflowSessionService.java @@ -553,7 +553,7 @@ public class WorkflowSessionService { dto.setMyStatus(p.getStatus()); return dto; }) - .collect(java.util.stream.Collectors.toList()); + .toList(); } /** diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/util/WorkflowMapper.java b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/util/WorkflowMapper.java index 6be7197d5..b2f53c282 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/util/WorkflowMapper.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/util/WorkflowMapper.java @@ -3,7 +3,6 @@ package stirling.software.proprietary.workflow.util; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import com.fasterxml.jackson.databind.ObjectMapper; @@ -80,12 +79,12 @@ public class WorkflowMapper { response.setParticipants( session.getParticipants().stream() .map(p -> toParticipantResponse(p, objectMapper, includeShareTokens)) - .collect(Collectors.toList())); + .toList()); } else { response.setParticipants( session.getParticipants().stream() .map(p -> toParticipantResponse(p, includeShareTokens)) - .collect(Collectors.toList())); + .toList()); } // Calculate participant counts diff --git a/scripts/PropSync.java b/scripts/PropSync.java index 2c78f64c0..5fce1c33a 100644 --- a/scripts/PropSync.java +++ b/scripts/PropSync.java @@ -12,7 +12,7 @@ public class PropSync { File folder = new File("C:\\Users\\systo\\git\\Stirling-PDF\\app\\core\\src\\main\\resources"); File[] files = folder.listFiles((dir, name) -> name.matches("messages_.*\\.properties")); - List enLines = Files.readAllLines(Paths.get(folder + "\\messages_en_GB.properties"), StandardCharsets.UTF_8); + List enLines = Files.readAllLines(Path.of(folder + "\\messages_en_GB.properties"), StandardCharsets.UTF_8); Map enProps = linesToProps(enLines); for (File file : files) { diff --git a/scripts/RestartHelper.java b/scripts/RestartHelper.java index 322beb522..fe48dd703 100644 --- a/scripts/RestartHelper.java +++ b/scripts/RestartHelper.java @@ -19,9 +19,9 @@ public class RestartHelper { Map cli = parseArgs(args); long pid = Long.parseLong(req(cli, "pid")); - Path appJar = Paths.get(req(cli, "app")).toAbsolutePath().normalize(); + Path appJar = Path.of(req(cli, "app")).toAbsolutePath().normalize(); String javaBin = cli.getOrDefault("java", "java"); - Path argsFile = cli.containsKey("argsFile") ? Paths.get(cli.get("argsFile")) : null; + Path argsFile = cli.containsKey("argsFile") ? Path.of(cli.get("argsFile")) : null; long backoffMs = Long.parseLong(cli.getOrDefault("backoffMs", "1000")); if (!Files.isRegularFile(appJar)) {