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

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


The following commit(s) were added to refs/heads/branch-1.3 by this push:
     new 7b64aefcff [Cherry-pick to branch-1.3] [#11412] feat(auth): Add 
initialize(Config) to PrincipalMapper and GroupMapper interfaces (#11411) 
(#11420)
7b64aefcff is described below

commit 7b64aefcfff9c02126db0953f448bfb1bfcedc13
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Jun 4 15:25:07 2026 +0800

    [Cherry-pick to branch-1.3] [#11412] feat(auth): Add initialize(Config) to 
PrincipalMapper and GroupMapper interfaces (#11411) (#11420)
    
    **Cherry-pick Information:**
    - Original commit: 95be458a81c7e5f58732d6d1d9841ebc7f7e9cc0
    - Target branch: `branch-1.3`
    - Status: ✅ Clean cherry-pick (no conflicts)
    
    Co-authored-by: Bharath Krishna <[email protected]>
---
 .../org/apache/gravitino/auth/GroupMapper.java     | 11 +++++++
 .../apache/gravitino/auth/GroupMapperFactory.java  | 37 ++++++++++++----------
 .../org/apache/gravitino/auth/PrincipalMapper.java | 11 +++++++
 .../gravitino/auth/PrincipalMapperFactory.java     | 36 ++++++++++++---------
 .../gravitino/auth/TestGroupMapperFactory.java     | 35 +++++++++++++++++---
 .../gravitino/auth/TestPrincipalMapperFactory.java | 33 ++++++++++++++++---
 .../server/authentication/JwksTokenValidator.java  |  4 +--
 .../authentication/KerberosAuthenticator.java      |  2 +-
 .../authentication/StaticSignKeyValidator.java     |  4 +--
 9 files changed, 128 insertions(+), 45 deletions(-)

diff --git a/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java 
b/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java
index 65acf7b7d2..2e744c4355 100644
--- a/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java
+++ b/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java
@@ -20,6 +20,7 @@
 package org.apache.gravitino.auth;
 
 import java.util.List;
+import org.apache.gravitino.Config;
 import org.apache.gravitino.UserGroup;
 
 /**
@@ -30,6 +31,16 @@ import org.apache.gravitino.UserGroup;
  */
 public interface GroupMapper {
 
+  /**
+   * Initializes the mapper with server configuration. Called by the factory 
after instantiation.
+   *
+   * <p>Custom implementations can override this to read additional 
configuration properties. The
+   * default implementation is a no-op for backward compatibility.
+   *
+   * @param config the server configuration
+   */
+  default void initialize(Config config) {}
+
   /**
    * Maps a list of group strings to a new list of group strings.
    *
diff --git 
a/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java 
b/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java
index d66cd46f91..61b12ea639 100644
--- a/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java
+++ b/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java
@@ -19,6 +19,7 @@
 
 package org.apache.gravitino.auth;
 
+import org.apache.gravitino.Config;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -34,30 +35,34 @@ public class GroupMapperFactory {
    *
    * @param mapperType the type of the mapper (e.g., "regex" or fully 
qualified class name)
    * @param regexPattern the regex pattern to use (only for "regex" mapper 
type)
+   * @param config the server configuration passed to {@link 
GroupMapper#initialize(Config)}
    * @return a configured GroupMapper instance
    * @throws IllegalArgumentException if the mapper type is invalid or 
initialization fails
    */
-  public static GroupMapper create(String mapperType, String regexPattern) {
+  public static GroupMapper create(String mapperType, String regexPattern, 
Config config) {
+    GroupMapper mapper;
     if ("regex".equalsIgnoreCase(mapperType)) {
       if (regexPattern == null) {
         throw new IllegalArgumentException("Regex pattern cannot be null for 
regex mapper");
       }
-      return new RegexGroupMapper(regexPattern);
-    }
-
-    try {
-      Class<?> clazz = Class.forName(mapperType);
-      if (!GroupMapper.class.isAssignableFrom(clazz)) {
-        throw new IllegalArgumentException(
-            "Class " + mapperType + " does not implement GroupMapper");
+      mapper = new RegexGroupMapper(regexPattern);
+    } else {
+      try {
+        Class<?> clazz = Class.forName(mapperType);
+        if (!GroupMapper.class.isAssignableFrom(clazz)) {
+          throw new IllegalArgumentException(
+              "Class " + mapperType + " does not implement GroupMapper");
+        }
+        mapper = (GroupMapper) clazz.getDeclaredConstructor().newInstance();
+      } catch (ClassNotFoundException e) {
+        LOG.error("Failed to load GroupMapper class: {}", mapperType, e);
+        throw new IllegalArgumentException("Failed to load GroupMapper class: 
" + mapperType, e);
+      } catch (Exception e) {
+        LOG.error("Failed to create GroupMapper: {}", mapperType, e);
+        throw new IllegalArgumentException("Failed to create GroupMapper: " + 
mapperType, e);
       }
-      return (GroupMapper) clazz.getDeclaredConstructor().newInstance();
-    } catch (ClassNotFoundException e) {
-      LOG.error("Failed to load GroupMapper class: {}", mapperType, e);
-      throw new IllegalArgumentException("Failed to load GroupMapper class: " 
+ mapperType, e);
-    } catch (Exception e) {
-      LOG.error("Failed to create GroupMapper: {}", mapperType, e);
-      throw new IllegalArgumentException("Failed to create GroupMapper: " + 
mapperType, e);
     }
+    mapper.initialize(config);
+    return mapper;
   }
 }
diff --git a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java 
b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java
index f4af0e6c3d..dedce4d0ad 100644
--- a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java
+++ b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java
@@ -20,6 +20,7 @@
 package org.apache.gravitino.auth;
 
 import java.security.Principal;
+import org.apache.gravitino.Config;
 
 /**
  * Interface for mapping authenticated principals to user identities.
@@ -29,6 +30,16 @@ import java.security.Principal;
  */
 public interface PrincipalMapper {
 
+  /**
+   * Initializes the mapper with server configuration. Called by the factory 
after instantiation.
+   *
+   * <p>Custom implementations can override this to read additional 
configuration properties. The
+   * default implementation is a no-op for backward compatibility.
+   *
+   * @param config the server configuration
+   */
+  default void initialize(Config config) {}
+
   /**
    * Maps a principal string to a Principal object.
    *
diff --git 
a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java 
b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java
index 01439fd020..613b48de51 100644
--- a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java
+++ b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java
@@ -19,6 +19,8 @@
 
 package org.apache.gravitino.auth;
 
+import org.apache.gravitino.Config;
+
 /** Factory class for creating {@link PrincipalMapper} instances. */
 public class PrincipalMapperFactory {
 
@@ -30,27 +32,31 @@ public class PrincipalMapperFactory {
    * @param mapperType "regex" for built-in regex mapper, or fully qualified 
class name for custom
    *     mapper
    * @param regexPattern the regex pattern (only used when mapperType is 
"regex")
+   * @param config the server configuration passed to {@link 
PrincipalMapper#initialize(Config)}
    * @return a configured PrincipalMapper instance
    * @throws IllegalArgumentException if the mapper cannot be created
    */
-  public static PrincipalMapper create(String mapperType, String regexPattern) 
{
+  public static PrincipalMapper create(String mapperType, String regexPattern, 
Config config) {
+    PrincipalMapper mapper;
     if ("regex".equalsIgnoreCase(mapperType)) {
-      return new RegexPrincipalMapper(regexPattern);
-    }
-
-    // Load custom mapper class
-    try {
-      Class<?> clazz = Class.forName(mapperType);
-      if (!PrincipalMapper.class.isAssignableFrom(clazz)) {
+      mapper = new RegexPrincipalMapper(regexPattern);
+    } else {
+      // Load custom mapper class
+      try {
+        Class<?> clazz = Class.forName(mapperType);
+        if (!PrincipalMapper.class.isAssignableFrom(clazz)) {
+          throw new IllegalArgumentException(
+              "Class " + mapperType + " does not implement PrincipalMapper");
+        }
+        mapper = (PrincipalMapper) 
clazz.getDeclaredConstructor().newInstance();
+      } catch (ClassNotFoundException e) {
+        throw new IllegalArgumentException("Unknown principal mapper type: " + 
mapperType, e);
+      } catch (Exception e) {
         throw new IllegalArgumentException(
-            "Class " + mapperType + " does not implement PrincipalMapper");
+            "Failed to instantiate principal mapper: " + mapperType, e);
       }
-      return (PrincipalMapper) clazz.getDeclaredConstructor().newInstance();
-    } catch (ClassNotFoundException e) {
-      throw new IllegalArgumentException("Unknown principal mapper type: " + 
mapperType, e);
-    } catch (Exception e) {
-      throw new IllegalArgumentException(
-          "Failed to instantiate principal mapper: " + mapperType, e);
     }
+    mapper.initialize(config);
+    return mapper;
   }
 }
diff --git 
a/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java 
b/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java
index 35dc34c8e5..6b7dbc6b29 100644
--- a/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java
+++ b/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java
@@ -29,14 +29,17 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
+import org.apache.gravitino.Config;
 import org.apache.gravitino.UserGroup;
 import org.junit.jupiter.api.Test;
 
 public class TestGroupMapperFactory {
 
+  private final Config config = new Config(false) {};
+
   @Test
   public void testCreateRegexMapper() {
-    GroupMapper mapper = GroupMapperFactory.create("regex", "group-(.*)");
+    GroupMapper mapper = GroupMapperFactory.create("regex", "group-(.*)", 
config);
 
     assertNotNull(mapper);
     assertTrue(mapper instanceof RegexGroupMapper);
@@ -53,7 +56,7 @@ public class TestGroupMapperFactory {
 
   @Test
   public void testCreateRegexMapperWithDefaultPattern() {
-    GroupMapper mapper = GroupMapperFactory.create("regex", "^(.*)$");
+    GroupMapper mapper = GroupMapperFactory.create("regex", "^(.*)$", config);
 
     assertNotNull(mapper);
     assertTrue(mapper instanceof RegexGroupMapper);
@@ -70,7 +73,7 @@ public class TestGroupMapperFactory {
 
   @Test
   public void testCreateRegexMapperWithSlash() {
-    GroupMapper mapper = GroupMapperFactory.create("regex", "/(.*)");
+    GroupMapper mapper = GroupMapperFactory.create("regex", "/(.*)", config);
 
     assertNotNull(mapper);
     assertTrue(mapper instanceof RegexGroupMapper);
@@ -91,12 +94,21 @@ public class TestGroupMapperFactory {
         assertThrows(
             IllegalArgumentException.class,
             () -> {
-              GroupMapperFactory.create("unknown.InvalidClass", null);
+              GroupMapperFactory.create("unknown.InvalidClass", null, config);
             });
     assertTrue(exception.getMessage().contains("Failed to load GroupMapper 
class"));
   }
 
   public static class TestCustomGroupMapper implements GroupMapper {
+    private boolean initialized = false;
+    private Config receivedConfig;
+
+    @Override
+    public void initialize(Config config) {
+      this.initialized = true;
+      this.receivedConfig = config;
+    }
+
     @Override
     public List<UserGroup> map(List<Object> groups) {
       if (groups == null) {
@@ -106,12 +118,16 @@ public class TestGroupMapperFactory {
           .map(g -> new UserGroup(Optional.empty(), "custom:" + g.toString()))
           .collect(Collectors.toList());
     }
+
+    public boolean isInitialized() {
+      return initialized;
+    }
   }
 
   @Test
   public void testCreateCustomMapperWithInlineClass() {
     String className = TestCustomGroupMapper.class.getName();
-    GroupMapper mapper = GroupMapperFactory.create(className, null);
+    GroupMapper mapper = GroupMapperFactory.create(className, null, config);
 
     assertNotNull(mapper);
     assertTrue(mapper instanceof TestCustomGroupMapper);
@@ -122,4 +138,13 @@ public class TestGroupMapperFactory {
     assertEquals(1, mappedGroups.size());
     assertEquals("custom:foo", mappedGroups.get(0).getGroupname());
   }
+
+  @Test
+  public void testCustomMapperInitializeCalledWithConfig() {
+    String className = TestCustomGroupMapper.class.getName();
+    GroupMapper mapper = GroupMapperFactory.create(className, null, config);
+    TestCustomGroupMapper custom = (TestCustomGroupMapper) mapper;
+    assertTrue(custom.isInitialized());
+    assertEquals(config, custom.receivedConfig);
+  }
 }
diff --git 
a/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java 
b/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java
index 117e6167a8..9b0a024cfe 100644
--- 
a/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java
+++ 
b/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java
@@ -25,14 +25,17 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.security.Principal;
+import org.apache.gravitino.Config;
 import org.apache.gravitino.UserPrincipal;
 import org.junit.jupiter.api.Test;
 
 public class TestPrincipalMapperFactory {
 
+  private final Config config = new Config(false) {};
+
   @Test
   public void testCreateRegexMapper() {
-    PrincipalMapper mapper = PrincipalMapperFactory.create("regex", 
"([^@]+)@.*");
+    PrincipalMapper mapper = PrincipalMapperFactory.create("regex", 
"([^@]+)@.*", config);
 
     assertNotNull(mapper);
     assertTrue(mapper instanceof RegexPrincipalMapper);
@@ -43,7 +46,7 @@ public class TestPrincipalMapperFactory {
 
   @Test
   public void testCreateRegexMapperWithDefaultPattern() {
-    PrincipalMapper mapper = PrincipalMapperFactory.create("regex", "^(.*)$");
+    PrincipalMapper mapper = PrincipalMapperFactory.create("regex", "^(.*)$", 
config);
 
     assertNotNull(mapper);
     assertTrue(mapper instanceof RegexPrincipalMapper);
@@ -59,25 +62,47 @@ public class TestPrincipalMapperFactory {
         assertThrows(
             IllegalArgumentException.class,
             () -> {
-              PrincipalMapperFactory.create("unknown.InvalidClass", null);
+              PrincipalMapperFactory.create("unknown.InvalidClass", null, 
config);
             });
     assertTrue(exception.getMessage().contains("Unknown principal mapper 
type"));
   }
 
   public static class TestCustomMapper implements PrincipalMapper {
+    private boolean initialized = false;
+    private Config receivedConfig;
+
+    @Override
+    public void initialize(Config config) {
+      this.initialized = true;
+      this.receivedConfig = config;
+    }
+
     @Override
     public Principal map(String principal) {
       return new UserPrincipal("custom:" + principal);
     }
+
+    public boolean isInitialized() {
+      return initialized;
+    }
   }
 
   @Test
   public void testCreateCustomMapperWithInlineClass() {
     String className = TestCustomMapper.class.getName();
-    PrincipalMapper mapper = PrincipalMapperFactory.create(className, null);
+    PrincipalMapper mapper = PrincipalMapperFactory.create(className, null, 
config);
     assertNotNull(mapper);
     assertTrue(mapper instanceof TestCustomMapper);
     Principal principal = mapper.map("foo");
     assertEquals("custom:foo", principal.getName());
   }
+
+  @Test
+  public void testCustomMapperInitializeCalledWithConfig() {
+    String className = TestCustomMapper.class.getName();
+    PrincipalMapper mapper = PrincipalMapperFactory.create(className, null, 
config);
+    TestCustomMapper custom = (TestCustomMapper) mapper;
+    assertTrue(custom.isInitialized());
+    assertEquals(config, custom.receivedConfig);
+  }
 }
diff --git 
a/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
 
b/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
index cdbf294357..32e47b84e1 100644
--- 
a/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
+++ 
b/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
@@ -78,12 +78,12 @@ public class JwksTokenValidator implements 
OAuthTokenValidator {
     // Create principal mapper based on configuration
     String mapperType = config.get(OAuthConfig.PRINCIPAL_MAPPER);
     String regexPattern = 
config.get(OAuthConfig.PRINCIPAL_MAPPER_REGEX_PATTERN);
-    this.principalMapper = PrincipalMapperFactory.create(mapperType, 
regexPattern);
+    this.principalMapper = PrincipalMapperFactory.create(mapperType, 
regexPattern, config);
 
     // Create group mapper based on configuration
     String groupMapperType = config.get(OAuthConfig.GROUP_MAPPER);
     String groupRegexPattern = 
config.get(OAuthConfig.GROUP_MAPPER_REGEX_PATTERN);
-    this.groupMapper = GroupMapperFactory.create(groupMapperType, 
groupRegexPattern);
+    this.groupMapper = GroupMapperFactory.create(groupMapperType, 
groupRegexPattern, config);
 
     LOG.info("Initializing JWKS token validator");
 
diff --git 
a/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
 
b/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
index 801133834f..5f10b1bd56 100644
--- 
a/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
+++ 
b/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
@@ -81,7 +81,7 @@ public class KerberosAuthenticator implements Authenticator {
       // "HTTP/host" from "HTTP/host@REALM")
       String mapperType = config.get(KerberosConfig.PRINCIPAL_MAPPER);
       String regexPattern = 
config.get(KerberosConfig.PRINCIPAL_MAPPER_REGEX_PATTERN);
-      this.principalMapper = PrincipalMapperFactory.create(mapperType, 
regexPattern);
+      this.principalMapper = PrincipalMapperFactory.create(mapperType, 
regexPattern, config);
 
       gssManager =
           Subject.doAs(
diff --git 
a/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
 
b/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
index efc857041e..611712e84d 100644
--- 
a/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
+++ 
b/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
@@ -85,12 +85,12 @@ public class StaticSignKeyValidator implements 
OAuthTokenValidator {
     // Create principal mapper based on configuration
     String mapperType = config.get(OAuthConfig.PRINCIPAL_MAPPER);
     String regexPattern = 
config.get(OAuthConfig.PRINCIPAL_MAPPER_REGEX_PATTERN);
-    this.principalMapper = PrincipalMapperFactory.create(mapperType, 
regexPattern);
+    this.principalMapper = PrincipalMapperFactory.create(mapperType, 
regexPattern, config);
 
     // Create group mapper based on configuration
     String groupMapperType = config.get(OAuthConfig.GROUP_MAPPER);
     String groupRegexPattern = 
config.get(OAuthConfig.GROUP_MAPPER_REGEX_PATTERN);
-    this.groupMapper = GroupMapperFactory.create(groupMapperType, 
groupRegexPattern);
+    this.groupMapper = GroupMapperFactory.create(groupMapperType, 
groupRegexPattern, config);
   }
 
   @Override

Reply via email to