This is an automated email from the ASF dual-hosted git repository.

mchades pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 8867d8256b [#7190] fix(catalogs): Validate and filter empty 
storageLocations in HadoopCatalogOperations (#7238)
8867d8256b is described below

commit 8867d8256b84d75ca1d44dcd19930b723ad507d6
Author: Kyle Lin <[email protected]>
AuthorDate: Thu Jun 5 16:40:05 2025 +0800

    [#7190] fix(catalogs): Validate and filter empty storageLocations in 
HadoopCatalogOperations (#7238)
    
    ### What changes were proposed in this pull request?
    
    Add validation: throw error if StorageLocation is null or blank `Storage
    location for name '" + e.getKey() + "' must not be null or blank`
    
    ### Why are the changes needed?
    
    Fixes #7190
    
    ### Does this PR introduce any user-facing change?
    
    No. APIs and behavior are unchanged, only error messages for invalid
    input are clearer.
    
    ### How was this patch tested?
    
    - Added new unit tests.
    - Verified with `./gradlew clean build`.
---
 .../catalog/hadoop/HadoopCatalogOperations.java    | 32 +++++++++++-
 .../hadoop/TestHadoopCatalogOperations.java        | 58 +++++++++++++++++++---
 2 files changed, 83 insertions(+), 7 deletions(-)

diff --git 
a/catalogs/catalog-hadoop/src/main/java/org/apache/gravitino/catalog/hadoop/HadoopCatalogOperations.java
 
b/catalogs/catalog-hadoop/src/main/java/org/apache/gravitino/catalog/hadoop/HadoopCatalogOperations.java
index c6b98791c1..fab9b4b9f6 100644
--- 
a/catalogs/catalog-hadoop/src/main/java/org/apache/gravitino/catalog/hadoop/HadoopCatalogOperations.java
+++ 
b/catalogs/catalog-hadoop/src/main/java/org/apache/gravitino/catalog/hadoop/HadoopCatalogOperations.java
@@ -294,6 +294,10 @@ public class HadoopCatalogOperations extends 
ManagedSchemaOperations
           if (StringUtils.isBlank(name)) {
             throw new IllegalArgumentException("Location name must not be 
blank");
           }
+          if (StringUtils.isBlank(path)) {
+            throw new IllegalArgumentException(
+                "Storage location must not be blank for location name: " + 
name);
+          }
         });
 
     // Check if the fileset already existed in cache first. If it does, it 
means the fileset is
@@ -1018,7 +1022,19 @@ public class HadoopCatalogOperations extends 
ManagedSchemaOperations
                 }));
   }
 
