Commit Graph

305 Commits

Author SHA1 Message Date
Artem Bilan
08400df280 Fix some race conditions in tests
* `SftpSessionFactoryTests.concurrentGetSessionDoesntCauseFailure()`
may not report properly into an `ArrayList` from another thread.
Use `asyncTaskExecutor.submitCompletable()` instead and deal with their result afterward.
* Use `CompletableFuture` for the `TcpListener` logic in the `FailoverClientConnectionFactoryTests.failoverAllDeadAfterSuccess()`
2025-03-20 10:19:36 -04:00
Artem Bilan
2df9611dde GH-9909: Fix SftpSession for shared client
Fixes: #9909
Issue link: https://github.com/spring-projects/spring-integration/issues/9909

The `SftpSession.close()` closes `sftpClient` and its `clientSession` unconditionally.
At the same time the `DefaultSftpSessionFactory.isSharedSession` is expected to expose only a single shared client.
When this `DefaultSftpSessionFactory` is used concurrently, there is a chance that one thread would close
that shared client and another won't be able to interact due to `clientSession` is closed.

* Fix `SftpSession` accepting an `isSharedClient` flag and doing nothing in the `close()` if client is shared.
* Propagate `isSharedSession` state down to the `SftpSession` from the `DefaultSftpSessionFactory`
* Closed shared client and its `clientSession` in the `DefaultSftpSessionFactory.destroy()`

**Auto-cherry-pick to `6.4.x` & `6.3.x`**
2025-03-18 12:40:27 -04:00
Artem Bilan
180c50ec9f Fix race condition in the SftpSessionFactoryTests
Related to: https://github.com/apache/mina-sshd/issues/700
2025-03-17 10:46:30 -04:00
Artem Bilan
8bfb5d248f GH-9869: Introduce AbstractRecentFileListFilter strategy
Fixes: https://github.com/spring-projects/spring-integration/issues/9869

Currently, FileListFilters on the last modified attribute of a file are limited to the use case of discarding files that are too young.
It would be great to have a filter implementation which would accept files which are not old enough.

* Implement `AbstractRecentFileListFilter` for all the supported file protocols
2025-02-27 10:59:20 -05:00
Mohammadreza Yektamaram
173f7954a2 Removed unused bean from SFTP test config
The present bean is left over there after migration from JSch to Apache MINA.

Signed-off-by: Mohammadreza Yektamaram <mohammad.1ta@gmail.com>
2025-02-13 11:24:19 -05:00
Artem Bilan
efa8dc50b7 GH-9821: SFTP: Use STAT command to follow symlinks
Fixes: #9821
Issue link: https://github.com/spring-projects/spring-integration/issues/9821

Previously, Spring Integration used JSch library for SFTP protocol,
and that one was able to follow symlinks.
Currently, the `SftpSession` uses `LSTAT` command which does not follow symlinks

* Fix `SftpSession` to call `sftpClient.stat()` instead of `lstat()`
to mitigate migration pain from JSch

**Auto-cherry-pick to `6.4.x` & `6.3.x`**
2025-02-12 13:28:41 -05:00
Artem Bilan
a4b193fa64 GH-9684: Auto-create temporary remote directory
Fixes: #9684
Issue link: https://github.com/spring-projects/spring-integration/issues/9684

The `RemoteFileTemplate` is missing to create a temporary remote directory

* Fix `RemoteFileTemplate.sendFileToRemoteDirectory()` to create a `temporaryRemoteDirectory`
as well if it is different from already created `remoteDirectory`
* Add `SftpServerOutboundTests.autoCreateTemporaryDirectory()` to verify that `temporaryRemoteDirectory` is created and in-use
* Some other `SftpServerOutboundTests` refactoring for better code style

**Auto-cherry-pick to `6.3.x`**
2024-12-12 17:31:07 -05:00
Artem Bilan
15e914b75b Remove Bamboo mentioning from the tests 2024-10-18 14:33:43 -04:00
Artem Bilan
57c98e1611 GH-9380: Add DefaultSftpSessionFactory.setSshClientConfigurer()
Fixes: #9380

Expose a `Consumer<SshClient> sshClientConfigurer` option for the `DefaultSftpSessionFactory`
to further customize an internal `SshClient` instance.
2024-08-14 15:56:22 -04:00
Artem Bilan
fdac8f1634 Fix tests for executorService.shutdown()
Even if `Executors.newSingleThreadExecutor()` returns a `FinalizableDelegatedExecutorService`,
an instance is kept in the memory until JVM exists.
That may lead to memory leak since we have a lot of threads in memory.

**Auto-cherry-pick to `6.3.x` & `6.2.x`**
2024-08-13 15:57:25 -04:00
darrylsmithUGA
a3fb68a831 GH-9272: Close ClientSession from SftpSession
Fixes: #9272

* close ClientSession when closing SftpSession
* fix whitespace issues
* stop the SshClient on bean destruction
* use convenient assertions

**Auto-cherry-pick to `6.3.x` & `6.2.x`**
2024-07-01 13:02:35 -04:00
Artem Bilan
d87a7098ca GH-9129: SFTP: Remove extra / for the file_remoteDirectory header
Fixes: #9129

If `.remoteDirectory("/sftpSource")`, then `FileHeaders.REMOTE_DIRECTORY` is `//sftpSource`

* Fix `AbstractInboundFileSynchronizer` to not add `/` if one is already present in the beginning of the `remoteDirectoryPath`

**Auto-cherry-pick to `6.2.x` & `6.1.x`**
2024-05-08 15:48:08 -04:00
Artem Bilan
8b88668fbe GH-9114: SFTP: Use canonicalPath exists operation
Fixes: #9114

If path is not in normalized presentation, the SFTP operation might fail like:
```
Caused by: SFTP error (SSH_FX_NO_SUCH_PATH): The file path does not exist or is invalid.
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.throwStatusException(AbstractSftpClient.java:277)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributesResponse(AbstractSftpClient.java:333)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributes(AbstractSftpClient.java:325)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.lstat(AbstractSftpClient.java:1010)
at org.springframework.integration.sftp.session.SftpSession.exists(SftpSession.java:191)
```

* Use it now like this `this.sftpClient.lstat(normalizePath(path))`

**Auto-cherry-pick to `6.2.x` & `6.1.x`**
2024-05-07 14:23:17 -04:00
Artem Bilan
a2215afdf7 GH-9123: SFTP: Use canonicalPath for read operation
Fixes: #9123

The `/` at the beginning of the remote dir path is not necessary when listing files, although it is necessary to download them
The `SftpTemplate.get()` should work also with `remote-dir/MyFile.csv` as input.

* Fix `SftpSession.readRaw()` to call `sftpClient.canonicalPath(source)` if the path does not start with a `/`.
Something similar what is does
* Delegate to `SftpSession.readRaw()` from the `SftpSession.read()`
* Reuse `normalizePath()` for `doList()`

**Auto-cherry-pick to `6.2.x` & `6.1.x`**
2024-05-07 13:46:27 -04:00
Artem Bilan
c155d5d418 Add EmptyLineSeparator Checkstyle rule
* Support "blank lines around" via `spring-framework.xml` IDEA config
* Fix all the Checkstyle violations
2024-03-27 16:54:25 -04:00
Artem Bilan
ba287aeb5b GH-8797: Fix DefSftpSessionFactory.timeout logic
Fixes https://github.com/spring-projects/spring-integration/issues/8797

After migration to Apache MINA we have missed to fix `DefaultSftpSessionFactory.timeout`
to be `0` by default as it states in its Javadocs and reference manual
It is `null` by default which really means an infinite wait.

* Fix `DefaultSftpSessionFactory.timeout` to be a reasonable 30 seconds by default
* Fix `setTimeout()` Javadocs and respective `session-factory.adoc`
* Propagate this `timeout` down to the `SftpClient` for its commands interactions
2023-12-04 13:30:33 +01:00
Artem Bilan
22c4db291b GH-8792: Fix File StreamingMS for one file filter
Fixes https://github.com/spring-projects/spring-integration/issues/8792

