This is an automated email from the ASF dual-hosted git repository.
bamaer pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 8f614e8045 fix folder check button, fixes #8252 (#9015)
8f614e8045 is described below
commit 8f614e8045d7f7f6fee37bcb206402ead3af9a59
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Mon Oct 19 17:14:06 2026 +0200
fix folder check button, fixes #8252 (#9015)
---
.../apache/hop/workflow/actions/ftp/ActionFtp.java | 20 +++++++
.../hop/workflow/actions/ftp/ActionFtpDialog.java | 62 ++++++++++++++--------
.../actions/ftp/ActionFtpExecutionTest.java | 47 ++++++++++++++++
3 files changed, 108 insertions(+), 21 deletions(-)
diff --git
a/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtp.java
b/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtp.java
index 848f0e284f..a76c6b553f 100644
---
a/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtp.java
+++
b/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtp.java
@@ -18,6 +18,7 @@
package org.apache.hop.workflow.actions.ftp;
import com.google.common.annotations.VisibleForTesting;
+import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -485,6 +486,25 @@ public class ActionFtp extends ActionBase implements
Cloneable, IAction, IFtpCon
return normalizedPath;
}
+ /**
+ * Change into each folder in turn, the way the action does when it runs:
the remote directory
+ * from the folder the login lands in, the move-to folder from inside the
remote directory. The
+ * dialog checks its folders with this.
+ *
+ * @param ftpClient a logged in client, left in the last folder it could
change into
+ * @param folders the resolved and normalized folders, the remote directory
first
+ * @return the first folder which isn't there, or null when they all are
+ */
+ public static String findMissingFolder(FTPClient ftpClient, String...
folders)
+ throws IOException {
+ for (String folder : folders) {
+ if (!ftpClient.changeWorkingDirectory(folder)) {
+ return folder;
+ }
+ }
+ return null;
+ }
+
private void addFilenameToResultFilenames(
Result result, IWorkflowEngine<WorkflowMeta> parentWorkflow, String
filename)
throws HopException {
diff --git
a/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtpDialog.java
b/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtpDialog.java
index 3a995c5c1e..a8e56597e3 100644
---
a/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtpDialog.java
+++
b/plugins/tech/ftp/src/main/java/org/apache/hop/workflow/actions/ftp/ActionFtpDialog.java
@@ -17,6 +17,7 @@
package org.apache.hop.workflow.actions.ftp;
+import java.util.Arrays;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.hop.core.Const;
import org.apache.hop.core.Props;
@@ -1209,7 +1210,7 @@ public class ActionFtpDialog extends ActionDialog {
// Add listeners
wTest.addListener(SWT.Selection, e -> test());
wbTestFolderExists.addListener(
- SWT.Selection, e -> checkRemoteFolder(wMoveToDirectory.getText()));
+ SWT.Selection, e -> checkRemoteFolder(wFtpDirectory.getText(),
wMoveToDirectory.getText()));
wbTestChangeFolderExists.addListener(
SWT.Selection, e -> checkRemoteFolder(wFtpDirectory.getText()));
@@ -1244,29 +1245,48 @@ public class ActionFtpDialog extends ActionDialog {
closeFtpConnection();
}
- private void checkRemoteFolder(String folderName) {
- if (!Utils.isEmpty(folderName) && connectToFtp()) {
- try {
- boolean exists = ftpclient.changeWorkingDirectory(folderName);
- if (exists) {
- MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION);
- mb.setMessage(
- BaseMessages.getString(PKG, "ActionFtp.FolderExists.OK",
folderName) + Const.CR);
- mb.setText(BaseMessages.getString(PKG,
"ActionFtp.FolderExists.Title.Ok"));
- mb.open();
- } else {
- MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
- mb.setMessage(
- BaseMessages.getString(PKG, "ActionFtp.FolderExists.NOK",
folderName) + Const.CR);
- mb.setText(BaseMessages.getString(PKG,
"ActionFtp.FolderExists.Title.Bad"));
- mb.open();
- }
- } catch (Exception e) {
+ /**
+ * Check a remote folder the way the action finds it when it runs, on a
fresh login. A client kept
+ * open between checks is still in the folder the previous check changed
into, which made a
+ * relative folder look missing the second time it was checked.
+ *
+ * @param folders the folders to change into in turn, the one to check last
+ */
+ private void checkRemoteFolder(String... folders) {
+ if (Utils.isEmpty(folders[folders.length - 1])) {
+ return;
+ }
+ String[] path =
+ Arrays.stream(folders)
+ .filter(folder -> !Utils.isEmpty(folder))
+ .map(folder -> action.normalizePath(variables.resolve(folder)))
+ .toArray(String[]::new);
+ try {
+ if (!connectToFtp()) {
+ return;
+ }
+ String missing = ActionFtp.findMissingFolder(ftpclient, path);
+ if (missing == null) {
+ MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION);
+ mb.setMessage(
+ BaseMessages.getString(PKG, "ActionFtp.FolderExists.OK",
path[path.length - 1])
+ + Const.CR);
+ mb.setText(BaseMessages.getString(PKG,
"ActionFtp.FolderExists.Title.Ok"));
+ mb.open();
+ } else {
MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
- mb.setMessage("Error checking remote folder: " + e.getMessage());
- mb.setText("Folder Check Failed");
+ mb.setMessage(
+ BaseMessages.getString(PKG, "ActionFtp.FolderExists.NOK", missing)
+ Const.CR);
+ mb.setText(BaseMessages.getString(PKG,
"ActionFtp.FolderExists.Title.Bad"));
mb.open();
}
+ } catch (Exception e) {
+ MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+ mb.setMessage("Error checking remote folder: " + e.getMessage());
+ mb.setText("Folder Check Failed");
+ mb.open();
+ } finally {
+ closeFtpConnection();
}
}
diff --git
a/plugins/tech/ftp/src/test/java/org/apache/hop/workflow/actions/ftp/ActionFtpExecutionTest.java
b/plugins/tech/ftp/src/test/java/org/apache/hop/workflow/actions/ftp/ActionFtpExecutionTest.java
index 74734edaa6..68b1baa7fb 100644
---
a/plugins/tech/ftp/src/test/java/org/apache/hop/workflow/actions/ftp/ActionFtpExecutionTest.java
+++
b/plugins/tech/ftp/src/test/java/org/apache/hop/workflow/actions/ftp/ActionFtpExecutionTest.java
@@ -28,11 +28,13 @@ import static org.mockito.Mockito.when;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
+import org.apache.commons.net.ftp.FTPClient;
import org.apache.hop.core.HopEnvironment;
import org.apache.hop.core.Result;
import org.apache.hop.core.logging.LogLevel;
import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.metadata.serializer.memory.MemoryMetadataProvider;
+import org.apache.hop.vfs.ftp.FtpHelper;
import org.apache.hop.vfs.ftp.FtpSecurityMode;
import org.apache.hop.vfs.ftp.FtpTestServer;
import org.apache.hop.vfs.ftp.metadata.FtpConnection;
@@ -431,6 +433,51 @@ class ActionFtpExecutionTest {
assertEquals("from the outbox",
Files.readString(targetDir.resolve("wanted.txt")));
}
+ /**
+ * The "Check folder" buttons of the dialog have to find a folder where the
action does: a
+ * relative move-to folder inside the remote directory.
+ */
+ @Test
+ @DisplayName("The folder check finds a relative move-to folder where the
action does")
+ void theFolderCheckFollowsTheAction(@TempDir Path targetDir) throws
Exception {
+ Files.createDirectories(serverRoot.resolve("outbox/done"));
+ server.writeFile("outbox/moved.txt", "move me");
+
+ ActionFtp action = configure(targetDir);
+ action.setRemoteDirectory("outbox");
+ action.setMoveFiles(true);
+ action.setMoveToDirectory("done");
+
+ FTPClient client = FtpHelper.connect(action, null);
+ try {
+ assertNull(ActionFtp.findMissingFolder(client, "outbox", "done"));
+ } finally {
+ FtpHelper.disconnect(action.getLogChannel(), client);
+ }
+
+ Result result = action.execute(new Result(), 0);
+
+ assertTrue(result.isResult());
+ assertEquals("move me", server.readFile("outbox/done/moved.txt"));
+ }
+
+ @Test
+ @DisplayName("The folder check names the first folder which isn't there")
+ void theFolderCheckNamesTheMissingFolder(@TempDir Path targetDir) throws
Exception {
+ Files.createDirectories(serverRoot.resolve("outbox/done"));
+
+ ActionFtp action = configure(targetDir);
+ FTPClient client = FtpHelper.connect(action, null);
+ try {
+ String home = client.printWorkingDirectory();
+ assertEquals("not-there", ActionFtp.findMissingFolder(client,
"not-there", "done"));
+ client.changeWorkingDirectory(home);
+ assertEquals("not-there", ActionFtp.findMissingFolder(client, "outbox",
"not-there"));
+ } finally {
+ FtpHelper.disconnect(action.getLogChannel(), client);
+ }
+ }
+
@Test
@DisplayName("A unique name is found for a file which has no extension
either")
void createUniqueForAFileWithoutAnExtension(@TempDir Path targetDir) throws
Exception {