+  private boolean existBlankValue(Map<String, String> properties, String key) {
+    return properties.containsKey(key) && 
StringUtils.isBlank(properties.get(key));
+  }
+
   private Map<String, Path> getAndCheckCatalogStorageLocations(Map<String, 
String> properties) {
+    if (existBlankValue(properties, HadoopCatalogPropertiesMetadata.LOCATION)) 
{
+      // If the properties contain the catalog property "location", it must 
not be blank.
+      throw new IllegalArgumentException(
+          "The value of the catalog property "
+              + HadoopCatalogPropertiesMetadata.LOCATION
+              + " must not be blank");
+    }
+
     ImmutableMap.Builder<String, Path> catalogStorageLocations = 
ImmutableMap.builder();
     String unnamedLocation =
         (String)
@@ -1033,11 +1049,17 @@ public class HadoopCatalogOperations extends 
ManagedSchemaOperations
 
     properties.forEach(
         (k, v) -> {
-          if (k.startsWith(PROPERTY_MULTIPLE_LOCATIONS_PREFIX) && 
StringUtils.isNotBlank(v)) {
+          if (k.startsWith(PROPERTY_MULTIPLE_LOCATIONS_PREFIX)) {
             String locationName = 
k.substring(PROPERTY_MULTIPLE_LOCATIONS_PREFIX.length());
             if (StringUtils.isBlank(locationName)) {
               throw new IllegalArgumentException("Location name must not be 
blank");
             }
+
+            if (StringUtils.isBlank(v)) {
+              throw new IllegalArgumentException(
+                  "Location value must not be blank for " + "location name: " 
+ locationName);
+            }
+
             checkPlaceholderValue(v);
             catalogStorageLocations.put(locationName, new 
Path((ensureTrailingSlash(v))));
           }
@@ -1047,6 +1069,14 @@ public class HadoopCatalogOperations extends 
ManagedSchemaOperations
 
   private Map<String, Path> getAndCheckSchemaPaths(
       String schemaName, Map<String, String> schemaProps) {
+    if (existBlankValue(schemaProps, HadoopSchemaPropertiesMetadata.LOCATION)) 
{
+      // If the properties contain the schema property "location", it must not 
be blank.
+      throw new IllegalArgumentException(
+          "The value of the schema property "
+              + HadoopSchemaPropertiesMetadata.LOCATION
+              + " must not be blank");
+    }
+
     Map<String, Path> schemaPaths = new HashMap<>();
     catalogStorageLocations.forEach(
         (name, path) -> {
diff --git 
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
 
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
index 41f7b2aee9..ff4924381e 100644
--- 
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
+++ 
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/TestHadoopCatalogOperations.java
@@ -50,6 +50,7 @@ import java.io.IOException;
 import java.net.ConnectException;
 import java.nio.file.Paths;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
@@ -383,15 +384,15 @@ public class TestHadoopCatalogOperations {
     String name = "schema28";
     String comment = "comment28";
     String catalogPath = "";
-    Schema schema = createSchema(name, comment, catalogPath, null);
-    Assertions.assertEquals(name, schema.name());
-    Assertions.assertEquals(comment, schema.comment());
 
     Throwable exception =
         Assertions.assertThrows(
-            SchemaAlreadyExistsException.class,
-            () -> createSchema(name, comment, catalogPath, null));
-    Assertions.assertEquals("Schema m1.c1.schema28 already exists", 
exception.getMessage());
+            IllegalArgumentException.class, () -> createSchema(name, comment, 
catalogPath, null));
+    Assertions.assertEquals(
+        "The value of the catalog property "
+            + HadoopCatalogPropertiesMetadata.LOCATION
+            + " must not be blank",
+        exception.getMessage());
   }
 
   @Test
@@ -1598,6 +1599,51 @@ public class TestHadoopCatalogOperations {
                       null));
       Assertions.assertEquals("Location name must not be blank", 
exception.getMessage());
 
+      // empty location in catalog location
+      Map<String, String> illegalLocations2 =
+          new HashMap<String, String>() {
+            {
+              put(PROPERTY_MULTIPLE_LOCATIONS_PREFIX + "v1", null);
+            }
+          };
+      exception =
+          Assertions.assertThrows(
+              IllegalArgumentException.class,
+              () ->
+                  ops.initialize(
+                      illegalLocations2,
+                      randomCatalogInfo("m1", "c1"),
+                      HADOOP_PROPERTIES_METADATA));
+      Assertions.assertEquals(
+          "Location value must not be blank for location name: v1", 
exception.getMessage());
+
+      // empty location in schema location
+      exception =
+          Assertions.assertThrows(
+              IllegalArgumentException.class,
+              () ->
+                  createMultiLocationSchema(
+                      "s1", "comment", ImmutableMap.of(), 
ImmutableMap.of("location", "")));
+      Assertions.assertEquals(
+          "The value of the schema property location must not be blank", 
exception.getMessage());
+
+      // empty fileset storage location
+      exception =
+          Assertions.assertThrows(
+              IllegalArgumentException.class,
+              () ->
+                  createMultiLocationFileset(
+                      "fileset_test",
+                      "s1",
+                      null,
+                      Fileset.Type.MANAGED,
+                      ImmutableMap.of(),
+                      ImmutableMap.of("location1", ""),
+                      null));
+      Assertions.assertEquals(
+          "Storage location must not be blank for location name: location1",
+          exception.getMessage());
+
       // storage location is parent of schema location
       Schema multipLocationSchema =
           createMultiLocationSchema(

Reply via email to