package com.scraper.agents.dataextract; import com.highradius.cpacommon.model.CPADataExtractConfig; import com.scraper.fs.cpa.FSClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.regex.Pattern; /** * Uses framework DataExtractTransporter to establish SFTP connection (via FSClient), * lists files in remote directory and validates name & size. * Retry logic is encapsulated here (configurable). */ public class SftpValidationService { private static final Logger LOGGER = LoggerFactory.getLogger(SftpValidationService.class); private static final Pattern FILE_PATTERN = Pattern.compile("^Deductions-\\d{8}T\\d{6}Z-\\d+\\.zip$", Pattern.CASE_INSENSITIVE); private final DataExtractTransporter transporter; // existing framework transporter private final int retryCount; private final long retryDelayMs; public SftpValidationService(DataExtractTransporter transporter, int retryCount, long retryDelayMs) { this.transporter = transporter; this.retryCount = retryCount; this.retryDelayMs = retryDelayMs; } public SftpValidationSummary validate(CPADataExtractConfig config, String remotePath) { int attempt = 0; Exception lastEx = null; while (attempt < retryCount) { attempt++; try { LOGGER.info("SFTP validation attempt {}/{} for path: {}", attempt, retryCount, remotePath); return performValidation(config, remotePath); } catch (Exception e) { lastEx = e; LOGGER.error("Attempt {}/{} failed: {}", attempt, retryCount, e.getMessage(), e); sleepQuietly(); } } SftpValidationSummary summary = new SftpValidationSummary(); summary.setFailed(true); summary.setFailureReason("SFTP validation failed after " + retryCount + " attempts: " + (lastEx != null ? lastEx.getMessage() : "unknown")); return summary; } private SftpValidationSummary performValidation(CPADataExtractConfig config, String remotePath) throws Exception { SftpValidationSummary summary = new SftpValidationSummary(); // DataExtractTransporter exposes connectToSFTP(...) in your framework (see your transporter). FSClient fsClient = transporter.connectToSFTP(config, true); if (fsClient == null) { throw new Exception("FSClient is null after connectToSFTP."); } List files = fsClient.listNames(remotePath); if (files == null || files.isEmpty()) { summary.setFailed(true); summary.setFailureReason("No files found in remote path: " + remotePath); try { fsClient.closeConnection(); } catch (Exception ignored) {} return summary; } for (String f : files) { SftpValidationResult r = new SftpValidationResult(f); r.setValidName(FILE_PATTERN.matcher(f).matches()); long sizeBytes = fsClient.getFileSize(remotePath + (remotePath.endsWith("/") ? "" : "/") + f); r.setFileSizeBytes(sizeBytes); r.setValidSize(sizeBytes > 0); r.setRemarks( !r.isValidName() && !r.isValidSize() ? "Invalid name & 0KB" : !r.isValidName() ? "Invalid name" : !r.isValidSize() ? "0KB file" : "Valid file" ); summary.addResult(r); } fsClient.closeConnection(); summary.computeMessage(); return summary; } private void sleepQuietly() { try { Thread.sleep(retryDelayMs); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } }