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

jshao pushed a commit to branch branch-1.0
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-1.0 by this push:
     new ee3f516ffe [#8379] fix(core): Handle duplicate PathContext keys by 
merging contexts with Sets (#8426)
ee3f516ffe is described below

commit ee3f516ffe8b61ec847f8c9535ef04055b90be74
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Sep 4 15:48:28 2025 +0800

    [#8379] fix(core): Handle duplicate PathContext keys by merging contexts 
with Sets (#8426)
    
    ### What changes were proposed in this pull request?
    
    This PR introduces a merge function to handle duplicate `PathContext`
    entries when building `CredentialContext` maps.
    
    ### Why are the changes needed?
    
    Without this fix, duplicate `PathContext` entries with the same
    `credentialType` would cause an `IllegalStateException`.
    
    Fix: #8379
    
    ### Does this PR introduce _any_ user-facing change?
    
    No user-facing changes.
    
    ### How was this patch tested?
    
      1. Added unit tests with duplicate `PathContext` entries.
      2. Executed existing unit tests
    
    Co-authored-by: keepConcentration <[email protected]>
    Co-authored-by: Jerry Shao <[email protected]>
---
 .../credential/CredentialOperationDispatcher.java  | 12 ++++-
 .../TestCredentialOperationDispatcher.java         | 61 ++++++++++++++++++++++
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/credential/CredentialOperationDispatcher.java
 
b/core/src/main/java/org/apache/gravitino/credential/CredentialOperationDispatcher.java
index 2ec76aeb4a..208791569f 100644
--- 
a/core/src/main/java/org/apache/gravitino/credential/CredentialOperationDispatcher.java
+++ 
b/core/src/main/java/org/apache/gravitino/credential/CredentialOperationDispatcher.java
@@ -112,7 +112,17 @@ public class CredentialOperationDispatcher extends 
OperationDispatcher {
                   }
                   return new PathBasedCredentialContext(
                       PrincipalUtils.getCurrentUserName(), writePaths, 
readPaths);
-                }));
+                },
+                CredentialOperationDispatcher::mergeContexts));
+  }
+
+  private static PathBasedCredentialContext mergeContexts(
+      CredentialContext oldValue, CredentialContext newValue) {
+    PathBasedCredentialContext oldContext = (PathBasedCredentialContext) 
oldValue;
+    PathBasedCredentialContext newContext = (PathBasedCredentialContext) 
newValue;
+    oldContext.getWritePaths().addAll(newContext.getWritePaths());
+    oldContext.getReadPaths().addAll(newContext.getReadPaths());
+    return oldContext;
   }
 
   @SuppressWarnings("UnusedVariable")
diff --git 
a/core/src/test/java/org/apache/gravitino/credential/TestCredentialOperationDispatcher.java
 
b/core/src/test/java/org/apache/gravitino/credential/TestCredentialOperationDispatcher.java
new file mode 100644
index 0000000000..6af65237e0
--- /dev/null
+++ 
b/core/src/test/java/org/apache/gravitino/credential/TestCredentialOperationDispatcher.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.credential;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.gravitino.catalog.TestOperationDispatcher;
+import org.apache.gravitino.connector.credential.PathContext;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestCredentialOperationDispatcher extends TestOperationDispatcher 
{
+
+  @Test
+  public void testMergePathContextsWithSameCredentialType() {
+    List<PathContext> pathContexts =
+        Arrays.asList(new PathContext("path1", "dummy"), new 
PathContext("path2", "dummy"));
+
+    Map<String, CredentialContext> contexts =
+        CredentialOperationDispatcher.getPathBasedCredentialContexts(
+            CredentialPrivilege.WRITE, pathContexts);
+
+    Assertions.assertEquals(1, contexts.size());
+    PathBasedCredentialContext context = (PathBasedCredentialContext) 
contexts.get("dummy");
+    Assertions.assertEquals(Set.of("path1", "path2"), context.getWritePaths());
+    Assertions.assertTrue(context.getReadPaths().isEmpty());
+  }
+
+  @Test
+  public void testMergePathContextsWithSameCredentialTypeAndSamePath() {
+    List<PathContext> pathContexts =
+        Arrays.asList(new PathContext("path1", "dummy"), new 
PathContext("path1", "dummy"));
+
+    Map<String, CredentialContext> contexts =
+        CredentialOperationDispatcher.getPathBasedCredentialContexts(
+            CredentialPrivilege.WRITE, pathContexts);
+
+    Assertions.assertEquals(1, contexts.size());
+    PathBasedCredentialContext context = (PathBasedCredentialContext) 
contexts.get("dummy");
+    Assertions.assertEquals(Set.of("path1"), context.getWritePaths());
+    Assertions.assertTrue(context.getReadPaths().isEmpty());
+  }
+}

Reply via email to