Refactor Path Handling (#3041)

# Description of Changes

Please provide a summary of the changes, including:

What was changed:

- Refactored path constructions in multiple classes (e.g.,
SPDFApplication.java, InstallationPathConfig.java,
RuntimePathConfig.java) to use Java NIO’s Paths.get() and Path.of()
instead of manual string concatenation.


Why the change was made:

- To improve code readability, maintainability, and robustness by
leveraging modern Java NIO utilities.
- To ensure better portability across different operating systems by
avoiding hardcoded file separators.


Challenges encountered:

- Maintaining backward compatibility while transitioning from manual
string concatenation to using Paths for file path construction.
- Ensuring that the refactored path resolution works consistently across
all supported environments (Windows, macOS, Linux, and Docker).

@Frooodle can you check the docker path `/.dockerenv`?

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [x] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Ludy 2025-02-25 22:31:20 +01:00 committed by GitHub
parent f64d7d42d9
commit a1f7bb3e4a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 68 additions and 69 deletions

View File

@ -83,18 +83,17 @@ public class SPDFApplication {
Map<String, String> propertyFiles = new HashMap<>(); Map<String, String> propertyFiles = new HashMap<>();
// External config files // External config files
log.info("Settings file: {}", InstallationPathConfig.getSettingsPath()); String settingsPath = InstallationPathConfig.getSettingsPath();
if (Files.exists(Paths.get(InstallationPathConfig.getSettingsPath()))) { log.info("Settings file: {}", settingsPath);
propertyFiles.put( if (Files.exists(Paths.get(settingsPath))) {
"spring.config.additional-location", propertyFiles.put("spring.config.additional-location", "file:" + settingsPath);
"file:" + InstallationPathConfig.getSettingsPath());
} else { } else {
log.warn( log.warn("External configuration file '{}' does not exist.", settingsPath);
"External configuration file '{}' does not exist.",
InstallationPathConfig.getSettingsPath());
} }
if (Files.exists(Paths.get(InstallationPathConfig.getCustomSettingsPath()))) { String customSettingsPath = InstallationPathConfig.getCustomSettingsPath();
log.info("Custom settings file: {}", customSettingsPath);
if (Files.exists(Paths.get(customSettingsPath))) {
String existingLocation = String existingLocation =
propertyFiles.getOrDefault("spring.config.additional-location", ""); propertyFiles.getOrDefault("spring.config.additional-location", "");
if (!existingLocation.isEmpty()) { if (!existingLocation.isEmpty()) {
@ -102,11 +101,9 @@ public class SPDFApplication {
} }
propertyFiles.put( propertyFiles.put(
"spring.config.additional-location", "spring.config.additional-location",
existingLocation + "file:" + InstallationPathConfig.getCustomSettingsPath()); existingLocation + "file:" + customSettingsPath);
} else { } else {
log.warn( log.warn("Custom configuration file '{}' does not exist.", customSettingsPath);
"Custom configuration file '{}' does not exist.",
InstallationPathConfig.getCustomSettingsPath());
} }
Properties finalProps = new Properties(); Properties finalProps = new Properties();
@ -128,7 +125,7 @@ public class SPDFApplication {
try { try {
Files.createDirectories(Path.of(InstallationPathConfig.getTemplatesPath())); Files.createDirectories(Path.of(InstallationPathConfig.getTemplatesPath()));
Files.createDirectories(Path.of(InstallationPathConfig.getStaticPath())); Files.createDirectories(Path.of(InstallationPathConfig.getStaticPath()));
} catch (Exception e) { } catch (IOException e) {
log.error("Error creating directories: {}", e.getMessage()); log.error("Error creating directories: {}", e.getMessage());
} }

View File

@ -1,6 +1,7 @@
package stirling.software.SPDF.config; package stirling.software.SPDF.config;
import java.io.File; import java.io.File;
import java.nio.file.Paths;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -46,26 +47,29 @@ public class InstallationPathConfig {
if (Boolean.parseBoolean(System.getProperty("STIRLING_PDF_DESKTOP_UI", "false"))) { if (Boolean.parseBoolean(System.getProperty("STIRLING_PDF_DESKTOP_UI", "false"))) {
String os = System.getProperty("os.name").toLowerCase(); String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) { if (os.contains("win")) {
return System.getenv("APPDATA") + File.separator + "Stirling-PDF" + File.separator; return Paths.get(
System.getenv("APPDATA"), // parent path
"Stirling-PDF")
.toString()
+ File.separator;
} else if (os.contains("mac")) { } else if (os.contains("mac")) {
return System.getProperty("user.home") return Paths.get(
+ File.separator System.getProperty("user.home"),
+ "Library" "Library",
+ File.separator "Application Support",
+ "Application Support" "Stirling-PDF")
+ File.separator .toString()
+ "Stirling-PDF"
+ File.separator; + File.separator;
} else { } else {
return System.getProperty("user.home") return Paths.get(
+ File.separator System.getProperty("user.home"), // parent path
+ ".config" ".config",
+ File.separator "Stirling-PDF")
+ "Stirling-PDF" .toString()
+ File.separator; + File.separator;
} }
} }
return "./"; return "." + File.separator;
} }
public static String getPath() { public static String getPath() {

View File

@ -1,8 +1,7 @@
package stirling.software.SPDF.config; package stirling.software.SPDF.config;
import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Path;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -33,52 +32,48 @@ public class RuntimePathConfig {
this.properties = properties; this.properties = properties;
this.basePath = InstallationPathConfig.getPath(); this.basePath = InstallationPathConfig.getPath();
String pipelinePath = basePath + "pipeline" + File.separator; this.pipelinePath = Path.of(basePath, "pipeline").toString();
String watchedFoldersPath = pipelinePath + "watchedFolders" + File.separator; String defaultWatchedFolders = Path.of(this.pipelinePath, "watchedFolders").toString();
String finishedFoldersPath = pipelinePath + "finishedFolders" + File.separator; String defaultFinishedFolders = Path.of(this.pipelinePath, "finishedFolders").toString();
String webUiConfigsPath = pipelinePath + "defaultWebUIConfigs" + File.separator; String defaultWebUIConfigs = Path.of(this.pipelinePath, "defaultWebUIConfigs").toString();
Pipeline pipeline = properties.getSystem().getCustomPaths().getPipeline(); Pipeline pipeline = properties.getSystem().getCustomPaths().getPipeline();
if (pipeline != null) {
if (!StringUtils.isEmpty(pipeline.getWatchedFoldersDir())) {
watchedFoldersPath = pipeline.getWatchedFoldersDir();
}
if (!StringUtils.isEmpty(pipeline.getFinishedFoldersDir())) {
finishedFoldersPath = pipeline.getFinishedFoldersDir();
}
if (!StringUtils.isEmpty(pipeline.getWebUIConfigsDir())) {
webUiConfigsPath = pipeline.getWebUIConfigsDir();
}
}
this.pipelinePath = pipelinePath; this.pipelineWatchedFoldersPath =
this.pipelineWatchedFoldersPath = watchedFoldersPath; resolvePath(
this.pipelineFinishedFoldersPath = finishedFoldersPath; defaultWatchedFolders,
this.pipelineDefaultWebUiConfigs = webUiConfigsPath; pipeline != null ? pipeline.getWatchedFoldersDir() : null);
this.pipelineFinishedFoldersPath =
resolvePath(
defaultFinishedFolders,
pipeline != null ? pipeline.getFinishedFoldersDir() : null);
this.pipelineDefaultWebUiConfigs =
resolvePath(
defaultWebUIConfigs,
pipeline != null ? pipeline.getWebUIConfigsDir() : null);
boolean isDocker = isRunningInDocker(); boolean isDocker = isRunningInDocker();
// Initialize Operation paths // Initialize Operation paths
String weasyPrintPath = isDocker ? "/opt/venv/bin/weasyprint" : "weasyprint"; String defaultWeasyPrintPath = isDocker ? "/opt/venv/bin/weasyprint" : "weasyprint";
String unoConvertPath = isDocker ? "/opt/venv/bin/unoconvert" : "unoconvert"; String defaultUnoConvertPath = isDocker ? "/opt/venv/bin/unoconvert" : "unoconvert";
// Check for custom operation paths
Operations operations = properties.getSystem().getCustomPaths().getOperations(); Operations operations = properties.getSystem().getCustomPaths().getOperations();
if (operations != null) { this.weasyPrintPath =
if (!StringUtils.isEmpty(operations.getWeasyprint())) { resolvePath(
weasyPrintPath = operations.getWeasyprint(); defaultWeasyPrintPath,
} operations != null ? operations.getWeasyprint() : null);
if (!StringUtils.isEmpty(operations.getUnoconvert())) { this.unoConvertPath =
unoConvertPath = operations.getUnoconvert(); resolvePath(
} defaultUnoConvertPath,
} operations != null ? operations.getUnoconvert() : null);
}
// Assign operations final fields private String resolvePath(String defaultPath, String customPath) {
this.weasyPrintPath = weasyPrintPath; return StringUtils.isNotBlank(customPath) ? customPath : defaultPath;
this.unoConvertPath = unoConvertPath;
} }
private boolean isRunningInDocker() { private boolean isRunningInDocker() {
return Files.exists(Paths.get("/.dockerenv")); return Files.exists(Path.of("/.dockerenv"));
} }
} }

