From 5e8563fc017316bf5c23b33c93daa21274df8c93 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 13 Aug 2025 12:17:40 -0400 Subject: [PATCH] GH-10083: Apply Nullability to FTP module Related to: https://github.com/spring-projects/spring-integration/issues/10083 --- .../FtpOutboundChannelAdapterParser.java | 5 ++- .../ftp/config/FtpOutboundGatewayParser.java | 5 ++- .../integration/ftp/config/package-info.java | 1 + .../integration/ftp/dsl/Ftp.java | 4 +- .../ftp/dsl/FtpInboundChannelAdapterSpec.java | 2 +- ...FtpStreamingInboundChannelAdapterSpec.java | 2 +- .../integration/ftp/dsl/package-info.java | 3 +- .../FtpRegexPatternFileListFilter.java | 2 +- .../FtpSimplePatternFileListFilter.java | 2 +- .../integration/ftp/filters/package-info.java | 1 + .../ftp/gateway/FtpOutboundGateway.java | 15 ++++--- .../integration/ftp/gateway/package-info.java | 1 + .../inbound/FtpInboundFileSynchronizer.java | 8 ++-- ...InboundFileSynchronizingMessageSource.java | 7 ++- .../inbound/FtpStreamingMessageSource.java | 7 +-- .../integration/ftp/inbound/package-info.java | 1 + .../ftp/outbound/package-info.java | 1 + .../ftp/server/ApacheMinaFtplet.java | 14 +++--- .../integration/ftp/server/package-info.java | 1 + .../session/AbstractFtpSessionFactory.java | 17 +++---- .../session/DefaultFtpsSessionFactory.java | 45 +++++++------------ .../ftp/session/FtpRemoteFileTemplate.java | 15 ++++--- .../integration/ftp/session/FtpSession.java | 2 +- .../integration/ftp/session/package-info.java | 1 + 24 files changed, 83 insertions(+), 79 deletions(-) diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java index d1cda816f38..10da5920be7 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java @@ -16,6 +16,8 @@ package org.springframework.integration.ftp.config; +import java.util.Objects; + import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -55,7 +57,8 @@ protected void postProcessBuilder(BeanDefinitionBuilder builder, Element element .iterator() .next() .getValue(); - templateDefinition.getPropertyValues() // NOSONAR never null + + Objects.requireNonNull(templateDefinition).getPropertyValues() .add("existsMode", FtpRemoteFileTemplate.ExistsMode.NLST); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "chmod", "chmodOctal"); } diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParser.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParser.java index 9709e273bf1..4345033696c 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParser.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParser.java @@ -16,6 +16,8 @@ package org.springframework.integration.ftp.config; +import java.util.Objects; + import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; @@ -66,7 +68,8 @@ protected void postProcessBuilder(BeanDefinitionBuilder builder, Element element .iterator() .next() .getValue(); - templateDefinition.getPropertyValues() // NOSONAR never null + + Objects.requireNonNull(templateDefinition).getPropertyValues() .add("existsMode", FtpRemoteFileTemplate.ExistsMode.NLST); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "working-dir-expression", diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/package-info.java index 6dc81f4f185..bb601a1b329 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/config/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes for configuration - parsers, namespace handlers. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.config; diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/Ftp.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/Ftp.java index 34621dba44d..ee8869fa890 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/Ftp.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/Ftp.java @@ -20,6 +20,7 @@ import java.util.Comparator; import org.apache.commons.net.ftp.FTPFile; +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.ftp.gateway.FtpOutboundGateway; import org.springframework.integration.ftp.session.FtpRemoteFileTemplate; -import org.springframework.lang.Nullable; /** * The factory for FTP components. @@ -216,7 +216,7 @@ public static FtpOutboundGatewaySpec outboundGateway(RemoteFileTemplate * @see RemoteFileTemplate */ public static FtpOutboundGatewaySpec outboundGateway(RemoteFileTemplate remoteFileTemplate, - AbstractRemoteFileOutboundGateway.Command command, String expression) { + AbstractRemoteFileOutboundGateway.Command command, @Nullable String expression) { return outboundGateway(remoteFileTemplate, command.getCommand(), expression); } diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpInboundChannelAdapterSpec.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpInboundChannelAdapterSpec.java index 97c1c4ad2b1..051bc6e2065 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpInboundChannelAdapterSpec.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpInboundChannelAdapterSpec.java @@ -20,6 +20,7 @@ import java.util.Comparator; import org.apache.commons.net.ftp.FTPFile; +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.ftp.inbound.FtpInboundFileSynchronizer; import org.springframework.integration.ftp.inbound.FtpInboundFileSynchronizingMessageSource; import org.springframework.integration.metadata.SimpleMetadataStore; -import org.springframework.lang.Nullable; /** * A {@link RemoteFileInboundChannelAdapterSpec} for an {@link FtpInboundFileSynchronizingMessageSource}. diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpStreamingInboundChannelAdapterSpec.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpStreamingInboundChannelAdapterSpec.java index de04fca37ec..95f075005f4 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpStreamingInboundChannelAdapterSpec.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/FtpStreamingInboundChannelAdapterSpec.java @@ -19,6 +19,7 @@ import java.util.Comparator; import org.apache.commons.net.ftp.FTPFile; +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.ftp.filters.FtpSimplePatternFileListFilter; import org.springframework.integration.ftp.inbound.FtpStreamingMessageSource; import org.springframework.integration.metadata.SimpleMetadataStore; -import org.springframework.lang.Nullable; /** * A {@link RemoteFileStreamingInboundChannelAdapterSpec} for a {@link FtpStreamingMessageSource}. diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/package-info.java index 55e82bb003a..66b0df941fb 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/dsl/package-info.java @@ -1,6 +1,5 @@ /** * Provides FTP Components for the Java DSL. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.dsl; diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRegexPatternFileListFilter.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRegexPatternFileListFilter.java index dd934cee0e2..bb54bf05eae 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRegexPatternFileListFilter.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRegexPatternFileListFilter.java @@ -41,7 +41,7 @@ public FtpRegexPatternFileListFilter(Pattern pattern) { @Override protected String getFilename(FTPFile file) { - return (file != null) ? file.getName() : null; + return file.getName(); } @Override diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpSimplePatternFileListFilter.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpSimplePatternFileListFilter.java index d19e8d11981..98991ef4c2e 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpSimplePatternFileListFilter.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpSimplePatternFileListFilter.java @@ -35,7 +35,7 @@ public FtpSimplePatternFileListFilter(String pattern) { @Override protected String getFilename(FTPFile file) { - return (file != null) ? file.getName() : null; + return file.getName(); } @Override diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/package-info.java index 0e05211d77c..aecf63fbbc5 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting FTP file filtering. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.filters; diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java index c1d83043b41..fa78217a199 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java @@ -27,6 +27,7 @@ import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; +import org.jspecify.annotations.Nullable; import org.springframework.expression.Expression; import org.springframework.expression.spel.support.StandardEvaluationContext; @@ -41,7 +42,6 @@ import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.integration.ftp.session.FtpFileInfo; import org.springframework.integration.ftp.session.FtpRemoteFileTemplate; -import org.springframework.lang.Nullable; import org.springframework.messaging.Message; /** @@ -54,8 +54,9 @@ */ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway { - private Expression workingDirExpression; + private @Nullable Expression workingDirExpression; + @SuppressWarnings("NullAway.Init") private StandardEvaluationContext evaluationContext; /** @@ -210,18 +211,18 @@ protected FTPFile enhanceNameWithSubDirectory(FTPFile file, String directory) { } @Override - protected List ls(Message message, Session session, String dir) throws IOException { + protected List ls(Message message, Session session, @Nullable String dir) throws IOException { return doInWorkingDirectory(message, session, () -> super.ls(message, session, dir)); } @Override - protected List nlst(Message message, Session session, String dir) throws IOException { + protected List nlst(Message message, Session session, @Nullable String dir) throws IOException { return doInWorkingDirectory(message, session, () -> super.nlst(message, session, dir)); } @Override - protected File get(Message message, Session session, String remoteDir, String remoteFilePath, - String remoteFilename, FTPFile fileInfoParam) throws IOException { + protected File get(Message message, Session session, @Nullable String remoteDir, String remoteFilePath, + String remoteFilename, @Nullable FTPFile fileInfoParam) throws IOException { return doInWorkingDirectory(message, session, () -> super.get(message, session, remoteDir, remoteFilePath, remoteFilename, fileInfoParam)); @@ -249,7 +250,7 @@ protected boolean mv(Message message, Session session, String remote } @Override - protected String put(Message message, Session session, String subDirectory) { + protected String put(Message message, Session session, @Nullable String subDirectory) { try { return doInWorkingDirectory(message, session, () -> super.put(message, session, subDirectory)); diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/package-info.java index 1c2fcc16692..411894b6a89 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting FTP gateways. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.gateway; diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizer.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizer.java index debdf48ec94..b0bde478959 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizer.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizer.java @@ -42,21 +42,21 @@ public class FtpInboundFileSynchronizer extends AbstractInboundFileSynchronizer< * {@link org.springframework.integration.file.remote.session.Session} instances. * @param sessionFactory The session factory. */ - @SuppressWarnings("this-escape") + @SuppressWarnings({ "this-escape", "NullAway"})// The LiteralExpression can actually handle null ok public FtpInboundFileSynchronizer(SessionFactory sessionFactory) { super(sessionFactory); - doSetRemoteDirectoryExpression(new LiteralExpression(null)); // NOSONAR - LE can actually handle null ok + doSetRemoteDirectoryExpression(new LiteralExpression(null)); doSetFilter(new FtpPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "ftpMessageSource")); } @Override protected boolean isFile(FTPFile file) { - return file != null && file.isFile(); + return file.isFile(); } @Override protected String getFilename(FTPFile file) { - return (file != null ? file.getName() : null); + return file.getName(); } @Override diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizingMessageSource.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizingMessageSource.java index 6d56dde8e58..f77365068b1 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizingMessageSource.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpInboundFileSynchronizingMessageSource.java @@ -20,6 +20,7 @@ import java.util.Comparator; import org.apache.commons.net.ftp.FTPFile; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer; import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizingMessageSource; @@ -31,6 +32,8 @@ * @author Josh Long * @author Mark Fisher * @author Oleg Zhurakousky + * @author Artem Bilan + * * @since 2.0 */ public class FtpInboundFileSynchronizingMessageSource extends AbstractInboundFileSynchronizingMessageSource { @@ -39,7 +42,9 @@ public FtpInboundFileSynchronizingMessageSource(AbstractInboundFileSynchronizer< super(synchronizer); } - public FtpInboundFileSynchronizingMessageSource(AbstractInboundFileSynchronizer synchronizer, Comparator comparator) { + public FtpInboundFileSynchronizingMessageSource(AbstractInboundFileSynchronizer synchronizer, + @Nullable Comparator comparator) { + super(synchronizer, comparator); } diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpStreamingMessageSource.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpStreamingMessageSource.java index 150a2383d69..0baf70e804b 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpStreamingMessageSource.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/FtpStreamingMessageSource.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.commons.net.ftp.FTPFile; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.AbstractFileInfo; import org.springframework.integration.file.remote.AbstractRemoteFileStreamingMessageSource; @@ -57,7 +58,7 @@ public FtpStreamingMessageSource(RemoteFileTemplate template) { * @param comparator the comparator. */ @SuppressWarnings("this-escape") - public FtpStreamingMessageSource(RemoteFileTemplate template, Comparator comparator) { + public FtpStreamingMessageSource(RemoteFileTemplate template, @Nullable Comparator comparator) { super(template, comparator); doSetFilter(new FtpPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "ftpStreamingMessageSource")); } @@ -69,7 +70,7 @@ public String getComponentType() { @Override protected List> asFileInfoList(Collection files) { - List> canonicalFiles = new ArrayList>(); + List> canonicalFiles = new ArrayList<>(); for (FTPFile file : files) { canonicalFiles.add(new FtpFileInfo(file)); } @@ -78,7 +79,7 @@ protected List> asFileInfoList(Collection fil @Override protected boolean isDirectory(FTPFile file) { - return file != null && file.isDirectory(); + return file.isDirectory(); } } diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/package-info.java index 2788dfd40b0..71bc8920b2c 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/inbound/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting inbound endpoints. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.inbound; diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/outbound/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/outbound/package-info.java index 196ff128f7e..5467f6c4337 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/outbound/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/outbound/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes for the FTP outbound channel adapter. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.outbound; diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/ApacheMinaFtplet.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/ApacheMinaFtplet.java index af728bb5d44..0ff75f145d4 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/ApacheMinaFtplet.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/ApacheMinaFtplet.java @@ -25,10 +25,8 @@ import org.apache.ftpserver.ftplet.FtpletResult; import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; -import org.springframework.util.Assert; /** * A listener for FTP events emitted by an Apache Mina ftp server. @@ -36,14 +34,17 @@ * which are subclasses of {@link ApacheMinaFtpEvent}. * * @author Gary Russell + * @author Artem Bilan + * * @since 5.2 * */ -public class ApacheMinaFtplet extends DefaultFtplet - implements ApplicationEventPublisherAware, BeanNameAware, InitializingBean { +public class ApacheMinaFtplet extends DefaultFtplet implements ApplicationEventPublisherAware, BeanNameAware { + @SuppressWarnings("NullAway.Init") private ApplicationEventPublisher applicationEventPublisher; + @SuppressWarnings("NullAway.Init") private String beanName; @Override @@ -64,11 +65,6 @@ public String getBeanName() { return this.beanName; } - @Override - public void afterPropertiesSet() { - Assert.state(this.applicationEventPublisher != null, "An ApplicationEventPublisher is required"); - } - @Override public FtpletResult onConnect(FtpSession session) throws FtpException, IOException { this.applicationEventPublisher.publishEvent(new SessionOpenedEvent(session)); diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/package-info.java index b93548703da..6ef177f9ee2 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/server/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes related to FTP servers. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.server; diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/AbstractFtpSessionFactory.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/AbstractFtpSessionFactory.java index 7dc53bea12b..116f3910748 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/AbstractFtpSessionFactory.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/AbstractFtpSessionFactory.java @@ -26,6 +26,7 @@ import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; +import org.jspecify.annotations.Nullable; import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.messaging.MessagingException; @@ -46,13 +47,13 @@ public abstract class AbstractFtpSessionFactory implements protected final Log logger = LogFactory.getLog(this.getClass()); // NOSONAR - private FTPClientConfig config; + private @Nullable FTPClientConfig config; - private String username; + private @Nullable String username; - private String host; + private @Nullable String host; - private String password; + private @Nullable String password; private int port = FTP.DEFAULT_PORT; @@ -64,11 +65,11 @@ public abstract class AbstractFtpSessionFactory implements private String controlEncoding = FTP.DEFAULT_CONTROL_ENCODING; - private Integer connectTimeout; + private @Nullable Integer connectTimeout; - private Integer defaultTimeout; + private @Nullable Integer defaultTimeout; - private Integer dataTimeout; + private @Nullable Integer dataTimeout; /** * File types defined by {@link org.apache.commons.net.ftp.FTP} constants: @@ -175,7 +176,7 @@ public FtpSession getSession() { } private T createClient() throws IOException { - final T client = this.createClientInstance(); + final T client = createClientInstance(); Assert.notNull(client, "client must not be null"); client.configure(this.config); Assert.hasText(this.username, "username is required"); diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/DefaultFtpsSessionFactory.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/DefaultFtpsSessionFactory.java index 09d880afade..cc00219474b 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/DefaultFtpsSessionFactory.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/DefaultFtpsSessionFactory.java @@ -23,6 +23,7 @@ import javax.net.ssl.TrustManager; import org.apache.commons.net.ftp.FTPSClient; +import org.jspecify.annotations.Nullable; import org.springframework.integration.JavaUtils; import org.springframework.util.StringUtils; @@ -34,33 +35,35 @@ * @author Iwein Fuld * @author Mark Fisher * @author Gary Russell + * @author Artem Bilan + * * @since 2.0 */ public class DefaultFtpsSessionFactory extends AbstractFtpSessionFactory { - private Boolean useClientMode; + private @Nullable Boolean useClientMode; - private Boolean sessionCreation; + private @Nullable Boolean sessionCreation; - private String authValue; + private @Nullable String authValue; - private TrustManager trustManager; + private @Nullable TrustManager trustManager; - private String[] cipherSuites; + private String @Nullable [] cipherSuites; - private String[] protocols; + private String @Nullable [] protocols; - private KeyManager keyManager; + private @Nullable KeyManager keyManager; - private Boolean needClientAuth; + private @Nullable Boolean needClientAuth; - private Boolean wantsClientAuth; + private @Nullable Boolean wantsClientAuth; private boolean implicit = false; private String prot = "P"; - private String protocol; + private @Nullable String protocol; public void setProtocol(String protocol) { this.protocol = protocol; @@ -112,26 +115,10 @@ public void setImplicit(boolean implicit) { @Override protected FTPSClient createClientInstance() { - try { - if (StringUtils.hasText(this.protocol)) { - return new FTPSClient(this.protocol, this.implicit); - } - return new FTPSClient(this.implicit); - } - catch (Exception e) { - - /* - This catch block is technically not necessary but it allows users - to use the older Commons Net 2.0 if necessary, which requires you - to catch a NoSuchAlgorithmException. - */ - - if (e instanceof RuntimeException) { //NOSONAR false positive - throw (RuntimeException) e; - } - - throw new IllegalStateException("Failed to create FTPS client.", e); + if (StringUtils.hasText(this.protocol)) { + return new FTPSClient(this.protocol, this.implicit); } + return new FTPSClient(this.implicit); } @Override 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 de6317f324d..902afe5177c 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 @@ -21,11 +21,11 @@ import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; +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; import org.springframework.messaging.MessagingException; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -50,7 +50,7 @@ public FtpRemoteFileTemplate(SessionFactory sessionFactory) { @SuppressWarnings("unchecked") @Override - public T executeWithClient(final ClientCallback callback) { + public @Nullable T executeWithClient(final ClientCallback callback) { return doExecuteWithClient((ClientCallback) callback); } @@ -67,7 +67,7 @@ public void setExistsMode(ExistsMode existsMode) { this.existsMode = existsMode; } - protected T doExecuteWithClient(final ClientCallback callback) { + protected @Nullable T doExecuteWithClient(final ClientCallback callback) { return execute(session -> callback.doWithClient((FTPClient) session.getClientInstance())); } @@ -83,7 +83,7 @@ protected T doExecuteWithClient(final ClientCallback callback) */ @Override public boolean exists(final String path) { - return doExecuteWithClient(client -> { + Boolean exists = doExecuteWithClient(client -> { try { return switch (FtpRemoteFileTemplate.this.existsMode) { case STAT -> client.getStatus(path) != null; @@ -95,13 +95,15 @@ public boolean exists(final String path) { throw new MessagingException("Failed to check the remote path for " + path, e); } }); + return Boolean.TRUE.equals(exists); } @Override protected boolean shouldMarkSessionAsDirty(Exception ex) { IOException ftpException = findIoException(ex); if (ftpException != null) { - return isStatusDirty(ftpException.getMessage()); + String message = ftpException.getMessage(); + return message != null && isStatusDirty(message); } else { return super.shouldMarkSessionAsDirty(ex); @@ -119,8 +121,7 @@ protected boolean isStatusDirty(String ftpErrorMessage) { && !ftpErrorMessage.contains("" + FTPReply.FILE_NAME_NOT_ALLOWED); } - @Nullable - private static IOException findIoException(Throwable ex) { + private static @Nullable IOException findIoException(@Nullable Throwable ex) { if (ex == null || ex instanceof IOException) { return (IOException) ex; } diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java index aa91cfdd6e4..00c3bd7e951 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSession.java @@ -75,7 +75,7 @@ public FTPFile[] list(@Nullable String path) throws IOException { } @Override - public String[] listNames(String path) throws IOException { + public String[] listNames(@Nullable String path) throws IOException { return this.client.listNames(path); } diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/package-info.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/package-info.java index 9a69c0ef623..a2b9624976b 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/package-info.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes supporting FTP sessions. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.ftp.session;