package stirling.software.SPDF.config; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; @Configuration @Slf4j public class ExternalAppDepConfig { @Autowired private EndpointConfiguration endpointConfiguration; private boolean isCommandAvailable(String command) { try { ProcessBuilder processBuilder = new ProcessBuilder(); if (System.getProperty("os.name").toLowerCase().contains("windows")) { processBuilder.command("where", command); } else { processBuilder.command("which", command); } Process process = processBuilder.start(); int exitCode = process.waitFor(); return exitCode == 0; } catch (Exception e) { log.debug("Error checking for command {}: {}", command, e.getMessage()); return false; } } private final Map> commandToGroupMapping = new HashMap<>() { { put("soffice", List.of("LibreOffice")); put("weasyprint", List.of("Weasyprint")); put("pdftohtml", List.of("Pdftohtml")); put("unoconv", List.of("Unoconv")); put("qpdf", List.of("qpdf")); } }; private List getAffectedFeatures(String group) { return endpointConfiguration.getEndpointsForGroup(group).stream() .map(endpoint -> formatEndpointAsFeature(endpoint)) .collect(Collectors.toList()); } private String formatEndpointAsFeature(String endpoint) { // First replace common terms String feature = endpoint.replace("-", " ").replace("pdf", "PDF").replace("img", "image"); // Split into words and capitalize each word return Arrays.stream(feature.split("\\s+")) .map(word -> capitalizeWord(word)) .collect(Collectors.joining(" ")); } private String capitalizeWord(String word) { if (word.isEmpty()) { return word; } if ("pdf".equalsIgnoreCase(word)) { return "PDF"; } return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase(); } private void checkDependencyAndDisableGroup(String command) { boolean isAvailable = isCommandAvailable(command); if (!isAvailable) { List affectedGroups = commandToGroupMapping.get(command); if (affectedGroups != null) { for (String group : affectedGroups) { List affectedFeatures = getAffectedFeatures(group); endpointConfiguration.disableGroup(group); log.warn( "Missing dependency: {} - Disabling group: {} (Affected features: {})", command, group, affectedFeatures != null && !affectedFeatures.isEmpty() ? String.join(", ", affectedFeatures) : "unknown"); } } } } @PostConstruct public void checkDependencies() { // Check core dependencies checkDependencyAndDisableGroup("soffice"); checkDependencyAndDisableGroup("qpdf"); checkDependencyAndDisableGroup("weasyprint"); checkDependencyAndDisableGroup("pdftohtml"); checkDependencyAndDisableGroup("unoconv"); // Special handling for Python/OpenCV dependencies boolean pythonAvailable = isCommandAvailable("python3") || isCommandAvailable("python"); if (!pythonAvailable) { List pythonFeatures = getAffectedFeatures("Python"); List openCVFeatures = getAffectedFeatures("OpenCV"); endpointConfiguration.disableGroup("Python"); endpointConfiguration.disableGroup("OpenCV"); log.warn( "Missing dependency: Python - Disabling Python features: {} and OpenCV features: {}", String.join(", ", pythonFeatures), String.join(", ", openCVFeatures)); } else { // If Python is available, check for OpenCV try { ProcessBuilder processBuilder = new ProcessBuilder(); if (System.getProperty("os.name").toLowerCase().contains("windows")) { processBuilder.command("python", "-c", "import cv2"); } else { processBuilder.command("python3", "-c", "import cv2"); } Process process = processBuilder.start(); int exitCode = process.waitFor(); if (exitCode != 0) { List openCVFeatures = getAffectedFeatures("OpenCV"); endpointConfiguration.disableGroup("OpenCV"); log.warn( "OpenCV not available in Python - Disabling OpenCV features: {}", String.join(", ", openCVFeatures)); } } catch (Exception e) { List openCVFeatures = getAffectedFeatures("OpenCV"); endpointConfiguration.disableGroup("OpenCV"); log.warn( "Error checking OpenCV: {} - Disabling OpenCV features: {}", e.getMessage(), String.join(", ", openCVFeatures)); } } endpointConfiguration.logDisabledEndpointsSummary(); } }