fi.evolver.basics.spring.messaging.sender.FtpSender Maven / Gradle / Ivy
package fi.evolver.basics.spring.messaging.sender;
import static fi.evolver.basics.spring.messaging.util.SendUtils.PROPERTY_CONNECT_TIMEOUT_MS;
import static fi.evolver.basics.spring.messaging.util.SendUtils.PROPERTY_READ_TIMEOUT_MS;
import static fi.evolver.basics.spring.messaging.util.SendUtils.createDataStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.io.input.TeeInputStream;
import org.apache.commons.io.output.CountingOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import fi.evolver.basics.spring.log.MessageLogService;
import fi.evolver.basics.spring.log.entity.MessageLog.Direction;
import fi.evolver.basics.spring.log.entity.MessageLogMetadata;
import fi.evolver.basics.spring.messaging.SendResult;
import fi.evolver.basics.spring.messaging.entity.Message;
import fi.evolver.basics.spring.messaging.util.SendUtils;
import fi.evolver.utils.UriUtils;
import fi.evolver.utils.ftp.ConnectionFactory;
import fi.evolver.utils.ftp.RemoteConnection;
import fi.evolver.utils.stream.FinishingInputStream;
@Component
public class FtpSender implements Sender {
private static final String PROPERTY_CREATE_MISSING_DIRS = "CreateMissingDirs";
private static final String PROPERTY_OVERWRITE = "Overwrite";
private static final String PROPERTY_TEMP_NAME = "TempName";
private static final String PROPERTY_IDENTITY_FILE = "IdentityFile";
private final MessageLogService messageLogService;
@Autowired
public FtpSender(MessageLogService messageLogService) {
this.messageLogService = messageLogService;
}
@Override
public SendResult send(Message message, URI uri) {
String statusCode = "OK";
String statusMessage = "OK";
LocalDateTime start = LocalDateTime.now();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CountingOutputStream counter = null;
URI connectionUri = removeTargetFileName(uri);
int connectTimeoutMs = message.getMessageTargetConfig().getIntProperty(PROPERTY_CONNECT_TIMEOUT_MS).orElse(10_000);
int readTimeoutMs = message.getMessageTargetConfig().getIntProperty(PROPERTY_READ_TIMEOUT_MS).orElse(60_000);
boolean createDirs = message.getMessageTargetConfig().getBooleanProperty(PROPERTY_CREATE_MISSING_DIRS).orElse(false);
List identityFiles = message.getMessageTargetConfig().getProperty(PROPERTY_IDENTITY_FILE).map(Collections::singletonList).orElse(Collections.emptyList());
try (InputStream dataStream = createDataStream(message); RemoteConnection connection = ConnectionFactory.connect(connectionUri, connectTimeoutMs, readTimeoutMs, createDirs, identityFiles)) {
OutputStream out = new GZIPOutputStream(baos);
counter = new CountingOutputStream(out);
File targetFile = new File(uri.getPath());
String tempName = SendUtils.getTagReplacedTargetProperty(message, PROPERTY_TEMP_NAME).orElse(null);
boolean overwrite = message.getMessageTargetConfig().getBooleanProperty(PROPERTY_OVERWRITE).orElse(false);
if (createDirs) {
Optional tempDir = Optional.ofNullable(tempName).map(File::new).map(File::getParent);
if (tempDir.isPresent())
connection.mkdirs(tempDir.get());
}
try (InputStream in = new FinishingInputStream(new TeeInputStream(dataStream, counter, true))) {
connection.upload(targetFile.getName(), in, tempName, overwrite);
}
return SendResult.success();
}
catch (RuntimeException e) {
statusCode = "UNEXPECTED_ERROR";
statusMessage = "Unexpected error";
throw e;
}
catch (IOException e) {
statusCode = "IO_ERROR";
statusMessage = "Communication problems";
return SendResult.error("IO ERROR: %s", e.getMessage());
}
finally {
messageLogService.logZippedMessage(
start,
message.getMessageType(),
uri.getScheme(),
uri.toString(),
messageLogService.getApplicationName(),
message.getTargetSystem(),
Direction.OUTBOUND,
counter == null ? - 1 : counter.getCount(),
baos.toByteArray(),
null,
0,
null,
null,
statusCode,
statusMessage,
convertToMetadataList(message.getMetadata()));
}
}
private static List convertToMetadataList(Map metadata) {
List result = new ArrayList<>();
metadata.forEach((k, v) -> result.add(new MessageLogMetadata(k, v)));
return result;
}
private static URI removeTargetFileName(URI uri) {
try {
File target = new File(uri.getPath());
String username = UriUtils.getUserName(uri);
String password = UriUtils.getPassword(uri);
return UriUtils.create(uri.getScheme(), username, password, uri.getHost(), target.getParent().replace(File.separatorChar, '/'), null, uri.getFragment());
}
catch (URISyntaxException e) {
throw new IllegalArgumentException("Failed removing target file name from " + uri.getScheme() + " URI", e);
}
}
@Override
public Set getSupportedProtocols() {
return Set.of("ftp", "sftp");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy