From b92963d7dd2d5af50e4156ddc2d14a712068a3f7 Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Sat, 9 Aug 2025 01:24:42 +0700 Subject: [PATCH 1/5] GH-10083: Apply NullAbility to sftp module Related to: #10083 Signed-off-by: Tran Ngoc Nhan --- .../integration/sftp/config/package-info.java | 1 + .../integration/sftp/dsl/Sftp.java | 2 +- .../dsl/SftpInboundChannelAdapterSpec.java | 2 +- ...ftpStreamingInboundChannelAdapterSpec.java | 2 +- .../integration/sftp/dsl/package-info.java | 3 +-- .../SftpRegexPatternFileListFilter.java | 2 +- .../SftpSimplePatternFileListFilter.java | 2 +- .../sftp/filters/package-info.java | 1 + .../sftp/gateway/SftpOutboundGateway.java | 2 +- .../sftp/gateway/package-info.java | 1 + .../inbound/SftpInboundFileSynchronizer.java | 5 +++-- ...InboundFileSynchronizingMessageSource.java | 3 ++- .../inbound/SftpStreamingMessageSource.java | 5 +++-- .../sftp/inbound/package-info.java | 1 + .../sftp/outbound/package-info.java | 1 + .../sftp/server/ApacheMinaSftpEvent.java | 4 +++- .../server/ApacheMinaSftpEventListener.java | 6 +++-- .../sftp/server/DirectoryCreatedEvent.java | 5 ++--- .../sftp/server/FileWrittenEvent.java | 5 ++--- .../sftp/server/PathMovedEvent.java | 8 +++---- .../sftp/server/PathRemovedEvent.java | 5 ++--- .../integration/sftp/server/package-info.java | 1 + .../session/DefaultSftpSessionFactory.java | 19 +++++++++------- .../sftp/session/SftpRemoteFileTemplate.java | 22 ++++++++++--------- .../integration/sftp/session/SftpSession.java | 12 +++++++--- .../sftp/session/package-info.java | 1 + 26 files changed, 70 insertions(+), 51 deletions(-) diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/config/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/config/package-info.java index 2ea284b8236..15977fa1902 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/config/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/config/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes for configuration - parsers, namespace handlers. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.config; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/Sftp.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/Sftp.java index c881cfeff37..a37351f2b35 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/Sftp.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/Sftp.java @@ -20,6 +20,7 @@ import java.util.Comparator; import org.apache.sshd.sftp.client.SftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.MessageSessionCallback; import org.springframework.integration.file.remote.RemoteFileTemplate; @@ -28,7 +29,6 @@ import org.springframework.integration.file.support.FileExistsMode; import org.springframework.integration.sftp.gateway.SftpOutboundGateway; import org.springframework.integration.sftp.session.SftpRemoteFileTemplate; -import org.springframework.lang.Nullable; /** * The factory for SFTP components. diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpInboundChannelAdapterSpec.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpInboundChannelAdapterSpec.java index 126d905a742..6e9cda24e8d 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpInboundChannelAdapterSpec.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpInboundChannelAdapterSpec.java @@ -20,6 +20,7 @@ import java.util.Comparator; import org.apache.sshd.sftp.client.SftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.dsl.RemoteFileInboundChannelAdapterSpec; import org.springframework.integration.file.filters.CompositeFileListFilter; @@ -31,7 +32,6 @@ import org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter; import org.springframework.integration.sftp.inbound.SftpInboundFileSynchronizer; import org.springframework.integration.sftp.inbound.SftpInboundFileSynchronizingMessageSource; -import org.springframework.lang.Nullable; /** * A {@link RemoteFileInboundChannelAdapterSpec} for an {@link SftpInboundFileSynchronizingMessageSource}. diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpStreamingInboundChannelAdapterSpec.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpStreamingInboundChannelAdapterSpec.java index ec2172449b7..d581d7c8a23 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpStreamingInboundChannelAdapterSpec.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/SftpStreamingInboundChannelAdapterSpec.java @@ -19,6 +19,7 @@ import java.util.Comparator; import org.apache.sshd.sftp.client.SftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.dsl.RemoteFileStreamingInboundChannelAdapterSpec; import org.springframework.integration.file.filters.CompositeFileListFilter; @@ -29,7 +30,6 @@ import org.springframework.integration.sftp.filters.SftpRegexPatternFileListFilter; import org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter; import org.springframework.integration.sftp.inbound.SftpStreamingMessageSource; -import org.springframework.lang.Nullable; /** * @author Gary Russell diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/package-info.java index d17169b3ed7..a9d344d123a 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/dsl/package-info.java @@ -1,6 +1,5 @@ /** * Provides SFTP Components for the Java DSL. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.dsl; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRegexPatternFileListFilter.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRegexPatternFileListFilter.java index 7b9ac6ff132..3704999b993 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRegexPatternFileListFilter.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRegexPatternFileListFilter.java @@ -43,7 +43,7 @@ public SftpRegexPatternFileListFilter(Pattern pattern) { @Override protected String getFilename(SftpClient.DirEntry entry) { - return (entry != null) ? entry.getFilename() : null; + return entry.getFilename(); } @Override diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpSimplePatternFileListFilter.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpSimplePatternFileListFilter.java index 2d6a769b5d7..302d347161e 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpSimplePatternFileListFilter.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpSimplePatternFileListFilter.java @@ -37,7 +37,7 @@ public SftpSimplePatternFileListFilter(String pattern) { @Override protected String getFilename(SftpClient.DirEntry entry) { - return (entry != null) ? entry.getFilename() : null; + return entry.getFilename(); } @Override diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/package-info.java index f78b5598c48..1c2d7cc0003 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting SFTP file filtering. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.filters; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/SftpOutboundGateway.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/SftpOutboundGateway.java index 7777083e1d4..2695c7f55ed 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/SftpOutboundGateway.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/SftpOutboundGateway.java @@ -23,6 +23,7 @@ import java.util.stream.Collectors; import org.apache.sshd.sftp.client.SftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.AbstractFileInfo; import org.springframework.integration.file.remote.ClientCallbackWithoutResult; @@ -33,7 +34,6 @@ import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.integration.sftp.session.SftpFileInfo; import org.springframework.integration.sftp.session.SftpRemoteFileTemplate; -import org.springframework.lang.Nullable; /** * Outbound Gateway for performing remote file operations via SFTP. diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/package-info.java index 6539c47db16..c2d89a69e75 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/gateway/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting SFTP gateways. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.gateway; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java index c3fe45648e2..6c7e0ffa49b 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java @@ -17,6 +17,7 @@ package org.springframework.integration.sftp.inbound; import org.apache.sshd.sftp.client.SftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer; @@ -46,13 +47,13 @@ public SftpInboundFileSynchronizer(SessionFactory sessionFa } @Override - protected boolean isFile(SftpClient.DirEntry file) { + protected boolean isFile(SftpClient.@Nullable DirEntry file) { return file != null && file.getAttributes().isRegularFile(); } @Override protected String getFilename(SftpClient.DirEntry file) { - return file != null ? file.getFilename() : null; + return file.getFilename(); } @Override diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizingMessageSource.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizingMessageSource.java index 730b1eae622..5ab858f84eb 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizingMessageSource.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizingMessageSource.java @@ -20,6 +20,7 @@ import java.util.Comparator; import org.apache.sshd.sftp.client.SftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer; import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizingMessageSource; @@ -42,7 +43,7 @@ public SftpInboundFileSynchronizingMessageSource(AbstractInboundFileSynchronizer } public SftpInboundFileSynchronizingMessageSource(AbstractInboundFileSynchronizer synchronizer, - Comparator comparator) { + @Nullable Comparator comparator) { super(synchronizer, comparator); } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java index eef5d405b10..b317adb4ec1 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.sshd.sftp.client.SftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.AbstractFileInfo; import org.springframework.integration.file.remote.AbstractRemoteFileStreamingMessageSource; @@ -58,7 +59,7 @@ public SftpStreamingMessageSource(RemoteFileTemplate templa */ @SuppressWarnings("this-escape") public SftpStreamingMessageSource(RemoteFileTemplate template, - Comparator comparator) { + @Nullable Comparator comparator) { super(template, comparator); doSetFilter(new SftpPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "sftpStreamingMessageSource")); @@ -79,7 +80,7 @@ protected List> asFileInfoList(Collection< } @Override - protected boolean isDirectory(SftpClient.DirEntry file) { + protected boolean isDirectory(SftpClient.@Nullable DirEntry file) { return file != null && file.getAttributes().isDirectory(); } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/package-info.java index d1f9565319a..7c6f05491e0 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting inbound endpoints. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.inbound; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/outbound/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/outbound/package-info.java index ade8d224fb7..da36f5f9ef1 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/outbound/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/outbound/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes for the SFTP outbound channel adapter. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.outbound; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java index c6d9a21bf9a..376cfbcbdca 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java @@ -17,6 +17,7 @@ package org.springframework.integration.sftp.server; import org.apache.sshd.server.session.ServerSession; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.server.FileServerEvent; @@ -35,7 +36,8 @@ public ApacheMinaSftpEvent(Object source) { super(source); } - public ApacheMinaSftpEvent(Object source, Throwable cause) { + @SuppressWarnings("NullAway") // Overridden method does not define nullability + public ApacheMinaSftpEvent(Object source, @Nullable Throwable cause) { super(source, cause); } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEventListener.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEventListener.java index 5a7d72e8176..35232e003b2 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEventListener.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEventListener.java @@ -24,6 +24,7 @@ import org.apache.sshd.server.session.ServerSession; import org.apache.sshd.sftp.server.FileHandle; import org.apache.sshd.sftp.server.SftpEventListener; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; @@ -45,9 +46,10 @@ public class ApacheMinaSftpEventListener implements SftpEventListener, ApplicationEventPublisherAware, BeanNameAware, InitializingBean { + @SuppressWarnings("NullAway.Init") private ApplicationEventPublisher applicationEventPublisher; - private String beanName; + private @Nullable String beanName; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { @@ -63,7 +65,7 @@ public void setBeanName(String name) { this.beanName = name; } - public String getBeanName() { + public @Nullable String getBeanName() { return this.beanName; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java index f235284b619..0bd94bed591 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java @@ -19,7 +19,7 @@ import java.nio.file.Path; import java.util.Map; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * An event emitted when a directory is created. @@ -43,8 +43,7 @@ public DirectoryCreatedEvent(Object source, Path path, Map attrs) { this.attrs = attrs; } - @Nullable - public Path getPath() { + public @Nullable Path getPath() { return this.path; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java index 38430ee4742..a0fd84a7965 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java @@ -18,7 +18,7 @@ import java.nio.file.Path; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * An event that is emitted when a file is written. @@ -48,8 +48,7 @@ public String getRemoteHandle() { return this.remoteHandle; } - @Nullable - public Path getFile() { + public @Nullable Path getFile() { return this.file; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java index b0c1aa44ab1..8b5c53e1e6d 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java @@ -18,7 +18,7 @@ import java.nio.file.Path; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * An event emitted when a path is moved. @@ -41,13 +41,11 @@ public PathMovedEvent(Object source, Path srcPath, Path dstPath, @Nullable Throw this.dstPath = dstPath; } - @Nullable - public Path getSrcPath() { + public @Nullable Path getSrcPath() { return this.srcPath; } - @Nullable - public Path getDstPath() { + public @Nullable Path getDstPath() { return this.dstPath; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java index 8f24df82261..8f57da97188 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java @@ -18,7 +18,7 @@ import java.nio.file.Path; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * An event emitted when a file or directory is removed. @@ -41,8 +41,7 @@ public PathRemovedEvent(Object source, Path path, boolean isDirectory, @Nullable this.isDirectory = isDirectory; } - @Nullable - public Path getPath() { + public @Nullable Path getPath() { return this.path; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/package-info.java index 5bc2acec1e2..bb9434570b4 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes related to SFTP servers. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.server; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/DefaultSftpSessionFactory.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/DefaultSftpSessionFactory.java index 43a8b51fecf..73ca9085920 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/DefaultSftpSessionFactory.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/DefaultSftpSessionFactory.java @@ -51,6 +51,7 @@ import org.apache.sshd.sftp.client.SftpVersionSelector; import org.apache.sshd.sftp.client.impl.AbstractSftpClient; import org.apache.sshd.sftp.client.impl.DefaultSftpClient; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.DisposableBean; import org.springframework.core.io.Resource; @@ -94,27 +95,29 @@ public class DefaultSftpSessionFactory private final boolean isSharedSession; - private final Lock sharedSessionLock; + private final @Nullable Lock sharedSessionLock; private boolean isInnerClient = false; + @SuppressWarnings("NullAway.Init") private String host; private int port = SshConstants.DEFAULT_PORT; + @SuppressWarnings("NullAway.Init") private String user; - private String password; + private @Nullable String password; - private HostConfigEntry hostConfig; + private @Nullable HostConfigEntry hostConfig; - private Resource knownHosts; + private @Nullable Resource knownHosts; - private Resource privateKey; + private @Nullable Resource privateKey; - private String privateKeyPassphrase; + private @Nullable String privateKeyPassphrase; - private UserInteraction userInteraction; + private @Nullable UserInteraction userInteraction; private boolean allowUnknownKeys = false; @@ -122,7 +125,7 @@ public class DefaultSftpSessionFactory private SftpVersionSelector sftpVersionSelector = SftpVersionSelector.CURRENT; - private volatile SftpClient sharedSftpClient; + private volatile @Nullable SftpClient sharedSftpClient; private Consumer sshClientConfigurer = (sshClient) -> { }; 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 3c0b25564dc..a55b8c75e70 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 @@ -21,11 +21,11 @@ import org.apache.sshd.sftp.client.SftpClient; import org.apache.sshd.sftp.common.SftpConstants; import org.apache.sshd.sftp.common.SftpException; +import org.jspecify.annotations.Nullable; 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 @@ -58,13 +58,13 @@ public SftpRemoteFileTemplate(SessionFactory sessionFactory super(sessionFactory); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "NullAway"}) // Overridden method does not define nullability @Override - public T executeWithClient(final ClientCallback callback) { + public @Nullable T executeWithClient(final ClientCallback callback) { return doExecuteWithClient((ClientCallback) callback); } - protected T doExecuteWithClient(final ClientCallback callback) { + protected @Nullable T doExecuteWithClient(final ClientCallback callback) { return execute(session -> callback.doWithClient((SftpClient) session.getClientInstance())); } @@ -89,14 +89,16 @@ 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; + private static @Nullable SftpException findSftpException(@Nullable Throwable ex) { + if (ex == null) { + return null; } - else { - return findSftpException(ex.getCause()); + + if (ex instanceof SftpException sftpException) { + return sftpException; } + + return findSftpException(ex.getCause()); } } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java index b5128c1cf6f..06893c657dd 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java @@ -31,6 +31,7 @@ import org.apache.sshd.sftp.client.SftpClient; import org.apache.sshd.sftp.common.SftpConstants; import org.apache.sshd.sftp.common.SftpException; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.session.Session; import org.springframework.util.Assert; @@ -92,19 +93,24 @@ public boolean remove(String path) throws IOException { } @Override - public SftpClient.DirEntry[] list(String path) throws IOException { + public SftpClient.DirEntry[] list(@Nullable String path) throws IOException { return doList(path) .toArray(SftpClient.DirEntry[]::new); } @Override - public String[] listNames(String path) throws IOException { + public String[] listNames(@Nullable String path) throws IOException { return doList(path) .map(SftpClient.DirEntry::getFilename) .toArray(String[]::new); } - public Stream doList(String path) throws IOException { + public Stream doList(@Nullable String path) throws IOException { + + if (path == null) { + return Stream.empty(); + } + String remotePath = StringUtils.trimTrailingCharacter(path, '/'); String remoteDir = remotePath; int lastIndex = remotePath.lastIndexOf('/'); diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/package-info.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/package-info.java index 70667be1c9b..5c653d6b5f5 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/package-info.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting SFTP sessions. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.sftp.session; From 61cce7abb25f427ec6c2ed5ee9fb87df6509a281 Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Sat, 9 Aug 2025 03:05:38 +0700 Subject: [PATCH 2/5] Adjust @Nullable annotations Signed-off-by: Tran Ngoc Nhan --- .../integration/file/remote/RemoteFileTemplate.java | 2 +- .../integration/file/remote/server/FileServerEvent.java | 4 +++- .../sftp/inbound/SftpInboundFileSynchronizer.java | 5 ++--- .../sftp/inbound/SftpStreamingMessageSource.java | 4 ++-- .../integration/sftp/server/ApacheMinaSftpEvent.java | 1 - .../integration/sftp/server/DirectoryCreatedEvent.java | 4 +--- .../integration/sftp/server/FileWrittenEvent.java | 2 +- .../integration/sftp/server/PathMovedEvent.java | 4 ++-- .../integration/sftp/server/PathRemovedEvent.java | 2 +- .../integration/sftp/session/SftpRemoteFileTemplate.java | 2 +- .../integration/sftp/session/SftpSession.java | 6 +----- 11 files changed, 15 insertions(+), 21 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 786dd619f35..93f9ec30ecf 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 @@ -511,7 +511,7 @@ protected boolean shouldMarkSessionAsDirty(Exception ex) { } @Override - public T executeWithClient(ClientCallback callback) { + public @Nullable T executeWithClient(ClientCallback callback) { throw new UnsupportedOperationException("executeWithClient() is not supported by the generic template"); } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/server/FileServerEvent.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/server/FileServerEvent.java index b2bdb507387..5a31293b839 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/server/FileServerEvent.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/server/FileServerEvent.java @@ -16,6 +16,8 @@ package org.springframework.integration.file.remote.server; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.events.IntegrationEvent; /** @@ -34,7 +36,7 @@ public FileServerEvent(Object source) { super(source); } - public FileServerEvent(Object source, Throwable cause) { + public FileServerEvent(Object source, @Nullable Throwable cause) { super(source, cause); } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java index 6c7e0ffa49b..4b0f67de06f 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpInboundFileSynchronizer.java @@ -17,7 +17,6 @@ package org.springframework.integration.sftp.inbound; import org.apache.sshd.sftp.client.SftpClient; -import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer; @@ -47,8 +46,8 @@ public SftpInboundFileSynchronizer(SessionFactory sessionFa } @Override - protected boolean isFile(SftpClient.@Nullable DirEntry file) { - return file != null && file.getAttributes().isRegularFile(); + protected boolean isFile(SftpClient.DirEntry file) { + return file.getAttributes().isRegularFile(); } @Override diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java index b317adb4ec1..30703816b12 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/inbound/SftpStreamingMessageSource.java @@ -80,8 +80,8 @@ protected List> asFileInfoList(Collection< } @Override - protected boolean isDirectory(SftpClient.@Nullable DirEntry file) { - return file != null && file.getAttributes().isDirectory(); + protected boolean isDirectory(SftpClient.DirEntry file) { + return file.getAttributes().isDirectory(); } } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java index 376cfbcbdca..d52472d1a07 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/ApacheMinaSftpEvent.java @@ -36,7 +36,6 @@ public ApacheMinaSftpEvent(Object source) { super(source); } - @SuppressWarnings("NullAway") // Overridden method does not define nullability public ApacheMinaSftpEvent(Object source, @Nullable Throwable cause) { super(source, cause); } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java index 0bd94bed591..28639874ed2 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/DirectoryCreatedEvent.java @@ -19,8 +19,6 @@ import java.nio.file.Path; import java.util.Map; -import org.jspecify.annotations.Nullable; - /** * An event emitted when a directory is created. * @@ -43,7 +41,7 @@ public DirectoryCreatedEvent(Object source, Path path, Map attrs) { this.attrs = attrs; } - public @Nullable Path getPath() { + public Path getPath() { return this.path; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java index a0fd84a7965..8c1e6630a40 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/FileWrittenEvent.java @@ -48,7 +48,7 @@ public String getRemoteHandle() { return this.remoteHandle; } - public @Nullable Path getFile() { + public Path getFile() { return this.file; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java index 8b5c53e1e6d..c88dc049766 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathMovedEvent.java @@ -41,11 +41,11 @@ public PathMovedEvent(Object source, Path srcPath, Path dstPath, @Nullable Throw this.dstPath = dstPath; } - public @Nullable Path getSrcPath() { + public Path getSrcPath() { return this.srcPath; } - public @Nullable Path getDstPath() { + public Path getDstPath() { return this.dstPath; } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java index 8f57da97188..ed43df0e158 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/server/PathRemovedEvent.java @@ -41,7 +41,7 @@ public PathRemovedEvent(Object source, Path path, boolean isDirectory, @Nullable this.isDirectory = isDirectory; } - public @Nullable Path getPath() { + public Path getPath() { return this.path; } 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 a55b8c75e70..f4b00fe1bb9 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 @@ -58,7 +58,7 @@ public SftpRemoteFileTemplate(SessionFactory sessionFactory super(sessionFactory); } - @SuppressWarnings({"unchecked", "NullAway"}) // Overridden method does not define nullability + @SuppressWarnings("unchecked") @Override public @Nullable T executeWithClient(final ClientCallback callback) { return doExecuteWithClient((ClientCallback) callback); diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java index 06893c657dd..d5ba2746477 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java @@ -106,11 +106,7 @@ public String[] listNames(@Nullable String path) throws IOException { } public Stream doList(@Nullable String path) throws IOException { - - if (path == null) { - return Stream.empty(); - } - + Assert.notNull(path, "The 'path' can not be null"); String remotePath = StringUtils.trimTrailingCharacter(path, '/'); String remoteDir = remotePath; int lastIndex = remotePath.lastIndexOf('/'); From 7a9c4a420e625cebd727376159b3bafd53459e2b Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Sat, 9 Aug 2025 03:14:12 +0700 Subject: [PATCH 3/5] Convert to dot if path is null Signed-off-by: Tran Ngoc Nhan --- .../integration/sftp/session/SftpSession.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java index d5ba2746477..a2934a51b5a 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java @@ -106,8 +106,8 @@ public String[] listNames(@Nullable String path) throws IOException { } public Stream doList(@Nullable String path) throws IOException { - Assert.notNull(path, "The 'path' can not be null"); - String remotePath = StringUtils.trimTrailingCharacter(path, '/'); + String validPath = path != null ? path : "."; + String remotePath = StringUtils.trimTrailingCharacter(validPath, '/'); String remoteDir = remotePath; int lastIndex = remotePath.lastIndexOf('/'); if (lastIndex > 0) { @@ -117,9 +117,9 @@ public Stream doList(@Nullable String path) throws IOExcept boolean isPattern = remoteFile != null && remoteFile.contains("*"); if (!isPattern && remoteFile != null) { - SftpClient.Attributes attributes = this.sftpClient.stat(path); + SftpClient.Attributes attributes = this.sftpClient.stat(validPath); if (!attributes.isDirectory()) { - return Stream.of(new SftpClient.DirEntry(remoteFile, path, attributes)); + return Stream.of(new SftpClient.DirEntry(remoteFile, validPath, attributes)); } else { remoteDir = remotePath; From a0fb5617210eafc697faa3e05564b4e1d4d0fd49 Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Sat, 9 Aug 2025 03:35:39 +0700 Subject: [PATCH 4/5] Overridden method does not define nullability Signed-off-by: Tran Ngoc Nhan --- .../integration/file/remote/RemoteFileTemplate.java | 2 +- .../integration/sftp/session/SftpRemoteFileTemplate.java | 4 ++-- 2 files changed, 3 insertions(+), 3 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 93f9ec30ecf..786dd619f35 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 @@ -511,7 +511,7 @@ protected boolean shouldMarkSessionAsDirty(Exception ex) { } @Override - public @Nullable T executeWithClient(ClientCallback callback) { + public T executeWithClient(ClientCallback callback) { throw new UnsupportedOperationException("executeWithClient() is not supported by the generic template"); } 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 f4b00fe1bb9..0ad094dddee 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 @@ -58,13 +58,13 @@ public SftpRemoteFileTemplate(SessionFactory sessionFactory super(sessionFactory); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "NullAway"}) // Overridden method does not define nullability @Override public @Nullable T executeWithClient(final ClientCallback callback) { return doExecuteWithClient((ClientCallback) callback); } - protected @Nullable T doExecuteWithClient(final ClientCallback callback) { + protected @Nullable T doExecuteWithClient(final ClientCallback callback) { return execute(session -> callback.doWithClient((SftpClient) session.getClientInstance())); } From 7a84842a9f0f0910efacabf1f6fbf1762d69d547 Mon Sep 17 00:00:00 2001 From: Tran Ngoc Nhan Date: Sat, 9 Aug 2025 03:41:04 +0700 Subject: [PATCH 5/5] Revert SuppressWarnings NullAway Signed-off-by: Tran Ngoc Nhan --- .../integration/file/remote/RemoteFileTemplate.java | 2 +- .../integration/sftp/session/SftpRemoteFileTemplate.java | 2 +- 2 files changed, 2 insertions(+), 2 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 786dd619f35..93f9ec30ecf 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 @@ -511,7 +511,7 @@ protected boolean shouldMarkSessionAsDirty(Exception ex) { } @Override - public T executeWithClient(ClientCallback callback) { + public @Nullable T executeWithClient(ClientCallback callback) { throw new UnsupportedOperationException("executeWithClient() is not supported by the generic template"); } 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 0ad094dddee..28602bbd6df 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 @@ -58,7 +58,7 @@ public SftpRemoteFileTemplate(SessionFactory sessionFactory super(sessionFactory); } - @SuppressWarnings({"unchecked", "NullAway"}) // Overridden method does not define nullability + @SuppressWarnings("unchecked") @Override public @Nullable T executeWithClient(final ClientCallback callback) { return doExecuteWithClient((ClientCallback) callback);