From 9c6c2971b8b154a8fd1b330df786946c5de84e71 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Wed, 01 Feb 2012 11:43:19 +0000
Subject: [PATCH] Fix OPENDJ-417: Minor improvements to server-side SSL support

---
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPListenerImpl.java              |   17 -
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPListenerOptions.java           |   63 ----
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPServerFilter.java              |   49 ++-
 /dev/null                                                                                                     |   50 ----
 opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java                    |    6 
 opendj-sdk/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java           |  132 +++++++-----
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionSecurityLayer.java       |    3 
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPClientContext.java             |   20 +
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ConnectionSecurityLayerFilter.java |  180 ++++++++++++++++
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPClientFilter.java              |    3 
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java                   |  114 +++++----
 11 files changed, 377 insertions(+), 260 deletions(-)

diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java b/opendj-sdk/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java
index f87cd59..bc7ba0e 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java
@@ -40,6 +40,8 @@
 import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import javax.net.ssl.SSLContext;
+
 import org.forgerock.opendj.ldap.*;
 import org.forgerock.opendj.ldap.requests.*;
 import org.forgerock.opendj.ldap.responses.*;
@@ -68,13 +70,11 @@
       RequestHandler<RequestContext>
   {
     private final ConcurrentSkipListMap<DN, Entry> entries;
-    private final ReentrantReadWriteLock entryLock =
-        new ReentrantReadWriteLock();
+    private final ReentrantReadWriteLock entryLock = new ReentrantReadWriteLock();
 
 
 
-    private MemoryBackend(
-        final ConcurrentSkipListMap<DN, Entry> entries)
+    private MemoryBackend(final ConcurrentSkipListMap<DN, Entry> entries)
     {
       this.entries = entries;
     }
@@ -97,24 +97,22 @@
         DN dn = request.getName();
         if (entries.containsKey(dn))
         {
-          resultHandler.handleErrorResult(ErrorResultException
-              .newErrorResult(ResultCode.ENTRY_ALREADY_EXISTS,
-                  "The entry " + dn.toString() + " already exists"));
+          resultHandler.handleErrorResult(ErrorResultException.newErrorResult(
+              ResultCode.ENTRY_ALREADY_EXISTS, "The entry " + dn.toString()
+                  + " already exists"));
         }
 
         DN parent = dn.parent();
         if (!entries.containsKey(parent))
         {
-          resultHandler.handleErrorResult(ErrorResultException
-              .newErrorResult(ResultCode.NO_SUCH_OBJECT,
-                  "The parent entry " + parent.toString()
-                      + " does not exist"));
+          resultHandler.handleErrorResult(ErrorResultException.newErrorResult(
+              ResultCode.NO_SUCH_OBJECT,
+              "The parent entry " + parent.toString() + " does not exist"));
         }
         else
         {
           entries.put(dn, request);
-          resultHandler.handleResult(Responses
-              .newResult(ResultCode.SUCCESS));
+          resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
         }
       }
       finally
@@ -145,8 +143,7 @@
       else
       {
         // TODO: always succeed.
-        resultHandler.handleResult(Responses
-            .newBindResult(ResultCode.SUCCESS));
+        resultHandler.handleResult(Responses.newBindResult(ResultCode.SUCCESS));
       }
     }
 
@@ -183,15 +180,14 @@
         DN dn = request.getName();
         if (!entries.containsKey(dn))
         {
-          resultHandler.handleErrorResult(ErrorResultException
-              .newErrorResult(ResultCode.NO_SUCH_OBJECT, "The entry "
-                  + dn.toString() + " does not exist"));
+          resultHandler.handleErrorResult(ErrorResultException.newErrorResult(
+              ResultCode.NO_SUCH_OBJECT, "The entry " + dn.toString()
+                  + " does not exist"));
         }
         else
         {
           entries.remove(dn);
-          resultHandler.handleResult(Responses
-              .newResult(ResultCode.SUCCESS));
+          resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
         }
       }
       finally
@@ -207,14 +203,12 @@
      */
     @Override
     public <R extends ExtendedResult> void handleExtendedRequest(
-        final RequestContext requestContext,
-        final ExtendedRequest<R> request,
+        final RequestContext requestContext, final ExtendedRequest<R> request,
         final IntermediateResponseHandler intermediateResponseHandler,
         final ResultHandler<? super R> resultHandler)
     {
       // TODO: not implemented.
-      resultHandler.handleErrorResult(newErrorResult(
-          ResultCode.PROTOCOL_ERROR,
+      resultHandler.handleErrorResult(newErrorResult(ResultCode.PROTOCOL_ERROR,
           "Extended request operation not supported"));
     }
 
@@ -239,9 +233,9 @@
         Entry entry = entries.get(dn);
         if (entry == null)
         {
-          resultHandler.handleErrorResult(ErrorResultException
-              .newErrorResult(ResultCode.NO_SUCH_OBJECT, "The entry "
-                  + dn.toString() + " does not exist"));
+          resultHandler.handleErrorResult(ErrorResultException.newErrorResult(
+              ResultCode.NO_SUCH_OBJECT, "The entry " + dn.toString()
+                  + " does not exist"));
         }
 
         Entry newEntry = new LinkedHashMapEntry(entry);
@@ -264,17 +258,15 @@
           }
           else
           {
-            resultHandler
-                .handleErrorResult(newErrorResult(
-                  ResultCode.PROTOCOL_ERROR,
-                  "Modify request contains an unsupported modification type"));
+            resultHandler.handleErrorResult(newErrorResult(
+                ResultCode.PROTOCOL_ERROR,
+                "Modify request contains an unsupported modification type"));
             return;
           }
         }
 
         entries.put(dn, newEntry);
