INT-3537 RemoteFileTemplate Close Stream

JIRA: https://jira.spring.io/browse/INT-3537

Stream not closed if session cannot be created.

Add `try {} finally {}`.

__cherry-pick to 4.0.x, 3.0.x__
This commit is contained in:
Gary Russell
2014-10-21 13:57:21 -04:00
committed by Artem Bilan
parent 869a8de05f
commit e4f1ee14aa
2 changed files with 79 additions and 37 deletions

View File

@@ -205,48 +205,57 @@ public class RemoteFileTemplate<F> implements RemoteFileOperations<F>, Initializ
"Cannot append when using a temporary file name");
final StreamHolder inputStreamHolder = this.payloadToInputStream(message);
if (inputStreamHolder != null) {
return this.execute(new SessionCallback<F, String>() {
try {
return this.execute(new SessionCallback<F, String>() {
@Override
public String doInSession(Session<F> session) throws IOException {
String fileName = inputStreamHolder.getName();
try {
String remoteDirectory = RemoteFileTemplate.this.directoryExpressionProcessor
.processMessage(message);
remoteDirectory = RemoteFileTemplate.this.normalizeDirectoryPath(remoteDirectory);
if (StringUtils.hasText(subDirectory)) {
if (subDirectory.startsWith(RemoteFileTemplate.this.remoteFileSeparator)) {
remoteDirectory += subDirectory.substring(1);
}
else {
remoteDirectory += RemoteFileTemplate.this.normalizeDirectoryPath(subDirectory);
}
}
String temporaryRemoteDirectory = remoteDirectory;
if (RemoteFileTemplate.this.temporaryDirectoryExpressionProcessor != null) {
temporaryRemoteDirectory = RemoteFileTemplate.this.temporaryDirectoryExpressionProcessor
@Override
public String doInSession(Session<F> session) throws IOException {
String fileName = inputStreamHolder.getName();
try {
String remoteDirectory = RemoteFileTemplate.this.directoryExpressionProcessor
.processMessage(message);
remoteDirectory = RemoteFileTemplate.this.normalizeDirectoryPath(remoteDirectory);
if (StringUtils.hasText(subDirectory)) {
if (subDirectory.startsWith(RemoteFileTemplate.this.remoteFileSeparator)) {
remoteDirectory += subDirectory.substring(1);
}
else {
remoteDirectory += RemoteFileTemplate.this.normalizeDirectoryPath(subDirectory);
}
}
String temporaryRemoteDirectory = remoteDirectory;
if (RemoteFileTemplate.this.temporaryDirectoryExpressionProcessor != null) {
temporaryRemoteDirectory = RemoteFileTemplate.this.temporaryDirectoryExpressionProcessor
.processMessage(message);
}
fileName = RemoteFileTemplate.this.fileNameGenerator.generateFileName(message);
RemoteFileTemplate.this.sendFileToRemoteDirectory(inputStreamHolder.getStream(),
temporaryRemoteDirectory, remoteDirectory, fileName, session, mode);
return remoteDirectory + fileName;
}
catch (FileNotFoundException e) {
throw new MessageDeliveryException(message, "File [" + inputStreamHolder.getName()
+ "] not found in local working directory; it was moved or deleted unexpectedly.", e);
}
catch (IOException e) {
throw new MessageDeliveryException(message, "Failed to transfer file ["
+ inputStreamHolder.getName() + " -> " + fileName
+ "] from local directory to remote directory.", e);
}
catch (Exception e) {
throw new MessageDeliveryException(message, "Error handling message for file ["
+ inputStreamHolder.getName() + " -> " + fileName + "]", e);
}
fileName = RemoteFileTemplate.this.fileNameGenerator.generateFileName(message);
RemoteFileTemplate.this.sendFileToRemoteDirectory(inputStreamHolder.getStream(),
temporaryRemoteDirectory, remoteDirectory, fileName, session, mode);
return remoteDirectory + fileName;
}
catch (FileNotFoundException e) {
throw new MessageDeliveryException(message, "File [" + inputStreamHolder.getName()
+ "] not found in local working directory; it was moved or deleted unexpectedly.", e);
}
catch (IOException e) {
throw new MessageDeliveryException(message, "Failed to transfer file ["
+ inputStreamHolder.getName() + " -> " + fileName
+ "] from local directory to remote directory.", e);
}
catch (Exception e) {
throw new MessageDeliveryException(message, "Error handling message for file ["
+ inputStreamHolder.getName() + " -> " + fileName + "]", e);
}
});
}
finally {
try {
inputStreamHolder.getStream().close();
}
});
catch (IOException e) {
}
}
}
else {
// A null holder means a File payload that does not exist.

View File

@@ -18,8 +18,14 @@ package org.springframework.integration.ftp.session;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
@@ -35,7 +41,9 @@ import org.springframework.integration.file.remote.ClientCallbackWithoutResult;
import org.springframework.integration.file.remote.SessionCallback;
import org.springframework.integration.file.remote.SessionCallbackWithoutResult;
import org.springframework.integration.file.remote.session.Session;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.ftp.TestFtpServer;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -109,4 +117,29 @@ public class FtpRemoteFileTemplateTests {
assertFalse(template.exists("foo"));
}
@Test
public void testFileCloseOnBadConnect() throws Exception {
@SuppressWarnings("unchecked")
SessionFactory<FTPFile> sessionFactory = mock(SessionFactory.class);
when(sessionFactory.getSession()).thenThrow(new RuntimeException("bar"));
FtpRemoteFileTemplate template = new FtpRemoteFileTemplate(sessionFactory);
template.setRemoteDirectoryExpression(new LiteralExpression("foo"));
template.afterPropertiesSet();
File file = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write("foo".getBytes());
fileOutputStream.close();
try {
template.send(new GenericMessage<File>(file));
fail("exception expected");
}
catch(MessagingException e) {
assertEquals("bar", e.getCause().getMessage());
}
File newFile = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());
assertTrue(file.renameTo(newFile));
file.delete();
newFile.delete();
}
}