From 7057e430ce059963724928296ff166e68b4e2ebb Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 09 Apr 2013 09:58:22 +0000
Subject: [PATCH] Partial fix for OPENDJ-856: Make Rest2LDAP close the cached authenticated connection

---
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnectionWrapper.java      |   53 +++++++----------
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java |    3 
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java                    |   26 ++++++++
 opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionsTestCase.java            |   60 ++++++++++++++++++++
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactory.java     |    3 
 5 files changed, 109 insertions(+), 36 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/ConnectionDecorator.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnectionWrapper.java
similarity index 93%
rename from opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/ConnectionDecorator.java
rename to opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnectionWrapper.java
index e865863..5de8c93 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/ConnectionDecorator.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnectionWrapper.java
@@ -25,21 +25,10 @@
  *      Portions copyright 2011-2013 ForgeRock AS
  */
 
-package com.forgerock.opendj.util;
+package org.forgerock.opendj.ldap;
 
 import java.util.Collection;
 
-import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.Connection;
-import org.forgerock.opendj.ldap.ConnectionEventListener;
-import org.forgerock.opendj.ldap.DN;
-import org.forgerock.opendj.ldap.Entry;
-import org.forgerock.opendj.ldap.ErrorResultException;
-import org.forgerock.opendj.ldap.FutureResult;
-import org.forgerock.opendj.ldap.IntermediateResponseHandler;
-import org.forgerock.opendj.ldap.ResultHandler;
-import org.forgerock.opendj.ldap.SearchResultHandler;
-import org.forgerock.opendj.ldap.SearchScope;
 import org.forgerock.opendj.ldap.requests.AbandonRequest;
 import org.forgerock.opendj.ldap.requests.AddRequest;
 import org.forgerock.opendj.ldap.requests.BindRequest;
@@ -60,24 +49,26 @@
 import org.forgerock.opendj.ldif.ChangeRecord;
 import org.forgerock.opendj.ldif.ConnectionEntryReader;
 
+import com.forgerock.opendj.util.Validator;
+
 /**
- * A base class from which connection decorators may be easily implemented. The
- * default implementation of each method is to delegate to the decorated
- * connection.
+ * An abstract base class from which connection wrappers may be easily
+ * implemented. The default implementation of each method is to delegate to the
+ * wrapped connection.
  */
-public abstract class ConnectionDecorator implements Connection {
+public abstract class AbstractConnectionWrapper implements Connection {
     /**
-     * The decorated connection.
+     * The wrapped connection.
      */
     protected final Connection connection;
 
     /**
-     * Creates a new connection decorator.
+     * Creates a new connection wrapper.
      *
      * @param connection
-     *            The connection to be decorated.
+     *            The connection to be wrapped.
      */
-    protected ConnectionDecorator(final Connection connection) {
+    protected AbstractConnectionWrapper(final Connection connection) {
         Validator.ensureNotNull(connection);
         this.connection = connection;
     }
@@ -140,7 +131,17 @@
      * The default implementation is to delegate.
      */
     @Override
-    public Result applyChange(ChangeRecord request) throws ErrorResultException {
+    public void addConnectionEventListener(final ConnectionEventListener listener) {
+        connection.addConnectionEventListener(listener);
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * The default implementation is to delegate.
+     */
+    @Override
+    public Result applyChange(final ChangeRecord request) throws ErrorResultException {
         return connection.applyChange(request);
     }
 
@@ -162,16 +163,6 @@
      * The default implementation is to delegate.
      */
     @Override
-    public void addConnectionEventListener(final ConnectionEventListener listener) {
-        connection.addConnectionEventListener(listener);
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * The default implementation is to delegate.
-     */
-    @Override
     public BindResult bind(final BindRequest request) throws ErrorResultException {
         return connection.bind(request);
     }
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java
index e90c986..f4962ab 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java
@@ -30,7 +30,6 @@
 import org.forgerock.opendj.ldap.requests.BindRequest;
 import org.forgerock.opendj.ldap.responses.BindResult;
 
-import com.forgerock.opendj.util.ConnectionDecorator;
 import com.forgerock.opendj.util.FutureResultTransformer;
 import com.forgerock.opendj.util.RecursiveFutureResult;
 
@@ -52,7 +51,7 @@
      * An authenticated connection supports all operations except Bind
      * operations.
      */
-    public static final class AuthenticatedConnection extends ConnectionDecorator {
+    public static final class AuthenticatedConnection extends AbstractConnectionWrapper {
 
         private AuthenticatedConnection(final Connection connection) {
             super(connection);
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java
index 6d5a0e5..deea05a 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011-2012 ForgeRock AS
+ *      Portions copyright 2011-2013 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldap;
@@ -472,6 +472,30 @@
         return new RequestHandlerFactoryAdapter<C>(factory);
     }
 
+    /**
+     * Returns an uncloseable view of the provided connection. Attempts to call
+     * {@link Connection#close()} or
+     * {@link Connection#close(org.forgerock.opendj.ldap.requests.UnbindRequest, String)}
+     * will be ignored.
+     *
+     * @param connection
+     *            The connection whose {@code close} methods are to be disabled.
+     * @return An uncloseable view of the provided connection.
+     */
+    public static Connection uncloseable(Connection connection) {
+        return new AbstractConnectionWrapper(connection) {
+            @Override
+            public void close() {
+                // Do nothing.
+            }
+
+            public void close(org.forgerock.opendj.ldap.requests.UnbindRequest request,
+                    String reason) {
+                // Do nothing.
+            };
+        };
+    }
+
     // Prevent instantiation.
     private Connections() {
         // Do nothing.
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactory.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactory.java
index 10e018f..9f73c51 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactory.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactory.java
@@ -63,7 +63,6 @@
 import org.forgerock.opendj.ldif.ConnectionEntryReader;
 
 import com.forgerock.opendj.util.AsynchronousFutureResult;
-import com.forgerock.opendj.util.ConnectionDecorator;
 import com.forgerock.opendj.util.FutureResultTransformer;
 import com.forgerock.opendj.util.StaticUtils;
 import com.forgerock.opendj.util.Validator;
@@ -76,7 +75,7 @@
     /**
      * A connection that sends heart beats and supports all operations.
      */
-    private final class ConnectionImpl extends ConnectionDecorator implements
+    private final class ConnectionImpl extends AbstractConnectionWrapper implements
             ConnectionEventListener, SearchResultHandler {
 
         /**
diff --git a/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionsTestCase.java b/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionsTestCase.java
new file mode 100644
index 0000000..ff164c2
--- /dev/null
+++ b/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionsTestCase.java
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2013 ForgeRock AS
+ */
+package org.forgerock.opendj.ldap;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class ConnectionsTestCase extends SdkTestCase {
+
+    @Test
+    public void testUncloseableConnectionClose() throws Exception {
+        final Connection connection = mock(Connection.class);
+        final Connection uncloseable = Connections.uncloseable(connection);
+        uncloseable.close();
+        verifyZeroInteractions(connection);
+    }
+
+    @Test
+    public void testUncloseableConnectionNotClose() throws Exception {
+        final Connection connection = mock(Connection.class);
+        final Connection uncloseable = Connections.uncloseable(connection);
+        uncloseable.applyChange(null);
+        verify(connection).applyChange(null);
+    }
+
+    @Test
+    public void testUncloseableConnectionUnbind() throws Exception {
+        final Connection connection = mock(Connection.class);
+        final Connection uncloseable = Connections.uncloseable(connection);
+        uncloseable.close(null, null);
+        verifyZeroInteractions(connection);
+    }
+}

--
Gitblit v1.10.0