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

smolnar82 pushed a commit to branch knox_idf
in repository https://gitbox.apache.org/repos/asf/knox.git

commit 144c64f3e9de7e32d0d65e65a8050af8190af4f8
Author: hanicz <[email protected]>
AuthorDate: Mon Jun 1 12:35:41 2026 +0200

    KNOX-3332: Add listeners on gateway config changes (#1243)
    
    * KNOX-3332: New gatewayconfig change listener
    
    * KNOX-3332: Improve testOnGatewayConfigChanged test
    
    * KNOX-3332: Moved the listener into KnoxLDAPService
    
    * KNOX-3332: Simplify restart logic
---
 .../org/apache/knox/gateway/GatewayServer.java     | 15 ++++
 .../gateway/services/DefaultGatewayServices.java   |  2 +
 .../services/ldap/KnoxLDAPServerManager.java       | 37 ++++++---
 .../gateway/services/ldap/KnoxLDAPService.java     | 51 ++++++------
 .../knox/gateway/services/ldap/LdapMessages.java   |  8 ++
 .../org/apache/knox/gateway/GatewayServerTest.java | 32 ++++++++
 .../services/ldap/KnoxLDAPServerManagerTest.java   | 94 +++++++++++++++-------
 .../gateway/services/ldap/KnoxLDAPServiceTest.java | 27 ++++++-
 .../config/GatewayConfigChangeListener.java        | 22 +++++
 9 files changed, 216 insertions(+), 72 deletions(-)

diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
index cf1e8f998..a39e5e6c1 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayServer.java
@@ -28,6 +28,7 @@ import org.apache.knox.gateway.audit.api.Auditor;
 import org.apache.knox.gateway.audit.api.ResourceType;
 import org.apache.knox.gateway.audit.log4j.audit.AuditConstants;
 import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.config.GatewayConfigChangeListener;
 import org.apache.knox.gateway.config.GatewayConfigurationException;
 import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
 import org.apache.knox.gateway.deploy.DeploymentException;
@@ -127,6 +128,7 @@ import java.util.Properties;
 import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -148,6 +150,8 @@ public class GatewayServer {
   private static GatewayServer server;
   private static GatewayServices services;
 
+  private static final List<GatewayConfigChangeListener> configChangeListeners 
= new CopyOnWriteArrayList<>();
+
   private static Properties buildProperties;
 
   private static final ScheduledExecutorService exec = 
Executors.newSingleThreadScheduledExecutor();
@@ -239,6 +243,14 @@ public class GatewayServer {
     return services;
   }
 
+  public static void registerConfigChangeListener(GatewayConfigChangeListener 
listener) {
+    configChangeListeners.add(listener);
+  }
+
+  public static void 
unregisterConfigChangeListener(GatewayConfigChangeListener listener) {
+    configChangeListeners.remove(listener);
+  }
+
   private static void setupGatewayConfigRefresh(GatewayConfigImpl config) {
     Path resourcePath = Paths.get(config.getGatewayConfDir(), 
RELOADABLE_CONFIG_FILENAME);
     int refreshInterval = config.getConfigRefreshInterval();
@@ -261,6 +273,9 @@ public class GatewayServer {
           lastReloadTime = lastModifiedTime;
           config.reloadConfiguration();
           log.refreshedGatewayConfig();
+          for (GatewayConfigChangeListener listener : configChangeListeners) {
+            listener.onGatewayConfigChanged(config);
+          }
         }
       }
     } catch (IOException e) {
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
index cdbafc7bb..0e1c8419c 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/DefaultGatewayServices.java
@@ -21,6 +21,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.knox.gateway.GatewayMessages;
+import org.apache.knox.gateway.GatewayServer;
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.deploy.DeploymentContext;
 import org.apache.knox.gateway.descriptor.FilterParamDescriptor;
@@ -88,6 +89,7 @@ public class DefaultGatewayServices extends 
AbstractGatewayServices {
     if (config.isLDAPEnabled()) {
       KnoxLDAPService ldapService = new KnoxLDAPService();
       ldapService.init(config, options);
+      GatewayServer.registerConfigChangeListener(ldapService);
       addService(ServiceType.LDAP_SERVICE, ldapService);
     }
 
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
index 300e6f936..cd7bb1a80 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManager.java
@@ -30,6 +30,7 @@ import 
org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
 import org.apache.directory.server.core.partition.ldif.LdifPartition;
 import org.apache.directory.server.ldap.LdapServer;
 import org.apache.directory.server.protocol.shared.transport.TcpTransport;
+import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 import org.apache.knox.gateway.services.ldap.backend.BackendFactory;
 import org.apache.knox.gateway.services.ldap.backend.LdapBackend;
@@ -56,21 +57,33 @@ public class KnoxLDAPServerManager {
     /**
      * Initialize the LDAP server with the given configuration
      *
-     * @param workDir Directory for LDAP data storage
-     * @param port Port for LDAP server to listen on
-     * @param baseDn Base DN for LDAP entries in the proxy server
-     * @param backendType Type of backend to use
-     * @param backendConfig Backend-specific configuration
-     * @param remoteBaseDn Base DN of the remote LDAP server (for proxy 
backends)
+     * @param config Gateway configuration
      */
-    public void initialize(File workDir, int port, String baseDn, String 
backendType, Map<String, String> backendConfig, String remoteBaseDn) throws 
Exception {
-        this.workDir = workDir;
-        this.port = port;
-        this.baseDn = baseDn;
-        this.remoteBaseDn = remoteBaseDn;
+    public void initialize(GatewayConfig config) throws Exception {
+        // Prepare work directory for LDAP data
+        File gatewayDataDir = new File(config.getGatewayDataDir());
+        this.workDir = new File(gatewayDataDir, "ldap-server");
 
-        // Initialize backend
+        // Get configuration
+        this.port = config.getLDAPPort();
+        this.baseDn = config.getLDAPBaseDN();
+        String backendType = config.getLDAPBackendType();
+
+        // Get backend-specific configuration using prefixed properties
+        Map<String, String> backendConfig = 
config.getLDAPBackendConfig(backendType);
+
+        // Add common configuration
         backendConfig.put("baseDn", baseDn);
+
+        // Add legacy dataFile property for backwards compatibility with file 
backend
+        if ("file".equalsIgnoreCase(backendType) && 
!backendConfig.containsKey("dataFile")) {
+            backendConfig.put("dataFile", config.getLDAPBackendDataFile());
+        }
+
+        // For proxy backends, extract remoteBaseDn if present
+        this.remoteBaseDn = backendConfig.get("remoteBaseDn");
+
+        // Initialize backend
         backend = BackendFactory.createBackend(backendType, backendConfig);
 
         // Clean up previous run if it didn't shut down cleanly
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
index 1ec748da9..a6f66a67e 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/KnoxLDAPService.java
@@ -18,18 +18,18 @@
 package org.apache.knox.gateway.services.ldap;
 
 import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.config.GatewayConfigChangeListener;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 import org.apache.knox.gateway.services.Service;
 import org.apache.knox.gateway.services.ServiceLifecycleException;
 
-import java.io.File;
 import java.util.Map;
 
 /**
  * Knox LDAP Service - provides an embedded LDAP server with pluggable backends
  * for user and group lookups.
  */
-public class KnoxLDAPService implements Service {
+public class KnoxLDAPService implements Service, GatewayConfigChangeListener {
     private static final LdapMessages LOG = 
MessagesFactory.get(LdapMessages.class);
 
     private KnoxLDAPServerManager ldapServerManager;
@@ -46,32 +46,7 @@ public class KnoxLDAPService implements Service {
         try {
             // Initialize the LDAP server manager with configuration
             ldapServerManager = new KnoxLDAPServerManager();
-
-            // Prepare work directory for LDAP data
-            File gatewayDataDir = new File(config.getGatewayDataDir());
-            File ldapWorkDir = new File(gatewayDataDir, "ldap-server");
-
-            // Get configuration
-            int port = config.getLDAPPort();
-            String baseDn = config.getLDAPBaseDN();
-            String backendType = config.getLDAPBackendType();
-
-            // Get backend-specific configuration using prefixed properties
-            Map<String, String> backendConfig = 
config.getLDAPBackendConfig(backendType);
-
-            // Add common configuration
-            backendConfig.put("baseDn", baseDn);
-
-            // Add legacy dataFile property for backwards compatibility with 
file backend
-            if ("file".equalsIgnoreCase(backendType) && 
!backendConfig.containsKey("dataFile")) {
-                backendConfig.put("dataFile", config.getLDAPBackendDataFile());
-            }
-
-            // For proxy backends, extract remoteBaseDn if present
-            String remoteBaseDn = backendConfig.get("remoteBaseDn");
-
-            // Initialize but don't start yet
-            ldapServerManager.initialize(ldapWorkDir, port, baseDn, 
backendType, backendConfig, remoteBaseDn);
+            ldapServerManager.initialize(config);
 
         } catch (Exception e) {
             throw new ServiceLifecycleException("Failed to initialize LDAP 
service", e);
@@ -107,6 +82,26 @@ public class KnoxLDAPService implements Service {
         }
     }
 
+    @Override
+    public void onGatewayConfigChanged(GatewayConfig config) {
+        LOG.ldapReloadingConfig();
+        try {
+            this.enabled = config.isLDAPEnabled();
+
+            if (this.enabled) {
+                this.ldapServerManager = this.ldapServerManager == null ? new 
KnoxLDAPServerManager() : this.ldapServerManager;
+                ldapServerManager.stop();
+                ldapServerManager.initialize(config);
+                ldapServerManager.start();
+            } else if (ldapServerManager != null) {
+                ldapServerManager.stop();
+                ldapServerManager = null;
+            }
+        } catch (Exception e) {
+            LOG.ldapServiceReloadFailed(e);
+        }
+    }
+
     /**
      * Get the port the LDAP server is listening on
      */
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/LdapMessages.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/LdapMessages.java
index 4845cda79..cc92a099d 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/LdapMessages.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/ldap/LdapMessages.java
@@ -102,4 +102,12 @@ public interface LdapMessages {
 
     @Message(level = MessageLevel.WARN, text = "LDAP authentication failed for 
user: {0}")
     void ldapAuthFailed(String user, @StackTrace(level = MessageLevel.INFO) 
Throwable cause);
+
+    @Message(level = MessageLevel.INFO,
+            text = "Reloading LDAP configuration")
+    void ldapReloadingConfig();
+
+    @Message(level = MessageLevel.ERROR,
+            text = "Failed to reload LDAP service: {0}")
+    void ldapServiceReloadFailed(@StackTrace(level = MessageLevel.DEBUG) 
Exception e);
 }
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/GatewayServerTest.java 
b/gateway-server/src/test/java/org/apache/knox/gateway/GatewayServerTest.java
index 33d348190..a5938d7cd 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/GatewayServerTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/GatewayServerTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.knox.gateway;
 
+import org.apache.knox.gateway.config.GatewayConfigChangeListener;
 import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
 import org.easymock.EasyMock;
 import org.junit.Rule;
@@ -32,6 +33,7 @@ import java.nio.file.Path;
 import java.nio.file.attribute.FileTime;
 
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 public class GatewayServerTest {
 
@@ -95,4 +97,34 @@ public class GatewayServerTest {
     refreshMethod.invoke(null, config, configFile.toPath());
     EasyMock.verify(config);
   }
+
+  @Test
+  public void testGatewayConfigChangeListener() throws Exception {
+    GatewayConfigImpl config = 
EasyMock.createNiceMock(GatewayConfigImpl.class);
+    File configFile = folder.newFile("gateway-reloadable-listener.xml");
+    try (PrintWriter writer = new PrintWriter(configFile, 
StandardCharsets.UTF_8)) {
+      writer.println("<configuration></configuration>");
+    }
+
+    final boolean[] notified = {false};
+    GatewayConfigChangeListener listener = (c) -> notified[0] = true;
+
+    GatewayServer.registerConfigChangeListener(listener);
+
+    try {
+      Method refreshMethod = 
GatewayServer.class.getDeclaredMethod("refreshGatewayConfig", 
GatewayConfigImpl.class, Path.class);
+      refreshMethod.setAccessible(true);
+
+      // Reset lastReloadTime to ensure refresh happens
+      Field lastReloadTimeField = 
GatewayServer.class.getDeclaredField("lastReloadTime");
+      lastReloadTimeField.setAccessible(true);
+      lastReloadTimeField.set(null, null);
+
+      refreshMethod.invoke(null, config, configFile.toPath());
+
+      assertTrue("Listener should have been notified", notified[0]);
+    } finally {
+      GatewayServer.unregisterConfigChangeListener(listener);
+    }
+  }
 }
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
index a9450a96f..4528c8b4a 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServerManagerTest.java
@@ -17,6 +17,8 @@
  */
 package org.apache.knox.gateway.services.ldap;
 
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.easymock.EasyMock;
 import org.junit.Test;
 import org.junit.Before;
 import org.junit.After;
@@ -25,6 +27,8 @@ import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
@@ -71,9 +75,16 @@ public class KnoxLDAPServerManagerTest {
 
     @Test
     public void testInitializeWithFileBackend() throws Exception {
-        Map<String, String> backendConfig = createFileBackendConfig();
+        GatewayConfig mockConfig = 
EasyMock.createNiceMock(GatewayConfig.class);
+        
expect(mockConfig.getGatewayDataDir()).andReturn(tempWorkDir.getParent()).anyTimes();
+        expect(mockConfig.getLDAPPort()).andReturn(3890).anyTimes();
+        
expect(mockConfig.getLDAPBaseDN()).andReturn("dc=test,dc=com").anyTimes();
+        expect(mockConfig.getLDAPBackendType()).andReturn("file").anyTimes();
+        
expect(mockConfig.getLDAPBackendDataFile()).andReturn(tempLdapFile.getAbsolutePath()).anyTimes();
+        expect(mockConfig.getLDAPBackendConfig("file")).andReturn(new 
HashMap<>()).anyTimes();
+        replay(mockConfig);
 
-        serverManager.initialize(tempWorkDir, 3890, "dc=test,dc=com", "file", 
backendConfig, null);
+        serverManager.initialize(mockConfig);
 
         assertEquals("Port should be set correctly", 3890, 
serverManager.getPort());
         assertEquals("Base DN should be set correctly", "dc=test,dc=com", 
serverManager.getBaseDn());
@@ -82,9 +93,22 @@ public class KnoxLDAPServerManagerTest {
 
     @Test
     public void testInitializeWithLdapBackend() throws Exception {
-        Map<String, String> backendConfig = createLdapBackendConfig();
+        GatewayConfig mockConfig = 
EasyMock.createNiceMock(GatewayConfig.class);
+        
expect(mockConfig.getGatewayDataDir()).andReturn(tempWorkDir.getParent()).anyTimes();
+        expect(mockConfig.getLDAPPort()).andReturn(3891).anyTimes();
+        
expect(mockConfig.getLDAPBaseDN()).andReturn("dc=proxy,dc=com").anyTimes();
+        expect(mockConfig.getLDAPBackendType()).andReturn("ldap").anyTimes();
 
-        serverManager.initialize(tempWorkDir, 3891, "dc=proxy,dc=com", "ldap", 
backendConfig, "dc=hadoop,dc=apache,dc=org");
+        Map<String, String> backendConfig = new HashMap<>();
+        backendConfig.put("url", "ldap://localhost:33389";);
+        backendConfig.put("remoteBaseDn", "dc=hadoop,dc=apache,dc=org");
+        backendConfig.put("systemUsername", 
"cn=admin,dc=hadoop,dc=apache,dc=org");
+        backendConfig.put("systemPassword", "admin-password");
+
+        
expect(mockConfig.getLDAPBackendConfig("ldap")).andReturn(backendConfig).anyTimes();
+        replay(mockConfig);
+
+        serverManager.initialize(mockConfig);
 
         assertEquals("Port should be set correctly", 3891, 
serverManager.getPort());
         assertEquals("Base DN should be set correctly", "dc=proxy,dc=com", 
serverManager.getBaseDn());
@@ -93,23 +117,36 @@ public class KnoxLDAPServerManagerTest {
 
     @Test(expected = Exception.class)
     public void testInitializeWithInvalidBackendType() throws Exception {
-        Map<String, String> backendConfig = new HashMap<>();
-        backendConfig.put("baseDn", "dc=test,dc=com");
+        GatewayConfig mockConfig = 
EasyMock.createNiceMock(GatewayConfig.class);
+        
expect(mockConfig.getGatewayDataDir()).andReturn(tempWorkDir.getParent()).anyTimes();
+        
expect(mockConfig.getLDAPBackendType()).andReturn("invalid").anyTimes();
+        expect(mockConfig.getLDAPBackendConfig("invalid")).andReturn(new 
HashMap<>()).anyTimes();
+        replay(mockConfig);
 
-        serverManager.initialize(tempWorkDir, 3890, "dc=test,dc=com", 
"invalid", backendConfig, null);
+        serverManager.initialize(mockConfig);
     }
 
     @Test
     public void testLockFileCleanup() throws Exception {
+        GatewayConfig mockConfig = 
EasyMock.createNiceMock(GatewayConfig.class);
+        
expect(mockConfig.getGatewayDataDir()).andReturn(tempWorkDir.getParent()).anyTimes();
+        expect(mockConfig.getLDAPBackendType()).andReturn("file").anyTimes();
+        
expect(mockConfig.getLDAPBackendDataFile()).andReturn(tempLdapFile.getAbsolutePath()).anyTimes();
+        expect(mockConfig.getLDAPBackendConfig("file")).andReturn(new 
HashMap<>()).anyTimes();
+        replay(mockConfig);
+
+        // The manager will use tempWorkDir.getParent()/ldap-server as workDir
+        File actualWorkDir = new File(tempWorkDir.getParent(), "ldap-server");
+        actualWorkDir.mkdirs();
+
         // Create a lock file to simulate previous unclean shutdown
-        File runDir = new File(tempWorkDir, "run");
+        File runDir = new File(actualWorkDir, "run");
         runDir.mkdirs();
         File lockFile = new File(runDir, "instance.lock");
         lockFile.createNewFile();
         assertTrue("Lock file should exist before initialization", 
lockFile.exists());
 
-        Map<String, String> backendConfig = createFileBackendConfig();
-        serverManager.initialize(tempWorkDir, 3890, "dc=test,dc=com", "file", 
backendConfig, null);
+        serverManager.initialize(mockConfig);
 
         assertFalse("Lock file should be cleaned up during initialization", 
lockFile.exists());
     }
@@ -123,8 +160,14 @@ public class KnoxLDAPServerManagerTest {
 
     @Test
     public void testStopBeforeStart() throws Exception {
-        Map<String, String> backendConfig = createFileBackendConfig();
-        serverManager.initialize(tempWorkDir, 3890, "dc=test,dc=com", "file", 
backendConfig, null);
+        GatewayConfig mockConfig = 
EasyMock.createNiceMock(GatewayConfig.class);
+        
expect(mockConfig.getGatewayDataDir()).andReturn(tempWorkDir.getParent()).anyTimes();
+        expect(mockConfig.getLDAPBackendType()).andReturn("file").anyTimes();
+        
expect(mockConfig.getLDAPBackendDataFile()).andReturn(tempLdapFile.getAbsolutePath()).anyTimes();
+        expect(mockConfig.getLDAPBackendConfig("file")).andReturn(new 
HashMap<>()).anyTimes();
+        replay(mockConfig);
+
+        serverManager.initialize(mockConfig);
 
         // Should not throw exception when stopping before starting
         serverManager.stop();
@@ -132,8 +175,14 @@ public class KnoxLDAPServerManagerTest {
 
     @Test
     public void testMultipleStopCalls() throws Exception {
-        Map<String, String> backendConfig = createFileBackendConfig();
-        serverManager.initialize(tempWorkDir, 3890, "dc=test,dc=com", "file", 
backendConfig, null);
+        GatewayConfig mockConfig = 
EasyMock.createNiceMock(GatewayConfig.class);
+        
expect(mockConfig.getGatewayDataDir()).andReturn(tempWorkDir.getParent()).anyTimes();
+        expect(mockConfig.getLDAPBackendType()).andReturn("file").anyTimes();
+        
expect(mockConfig.getLDAPBackendDataFile()).andReturn(tempLdapFile.getAbsolutePath()).anyTimes();
+        expect(mockConfig.getLDAPBackendConfig("file")).andReturn(new 
HashMap<>()).anyTimes();
+        replay(mockConfig);
+
+        serverManager.initialize(mockConfig);
 
         // Multiple stop calls should not throw exceptions
         serverManager.stop();
@@ -147,23 +196,6 @@ public class KnoxLDAPServerManagerTest {
         serverManager.start();
     }
 
-    private Map<String, String> createFileBackendConfig() {
-        Map<String, String> config = new HashMap<>();
-        config.put("baseDn", "dc=test,dc=com");
-        config.put("dataFile", tempLdapFile.getAbsolutePath());
-        return config;
-    }
-
-    private Map<String, String> createLdapBackendConfig() {
-        Map<String, String> config = new HashMap<>();
-        config.put("baseDn", "dc=proxy,dc=com");
-        config.put("url", "ldap://localhost:33389";);
-        config.put("remoteBaseDn", "dc=hadoop,dc=apache,dc=org");
-        config.put("systemUsername", "cn=admin,dc=hadoop,dc=apache,dc=org");
-        config.put("systemPassword", "admin-password");
-        return config;
-    }
-
     private void cleanupTempFiles() {
         if (tempLdapFile != null && tempLdapFile.exists()) {
             tempLdapFile.delete();
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServiceTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServiceTest.java
index dbdb081da..fe045194b 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServiceTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/ldap/KnoxLDAPServiceTest.java
@@ -165,6 +165,31 @@ public class KnoxLDAPServiceTest {
         assertFalse("Should not be enabled when not initialized", 
ldapService.isEnabled());
     }
 
+    @Test
+    public void testOnGatewayConfigChanged() throws Exception {
+        expect(mockConfig.isLDAPEnabled()).andReturn(true).anyTimes();
+        
expect(mockConfig.getGatewayDataDir()).andReturn(tempDataDir.getAbsolutePath()).anyTimes();
+        
expect(mockConfig.getLDAPPort()).andReturn(3890).times(1).andReturn(3891).anyTimes();
+        
expect(mockConfig.getLDAPBaseDN()).andReturn("dc=test,dc=com").anyTimes();
+        expect(mockConfig.getLDAPBackendType()).andReturn("file").anyTimes();
+
+        Map<String, String> fileBackendConfig = new HashMap<>();
+        fileBackendConfig.put("dataFile", tempLdapFile.getAbsolutePath());
+        
expect(mockConfig.getLDAPBackendConfig("file")).andReturn(fileBackendConfig).anyTimes();
+
+        replay(mockConfig);
+
+        ldapService.init(mockConfig, new HashMap<>());
+        assertEquals("Initial port should be 3890", 3890, 
ldapService.getLdapPort());
+
+        // Test reload with new port
+        ldapService.onGatewayConfigChanged(mockConfig);
+
+        assertEquals("Port should be updated to 3891 after reload", 3891, 
ldapService.getLdapPort());
+
+        verify(mockConfig);
+    }
+
     private void setupMockConfigForFileBackend() {
         expect(mockConfig.isLDAPEnabled()).andReturn(true);
         
expect(mockConfig.getGatewayDataDir()).andReturn(tempDataDir.getAbsolutePath());
@@ -191,4 +216,4 @@ public class KnoxLDAPServiceTest {
         ldapBackendConfig.put("systemPassword", "admin-password");
         
expect(mockConfig.getLDAPBackendConfig("ldap")).andReturn(ldapBackendConfig);
     }
-}
\ No newline at end of file
+}
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfigChangeListener.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfigChangeListener.java
new file mode 100644
index 000000000..5dfd0fbf2
--- /dev/null
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfigChangeListener.java
@@ -0,0 +1,22 @@
+/*
+ * 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.knox.gateway.config;
+
+public interface GatewayConfigChangeListener {
+  void onGatewayConfigChanged(GatewayConfig config);
+}

Reply via email to