From 3f7ddbf313aaabbfba4650cb2036cb41e51a9bde Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 18 Apr 2013 11:37:28 +0000
Subject: [PATCH] Fix OPENDJ-838: Add ConnectionFactory.close() method to facilitate resource cleanup after application exit

---
 opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java |   93 +++++++++++-----------------------------------
 1 files changed, 22 insertions(+), 71 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java
index bb5c88a..dc20e65 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java
@@ -27,6 +27,7 @@
 
 package com.forgerock.opendj.ldap;
 
+import static com.forgerock.opendj.util.StaticUtils.DEBUG_LOG;
 import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
 
 import java.io.IOException;
@@ -81,7 +82,6 @@
 import org.glassfish.grizzly.ssl.SSLFilter;
 
 import com.forgerock.opendj.util.CompletedFutureResult;
-import com.forgerock.opendj.util.StaticUtils;
 import com.forgerock.opendj.util.Validator;
 
 /**
@@ -109,7 +109,7 @@
     private final org.glassfish.grizzly.Connection<?> connection;
     private final LDAPWriter ldapWriter = new LDAPWriter();
     private final AtomicInteger nextMsgID = new AtomicInteger(1);
-    private final LDAPOptions options;
+    private final LDAPConnectionFactoryImpl factory;
     private final ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>> pendingRequests =
             new ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>>();
     private final Object stateLock = new Object();
@@ -120,22 +120,12 @@
     private boolean isFailed = false;
     private List<ConnectionEventListener> listeners = null;
 
-    /**
-     * Creates a new LDAP connection.
-     *
-     * @param connection
-     *            The Grizzly connection.
-     * @param options
-     *            The LDAP client options.
-     */
-    LDAPConnection(final org.glassfish.grizzly.Connection<?> connection, final LDAPOptions options) {
+    LDAPConnection(final org.glassfish.grizzly.Connection<?> connection,
+            final LDAPConnectionFactoryImpl factory) {
         this.connection = connection;
-        this.options = options;
+        this.factory = factory;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<Void> abandonAsync(final AbandonRequest request) {
         final AbstractLDAPFutureResultImpl<?> pendingRequest;
@@ -148,9 +138,11 @@
                 pendingRequest = pendingRequests.remove(request.getRequestID());
             }
             if (pendingRequest == null) {
-                // There has never been a request with the specified message ID or
-                // the response has already been received and handled. We can ignore
-                // this abandon request.
+                /*
+                 * There has never been a request with the specified message ID
+                 * or the response has already been received and handled. We can
+                 * ignore this abandon request.
+                 */
 
                 // Message ID will be -1 since no request was sent.
                 return new CompletedFutureResult<Void>((Void) null);
@@ -173,9 +165,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<Result> addAsync(final AddRequest request,
             final IntermediateResponseHandler intermediateResponseHandler,
@@ -208,9 +197,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void addConnectionEventListener(final ConnectionEventListener listener) {
         Validator.ensureNotNull(listener);
@@ -236,9 +222,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<BindResult> bindAsync(final BindRequest request,
             final IntermediateResponseHandler intermediateResponseHandler,
@@ -308,9 +291,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void close(final UnbindRequest request, final String reason) {
         // FIXME: I18N need to internationalize this message.
@@ -321,9 +301,6 @@
                         "Connection closed by client" + (reason != null ? ": " + reason : "")));
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<CompareResult> compareAsync(final CompareRequest request,
             final IntermediateResponseHandler intermediateResponseHandler,
@@ -356,9 +333,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<Result> deleteAsync(final DeleteRequest request,
             final IntermediateResponseHandler intermediateResponseHandler,
@@ -391,9 +365,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public <R extends ExtendedResult> FutureResult<R> extendedRequestAsync(
             final ExtendedRequest<R> request,
@@ -447,9 +418,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean isClosed() {
         synchronized (stateLock) {
@@ -457,9 +425,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean isValid() {
         synchronized (stateLock) {
@@ -467,9 +432,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<Result> modifyAsync(final ModifyRequest request,
             final IntermediateResponseHandler intermediateResponseHandler,
@@ -502,9 +464,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<Result> modifyDNAsync(final ModifyDNRequest request,
             final IntermediateResponseHandler intermediateResponseHandler,
@@ -537,9 +496,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void removeConnectionEventListener(final ConnectionEventListener listener) {
         Validator.ensureNotNull(listener);
@@ -550,9 +506,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public FutureResult<Result> searchAsync(final SearchRequest request,
             final IntermediateResponseHandler intermediateResponseHandler,
@@ -585,9 +538,6 @@
         return future;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public String toString() {
         final StringBuilder builder = new StringBuilder();
@@ -600,7 +550,7 @@
     }
 
     long cancelExpiredRequests(final long currentTime) {
-        final long timeout = options.getTimeout(TimeUnit.MILLISECONDS);
+        final long timeout = factory.getLDAPOptions().getTimeout(TimeUnit.MILLISECONDS);
         long delay = timeout;
         if (timeout > 0) {
             for (final int requestID : pendingRequests.keySet()) {
@@ -608,10 +558,9 @@
                 if (future != null) {
                     final long diff = (future.getTimestamp() + timeout) - currentTime;
                     if (diff <= 0 && pendingRequests.remove(requestID) != null) {
-                        StaticUtils.DEBUG_LOG.fine("Cancelling expired future result: " + future);
+                        DEBUG_LOG.fine("Cancelling expired future result: " + future);
                         final Result result = Responses.newResult(ResultCode.CLIENT_SIDE_TIMEOUT);
                         future.adaptErrorResult(result);
-
                         abandonAsync(Requests.newAbandonRequest(future.getRequestID()));
                     } else {
                         delay = Math.min(delay, diff);
@@ -691,7 +640,7 @@
                 // Underlying channel prob blown up. Just ignore.
             }
         }
-        TimeoutChecker.INSTANCE.removeConnection(this);
+        factory.getTimeoutChecker().removeConnection(this);
         connection.closeSilently();
 
         // Notify listeners.
@@ -721,7 +670,7 @@
     }
 
     LDAPOptions getLDAPOptions() {
-        return options;
+        return factory.getLDAPOptions();
     }
 
     AbstractLDAPFutureResultImpl<?> getPendingRequest(final Integer messageID) {
@@ -837,12 +786,14 @@
     private void checkConnectionIsValid() throws ErrorResultException {
         if (!isValid0()) {
             if (failedDueToDisconnect) {
-                // Connection termination was triggered remotely. We don't want
-                // to blindly pass on the result code to requests since it could
-                // be confused for a genuine response. For example, if the
-                // disconnect contained the invalidCredentials result code then
-                // this could be misinterpreted as a genuine authentication
-                // failure for subsequent bind requests.
+                /*
+                 * Connection termination was triggered remotely. We don't want
+                 * to blindly pass on the result code to requests since it could
+                 * be confused for a genuine response. For example, if the
+                 * disconnect contained the invalidCredentials result code then
+                 * this could be misinterpreted as a genuine authentication
+                 * failure for subsequent bind requests.
+                 */
                 throw newErrorResult(ResultCode.CLIENT_SIDE_SERVER_DOWN,
                         "Connection closed by server");
             } else {

--
Gitblit v1.10.0