-        resultHandler.handleResult(Responses
-            .newResult(ResultCode.SUCCESS));
+        resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
       }
       finally
       {
@@ -294,8 +286,7 @@
         final ResultHandler<? super Result> resultHandler)
     {
       // TODO: not implemented.
-      resultHandler.handleErrorResult(newErrorResult(
-          ResultCode.PROTOCOL_ERROR,
+      resultHandler.handleErrorResult(newErrorResult(ResultCode.PROTOCOL_ERROR,
           "ModifyDN request operation not supported"));
     }
 
@@ -318,9 +309,9 @@
         Entry baseEntry = entries.get(dn);
         if (baseEntry == null)
         {
-          resultHandler.handleErrorResult(ErrorResultException
-              .newErrorResult(ResultCode.NO_SUCH_OBJECT, "The entry "
-                  + dn.toString() + " does not exist"));
+          resultHandler.handleErrorResult(ErrorResultException.newErrorResult(
+              ResultCode.NO_SUCH_OBJECT, "The entry " + dn.toString()
+                  + " does not exist"));
           return;
         }
 
@@ -337,8 +328,7 @@
         }
         else if (scope.equals(SearchScope.SINGLE_LEVEL))
         {
-          NavigableMap<DN, Entry> subtree = entries
-              .tailMap(dn, false);
+          NavigableMap<DN, Entry> subtree = entries.tailMap(dn, false);
           for (Entry entry : subtree.values())
           {
             // Check for cancellation.
@@ -402,8 +392,7 @@
           return;
         }
 
-        resultHandler.handleResult(Responses
-            .newResult(ResultCode.SUCCESS));
+        resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
       }
       catch (CancelledResultException e)
       {
@@ -421,8 +410,7 @@
         SearchResultHandler resultHandler, Entry entry)
     {
       // TODO: check filter, strip attributes.
-      return resultHandler.handleEntry(Responses
-          .newSearchResultEntry(entry));
+      return resultHandler.handleEntry(Responses.newSearchResultEntry(entry));
     }
   }
 