1. Use a `SftpStreamingMessageSource` with a `maxFetchSize = 5` and a `ChainFileListFilter` filter composed with
`SftpSystemMarkerFilePresentFileListFilter` which `supportsSingleFileFiltering == false`
2. Put 2 files in the folder and invoke `SftpStreamingMessageSource.receive()` method twice.
3. Put 5 files in the folder and invoke `SftpStreamingMessageSource.receive()`` method five times.
4. The last two files won't be received.

When you set max fetch size to a number bigger than one (for example 5) and at a certain point
it is necessary to `this.toBeReceived.clear()` inside `AbstractRemoteFileStreamingMessageSource.doReceive()`,
those removed elements from toBeReceived are not rolled back.

* Fix `AbstractRemoteFileStreamingMessageSource.listFiles()` to calculate `maxFetchSize` as `getMaxFetchSize() - this.fetched.get()`

**Cherry-pick to `6.1.x`, `6.0.x` & `5.5.x`**
2023-11-17 16:39:02 -05:00
Artem Bilan
44433ed8a1 GH-8745: Add RFT.shouldMarkSessionAsDirty() (#8759)
* 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`**

* * Fix tests for pool interaction

* * Fix language in Javadocs
* Add more `not dirty` statuses to `SftpRemoteFileTemplate` & `SmbRemoteFileTemplate`
2023-10-11 10:52:48 -04:00
Adama Sorho
73ed3eeebd GH-8691: Add (S)FTP, SMB aged file filters
Fixes https://github.com/spring-projects/spring-integration/issues/8691

