diff --git a/app/common/src/main/java/stirling/software/common/util/ChecksumUtils.java b/app/common/src/main/java/stirling/software/common/util/ChecksumUtils.java index ab39ca5da8..16cd26add0 100644 --- a/app/common/src/main/java/stirling/software/common/util/ChecksumUtils.java +++ b/app/common/src/main/java/stirling/software/common/util/ChecksumUtils.java @@ -140,20 +140,25 @@ public class ChecksumUtils { for (String algorithm : algorithms) { String key = algorithm; // keep original key for output - switch (algorithm.toUpperCase(Locale.ROOT)) { - case "CRC32": - checksums.put(key, new CRC32()); - break; - case "ADLER32": - checksums.put(key, new Adler32()); - break; - default: - try { - // For MessageDigest, pass the original name (case-insensitive per JCA) - digests.put(key, MessageDigest.getInstance(algorithm)); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("Unsupported algorithm: " + algorithm, e); - } + Object digestOrChecksum = + switch (algorithm.toUpperCase(Locale.ROOT)) { + case "CRC32" -> new CRC32(); + case "ADLER32" -> new Adler32(); + default -> { + try { + // For MessageDigest, pass the original name (case-insensitive + // per JCA) + yield MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException( + "Unsupported algorithm: " + algorithm, e); + } + } + }; + if (digestOrChecksum instanceof Checksum checksum) { + checksums.put(key, checksum); + } else { + digests.put(key, (MessageDigest) digestOrChecksum); } } diff --git a/app/common/src/test/java/stirling/software/common/util/PDFToFileTest.java b/app/common/src/test/java/stirling/software/common/util/PDFToFileTest.java index 4ec7164514..b3491f7183 100644 --- a/app/common/src/test/java/stirling/software/common/util/PDFToFileTest.java +++ b/app/common/src/test/java/stirling/software/common/util/PDFToFileTest.java @@ -721,7 +721,7 @@ class PDFToFileTest { .thenAnswer( invocation -> { List args = invocation.getArgument(0); - String outputPath = args.get(args.size() - 1); + String outputPath = args.getLast(); Files.write(Path.of(outputPath), "Fake DOCX content".getBytes()); return mockExecutorResult; }); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java index 9408aa821f..06d56e58fe 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/MergeController.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; -import java.util.regex.Pattern; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentCatalog; @@ -58,8 +57,6 @@ import stirling.software.jpdfium.doc.PdfBookmarkEditor.BookmarkTree; @Slf4j @RequiredArgsConstructor public class MergeController { - - private static final Pattern QUOTE_WRAP_PATTERN = Pattern.compile("^\"|\"$"); private final CustomPDFDocumentFactory pdfDocumentFactory; private final TempFileManager tempFileManager; @@ -161,30 +158,6 @@ public class MergeController { }; } - private String[] parseClientFileIds(String clientFileIds) { - if (clientFileIds == null || clientFileIds.trim().isEmpty()) { - return new String[0]; - } - try { - String trimmed = clientFileIds.trim(); - if (trimmed.startsWith("[") && trimmed.endsWith("]")) { - String inside = trimmed.substring(1, trimmed.length() - 1).trim(); - if (inside.isEmpty()) { - return new String[0]; - } - String[] parts = inside.split(","); - String[] result = new String[parts.length]; - for (int i = 0; i < parts.length; i++) { - result[i] = QUOTE_WRAP_PATTERN.matcher(parts[i].trim()).replaceAll(""); - } - return result; - } - } catch (Exception e) { - log.warn("Failed to parse client file IDs: {}", clientFileIds, e); - } - return new String[0]; - } - private void addTableOfContents(PDDocument mergedDocument, MultipartFile[] files) { PDDocumentOutline outline = new PDDocumentOutline(); mergedDocument.getDocumentCatalog().setDocumentOutline(outline); diff --git a/app/core/src/test/java/stirling/software/SPDF/config/MultipartConfigurationTest.java b/app/core/src/test/java/stirling/software/SPDF/config/MultipartConfigurationTest.java index 60b17a3534..276afbbe99 100644 --- a/app/core/src/test/java/stirling/software/SPDF/config/MultipartConfigurationTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/config/MultipartConfigurationTest.java @@ -4,8 +4,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.lang.reflect.Field; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -24,10 +22,7 @@ class MultipartConfigurationTest { void setUp() throws Exception { // Manually constructed config with a mocked service, so Spring env overrides do not apply. uploadLimitService = mock(UploadLimitService.class); - configuration = new MultipartConfiguration(); - Field field = MultipartConfiguration.class.getDeclaredField("uploadLimitService"); - field.setAccessible(true); - field.set(configuration, uploadLimitService); + configuration = new MultipartConfiguration(uploadLimitService); } @Nested diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeControllerTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeControllerTest.java index 90b6a370de..14c49b351a 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeControllerTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeControllerTest.java @@ -204,7 +204,7 @@ class ConvertOfficeControllerTest { inv -> { // unoconvert writes directly to the output path (last arg) List command = inv.getArgument(0); - Path out = Path.of(command.get(command.size() - 1)); + Path out = Path.of(command.getLast()); Files.writeString(out, "%PDF-1.4 produced"); return result; }); @@ -239,7 +239,7 @@ class ConvertOfficeControllerTest { inv -> { // soffice writes .pdf into the --outdir (workDir) List command = inv.getArgument(0); - Path inputPath = Path.of(command.get(command.size() - 1)); + Path inputPath = Path.of(command.getLast()); Path out = inputPath.getParent().resolve("report.pdf"); Files.writeString(out, "%PDF soffice"); return result; @@ -311,7 +311,7 @@ class ConvertOfficeControllerTest { .thenAnswer( inv -> { List command = inv.getArgument(0); - Path inputPath = Path.of(command.get(command.size() - 1)); + Path inputPath = Path.of(command.getLast()); Path out = inputPath.getParent().resolve("report.pdf"); Files.write(out, new byte[0]); return result; @@ -344,7 +344,7 @@ class ConvertOfficeControllerTest { .thenAnswer( inv -> { List command = inv.getArgument(0); - Path inputPath = Path.of(command.get(command.size() - 1)); + Path inputPath = Path.of(command.getLast()); Path out = inputPath.getParent().resolve("page.pdf"); Files.writeString(out, "%PDF html"); return result; @@ -398,7 +398,7 @@ class ConvertOfficeControllerTest { .thenAnswer( inv -> { List command = inv.getArgument(0); - Path inputPath = Path.of(command.get(command.size() - 1)); + Path inputPath = Path.of(command.getLast()); Path out = inputPath.getParent().resolve("report.pdf"); Files.writeString(out, "%PDF produced"); return result; diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFAMoreTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFAMoreTest.java index 31bbc9e1f8..e9d9b9ce1d 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFAMoreTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFAMoreTest.java @@ -197,7 +197,7 @@ class ConvertPDFToPDFAMoreTest { // qpdf normalize/clean writes its (last-arg) output file if (command.contains("--normalize-content=y")) { // qpdf produced file is the last argument - Path out = Path.of(command.get(command.size() - 1)); + Path out = Path.of(command.getLast()); Files.write(out, simplePdfBytes()); } return okResult; diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPdfToVideoControllerTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPdfToVideoControllerTest.java index 7a46611443..52104df48e 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPdfToVideoControllerTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertPdfToVideoControllerTest.java @@ -262,7 +262,7 @@ class ConvertPdfToVideoControllerTest { assertTrue(command.contains("+faststart")); assertFalse(command.contains("libvpx-vp9")); // Output path is always the last argument. - assertEquals(backing.getAbsolutePath(), command.get(command.size() - 1)); + assertEquals(backing.getAbsolutePath(), command.getLast()); } @Test @@ -278,7 +278,7 @@ class ConvertPdfToVideoControllerTest { assertTrue(command.contains("30")); assertFalse(command.contains("libx264")); assertFalse(command.contains("+faststart")); - assertEquals(backing.getAbsolutePath(), command.get(command.size() - 1)); + assertEquals(backing.getAbsolutePath(), command.getLast()); } @Test diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/CompressControllerMoreTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/CompressControllerMoreTest.java index b8f4e51b3f..4393c19e3f 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/CompressControllerMoreTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/CompressControllerMoreTest.java @@ -195,7 +195,7 @@ class CompressControllerMoreTest { // The qpdf output path is the last argument of the command. private static Path qpdfOutputPath(List command) { - return Path.of(command.get(command.size() - 1)); + return Path.of(command.getLast()); } /** Stub gs to write a valid PDF to its output file and report success. */ diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RemoveImagesControllerTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RemoveImagesControllerTest.java index 1a97cc1a55..db361b4302 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RemoveImagesControllerTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RemoveImagesControllerTest.java @@ -162,7 +162,7 @@ class RemoveImagesControllerTest { /** Counts every PDImageXObject reachable through page + nested form resources. */ private int countImagesInSavedOutput() throws IOException { assertFalse(savedTempFiles.isEmpty(), "expected the controller to create a temp file"); - File out = savedTempFiles.get(savedTempFiles.size() - 1); + File out = savedTempFiles.getLast(); try (PDDocument doc = Loader.loadPDF(out)) { int count = 0; for (PDPage page : doc.getPages()) { @@ -245,7 +245,7 @@ class RemoveImagesControllerTest { assertEquals(0, countImagesInSavedOutput()); // page count must be preserved - File out = savedTempFiles.get(savedTempFiles.size() - 1); + File out = savedTempFiles.getLast(); try (PDDocument result = Loader.loadPDF(out)) { assertEquals(3, result.getNumberOfPages()); } diff --git a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RepairControllerMoreTest.java b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RepairControllerMoreTest.java index 6565a84875..f564dafb11 100644 --- a/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RepairControllerMoreTest.java +++ b/app/core/src/test/java/stirling/software/SPDF/controller/api/misc/RepairControllerMoreTest.java @@ -98,12 +98,8 @@ class RepairControllerMoreTest { } } - /** - * Writes a valid PDF to the path at the given command index, mimicking a successful tool run. - */ - private static void writeValidPdfTo(List command, int outputPathIndex) - throws Exception { - Path out = Path.of(command.get(outputPathIndex)); + /** Writes a valid PDF to the given output path, mimicking a successful tool run. */ + private static void writeValidPdfTo(Path out) throws Exception { byte[] pdf = buildPdfBytes(1); Files.write(out, pdf); } @@ -133,7 +129,7 @@ class RepairControllerMoreTest { .thenAnswer( inv -> { List cmd = inv.getArgument(0); - writeValidPdfTo(cmd, 2); + writeValidPdfTo(Path.of(cmd.get(2))); return okResult; }); @@ -176,7 +172,7 @@ class RepairControllerMoreTest { .thenAnswer( inv -> { List cmd = inv.getArgument(0); - writeValidPdfTo(cmd, cmd.size() - 1); + writeValidPdfTo(Path.of(cmd.getLast())); return okResult; }); @@ -216,7 +212,7 @@ class RepairControllerMoreTest { .thenAnswer( inv -> { List cmd = inv.getArgument(0); - writeValidPdfTo(cmd, cmd.size() - 1); + writeValidPdfTo(Path.of(cmd.getLast())); return okResult; }); @@ -256,7 +252,7 @@ class RepairControllerMoreTest { .thenAnswer( inv -> { List cmd = inv.getArgument(0); - writeValidPdfTo(cmd, cmd.size() - 1); + writeValidPdfTo(Path.of(cmd.getLast())); return okResult; }); 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 3232f76e07..7376795c66 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 @@ -143,19 +143,12 @@ public class AuditRestController { @RequestParam(value = "period", defaultValue = "week") String period) { // Calculate days based on period - int days; - switch (period.toLowerCase()) { - case "day": - days = 1; - break; - case "month": - days = 30; - break; - case "week": - default: - days = 7; - break; - } + int days = + switch (period.toLowerCase()) { + case "day" -> 1; + case "month" -> 30; + default -> 7; + }; // Get events from the specified period Instant startDate = Instant.now().minus(java.time.Duration.ofDays(days)); @@ -269,19 +262,12 @@ public class AuditRestController { @RequestParam(value = "period", defaultValue = "week") String period) { // Calculate days based on period - int days; - switch (period.toLowerCase()) { - case "day": - days = 1; - break; - case "month": - days = 30; - break; - case "week": - default: - days = 7; - break; - } + int days = + switch (period.toLowerCase()) { + case "day" -> 1; + case "month" -> 30; + default -> 7; + }; // Get events from the specified period and previous period Instant now = Instant.now(); diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/UnifiedAccessControlService.java b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/UnifiedAccessControlService.java index 57ad1c97e7..dd3fcb9cc3 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/UnifiedAccessControlService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/workflow/service/UnifiedAccessControlService.java @@ -119,20 +119,18 @@ public class UnifiedAccessControlService { public ShareAccessRole getEffectiveRole(WorkflowParticipant participant) { ParticipantStatus status = participant.getStatus(); - switch (status) { - case SIGNED: - case DECLINED: - // After action completed, downgrade to read-only - return ShareAccessRole.VIEWER; - case PENDING: - case NOTIFIED: - case VIEWED: - // Active participants retain their assigned role - return participant.getAccessRole(); - default: + return switch (status) { + case SIGNED, DECLINED -> + // After action completed, downgrade to read-only + ShareAccessRole.VIEWER; + case PENDING, NOTIFIED, VIEWED -> + // Active participants retain their assigned role + participant.getAccessRole(); + default -> { log.warn("Unknown participant status: {}", status); - return ShareAccessRole.VIEWER; - } + yield ShareAccessRole.VIEWER; + } + }; } /** Checks if a user can access a specific file */ diff --git a/app/saas/src/main/java/stirling/software/saas/accountlink/AccountLinkController.java b/app/saas/src/main/java/stirling/software/saas/accountlink/AccountLinkController.java index 91974a6d04..98a234a8dc 100644 --- a/app/saas/src/main/java/stirling/software/saas/accountlink/AccountLinkController.java +++ b/app/saas/src/main/java/stirling/software/saas/accountlink/AccountLinkController.java @@ -152,7 +152,7 @@ public class AccountLinkController { if (rows.isEmpty()) { return new LeaderTeam(null, null, HttpStatus.FORBIDDEN); } - TeamMembership m = rows.get(0); + TeamMembership m = rows.getFirst(); if (m.getRole() != TeamRole.LEADER) { return new LeaderTeam(null, null, HttpStatus.FORBIDDEN); } diff --git a/app/saas/src/main/java/stirling/software/saas/payg/api/PaygInvoicesController.java b/app/saas/src/main/java/stirling/software/saas/payg/api/PaygInvoicesController.java index 6b8bb2c883..aa2bd4ee33 100644 --- a/app/saas/src/main/java/stirling/software/saas/payg/api/PaygInvoicesController.java +++ b/app/saas/src/main/java/stirling/software/saas/payg/api/PaygInvoicesController.java @@ -105,7 +105,7 @@ public class PaygInvoicesController { if (rows.isEmpty()) { return ResponseEntity.ok(List.of()); } - Long teamId = rows.get(0).getTeam().getId(); + Long teamId = rows.getFirst().getTeam().getId(); // No PAYG extension row OR no Stripe customer id → team has never subscribed → no // invoices. Empty list, not 404 — the UI distinguishes "no invoices yet" from a diff --git a/app/saas/src/main/java/stirling/software/saas/payg/api/PaygPaymentMethodController.java b/app/saas/src/main/java/stirling/software/saas/payg/api/PaygPaymentMethodController.java index 724d6715d3..879bffe340 100644 --- a/app/saas/src/main/java/stirling/software/saas/payg/api/PaygPaymentMethodController.java +++ b/app/saas/src/main/java/stirling/software/saas/payg/api/PaygPaymentMethodController.java @@ -85,7 +85,7 @@ public class PaygPaymentMethodController { if (rows.isEmpty()) { return ResponseEntity.ok(PaymentMethodResponse.absent()); } - Long teamId = rows.get(0).getTeam().getId(); + Long teamId = rows.getFirst().getTeam().getId(); Optional ext = extRepo.findById(teamId); if (ext.isEmpty() || ext.get().getStripeCustomerId() == null) { diff --git a/app/saas/src/main/java/stirling/software/saas/payg/api/PaygWalletController.java b/app/saas/src/main/java/stirling/software/saas/payg/api/PaygWalletController.java index 041eaa8f4a..7998ef5ee5 100644 --- a/app/saas/src/main/java/stirling/software/saas/payg/api/PaygWalletController.java +++ b/app/saas/src/main/java/stirling/software/saas/payg/api/PaygWalletController.java @@ -334,7 +334,7 @@ public class PaygWalletController { private Optional primaryMembership(Long userId) { List rows = memberRepo.findPrimaryMembership(userId); - return rows.isEmpty() ? Optional.empty() : Optional.of(rows.get(0)); + return rows.isEmpty() ? Optional.empty() : Optional.of(rows.getFirst()); } private List buildMemberRows(