@@ -436,9 +424,10 @@
    */
   public static void main(final String[] args)
   {
-    if (args.length != 3)
+    if (args.length != 3 && args.length != 6)
     {
-      System.err.println("Usage: listenAddress listenPort ldifFile");
+      System.err.println("Usage: listenAddress listenPort ldifFile "
+          + "[keyStoreFile keyStorePassword certNickname]");
       System.exit(1);
     }
 
@@ -446,6 +435,9 @@
     final String localAddress = args[0];
     final int localPort = Integer.parseInt(args[1]);
     final String ldifFileName = args[2];
+    final String keyStoreFileName = (args.length == 6) ? args[3] : null;
+    final String keyStorePassword = (args.length == 6) ? args[4] : null;
+    final String certNickname = (args.length == 6) ? args[5] : null;
 
     // Create the memory backend.
     final ConcurrentSkipListMap<DN, Entry> entries =
@@ -453,24 +445,54 @@
     final MemoryBackend backend = new MemoryBackend(entries);
 
     // Create a server connection adapter.
-    final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler
-      = Connections.newServerConnectionFactory(backend);
+    final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler =
+        Connections.newServerConnectionFactory(backend);
 
     // Create listener.
-    final LDAPListenerOptions options = new LDAPListenerOptions()
-        .setBacklog(4096);
     LDAPListener listener = null;
     try
     {
-      listener = new LDAPListener(localAddress, localPort,
-          connectionHandler, options);
+      final LDAPListenerOptions options = new LDAPListenerOptions()
+          .setBacklog(4096);
+
+      if (keyStoreFileName != null)
+      {
+        // Configure SSL/TLS and enable it when connections are accepted.
+        final SSLContext sslContext = new SSLContextBuilder()
+            .setKeyManager(
+                KeyManagers.useSingleCertificate(certNickname, KeyManagers
+                    .useKeyStoreFile(keyStoreFileName,
+                        keyStorePassword.toCharArray(), null)))
+            .setTrustManager(TrustManagers.trustAll()).getSSLContext();
+
+        ServerConnectionFactory<LDAPClientContext, Integer> sslWrapper =
+            new ServerConnectionFactory<LDAPClientContext, Integer>()
+        {
+
+          public ServerConnection<Integer> handleAccept(
+              LDAPClientContext clientContext) throws ErrorResultException
+          {
+            clientContext.enableTLS(sslContext, null, null, false, false);
+            return connectionHandler.handleAccept(clientContext);
+          }
+        };
+
+        listener = new LDAPListener(localAddress, localPort, sslWrapper,
+            options);
+      }
+      else
+      {
+        // No SSL.
+        listener = new LDAPListener(localAddress, localPort, connectionHandler,
+            options);
+      }
       System.out.println("Press any key to stop the server...");
       System.in.read();
     }
-    catch (final IOException e)
+    catch (final Exception e)
     {
-      System.out.println("Error listening on " + localAddress + ":"
-          + localPort);
+      System.out
+          .println("Error listening on " + localAddress + ":" + localPort);
       e.printStackTrace();
     }
     finally
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ConnectionSecurityLayerFilter.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ConnectionSecurityLayerFilter.java
new file mode 100644
index 0000000..f62b7cc
--- /dev/null
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ConnectionSecurityLayerFilter.java
@@ -0,0 +1,180 @@
+/*
+ * 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
+ * trunk/opendj3/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
+ * trunk/opendj3/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 2009-2010 Sun Microsystems, Inc.
+ *      Portions copyright 2012 ForgeRock AS.
+ */
+
+package com.forgerock.opendj.ldap;
+
+
+
+import org.forgerock.opendj.ldap.ConnectionSecurityLayer;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.glassfish.grizzly.AbstractTransformer;
+import org.glassfish.grizzly.Buffer;
+import org.glassfish.grizzly.TransformationResult;
+import org.glassfish.grizzly.attributes.AttributeStorage;
+import org.glassfish.grizzly.filterchain.AbstractCodecFilter;
+import org.glassfish.grizzly.memory.Buffers;
+import org.glassfish.grizzly.memory.MemoryManager;
+
+
+
+/**
+ * Connection security layer filter adapter.
+ */
+final class ConnectionSecurityLayerFilter extends
+    AbstractCodecFilter<Buffer, Buffer>
+{
+  /**
+   * <tt>Transformer</tt>, which decodes SASL encrypted data, contained in the
+   * input Buffer, to the output Buffer.
+   */
+  private static final class Decoder extends
+      AbstractTransformer<Buffer, Buffer>
+  {
+    private static final int BUFFER_SIZE = 4096;
+    private final byte[] buffer = new byte[BUFFER_SIZE];
+    private final ConnectionSecurityLayer layer;
+    private final MemoryManager<?> memoryManager;
+
+
+
+    public Decoder(final ConnectionSecurityLayer layer,
+        final MemoryManager<?> memoryManager)
+    {
+      this.layer = layer;
+      this.memoryManager = memoryManager;
+    }
+
+
+
+    public String getName()
+    {
+      return this.getClass().getName();
+    }
+
+
+
+    public boolean hasInputRemaining(final AttributeStorage storage,
+        final Buffer input)
+    {
+      return input != null && input.hasRemaining();
+    }
+
+
+
+    @Override
+    public TransformationResult<Buffer, Buffer> transformImpl(
+        final AttributeStorage storage, final Buffer input)
+    {
+
+      final int len = Math.min(buffer.length, input.remaining());
+      input.get(buffer, 0, len);
+
+      try
+      {
+        final Buffer output = Buffers.wrap(memoryManager,
+            layer.unwrap(buffer, 0, len));
+        return TransformationResult.createCompletedResult(output, input);
+      }
+      catch (final ErrorResultException e)
+      {
+        return TransformationResult.createErrorResult(e.getResult()
+            .getResultCode().intValue(), e.getMessage());
+      }
+    }
+  }
+
+
+
+  /**
+   * <tt>Transformer</tt>, which encodes SASL encrypted data, contained in the
+   * input Buffer, to the output Buffer.
+   */
+  private static final class Encoder extends
+      AbstractTransformer<Buffer, Buffer>
+  {
+    private static final int BUFFER_SIZE = 4096;
+    private final byte[] buffer = new byte[BUFFER_SIZE];
+    private final ConnectionSecurityLayer layer;
+    private final MemoryManager<?> memoryManager;
+
+
+
+    private Encoder(final ConnectionSecurityLayer layer,
+        final MemoryManager<?> memoryManager)
+    {
+      this.layer = layer;
+      this.memoryManager = memoryManager;
+    }
+
+
+
+    public String getName()
+    {
+      return this.getClass().getName();
+    }
+
+
+
+    public boolean hasInputRemaining(final AttributeStorage storage,
+        final Buffer input)
+    {
+      return input != null && input.hasRemaining();
+    }
+
+
+
+    @Override
+    public TransformationResult<Buffer, Buffer> transformImpl(
+        final AttributeStorage storage, final Buffer input)
+    {
+
+      final int len = Math.min(buffer.length, input.remaining());
+      input.get(buffer, 0, len);
+
+      try
+      {
+        final Buffer output = Buffers.wrap(memoryManager,
+            layer.wrap(buffer, 0, len));
+        return TransformationResult.createCompletedResult(output, input);
+      }
+      catch (final ErrorResultException e)
+      {
+        return TransformationResult.createErrorResult(e.getResult()
+            .getResultCode().intValue(), e.getMessage());
+      }
+    }
+  }
+
+
+
+  ConnectionSecurityLayerFilter(final ConnectionSecurityLayer layer,
+      final MemoryManager<?> memoryManager)
+  {
+    super(new Decoder(layer, memoryManager), new Encoder(layer, memoryManager));
+  }
+}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPClientFilter.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPClientFilter.java
index 9e27a56..9468824 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPClientFilter.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPClientFilter.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
+ *      Portions copyright 2012 ForgeRock AS.
  */
 
 package com.forgerock.opendj.ldap;
@@ -170,7 +171,7 @@
               {
                 // The connection needs to be secured by the SASL
                 // mechanism.
-                ldapConnection.installFilter(new SASLFilter(l, ctx
+                ldapConnection.installFilter(new ConnectionSecurityLayerFilter(l, ctx
                     .getConnection().getTransport().getMemoryManager()));
               }
             }
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPListenerImpl.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPListenerImpl.java
index a6adbfa..5dc3f19 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPListenerImpl.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPListenerImpl.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
- *      Portions copyright 2011 ForgeRock AS
+ *      Portions copyright 2011-2012 ForgeRock AS
  */
 
 package com.forgerock.opendj.ldap;
@@ -35,8 +35,6 @@
 import java.net.SocketAddress;
 import java.util.logging.Level;
 
-import javax.net.ssl.SSLContext;
-
 import org.forgerock.opendj.ldap.DecodeOptions;
 import org.forgerock.opendj.ldap.LDAPClientContext;
 import org.forgerock.opendj.ldap.LDAPListenerOptions;
@@ -46,8 +44,6 @@
 import org.glassfish.grizzly.filterchain.TransportFilter;
 import org.glassfish.grizzly.nio.transport.TCPNIOServerConnection;
 import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
-import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
-import org.glassfish.grizzly.ssl.SSLFilter;
 
 import com.forgerock.opendj.util.StaticUtils;
 
@@ -95,17 +91,6 @@
     this.connectionFactory = factory;
     this.defaultFilterChain = new DefaultFilterChain();
     this.defaultFilterChain.add(new TransportFilter());
-
-    if (options.getSSLContext() != null)
-    {
-      final SSLContext sslContext = options.getSSLContext();
-      SSLEngineConfigurator sslEngineConfigurator;
-
-      sslEngineConfigurator = new SSLEngineConfigurator(sslContext, false,
-          false, false);
-      this.defaultFilterChain.add(new SSLFilter(sslEngineConfigurator, null));
-    }
-
     this.defaultFilterChain.add(new LDAPServerFilter(this, new LDAPReader(
         new DecodeOptions(options.getDecodeOptions())), 0));
 
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPServerFilter.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPServerFilter.java
index ea79b9d..c7faa29 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPServerFilter.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPServerFilter.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
+ *      Portions copyright 2012 ForgeRock AS.
  */
 
 package com.forgerock.opendj.ldap;
@@ -48,6 +49,7 @@
 import org.glassfish.grizzly.Grizzly;
 import org.glassfish.grizzly.attributes.Attribute;
 import org.glassfish.grizzly.filterchain.*;
+import org.glassfish.grizzly.filterchain.Filter;
 import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
 import org.glassfish.grizzly.ssl.SSLFilter;
 import org.glassfish.grizzly.ssl.SSLUtils;
@@ -313,16 +315,17 @@
 
 
     @Override
-    public void startSASL(final ConnectionSecurityLayer bindContext)
+    public void enableConnectionSecurityLayer(
+        final ConnectionSecurityLayer layer)
     {
-      installFilter(connection, new SASLFilter(bindContext, connection
-          .getTransport().getMemoryManager()));
+      installFilter(connection, new ConnectionSecurityLayerFilter(layer,
+          connection.getTransport().getMemoryManager()));
     }
 
 
 
     @Override
-    public void startTLS(final SSLContext sslContext, final String[] protocols,
+    public void enableTLS(final SSLContext sslContext, final String[] protocols,
         final String[] suites, final boolean wantClientAuth,
         final boolean needClientAuth)
     {
@@ -1123,39 +1126,43 @@
       final org.glassfish.grizzly.filterchain.Filter filter)
   {
     FilterChain filterChain = (FilterChain) connection.getProcessor();
+
+    // Ensure that the SSL filter is not installed twice.
     if (filter instanceof SSLFilter)
     {
-      if (filterChain.get(filterChain.size() - 1) instanceof SSLFilter
-          || filterChain.get(filterChain.size() - 2) instanceof SSLFilter)
+      for (Filter f : filterChain)
       {
-        // SSLFilter already installed.
-        throw new IllegalStateException(
-            "SSLFilter already installed on connection");
-      }
-    }
-    if (filter instanceof SASLFilter)
-    {
-      if (filterChain.get(filterChain.size() - 1) instanceof SASLFilter)
-      {
-        // SASLFilter already installed.
-        throw new IllegalStateException(
-            "SASLFilter already installed on connection");
+        if (f instanceof SSLFilter)
+        {
+          // SSLFilter already installed.
+          throw new IllegalStateException("SSL already installed on connection");
+        }
       }
     }
 
+    // Copy on update the default filter chain.
     if (listener.getDefaultFilterChain() == filterChain)
     {
       filterChain = new DefaultFilterChain(filterChain);
       connection.setProcessor(filterChain);
     }
 
-    if (filter instanceof SSLFilter
-        && filterChain.get(filterChain.size() - 1) instanceof SASLFilter)
+    // Ensure that the SSL filter is beneath any connection security layer
+    // filters.
+    if (filter instanceof SSLFilter)
     {
-      filterChain.add(filterChain.size() - 2, filter);
+      for (int i = filterChain.size() - 1; i >= 0; i--)
+      {
+        if (!(filterChain.get(i) instanceof ConnectionSecurityLayerFilter))
+        {
+          filterChain.add(i, filter);
+          break;
+        }
+      }
     }
     else
     {
+      // Add connection security layers to the end of the chain.
       filterChain.add(filterChain.size() - 1, filter);
     }
 
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLDecoderTransformer.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLDecoderTransformer.java
deleted file mode 100644
index 1512821..0000000
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLDecoderTransformer.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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
- * trunk/opendj3/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
- * trunk/opendj3/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 2010 Sun Microsystems, Inc.
- *      Portions copyright 2012 ForgeRock AS.
- */
-
-package com.forgerock.opendj.ldap;
-
-
-
-import org.forgerock.opendj.ldap.ConnectionSecurityLayer;
-import org.forgerock.opendj.ldap.ErrorResultException;
-import org.glassfish.grizzly.AbstractTransformer;
-import org.glassfish.grizzly.Buffer;
-import org.glassfish.grizzly.TransformationResult;
-import org.glassfish.grizzly.attributes.AttributeStorage;
-import org.glassfish.grizzly.memory.Buffers;
-import org.glassfish.grizzly.memory.MemoryManager;
-
-
-
-/**
- * <tt>Transformer</tt>, which decodes SASL encrypted data, contained in the
- * input Buffer, to the output Buffer.
- */
-final class SASLDecoderTransformer extends AbstractTransformer<Buffer, Buffer>
-{
-  private static final int BUFFER_SIZE = 4096;
-  private final byte[] buffer = new byte[BUFFER_SIZE];
-  private final ConnectionSecurityLayer bindContext;
-
-  private final MemoryManager<?> memoryManager;
-
-
-
-  public SASLDecoderTransformer(final ConnectionSecurityLayer bindContext,
-      final MemoryManager<?> memoryManager)
-  {
-    this.bindContext = bindContext;
-    this.memoryManager = memoryManager;
-  }
-
-
-
-  public String getName()
-  {
-    return this.getClass().getName();
-  }
-
-
-
-  public boolean hasInputRemaining(final AttributeStorage storage,
-      final Buffer input)
-  {
-    return input != null && input.hasRemaining();
-  }
-
-
-
-  @Override
-  public TransformationResult<Buffer, Buffer> transformImpl(
-      final AttributeStorage storage, final Buffer input)
-  {
-
-    final int len = Math.min(buffer.length, input.remaining());
-    input.get(buffer, 0, len);
-
-    try
-    {
-      final Buffer output = Buffers.wrap(memoryManager, bindContext.unwrap(
-          buffer, 0, len));
-      return TransformationResult.createCompletedResult(output, input);
-    }
-    catch (final ErrorResultException e)
-    {
-      return TransformationResult.createErrorResult(e.getResult()
-          .getResultCode().intValue(), e.getMessage());
-    }
-  }
-}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLEncoderTransformer.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLEncoderTransformer.java
deleted file mode 100644
index 8811e31..0000000
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLEncoderTransformer.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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
- * trunk/opendj3/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
- * trunk/opendj3/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 2010 Sun Microsystems, Inc.
- *      Portions copyright 2012 ForgeRock AS.
- */
-
-package com.forgerock.opendj.ldap;
-
-
-
-import org.forgerock.opendj.ldap.ConnectionSecurityLayer;
-import org.forgerock.opendj.ldap.ErrorResultException;
-import org.glassfish.grizzly.AbstractTransformer;
-import org.glassfish.grizzly.Buffer;
-import org.glassfish.grizzly.TransformationResult;
-import org.glassfish.grizzly.attributes.AttributeStorage;
-import org.glassfish.grizzly.memory.Buffers;
-import org.glassfish.grizzly.memory.MemoryManager;
-
-
-
-/**
- * <tt>Transformer</tt>, which encodes SASL encrypted data, contained in the
- * input Buffer, to the output Buffer.
- */
-final class SASLEncoderTransformer extends AbstractTransformer<Buffer, Buffer>
-{
-  private static final int BUFFER_SIZE = 4096;
-  private final byte[] buffer = new byte[BUFFER_SIZE];
-  private final ConnectionSecurityLayer bindContext;
-
-  private final MemoryManager<?> memoryManager;
-
-
-
-  public SASLEncoderTransformer(final ConnectionSecurityLayer bindContext,
-      final MemoryManager<?> memoryManager)
-  {
-    this.bindContext = bindContext;
-    this.memoryManager = memoryManager;
-  }
-
-
-
-  public String getName()
-  {
-    return this.getClass().getName();
-  }
-
-
-
-  public boolean hasInputRemaining(final AttributeStorage storage,
-      final Buffer input)
-  {
-    return input != null && input.hasRemaining();
-  }
-
-
-
-  @Override
-  public TransformationResult<Buffer, Buffer> transformImpl(
-      final AttributeStorage storage, final Buffer input)
-  {
-
-    final int len = Math.min(buffer.length, input.remaining());
-    input.get(buffer, 0, len);
-
-    try
-    {
-      final Buffer output = Buffers.wrap(memoryManager, bindContext.wrap(
-          buffer, 0, len));
-      return TransformationResult.createCompletedResult(output, input);
-    }
-    catch (final ErrorResultException e)
-    {
-      return TransformationResult.createErrorResult(e.getResult()
-          .getResultCode().intValue(), e.getMessage());
-    }
-  }
-}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLFilter.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLFilter.java
deleted file mode 100644
index f43c1d9..0000000
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/SASLFilter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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
- * trunk/opendj3/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
- * trunk/opendj3/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 2009-2010 Sun Microsystems, Inc.
- */
-
-package com.forgerock.opendj.ldap;
-
-
-
-import org.forgerock.opendj.ldap.ConnectionSecurityLayer;
-import org.glassfish.grizzly.Buffer;
-import org.glassfish.grizzly.filterchain.AbstractCodecFilter;
-import org.glassfish.grizzly.memory.MemoryManager;
-
-
-
-/**
- * SASL filter adapter.
- */
-final class SASLFilter extends AbstractCodecFilter<Buffer, Buffer>
-{
-  public SASLFilter(final ConnectionSecurityLayer bindContext,
-      final MemoryManager<?> memoryManager)
-  {
-    super(new SASLDecoderTransformer(bindContext, memoryManager),
-        new SASLEncoderTransformer(bindContext, memoryManager));
-  }
-}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionSecurityLayer.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionSecurityLayer.java
index 6a5d959..ebd4081 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionSecurityLayer.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionSecurityLayer.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
+ *      Portions copyright 2012 ForgeRock AS.
  */
 
 package org.forgerock.opendj.ldap;
@@ -56,7 +57,7 @@
    * @param len
    *          The number of bytes from {@code incoming} to be unwrapped.
    * @return A non-{@code null} byte array containing the unwrapped bytes.
-   * @throws org.forgerock.opendj.ldap.ErrorResultException
+   * @throws ErrorResultException
    *           If {@code incoming} cannot be successfully unwrapped.
    */
   byte[] unwrap(byte[] incoming, int offset, int len)
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPClientContext.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPClientContext.java
index d39c50a..42ad6a1 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPClientContext.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPClientContext.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
+ *      Portions copyright 2012 ForgeRock AS.
  */
 
 package org.forgerock.opendj.ldap;
@@ -137,19 +138,24 @@
 
 
   /**
-   * Starts the SASL integrity and/or confidentiality protection layer on the
-   * underlying connection if possible.
+   * Installs the provided connection security layer to the underlying
+   * connection. This may be used to add a SASL integrity and/or confidentiality
+   * protection layer after SASL authentication has completed, but could also be
+   * used to add other layers such as compression. Multiple layers may be
+   * installed.
    *
-   * @param bindContext
+   * @param layer
    *          The negotiated bind context that can be used to encode and decode
    *          data on the connection.
    */
-  void startSASL(ConnectionSecurityLayer bindContext);
+  void enableConnectionSecurityLayer(ConnectionSecurityLayer layer);
 
 
 
   /**
-   * Starts the TLS/SSL security layer on the underlying connection if possible.
+   * Installs the TLS/SSL security layer on the underlying connection. The
+   * TLS/SSL security layer will be installed beneath any existing connection
+   * security layers and can only be installed at most once.
    *
    * @param sslContext
    *          The {@code SSLContext} which should be used to secure the
@@ -165,7 +171,9 @@
    * @param needClientAuth
    *          Set to {@code true} if client authentication is required, or
    *          {@code false} if no client authentication is desired.
+   * @throws IllegalStateException
+   *           If the TLS/SSL security layer has already been installed.
    */
-  void startTLS(SSLContext sslContext, String[] protocols, String[] suites,
+  void enableTLS(SSLContext sslContext, String[] protocols, String[] suites,
       boolean wantClientAuth, boolean needClientAuth);
 }
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPListenerOptions.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPListenerOptions.java
index d46b54e..d9238cd 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPListenerOptions.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPListenerOptions.java
@@ -30,8 +30,6 @@
 
 
 
-import javax.net.ssl.SSLContext;
-
 import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
 
 import com.forgerock.opendj.util.Validator;
@@ -44,12 +42,8 @@
 public final class LDAPListenerOptions
 {
 
-  private SSLContext sslContext;
-
   private DecodeOptions decodeOptions;
-
   private int backlog;
-
   private TCPNIOTransport transport;
 
 
@@ -60,7 +54,6 @@
    */
   public LDAPListenerOptions()
   {
-    this.sslContext = null;
     this.backlog = 0;
     this.decodeOptions = new DecodeOptions();
     this.transport = null;
@@ -77,7 +70,6 @@
    */
   public LDAPListenerOptions(final LDAPListenerOptions options)
   {
-    this.sslContext = options.sslContext;
     this.backlog = options.backlog;
     this.decodeOptions = new DecodeOptions(options.decodeOptions);
     this.transport = options.transport;
@@ -115,32 +107,15 @@
 
 
   /**
-   * Returns the SSL context which will be used when initiating connections with
-   * the Directory Server. By default no SSL context will be used, indicating
-   * that connections will not be secured. If a non-{@code null} SSL context is
-   * returned then connections will be secured using either SSL or StartTLS.
-   *
-   * @return The SSL context which will be used when initiating secure
-   *         connections with the Directory Server, which may be {@code null}
-   *         indicating that connections will not be secured.
-   */
-  public final SSLContext getSSLContext()
-  {
-    return sslContext;
-  }
-
-
-
-  /**
    * Returns the Grizzly TCP transport which will be used when initiating
-   * connections with the Directory Server. By default this method will return
-   * {@code null} indicating that the default transport factory should be
-   * used to obtain a TCP transport.
+   * connections with the Directory Server.
+   * <p>
+   * By default this method will return {@code null} indicating that the default
+   * transport factory should be used to obtain a TCP transport.
    *
    * @return The Grizzly TCP transport which will be used when initiating
    *         connections with the Directory Server, or {@code null} if the
-   *         default transport factory should be used to obtain a TCP
-   *         transport.
+   *         default transport factory should be used to obtain a TCP transport.
    */
   public final TCPNIOTransport getTCPNIOTransport()
   {
@@ -189,30 +164,11 @@
 
 
   /**
-   * Sets the SSL context which will be used when initiating connections with
-   * the Directory Server. By default no SSL context will be used, indicating
-   * that connections will not be secured. If a non-{@code null} SSL context is
-   * returned then connections will be secured using either SSL or StartTLS.
-   *
-   * @param sslContext
-   *          The SSL context which will be used when initiating secure
-   *          connections with the Directory Server, which may be {@code null}
-   *          indicating that connections will not be secured.
-   * @return A reference to this LDAP listener options.
-   */
-  public final LDAPListenerOptions setSSLContext(final SSLContext sslContext)
-  {
-    this.sslContext = sslContext;
-    return this;
-  }
-
-
-
-  /**
    * Sets the Grizzly TCP transport which will be used when initiating
-   * connections with the Directory Server. By default this method will return
-   * {@code null} indicating that the default transport factory should be
-   * used to obtain a TCP transport.
+   * connections with the Directory Server.
+   * <p>
+   * By default this method will return {@code null} indicating that the default
+   * transport factory should be used to obtain a TCP transport.
    *
    * @param transport
    *          The Grizzly TCP transport which will be used when initiating
@@ -227,4 +183,5 @@
     this.transport = transport;
     return this;
   }
+
 }
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java
index 14c0a71..9f1e706 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java
@@ -48,23 +48,11 @@
 public final class LDAPOptions
 {
   private SSLContext sslContext;
-
   private boolean useStartTLS;
-
   private long timeoutInMillis;
-
   private DecodeOptions decodeOptions;
-
-  /**
-   * The list of cipher suite
-   */
   private List<String> enabledCipherSuites = new LinkedList<String>();
-
-  /**
-   * the list of protocols
-   */
   private List<String> enabledProtocols = new LinkedList<String>();
-
   private TCPNIOTransport transport;
 
 
@@ -120,10 +108,12 @@
 
   /**
    * Returns the SSL context which will be used when initiating connections with
-   * the Directory Server. By default no SSL context will be used, indicating
-   * that connections will not be secured. If a non-{@code null} SSL context is
-   * returned then connections will be secured using either SSL or StartTLS
-   * depending on {@link #useStartTLS()}.
+   * the Directory Server.
+   * <p>
+   * By default no SSL context will be used, indicating that connections will
+   * not be secured. If a non-{@code null} SSL context is returned then
+   * connections will be secured using either SSL or StartTLS depending on
+   * {@link #useStartTLS()}.
    *
    * @return The SSL context which will be used when initiating secure
    *         connections with the Directory Server, which may be {@code null}
@@ -138,9 +128,10 @@
 
   /**
    * Returns the Grizzly TCP transport which will be used when initiating
-   * connections with the Directory Server. By default this method will return
-   * {@code null} indicating that the default transport factory should be used
-   * to obtain a TCP transport.
+   * connections with the Directory Server.
+   * <p>
+   * By default this method will return {@code null} indicating that the default
+   * transport factory should be used to obtain a TCP transport.
    *
    * @return The Grizzly TCP transport which will be used when initiating
    *         connections with the Directory Server, or {@code null} if the
@@ -189,10 +180,12 @@
 
   /**
    * Sets the SSL context which will be used when initiating connections with
-   * the Directory Server. By default no SSL context will be used, indicating
-   * that connections will not be secured. If a non-{@code null} SSL context is
-   * returned then connections will be secured using either SSL or StartTLS
-   * depending on {@link #useStartTLS()}.
+   * the Directory Server.
+   * <p>
+   * By default no SSL context will be used, indicating that connections will
+   * not be secured. If a non-{@code null} SSL context is returned then
+   * connections will be secured using either SSL or StartTLS depending on
+   * {@link #useStartTLS()}.
    *
    * @param sslContext
    *          The SSL context which will be used when initiating secure
@@ -210,9 +203,10 @@
 
   /**
    * Sets the Grizzly TCP transport which will be used when initiating
-   * connections with the Directory Server. By default this method will return
-   * {@code null} indicating that the default transport factory will be used to
-   * obtain a TCP transport.
+   * connections with the Directory Server.
+   * <p>
+   * By default this method will return {@code null} indicating that the default
+   * transport factory will be used to obtain a TCP transport.
    *
    * @param transport
    *          The Grizzly TCP transport which will be used when initiating
@@ -250,8 +244,9 @@
 
   /**
    * Specifies whether or not SSL or StartTLS should be used for securing
-   * connections when an SSL context is specified. By default SSL will be used
-   * in preference to StartTLS.
+   * connections when an SSL context is specified.
+   * <p>
+   * By default SSL will be used in preference to StartTLS.
    *
    * @param useStartTLS
    *          {@code true} if StartTLS should be used for securing connections
@@ -269,8 +264,9 @@
 
   /**
    * Indicates whether or not SSL or StartTLS should be used for securing
-   * connections when an SSL context is specified. By default SSL will be used
-   * in preference to StartTLS.
+   * connections when an SSL context is specified.
+   * <p>
+   * By default SSL will be used in preference to StartTLS.
    *
    * @return {@code true} if StartTLS should be used for securing connections
    *         when an SSL context is specified, otherwise {@code false}
@@ -281,70 +277,80 @@
     return useStartTLS;
   }
 
+
+
   /**
    * Adds the protocol versions enabled for secure connections with the
    * Directory Server.
-   *
+   * <p>
    * The protocols must be supported by the SSLContext specified in
-   * {@link #setSSLContext(SSLContext)}. Following a successful call to
-   * this method, only the protocols listed in the protocols parameter are
-   * enabled for use.
+   * {@link #setSSLContext(SSLContext)}. Following a successful call to this
+   * method, only the protocols listed in the protocols parameter are enabled
+   * for use.
    *
-   * @param protocols Names of all the protocols to enable.
+   * @param protocols
+   *          Names of all the protocols to enable.
    * @return A reference to this LDAP connection options.
    */
   public final LDAPOptions addEnabledProtocol(String... protocols)
   {
     for (final String protocol : protocols)
     {
-      this.enabledProtocols.add(Validator.ensureNotNull(protocol));
+      enabledProtocols.add(Validator.ensureNotNull(protocol));
     }
     return this;
   }
 
+
+
   /**
-   * Adds the cipher suites enabled for secure connections with the
-   * Directory Server.
-   *
+   * Adds the cipher suites enabled for secure connections with the Directory
+   * Server.
+   * <p>
    * The suites must be supported by the SSLContext specified in
-   * {@link #setSSLContext(SSLContext)}. Following a successful call to
-   * this method, only the suites listed in the protocols parameter are
-   * enabled for use.
+   * {@link #setSSLContext(SSLContext)}. Following a successful call to this
+   * method, only the suites listed in the protocols parameter are enabled for
+   * use.
    *
-   * @param suites Names of all the suites to enable.
+   * @param suites
+   *          Names of all the suites to enable.
    * @return A reference to this LDAP connection options.
    */
   public final LDAPOptions addEnabledCipherSuite(String... suites)
   {
     for (final String suite : suites)
     {
-      this.enabledCipherSuites.add(Validator.ensureNotNull(suite));
+      enabledCipherSuites.add(Validator.ensureNotNull(suite));
     }
     return this;
   }
 
+
+
   /**
-   * Returns the names of the protocol versions which are currently enabled
-   * for secure connections with the Directory Server.
+   * Returns the names of the protocol versions which are currently enabled for
+   * secure connections with the Directory Server.
    *
-   * @return an array of protocols or empty set if the default protocols
-   * are to be used.
+   * @return An array of protocols or empty set if the default protocols are to
+   *         be used.
    */
   public final List<String> getEnabledProtocols()
   {
-    return this.enabledProtocols;
+    return enabledProtocols;
   }
 
+
+
   /**
-   * Returns the names of the protocol versions which are currently enabled
-   * for secure connections with the Directory Server.
+   * Returns the names of the protocol versions which are currently enabled for
+   * secure connections with the Directory Server.
    *
-   * @return an array of protocols or empty set if the default protocols
-   * are to be used.
+   * @return An array of protocols or empty set if the default protocols are to
+   *         be used.
    */
   public final List<String> getEnabledCipherSuites()
   {
-    return this.enabledCipherSuites;
+    return enabledCipherSuites;
   }
 
 }
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
index 97e25b0..d6b4273 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
- *      Portions copyright 2011 ForgeRock AS
+ *      Portions copyright 2011-2012 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldap;
@@ -371,7 +371,7 @@
                 }
               };
 
-              clientContext.startSASL(csl);
+              clientContext.enableConnectionSecurityLayer(csl);
             }
 
           }
@@ -576,7 +576,7 @@
         final R result = request.getResultDecoder().newExtendedErrorResult(
             ResultCode.SUCCESS, "", "");
         resultHandler.handleResult(result);
-        clientContext.startTLS(sslContext, null, sslContext.getSocketFactory()
+        clientContext.enableTLS(sslContext, null, sslContext.getSocketFactory()
             .getSupportedCipherSuites(), false, false);
       }
     }

--
Gitblit v1.10.0