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 64c64e9dca Fix Create folder validation to check folderName and reject
a blank name (#8908)
64c64e9dca is described below
commit 64c64e9dca92a903c2fe6a6db0703636d93668d2
Author: Lance <[email protected]>
AuthorDate: Wed Oct 14 18:54:26 2026 +0800
Fix Create folder validation to check folderName and reject a blank name
(#8908)
Signed-off-by: leehaut <[email protected]>
---
.../actions/createfolder/ActionCreateFolder.java | 44 +----
.../createfolder/ActionCreateFolderTest.java | 182 +++++++++++++++++++++
2 files changed, 188 insertions(+), 38 deletions(-)
diff --git
a/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
b/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
index 8d78d71b59..66febf230b 100644
---
a/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
+++
b/plugins/actions/createfolder/src/main/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolder.java
@@ -18,6 +18,8 @@
package org.apache.hop.workflow.actions.createfolder;
import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileType;
@@ -40,6 +42,8 @@ import
org.apache.hop.workflow.action.validator.ValidatorContext;
* This defines a 'create folder' action. Its main use would be to create
empty folder that can be
* used to control the flow in ETL cycles.
*/
+@Getter
+@Setter
@Action(
id = "CREATE_FOLDER",
name = "i18n::ActionCreateFolder.Name",
@@ -136,48 +140,12 @@ public class ActionCreateFolder extends ActionBase
implements Cloneable, IAction
AbstractFileValidator.putVariableSpace(ctx, getVariables());
AndValidator.putValidators(
ctx,
- ActionValidatorUtils.notNullValidator(),
+ ActionValidatorUtils.notBlankValidator(),
ActionValidatorUtils.fileDoesNotExistValidator());
- ActionValidatorUtils.andValidator().validate(this, "filename", remarks,
ctx);
+ ActionValidatorUtils.andValidator().validate(this, "folderName", remarks,
ctx);
}
public String getRealFolderName() {
return resolve(getFolderName());
}
-
- /**
- * Gets folderName
- *
- * @return value of folderName
- */
- public String getFolderName() {
- return folderName;
- }
-
- /**
- * Sets folderName
- *
- * @param folderName value of folderName
- */
- public void setFolderName(String folderName) {
- this.folderName = folderName;
- }
-
- /**
- * Gets failIfFolderExists
- *
- * @return value of failIfFolderExists
- */
- public boolean isFailIfFolderExists() {
- return failIfFolderExists;
- }
-
- /**
- * Sets failIfFolderExists
- *
- * @param failIfFolderExists value of failIfFolderExists
- */
- public void setFailIfFolderExists(boolean failIfFolderExists) {
- this.failIfFolderExists = failIfFolderExists;
- }
}
diff --git
a/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
b/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
index 0d124cf312..9813e4faac 100644
---
a/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
+++
b/plugins/actions/createfolder/src/test/java/org/apache/hop/workflow/actions/createfolder/ActionCreateFolderTest.java
@@ -19,13 +19,32 @@
package org.apache.hop.workflow.actions.createfolder;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.Result;
+import org.apache.hop.core.logging.HopLogStore;
import org.apache.hop.workflow.action.ActionSerializationTestUtil;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+/** Unit test for {@link ActionCreateFolder} */
class ActionCreateFolderTest {
+ @TempDir Path tempDir;
+
+ @BeforeAll
+ static void setUpBeforeClass() {
+ HopLogStore.init();
+ }
+
@Test
void testSerialization() throws Exception {
ActionCreateFolder action =
@@ -35,4 +54,167 @@ class ActionCreateFolderTest {
assertEquals("${TEST_FOLDER}/one", action.getFolderName());
assertTrue(action.isFailIfFolderExists());
}
+
+ @Test
+ void testClone() throws Exception {
+ ActionCreateFolder action =
+ ActionSerializationTestUtil.testSerialization(
+ "/create-folder-action.xml", ActionCreateFolder.class);
+
+ ActionCreateFolder clone = (ActionCreateFolder) action.clone();
+
+ assertEquals(action.getFolderName(), clone.getFolderName());
+ assertEquals(action.isFailIfFolderExists(), clone.isFailIfFolderExists());
+ }
+
+ @Test
+ void constructorLeavesFolderNameEmptyAndFailsIfItExists() {
+ ActionCreateFolder action = new ActionCreateFolder();
+
+ assertNull(action.getFolderName());
+ assertTrue(action.isFailIfFolderExists());
+ assertTrue(action.isEvaluation());
+ }
+
+ @Test
+ void getRealFolderNameResolvesVariables() {
+ ActionCreateFolder action = new ActionCreateFolder();
+ action.setVariable("TEST_FOLDER", tempDir.toString());
+ action.setFolderName("${TEST_FOLDER}/one");
+
+ assertEquals(tempDir.toString() + "/one", action.getRealFolderName());
+ }
+
+ @Test
+ void checkAcceptsAFolderName() {
+ ActionCreateFolder action = new ActionCreateFolder();
+ action.setFolderName(tempDir.resolve("missing").toString());
+
+ List<ICheckResult> remarks = check(action);
+
+ assertTrue(errors(remarks).isEmpty());
+ assertTrue(remarks.stream().anyMatch(remark ->
remark.getText().contains("folderName is OK")));
+ assertTrue(remarks.stream().noneMatch(remark ->
remark.getText().contains("Reason: filename")));
+ }
+
+ @Test
+ void checkReportsAMissingFolderName() {
+ ActionCreateFolder action = new ActionCreateFolder();
+
+ List<String> errors = errors(check(action));
+
+ assertEquals(1, errors.size());
+ assertTrue(errors.getFirst().contains("folderName cannot be null or
blank"));
+ assertFalse(errors.getFirst().contains("Reason: filename"));
+ }
+
+ @Test
+ void checkReportsAnEmptyFolderName() {
+ ActionCreateFolder action = new ActionCreateFolder();
+ action.setFolderName("");
+
+ List<String> errors = errors(check(action));
+
+ assertEquals(1, errors.size());
+ assertTrue(errors.getFirst().contains("folderName cannot be null or
blank"));
+ }
+
+ @Test
+ void checkReportsAWhitespaceFolderName() {
+ ActionCreateFolder action = new ActionCreateFolder();
+ action.setFolderName(" ");
+
+ List<String> errors = errors(check(action));
+
+ assertEquals(1, errors.size());
+ assertTrue(errors.getFirst().contains("folderName cannot be null or
blank"));
+ }
+
+ @Test
+ void executeFailsWhenNoFolderNameIsDefined() {
+ ActionCreateFolder action = new ActionCreateFolder();
+
+ Result result = action.execute(new Result(), 0);
+
+ assertFalse(result.isResult());
+ assertEquals(0, result.getNrErrors());
+ }
+
+ @Test
+ void executeCreatesAMissingFolder() {
+ ActionCreateFolder action = new ActionCreateFolder();
+ Path folder = tempDir.resolve("created");
+ action.setFolderName(folder.toString());
+
+ Result result = action.execute(new Result(), 0);
+
+ assertTrue(result.isResult());
+ assertEquals(0, result.getNrErrors());
+ assertTrue(Files.isDirectory(folder));
+ }
+
+ @Test
+ void executeFailsWhenTheFolderAlreadyExists() throws Exception {
+ ActionCreateFolder action = new ActionCreateFolder();
+ Path folder = Files.createDirectory(tempDir.resolve("exists"));
+ action.setFolderName(folder.toString());
+
+ Result result = action.execute(new Result(), 0);
+
+ assertFalse(result.isResult());
+ assertEquals(0, result.getNrErrors());
+ }
+
+ @Test
+ void executeSucceedsWhenAnExistingFolderIsAllowed() throws Exception {
+ ActionCreateFolder action = new ActionCreateFolder();
+ Path folder = Files.createDirectory(tempDir.resolve("exists"));
+ action.setFolderName(folder.toString());
+ action.setFailIfFolderExists(false);
+
+ Result result = action.execute(new Result(), 0);
+
+ assertTrue(result.isResult());
+ assertEquals(0, result.getNrErrors());
+ }
+
+ @Test
+ void executeFailsWhenAFileOccupiesTheFolderName() throws Exception {
+ ActionCreateFolder action = new ActionCreateFolder();
+ Path file = Files.createFile(tempDir.resolve("not-a-folder"));
+ action.setFolderName(file.toString());
+
+ Result result = action.execute(new Result(), 0);
+
+ assertFalse(result.isResult());
+ assertEquals(0, result.getNrErrors());
+ }
+
+ @Test
+ void executeReportsAnErrorWhenTheFolderCannotBeCreated() throws Exception {
+ ActionCreateFolder action = new ActionCreateFolder();
+ Path file = Files.createFile(tempDir.resolve("parent-is-a-file"));
+ action.setFolderName(file.resolve("child").toString());
+
+ Result result = action.execute(new Result(), 0);
+
+ assertFalse(result.isResult());
+ assertEquals(1, result.getNrErrors());
+ }
+
+ private static List<ICheckResult> check(ActionCreateFolder action) {
+ List<ICheckResult> remarks = new ArrayList<>();
+ action.check(remarks, null, action, null);
+ return remarks;
+ }
+
+ private static List<String> errors(List<ICheckResult> remarks) {
+ List<String> errors = new ArrayList<>();
+ for (ICheckResult remark : remarks) {
+ if (remark.getType() == ICheckResult.TYPE_RESULT_ERROR) {
+ errors.add(remark.getText());
+ }
+ }
+ return errors;
+ }
}