* Remove setAge with TimeUnit
Turned out we don't need anymore since we're using Duration for age in FtpLastModifiedFileListFilter and SftpLastModifiedFileListFilter.
* Add changes to the docs
* Introduce AbstractLastModifiedFileListFilter
* Some code readability improvements
* Make language in the docs more official
2023-09-14 12:16:06 -04:00
Artem Bilan
e4bacc3e92 GH-8708: Fix concurrency around SFTP client (#8709)
Fixes https://github.com/spring-projects/spring-integration/issues/8708

According to the `org.apache.sshd.common.channel.ChannelAsyncOutputStream.writeBuffer()` JavaDocs cannot be used concurrently.

* Introduce internal `DefaultSftpSessionFactory.ConcurrentSftpClient` extension
of the `DefaultSftpClient` to set a `Lock` around `super.send(cmd, buffer);`
* Remove lock from the `SftpSession` since it now is managed by the mentioned `ConcurrentSftpClient`

**Cherry-pick to `6.1.x` & `6.0.x`**
2023-08-22 14:00:34 -04:00
Artem Bilan
152666116a Upgrade to MINA SSHD 2.10.0 (#8676)
* Remove trailing slashes from remote dirs to create in SFTP tests
2023-07-17 16:19:06 -04:00
Artem Bilan
d4535cab7d GH-8674: Fix ServerKeyVerifier impl for key type (#8675)
Fixes https://github.com/spring-projects/spring-integration/issues/8674

The `ResourceKnownHostsServerKeyVerifier` does not take into account that several different
keys can be present in the known hosts resource for the same host/port

* Fix `ResourceKnownHostsServerKeyVerifier` to find a list of knows host for the requested session.
Then iterate of this result to match the key type first and then compare keys and their `revoked` marker

**Cherry-pick to `6.1.x` & `6.0.x`**
2023-07-17 14:26:39 -04:00
abilan
03799293ce Add @LogLevels for SftpRemoteFileTemplateTests
Not clear why `SftpRemoteFileTemplateTests.testINT3412AppendStatRmdir()`
 is failing on CI Linux, so add a tracing diagnostics to see how Apache SSHD behaves over there
2023-06-22 11:55:38 -04:00
abilan
8a7293c680 An attempt to fix Sftp tests to new sshd-sftp 2023-06-22 10:19:46 -04:00
abilan
af4c7d2ad4 Bring back sshd-sftp-2.9.2
Looks like there is some bug in the latest version,
so the directory cannot be created on Linux

We will revise the problem in the next version
2023-05-16 15:38:04 -04:00
abilan
a937d5ff6c Add diagnostics to SftpRemoteFileTemplateTests 2023-05-16 15:10:29 -04:00
Auke Zaaiman
775e6fdac5 GH-8581: Don't overwrite external SshClient
Fixes https://github.com/spring-projects/spring-integration/issues/8581

Do not overwrite configuration of externally provided `SshClient` in the `DefaultSftpSessionFactory`

* Replace JUnit `assertDoesNotThrow` by AssertJ `assertThatNoException` in test

**Cherry-pick to `6.0.x`**
2023-03-28 11:23:39 -04:00
abilan
ee5ea036cc Fix deprecations from upstream dependencies 2023-02-21 13:47:15 -05:00
kdebski85
854e555e4e GH-3980: Fix DefaultSftpSFactory for concurrency
Fixes https://github.com/spring-projects/spring-integration/issues/3980

When not `isSharedSession`, the `initClient()` is called for every session
we request from the factory and in concurrent calls we end up with not initialized SSH client
in some threads.

* Add `synchronized` double check logic to the `initClient()` to block other threads while the first one
initialize the client
* Use `volatile boolean` instead of `AtomicBoolean` and change its state when `SshClient` is created and started
2023-01-05 10:01:48 -05:00
abilan
033cb7695b Migrate Mockito-effected test classes to JUnit 5 2022-12-21 09:42:18 -05:00
abilan
52d43ea8ed Upgrade dependencies; prepare for release
Fix XML configs for new `Mockito.mock()` factory method
2022-12-20 16:25:06 -05:00
Artem Bilan
d38e0d8720 GH-3962: Support SFTP < v5 for rename (#3964)
* GH-3962: Support SFTP < v5 for rename

Fixes https://github.com/spring-projects/spring-integration/issues/3962

Turns out the `SftpClient.CopyMode` options are supported only starting SFTP v5

* Check for the version from the client and fallback to the logic we had before with JSsch:
try to rename, delete existing file if such an exception status is thrown and retry to rename

* * Fix `SftpOutboundTests` with answering an explicit SFTP version for an `SftpClient` mock
2022-12-20 11:46:02 -05:00
abilan
3a743802c0 GH-3974: Fix SftpSession for absolute paths
Fixes https://github.com/spring-projects/spring-integration/issues/3974

* Treat a leading `/` as an indicator of absolute path request in the `SftpSession.doList()`
* Call `sftpClient.canonicalPath()` for path without a leading `/` to resolve it as relative path in the user home
* Add a note in docs for `LS` command
2022-12-16 12:59:07 -05:00
abilan
1c836f0698 GH-3969: SFTP: Bring back support for empty path
Fixes https://github.com/spring-projects/spring-integration/issues/3969

In previous version for SFTP client (Jsch), the empty path for `LS` command
has meant a `user home`.
Turns out the MINA `SftpClient` does not support automatic user home resolution
from the empty path.

* Fix `SftpSession` to resolve an empty path into a user home via `canicalPath()` operation
2022-12-12 11:43:01 -05:00
abilan
7864658d01 GH-3686: Apply SF editor config
Fixes https://github.com/spring-projects/spring-integration/issues/3686

* Add `src/idea` with respective editor config for IntelliJ IDEA.
Must be imported into an IDE
* Add `src/eclipse` with respective editor config for Eclipse/STS
* Reformat imports in source code according a new editor config
2022-11-14 10:55:21 -05:00
Artem Bilan
5ccfcbd96f Fix SftpSession for host:port resolution
The plain `SocketAddress.toString()` may resolve
to `hostName/IP` pair which is not parsed properly via `URI.getHost()`
downstream leaving `/IP` part for `uri.getPath()` request.
In the end this may lead to wrong file name to be used in the SFTP logic

* Fix `SftpSession.getHostPort()` to use `SshdSocketAddress` utility
to resolve host and port properly from the provided `SocketAddress`
2022-10-11 15:09:57 -04:00
Artem Bilan
6ce61ed7f2 Disable ResKnownHostsSerKeyVerifierTests on CI
Some server keys don't pass the verifier
2022-09-27 15:51:59 -04:00
Artem Bilan
82e3073fc9 Remove unused import from known_hosts test class 2022-09-27 14:26:32 -04:00
Artem Bilan
e32a5024ad Use hashed host for known_hosts tests
The `192.168.1.61` is Private Use IP.
It is an intranet IP address, which is usually allocated to mobile phones, desktops, laptops, TVs, smart speakers and other devices.

The logic is taken from a similar test class in the Apache MINA project
2022-09-27 13:46:24 -04:00
Artem Bilan
4aa2f91bd9 GH-3572: Migrate SFTP from jsch to sshd-sftp (#3892)
* GH-3572: Migrate SFTP from `jsch` to `sshd-sftp`

Fixes https://github.com/spring-projects/spring-integration/issues/3572

* Rework SFTP module from the JSch API to more modern `sshd-sftp`
* Migrate generics of most API from `ChannelSftp.LsEntry` to the `SftpClient.DirEntry`
* Rework `DefaultSftpSessionFactory` to deal with an `SshClient` and create `SftpClient`
wrapped to the `SftpSession`
* Implement a `ResourceKnownHostsServerKeyVerifier` to load `known-hosts` from any possible resource
* Implement an expected `SftpSession.list()` with just file name to take or pattern matching
* Remove some unused tests and their config
* Remove tests for custom `UserInfo` since we don't provide any custom out-of-the-box
* Test a new `ResourceKnownHostsServerKeyVerifier` against default `known-hosts` file

* * Some tests improvements

* * Improve generics handling for `FileUtils`
2022-09-27 13:10:11 -04:00
Artem Bilan
8f44870837 GH-3827: Fix RemoteFile GET STREAM session leak
Fixes https://github.com/spring-projects/spring-integration/issues/3827

The `AbstractRemoteFileOutboundGateway.doGet()` for a `STREAM` option
does not close the `session` in case of error.
This may lead to some leaks or exhausted caches

* Close `session` in the `catch()` of the `AbstractRemoteFileOutboundGateway.doGet()`
* Adjust the `SftpServerOutboundTests` to configure a `CachingSessionFactory`
for the `testStream()` to verify there is no leaks attempting to
`GET STREAM` non-existing remote file twice

**Cherry-pick to `5.5.x`**
2022-07-18 14:07:34 -04:00
Artem Bilan
e0f137905a Fix compatibility with the latest SF
* Mostly changes are related to the `TaskScheduler` and `Trigger` APIs
* Migrate to `micrometer-tracing` dependency
* Rework `SocketTestUtils` to use a `InetAddress.getLocalHost()`
for more stability and performance on Windows
* Fix docs for new `PeriodicTrigger` API
2022-07-08 17:36:15 -04:00
Artem Vozhdayenko
53dd050c5b GH-3623: Deprecarte an IntegrationFlows
Fixes https://github.com/spring-projects/spring-integration/issues/3623

* `IntegrationFlow` refactoring
* Apply several code style improvements and good practices
* Code style: no empty lines for methods javadocs
* make deprecated implementation reuse actual one instead of the copy-paste approach
* add whats-new comments
* Fix whats-new page according to standards
2022-07-05 15:47:30 -04:00
Artem Bilan
2022c40d55 Fix compatibility with the latest SF
* Upgrade Spring dependencies to the latest SNAPSHOTs
* Fix tests to verify against stack traces: the message
of the `NestedRuntimeException`  does not include the nested exception information.
Related to https://github.com/spring-projects/spring-framework/issues/25162
* Fix `JdbcMessageStore` and `DefaultLockRepository` to rely on the `DataIntegrityViolationException`
instead of only its `DuplicateKeyException` extension.
This is the current behavior of the SQL errors translation
* Disable `WebFluxDslTests.testValidation()` - doesn't subscribe to the reply somehow...
* Refine `SimplePool.PoolSemaphore.reducePermits()`
2022-06-27 20:30:14 -04:00
Artem Bilan
78366e7b00 GH-3647: Use remoteDirExpression in MV command (#3651)
* GH-3647: Use remoteDirExpression in MV command

Fixes https://github.com/spring-projects/spring-integration/issues/3647

To simplify a source and renameTo remote file expressions, the `remoteDirectoryExpression`
is consulted now, when they are not full paths.
This is useful when we want just to rename a remote file in some dir

* * Add JavaDoc for `getDirectoryExpressionProcessor()`
* Fix language in docs
2021-10-21 14:12:50 -04:00
Artem Bilan
e2e01db9a2 Add SFTP remote copy test-case 2021-02-18 11:31:08 -05:00
Gary Russell
338a26d34d GH-3488: Fix Persistent Filters with Recursion
Resolves https://github.com/spring-projects/spring-integration/issues/3488

Resolves two problems:

- When changes are made deep in the directory tree, they were not detected because
  the directory is in the metadata store and only passes the filter if a file
  immediately under it is changed, changing the directory's timestamp.

This is solved by subclassing `AbstractDirectoryAwareFileListFilter`, allowing its
`alwaysAcceptDirectories` property to be set.

- Only the filename was used as a metadata key; causing problems if a file with the
  same name appears multiple times in the tree.

This is solved with a new property on `AbstractDirectoryAwareFileListFilter` used by
the gateways to determine whether to filter the raw file names returned by the session
(previous behavior) or the full path relative to the root directory.

**cherry-pick to 5.4.x, 5.3.x**

* Some code style clean up
2021-02-05 16:49:31 -05:00
Gary Russell
d7740706bb GH-3482: (S)FTP: Fix Recursive LS (ARFOG)
Resolves https://github.com/spring-projects/spring-integration/issues/3482

`.` and `..` should be ignored when recursing.

**cherry-pick to 5.4.x, 5.3.x**

* Fix checkstyle.

* Fix test in `file` module - test was incorrect; it would have detected this problem.
2021-02-01 16:04:08 -05:00
Artem Bilan
5c7384316a Upgrade dependencies
* Fix compatibility with the latest dependency upgrades
2021-01-15 17:10:07 -05:00
Artem Bilan
3bf4fd687d More GH Actions goodies (#3441)
* More GH Actions goodies

* Add RabbitMQ, MongoDB & Redis services into GH actions
* Remove Travis

* * Add `distributionSha256Sum` into `gradle-wrapper.properties`
* Try `TERM: dumb` to see difference for Gradle output in GH action
* Add `-S` to see the reason of test failure

* * Try MQTT plugin for RabbitMQ image

* * Try `-i` for test failure in Gradle on Actions

* * Use `eclipse-mosquitto` image for MQTT on actions
* Fix `FtpServerOutboundTests` for the proper FTP file list
* Output file list for the failed session in the `RotatingServersTests`

* * Adjust SOUT in the test for Checkstyle

* * Make some change to `RotatingServersTests`.
Looks like the order for `@BeforeAll` methods is not determined
and we may start to interaction with FTP server which is not
started yet

* Fix SSL Handshake Test

- we already made this change for the NIO test, but the NET test is failing the same
  way - the cert failure switched to the server so the expected exception was not
  thrown on the client side. Due to JVM changes.

* * Fix SFTP tests for wrong host and auto-startup state
* Remove `-i` for Gradle in the GH Actions

* * Try `--no-parallel` for Gradle in the GH Actions

* * Try GH actions without Mosquitto

* * Try `cyrilix/rabbitmq-mqtt` for GH Actions

Co-authored-by: Gary Russell <grussell@pivotal.io>
2020-12-09 10:26:13 -05:00