From 5487deb6febc8f8432d82fbecfdea369110d0bab Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <yannick.lecaillez@forgerock.com>
Date: Thu, 07 Jul 2016 08:59:57 +0000
Subject: [PATCH] OPENDJ-3204: Unable to stop Rest2Ldap Gateway container.

---
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java |   38 +++++++++++++++++++++++++++-----------
 1 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java
index 82d391f..6736db4 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapHttpApplication.java
@@ -38,18 +38,20 @@
 import static org.forgerock.util.Utils.closeSilently;
 import static org.forgerock.util.Utils.joinAsString;
 
+import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.TrustManager;
@@ -121,6 +123,9 @@
     /** Used for token caching. */
     private ScheduledExecutorService executorService;
 
+    /** Resources which have to be closed when this application is stopped. */
+    private final Collection<Closeable> closeableResources = new ArrayList<>();
+
     private TrustManager trustManager;
     private X509KeyManager keyManager;
 
@@ -193,7 +198,16 @@
         try {
             logger.info(INFO_REST2LDAP_STARTING.get(configDirectory));
 
-            executorService = Executors.newSingleThreadScheduledExecutor();
+            final ScheduledThreadPoolExecutor scheduledExecutor = new ScheduledThreadPoolExecutor(1);
+            scheduledExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+            scheduledExecutor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
+            closeOnStop(new Closeable() {
+                @Override
+                public void close() throws IOException {
+                    scheduledExecutor.shutdown();
+                }
+            });
+            executorService = scheduledExecutor;
 
             final JsonValue config = readJson(new File(configDirectory, "config.json"));
             configureSecurity(config.get("security"));
@@ -225,10 +239,16 @@
     private void configureConnectionFactories(final JsonValue config) {
         connectionFactories.clear();
         for (String name : config.keys()) {
-            connectionFactories.put(name, configureConnectionFactory(config, name, trustManager, keyManager));
+            connectionFactories
+                .put(name, closeOnStop(configureConnectionFactory(config, name, trustManager, keyManager)));
         }
     }
 
+    private <T extends Closeable> T closeOnStop(T resource) {
+        closeableResources.add(resource);
+        return resource;
+    }
+
     @Override
     public Factory<Buffer> getBufferFactory() {
         // Use container default buffer factory.
@@ -237,14 +257,10 @@
 
     @Override
     public void stop() {
-        for (ConnectionFactory factory : connectionFactories.values()) {
-            closeSilently(factory);
-        }
+        closeSilently(closeableResources);
+        closeableResources.clear();
         connectionFactories.clear();
-        if (executorService != null) {
-            executorService.shutdown();
-            executorService = null;
-        }
+        executorService = null;
     }
 
     private Filter buildAuthorizationFilter(final JsonValue config) throws HttpApplicationException {
@@ -342,7 +358,7 @@
             httpOptions.set(OPTION_KEY_MANAGERS,
                     new KeyManager[] { keyAlias != null ? useSingleCertificate(keyAlias, keyManager) : keyManager });
         }
-        return new HttpClientHandler(httpOptions);
+        return closeOnStop(new HttpClientHandler(httpOptions));
     }
 
     private Duration parseCacheExpiration(final JsonValue expirationJson) {

--
Gitblit v1.10.0