Update SaaS to latest main (#6667)

# Description of Changes
> [!warning]
> **Do not** squash this on merge. It should be merged via a merge
commit

Fixes conflicts in `pgvector_store.py`. 

Also since codespell is failing, add comments to ignore the errors in
`sync_en_us_spelling.py`

---------

Co-authored-by: Ludy <[email protected]>
Co-authored-by: Anthony Stirling <[email protected]>
This commit is contained in:
James Brunton
2026-06-15 14:53:22 +01:00
committed by GitHub
co-authored by Ludy Anthony Stirling
79 changed files with 379 additions and 346 deletions
@@ -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<String, String> 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 =
@@ -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
@@ -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<Path> paths =
Files.walk(Paths.get(runtimePathConfig.getPipelineDefaultWebUiConfigs()))) {
Files.walk(Path.of(runtimePathConfig.getPipelineDefaultWebUiConfigs()))) {
List<Path> jsonFiles =
paths.filter(Files::isRegularFile)
.filter(p -> p.toString().endsWith(".json"))
@@ -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);
}
@@ -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<File> filesToProcess, Path processingDir)
@@ -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<Resource> 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)) {
@@ -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());
}
@@ -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(
@@ -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<SavedSignatureResponse> 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<Path> 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<Path> 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<Path> stream = Files.list(sharedFolder)) {
List<Path> matchingFiles =
@@ -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) {
@@ -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)) {
@@ -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<Path> waitForPipelineOutputs(PipelineFileInfo info) throws IOException {
Path finishedDir = Paths.get(runtimePathConfig.getPipelineFinishedFoldersPath());
Path finishedDir = Path.of(runtimePathConfig.getPipelineFinishedFoldersPath());
Files.createDirectories(finishedDir);
Instant start = info.savedAt();
@@ -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());