View File

@ -1,7 +1,5 @@
package stirling.software.SPDF.config.security.database; package stirling.software.SPDF.config.security.database;
import java.io.File;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -37,8 +35,8 @@ public class DatabaseConfig {
DATASOURCE_DEFAULT_URL = DATASOURCE_DEFAULT_URL =
"jdbc:h2:file:" "jdbc:h2:file:"
+ InstallationPathConfig.getConfigPath() + InstallationPathConfig.getConfigPath()
+ File.separator
+ "stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"; + "stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE";
log.debug("Database URL: {}", DATASOURCE_DEFAULT_URL);
this.applicationProperties = applicationProperties; this.applicationProperties = applicationProperties;
this.runningEE = runningEE; this.runningEE = runningEE;
} }

View File

@ -230,7 +230,11 @@ public class GeneralWebController {
// Extract font names from external directory // Extract font names from external directory
fontNames.addAll( fontNames.addAll(
getFontNamesFromLocation( getFontNamesFromLocation(
"file:" + InstallationPathConfig.getStaticPath() + "fonts/*")); "file:"
+ InstallationPathConfig.getStaticPath()
+ "fonts"
+ File.separator
+ "*"));
return fontNames; return fontNames;
} }

View File

@ -49,7 +49,8 @@ public class FileMonitor {
this.pathFilter = pathFilter; this.pathFilter = pathFilter;
this.readyForProcessingFiles = ConcurrentHashMap.newKeySet(); this.readyForProcessingFiles = ConcurrentHashMap.newKeySet();
this.watchService = FileSystems.getDefault().newWatchService(); this.watchService = FileSystems.getDefault().newWatchService();
this.rootDir = Path.of(runtimePathConfig.getPipelineWatchedFoldersPath()).toAbsolutePath(); log.info("Monitoring directory: {}", runtimePathConfig.getPipelineWatchedFoldersPath());
this.rootDir = Path.of(runtimePathConfig.getPipelineWatchedFoldersPath());
} }
private boolean shouldNotProcess(Path path) { private boolean shouldNotProcess(Path path) {