From 2cb41b1997aa8ff2e3ed876a3caacfee1e0b8bd9 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Tue, 10 Oct 2023 09:20:22 -0400 Subject: [PATCH 1/3] GH-8745: Add RFT.shouldMarkSessionAsDirty() Fixes https://github.com/spring-projects/spring-integration/issues/8745 Not all errors caught in the `RemoteFileTemplate.execute()` are fatal to mark session as dirty and physically close the target session in the cache * Introduce a `RemoteFileTemplate.shouldMarkSessionAsDirty()` to consult with an exception if it is really a fatal error to close the session in the end. * Override `shouldMarkSessionAsDirty()` in the `RemoteFileTemplate` implementations to check statuses of respective protocol errors **Cherry-pick to `6.1.x` & `6.0.x`** --- .../file/remote/RemoteFileTemplate.java | 46 ++++++++------- .../ftp/session/FtpRemoteFileTemplate.java | 56 +++++++++++++------ .../session/FtpRemoteFileTemplateTests.java | 19 ++++++- .../sftp/session/SftpRemoteFileTemplate.java | 50 +++++++++++++++++ .../session/SftpRemoteFileTemplateTests.java | 22 +++++++- .../smb/session/SmbRemoteFileTemplate.java | 53 ++++++++++++++++++ .../smb/session/SmbSessionTests.java | 22 ++++++++ 7 files changed, 226 insertions(+), 42 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java index 00fc723ac01..5066d58bb37 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java @@ -451,27 +451,42 @@ public T execute(SessionCallback callback) { } return callback.doInSession(session); } - catch (Exception e) { - if (session != null) { + catch (Exception ex) { + if (session != null && shouldMarkSessionAsDirty(ex)) { session.dirty(); } - if (e instanceof MessagingException) { // NOSONAR - throw (MessagingException) e; + if (ex instanceof MessagingException messagingException) { // NOSONAR + throw messagingException; } - throw new MessagingException("Failed to execute on session", e); + throw new MessagingException("Failed to execute on session", ex); } finally { if (!invokeScope && session != null) { try { session.close(); } - catch (Exception ignored) { - this.logger.debug("failed to close Session", ignored); + catch (Exception ex) { + this.logger.debug("failed to close Session", ex); } } } } + /** + * Determine whether {@link Session#dirty()} should be called + * in the {@link #execute(SessionCallback)} when exception is thrown from the callback. + * By default, this method returns {@code true}. + * Remote file protocol extensions can override this method to provide + * a specific strategy against thrown exception, e.g. {@code file not found} error + * is not a signal that session is broken. + * @param ex the exception to check if {@link Session} must be marked as dirty. + * @return true if {@link Session#dirty()} should be called. + * @since 6.0.8 + */ + protected boolean shouldMarkSessionAsDirty(Exception ex) { + return true; + } + @Override public T invoke(OperationsCallback action) { Session contextSession = this.contextSessions.get(); @@ -503,8 +518,7 @@ public T executeWithClient(ClientCallback callback) { private StreamHolder payloadToInputStream(Message message) throws MessageDeliveryException { Object payload = message.getPayload(); try { - if (payload instanceof File) { - File inputFile = (File) payload; + if (payload instanceof File inputFile) { if (inputFile.exists()) { return new StreamHolder( new BufferedInputStream(new FileInputStream(inputFile)), inputFile.getAbsolutePath()); @@ -526,8 +540,7 @@ else if (payload instanceof byte[] || payload instanceof String) { else if (payload instanceof InputStream) { return new StreamHolder((InputStream) payload, "InputStream payload"); } - else if (payload instanceof Resource) { - Resource resource = (Resource) payload; + else if (payload instanceof Resource resource) { String filename = resource.getFilename(); return new StreamHolder(resource.getInputStream(), filename != null ? filename : "Resource payload"); } @@ -619,16 +632,7 @@ else if (!directoryPath.endsWith(this.remoteFileSeparator)) { } } - private static final class StreamHolder { - - private final InputStream stream; - - private final String name; - - StreamHolder(InputStream stream, String name) { - this.stream = stream; - this.name = name; - } + private record StreamHolder(InputStream stream, String name) { } diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java index 142ea47ad2f..2690d8f1ab3 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java @@ -20,10 +20,12 @@ import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; +import org.apache.commons.net.ftp.FTPReply; import org.springframework.integration.file.remote.ClientCallback; import org.springframework.integration.file.remote.RemoteFileTemplate; import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.lang.Nullable; import org.springframework.messaging.MessagingException; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -34,6 +36,7 @@ * * @author Gary Russell * @author Artem Bilan + * * @since 4.1 * */ @@ -82,22 +85,11 @@ protected T doExecuteWithClient(final ClientCallback callback) public boolean exists(final String path) { return doExecuteWithClient(client -> { try { - switch (FtpRemoteFileTemplate.this.existsMode) { - - case STAT: - return client.getStatus(path) != null; - - case NLST: - String[] names = client.listNames(path); - return !ObjectUtils.isEmpty(names); - - case NLST_AND_DIRS: - return FtpRemoteFileTemplate.super.exists(path); - - default: - throw new IllegalStateException("Unsupported 'existsMode': " + - FtpRemoteFileTemplate.this.existsMode); - } + return switch (FtpRemoteFileTemplate.this.existsMode) { + case STAT -> client.getStatus(path) != null; + case NLST -> !ObjectUtils.isEmpty(client.listNames(path)); + case NLST_AND_DIRS -> FtpRemoteFileTemplate.super.exists(path); + }; } catch (IOException e) { throw new MessagingException("Failed to check the remote path for " + path, e); @@ -105,6 +97,38 @@ public boolean exists(final String path) { }); } + @Override + protected boolean shouldMarkSessionAsDirty(Exception ex) { + IOException ftpException = findIoException(ex); + if (ftpException != null) { + return isStatusDirty(ftpException.getMessage()); + } + else { + return super.shouldMarkSessionAsDirty(ex); + } + } + + /** + * Check if {@link IOException#getMessage()} is treated as fatal. + * @param ftpErrorMessage the value from {@link IOException#getMessage()}. + * @return true if {@link IOException#getMessage()} is treated as fatal. + * @since 6.0.8 + */ + protected boolean isStatusDirty(String ftpErrorMessage) { + return !ftpErrorMessage.contains("" + FTPReply.FILE_UNAVAILABLE) + && !ftpErrorMessage.contains("" + FTPReply.FILE_NAME_NOT_ALLOWED); + } + + @Nullable + private static IOException findIoException(Throwable ex) { + if (ex == null || ex instanceof IOException) { + return (IOException) ex; + } + else { + return findIoException(ex.getCause()); + } + } + /** * The {@link #exists(String)} operation mode. * @since 4.1.9 diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java index e1b482ee803..bd2b7047158 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java @@ -34,6 +34,7 @@ import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.integration.file.remote.ClientCallbackWithoutResult; 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.file.support.FileExistsMode; import org.springframework.integration.ftp.FtpTestSupport; @@ -53,9 +54,7 @@ /** * @author Gary Russell * @author Artem Bilan - * * @since 4.1 - * */ @SpringJUnitConfig @DirtiesContext @@ -142,6 +141,22 @@ public void testConnectionClosedAfterExists() throws Exception { assertThat(pool.getActiveCount()).isEqualTo(0); } + @Test + public void sessionIsNotDirtyOnNoSuchFileError() { + Session session = this.sessionFactory.getSession(); + session.close(); + + FtpRemoteFileTemplate template = new FtpRemoteFileTemplate(this.sessionFactory); + + assertThatExceptionOfType(MessagingException.class) + .isThrownBy(() -> template.rename("No_such_file1", "No_such_file2")) + .withRootCauseInstanceOf(IOException.class) + .withStackTraceContaining("553 : No such file or directory"); + + assertThat(TestUtils.getPropertyValue(this.sessionFactory.getSession(), "targetSession")) + .isSameAs(TestUtils.getPropertyValue(session, "targetSession")); + } + @Configuration public static class Config { diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java index 77a8405da01..183eb367f91 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java @@ -16,11 +16,16 @@ package org.springframework.integration.sftp.session; +import java.util.List; + import org.apache.sshd.sftp.client.SftpClient; +import org.apache.sshd.sftp.common.SftpConstants; +import org.apache.sshd.sftp.common.SftpException; import org.springframework.integration.file.remote.ClientCallback; import org.springframework.integration.file.remote.RemoteFileTemplate; import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.lang.Nullable; /** * SFTP version of {@code RemoteFileTemplate} providing type-safe access to @@ -34,6 +39,20 @@ */ public class SftpRemoteFileTemplate extends RemoteFileTemplate { + protected static final List NOT_DIRTY_STATUSES = + List.of( + SftpConstants.SSH_FX_NO_SUCH_FILE, + SftpConstants.SSH_FX_NO_SUCH_PATH, + SftpConstants.SSH_FX_INVALID_FILENAME, + SftpConstants.SSH_FX_INVALID_HANDLE, + SftpConstants.SSH_FX_FILE_ALREADY_EXISTS, + SftpConstants.SSH_FX_DIR_NOT_EMPTY, + SftpConstants.SSH_FX_NOT_A_DIRECTORY, + SftpConstants.SSH_FX_EOF, + SftpConstants.SSH_FX_INVALID_FILENAME, + SftpConstants.SSH_FX_INVALID_FILENAME + ); + public SftpRemoteFileTemplate(SessionFactory sessionFactory) { super(sessionFactory); } @@ -48,4 +67,35 @@ protected T doExecuteWithClient(final ClientCallback callback return execute(session -> callback.doWithClient((SftpClient) session.getClientInstance())); } + @Override + protected boolean shouldMarkSessionAsDirty(Exception ex) { + SftpException sftpException = findSftpException(ex); + if (sftpException != null) { + return isStatusDirty(sftpException.getStatus()); + } + else { + return super.shouldMarkSessionAsDirty(ex); + } + } + + /** + * Check if {@link SftpException#getStatus()} is treated as fatal. + * @param status the value from {@link SftpException#getStatus()}. + * @return true if {@link SftpException#getStatus()} is treated as fatal. + * @since 6.0.8 + */ + protected boolean isStatusDirty(int status) { + return !NOT_DIRTY_STATUSES.contains(status); + } + + @Nullable + private static SftpException findSftpException(Throwable ex) { + if (ex == null || ex instanceof SftpException) { + return (SftpException) ex; + } + else { + return findSftpException(ex.getCause()); + } + } + } diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java index d44f2446529..e8ff6fda2d3 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java @@ -22,6 +22,7 @@ import org.apache.sshd.sftp.client.SftpClient; import org.apache.sshd.sftp.client.SftpVersionSelector; +import org.apache.sshd.sftp.common.SftpException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanFactory; @@ -38,6 +39,7 @@ import org.springframework.integration.file.support.FileExistsMode; import org.springframework.integration.sftp.SftpTestSupport; import org.springframework.integration.test.condition.LogLevels; +import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.MessageDeliveryException; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.GenericMessage; @@ -52,9 +54,7 @@ /** * @author Gary Russell * @author Artem Bilan - * * @since 4.1 - * */ @SpringJUnitConfig @DirtiesContext @@ -63,7 +63,7 @@ public class SftpRemoteFileTemplateTests extends SftpTestSupport { @Autowired private CachingSessionFactory sessionFactory; - @LogLevels(level = "trace", categories = { "org.apache.sshd", "org.springframework.integration.sftp" }) + @LogLevels(level = "trace", categories = {"org.apache.sshd", "org.springframework.integration.sftp"}) @Test public void testINT3412AppendStatRmdir() { SftpRemoteFileTemplate template = new SftpRemoteFileTemplate(sessionFactory); @@ -164,6 +164,22 @@ public void renameWithOldSftpVersion() { oldVersionSession.close(); } + @Test + public void sessionIsNotDirtyOnNoSuchFileError() { + Session session = this.sessionFactory.getSession(); + session.close(); + + SftpRemoteFileTemplate template = new SftpRemoteFileTemplate(this.sessionFactory); + + assertThatExceptionOfType(MessagingException.class) + .isThrownBy(() -> template.list("No_such_dir")) + .withRootCauseInstanceOf(SftpException.class) + .withStackTraceContaining("(SSH_FX_NO_SUCH_FILE): No such file or directory"); + + assertThat(TestUtils.getPropertyValue(this.sessionFactory.getSession(), "targetSession")) + .isSameAs(TestUtils.getPropertyValue(session, "targetSession")); + } + @Configuration public static class Config { diff --git a/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java b/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java index 21de1767879..8b4febaf798 100644 --- a/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java +++ b/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java @@ -16,10 +16,15 @@ package org.springframework.integration.smb.session; +import java.util.List; + +import jcifs.smb.NtStatus; +import jcifs.smb.SmbException; import jcifs.smb.SmbFile; import org.springframework.integration.file.remote.RemoteFileTemplate; import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.lang.Nullable; /** * The SMB-specific {@link RemoteFileTemplate} implementation. @@ -30,12 +35,60 @@ */ public class SmbRemoteFileTemplate extends RemoteFileTemplate { + protected static final List NOT_DIRTY_STATUSES = + List.of( + NtStatus.NT_STATUS_INVALID_HANDLE, + NtStatus.NT_STATUS_END_OF_FILE, + NtStatus.NT_STATUS_NO_SUCH_FILE, + NtStatus.NT_STATUS_DUPLICATE_NAME, + NtStatus.NT_STATUS_FILE_IS_A_DIRECTORY, + NtStatus.NT_STATUS_NOT_A_DIRECTORY, + NtStatus.NT_STATUS_NOT_FOUND, + NtStatus.NT_STATUS_OBJECT_NAME_COLLISION, + NtStatus.NT_STATUS_OBJECT_NAME_INVALID, + NtStatus.NT_STATUS_OBJECT_NAME_NOT_FOUND, + NtStatus.NT_STATUS_OBJECT_PATH_INVALID, + NtStatus.NT_STATUS_OBJECT_PATH_NOT_FOUND, + NtStatus.NT_STATUS_OBJECT_PATH_SYNTAX_BAD + ); + /** * Construct a {@link SmbRemoteFileTemplate} with the supplied session factory. + * * @param sessionFactory the session factory. */ public SmbRemoteFileTemplate(SessionFactory sessionFactory) { super(sessionFactory); } + @Override + protected boolean shouldMarkSessionAsDirty(Exception ex) { + SmbException smbException = findSmbException(ex); + if (smbException != null) { + return isStatusDirty(smbException.getNtStatus()); + } + else { + return super.shouldMarkSessionAsDirty(ex); + } + } + + /** + * Check if {@link SmbException#getNtStatus()} is treated as fatal. + * @param status the value from {@link SmbException#getNtStatus()}. + * @return true if {@link SmbException#getNtStatus()} is treated as fatal. + * @since 6.0.8 + */ + protected boolean isStatusDirty(int status) { + return !NOT_DIRTY_STATUSES.contains(status); + } + + @Nullable + private static SmbException findSmbException(Throwable ex) { + if (ex == null || ex instanceof SmbException) { + return (SmbException) ex; + } + else { + return findSmbException(ex.getCause()); + } + } } diff --git a/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java b/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java index a8b8c3157c8..c05ccda44e7 100644 --- a/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java +++ b/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java @@ -21,9 +21,14 @@ import jcifs.smb.SmbFile; import org.junit.jupiter.api.Test; +import org.springframework.integration.file.remote.session.CachingSessionFactory; +import org.springframework.integration.file.remote.session.Session; import org.springframework.integration.smb.SmbTestSupport; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.messaging.MessagingException; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; /** * @@ -85,4 +90,21 @@ public void testCreateSmbFileObjectWithMissingTrailingSlash3() throws IOExceptio } } + @Test + public void sessionIsNotDirtyOnNoSuchFileError() { + CachingSessionFactory cachingSessionFactory = new CachingSessionFactory<>(smbSessionFactory); + Session session = cachingSessionFactory.getSession(); + session.close(); + + SmbRemoteFileTemplate template = new SmbRemoteFileTemplate(cachingSessionFactory); + + assertThatExceptionOfType(MessagingException.class) + .isThrownBy(() -> template.rename("No_such_file1", "No_such_file2")) + .withRootCauseInstanceOf(IOException.class) + .withStackTraceContaining("The system cannot find the file specified"); + + assertThat(TestUtils.getPropertyValue(cachingSessionFactory.getSession(), "targetSession")) + .isSameAs(TestUtils.getPropertyValue(session, "targetSession")); + } + } From c212ea665c26d5d5e32fe3c380ff8d30fc615af1 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Tue, 10 Oct 2023 09:50:01 -0400 Subject: [PATCH 2/3] * Fix tests for pool interaction --- .../ftp/session/FtpRemoteFileTemplateTests.java | 7 +++++-- .../sftp/session/SftpRemoteFileTemplateTests.java | 5 ++++- .../integration/smb/session/SmbSessionTests.java | 7 +++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java index bd2b7047158..69edd377c79 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 the original author or authors. + * Copyright 2014-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -153,8 +153,11 @@ public void sessionIsNotDirtyOnNoSuchFileError() { .withRootCauseInstanceOf(IOException.class) .withStackTraceContaining("553 : No such file or directory"); - assertThat(TestUtils.getPropertyValue(this.sessionFactory.getSession(), "targetSession")) + Session newSession = this.sessionFactory.getSession(); + assertThat(TestUtils.getPropertyValue(newSession, "targetSession")) .isSameAs(TestUtils.getPropertyValue(session, "targetSession")); + + newSession.close(); } @Configuration diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java index e8ff6fda2d3..acfed39d75e 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java @@ -176,8 +176,11 @@ public void sessionIsNotDirtyOnNoSuchFileError() { .withRootCauseInstanceOf(SftpException.class) .withStackTraceContaining("(SSH_FX_NO_SUCH_FILE): No such file or directory"); - assertThat(TestUtils.getPropertyValue(this.sessionFactory.getSession(), "targetSession")) + Session newSession = this.sessionFactory.getSession(); + assertThat(TestUtils.getPropertyValue(newSession, "targetSession")) .isSameAs(TestUtils.getPropertyValue(session, "targetSession")); + + newSession.close(); } @Configuration diff --git a/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java b/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java index c05ccda44e7..49f7caf2280 100644 --- a/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java +++ b/spring-integration-smb/src/test/java/org/springframework/integration/smb/session/SmbSessionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -103,8 +103,11 @@ public void sessionIsNotDirtyOnNoSuchFileError() { .withRootCauseInstanceOf(IOException.class) .withStackTraceContaining("The system cannot find the file specified"); - assertThat(TestUtils.getPropertyValue(cachingSessionFactory.getSession(), "targetSession")) + Session newSession = cachingSessionFactory.getSession(); + assertThat(TestUtils.getPropertyValue(newSession, "targetSession")) .isSameAs(TestUtils.getPropertyValue(session, "targetSession")); + + newSession.close(); } } From bb7a8722f5767c333d6dbfd6dcb54c91952cd2cf Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 11 Oct 2023 10:51:18 -0400 Subject: [PATCH 3/3] * Fix language in Javadocs * Add more `not dirty` statuses to `SftpRemoteFileTemplate` & `SmbRemoteFileTemplate` --- .../integration/file/remote/RemoteFileTemplate.java | 4 ++-- .../integration/sftp/session/SftpRemoteFileTemplate.java | 7 ++++--- .../integration/smb/session/SmbRemoteFileTemplate.java | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java index 5066d58bb37..ac70c06ab7a 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java @@ -474,10 +474,10 @@ public T execute(SessionCallback callback) { /** * Determine whether {@link Session#dirty()} should be called - * in the {@link #execute(SessionCallback)} when exception is thrown from the callback. + * in the {@link #execute(SessionCallback)} when an exception is thrown from the callback. * By default, this method returns {@code true}. * Remote file protocol extensions can override this method to provide - * a specific strategy against thrown exception, e.g. {@code file not found} error + * a specific strategy against the thrown exception, e.g. {@code file not found} error * is not a signal that session is broken. * @param ex the exception to check if {@link Session} must be marked as dirty. * @return true if {@link Session#dirty()} should be called. diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java index 183eb367f91..c3fe937fc6c 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java @@ -39,7 +39,7 @@ */ public class SftpRemoteFileTemplate extends RemoteFileTemplate { - protected static final List NOT_DIRTY_STATUSES = + protected static final List NOT_DIRTY_STATUSES = // NOSONAR List.of( SftpConstants.SSH_FX_NO_SUCH_FILE, SftpConstants.SSH_FX_NO_SUCH_PATH, @@ -49,8 +49,9 @@ public class SftpRemoteFileTemplate extends RemoteFileTemplate sessionFactory) { diff --git a/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java b/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java index 8b4febaf798..8a1c34211ba 100644 --- a/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java +++ b/spring-integration-smb/src/main/java/org/springframework/integration/smb/session/SmbRemoteFileTemplate.java @@ -35,7 +35,7 @@ */ public class SmbRemoteFileTemplate extends RemoteFileTemplate { - protected static final List NOT_DIRTY_STATUSES = + protected static final List NOT_DIRTY_STATUSES = // NOSONAR List.of( NtStatus.NT_STATUS_INVALID_HANDLE, NtStatus.NT_STATUS_END_OF_FILE, @@ -49,7 +49,8 @@ public class SmbRemoteFileTemplate extends RemoteFileTemplate { NtStatus.NT_STATUS_OBJECT_NAME_NOT_FOUND, NtStatus.NT_STATUS_OBJECT_PATH_INVALID, NtStatus.NT_STATUS_OBJECT_PATH_NOT_FOUND, - NtStatus.NT_STATUS_OBJECT_PATH_SYNTAX_BAD + NtStatus.NT_STATUS_OBJECT_PATH_SYNTAX_BAD, + NtStatus.NT_STATUS_CANNOT_DELETE ); /**