mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
29.31.2011 32034d853f3a284424ccfa87b6de210f1ca814e1
Fix OPENDJ-43 (Synchronous Connection decorator implementations should not use AsynchronousConnections) and OPENDJ-328 (Make it easier to implement connection decorators).

Merged AsynchronousConnection interface into Connection and added "Async" suffix to asynchronous operation methods so that they can be easily distinguished from their synchronous counterparts. Added AbstractAsynchronousConnection class which facilitates development of new Connection implementations whose underlying implementation is asynchronous.
5 files deleted
2 files added
43 files modified
7005 ■■■■ changed files
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/modify/Main.java 4 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/proxy/Main.java 202 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/searchasync/Main.java 17 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/server/Main.java 47 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/AbstractLDAPFutureResultImpl.java 7 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/InternalConnection.java 53 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPBindFutureResultImpl.java 5 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPCompareFutureResultImpl.java 5 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java 102 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java 70 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPExtendedFutureResultImpl.java 3 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPFutureResultImpl.java 5 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPSearchFutureResultImpl.java 5 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/AbstractConnectionFactory.java 89 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/AsynchronousConnectionDecorator.java 466 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/ConnectionDecorator.java 766 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/SynchronousConnection.java 365 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnection.java 491 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnection.java 334 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractLoadBalancingAlgorithm.java 58 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AsynchronousConnection.java 769 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java 113 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connection.java 581 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionFactory.java 17 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionPool.java 11 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java 12 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/FixedConnectionPool.java 610 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactory.java 94 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/IntermediateResponseHandler.java 17 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/InternalConnectionFactory.java 29 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java 12 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LoadBalancer.java 23 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandler.java 83 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactoryAdapter.java 139 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ResultHandler.java 3 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RootDSE.java 14 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/SearchResultHandler.java 3 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java 22 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java 25 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/ConnectionEntryReader.java 15 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/com/forgerock/opendj/util/SynchronousConnectionTestCase.java 186 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnectionTestCase.java 605 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java 63 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPListenerTestCase.java 61 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java 87 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java 28 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthenticatedConnectionFactory.java 209 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java 12 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java 52 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java 16 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/modify/Main.java
@@ -109,8 +109,8 @@
      connection.bind(userName, password.toCharArray());
      // Write the changes.
      final ConnectionChangeRecordWriter writer = new ConnectionChangeRecordWriter(
          connection);
      final ConnectionChangeRecordWriter writer =
          new ConnectionChangeRecordWriter(connection);
      while (reader.hasNext())
      {
        ChangeRecord changeRecord = reader.readChangeRecord();
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/proxy/Main.java
@@ -84,12 +84,11 @@
        implements ResultHandler<R>
    {
      final H resultHandler;
      final AsynchronousConnection connection;
      final Connection connection;
      AbstractRequestCompletionHandler(
          final AsynchronousConnection connection,
      AbstractRequestCompletionHandler(final Connection connection,
          final H resultHandler)
      {
        this.connection = connection;
@@ -99,8 +98,7 @@
      @Override
      public final void handleErrorResult(
          final ErrorResultException error)
      public final void handleErrorResult(final ErrorResultException error)
      {
        connection.close();
        resultHandler.handleErrorResult(error);
@@ -120,14 +118,13 @@
    private abstract class ConnectionCompletionHandler<R extends Result>
        implements ResultHandler<AsynchronousConnection>
        implements ResultHandler<Connection>
    {
      private final ResultHandler<? super R> resultHandler;
      ConnectionCompletionHandler(
          final ResultHandler<? super R> resultHandler)
      ConnectionCompletionHandler(final ResultHandler<? super R> resultHandler)
      {
        this.resultHandler = resultHandler;
      }
@@ -135,8 +132,7 @@
      @Override
      public final void handleErrorResult(
          final ErrorResultException error)
      public final void handleErrorResult(final ErrorResultException error)
      {
        resultHandler.handleErrorResult(error);
      }
@@ -144,19 +140,16 @@
      @Override
      public abstract void handleResult(
          AsynchronousConnection connection);
      public abstract void handleResult(Connection connection);
    }
    private final class RequestCompletionHandler<R extends Result>
        extends
    private final class RequestCompletionHandler<R extends Result> extends
        AbstractRequestCompletionHandler<R, ResultHandler<? super R>>
    {
      RequestCompletionHandler(
          final AsynchronousConnection connection,
      RequestCompletionHandler(final Connection connection,
          final ResultHandler<? super R> resultHandler)
      {
        super(connection, resultHandler);
@@ -166,12 +159,11 @@
    private final class SearchRequestCompletionHandler extends
        AbstractRequestCompletionHandler<Result, SearchResultHandler>
        implements SearchResultHandler
        AbstractRequestCompletionHandler<Result, SearchResultHandler> implements
        SearchResultHandler
    {
      SearchRequestCompletionHandler(
          final AsynchronousConnection connection,
      SearchRequestCompletionHandler(final Connection connection,
          final SearchResultHandler resultHandler)
      {
        super(connection, resultHandler);
@@ -214,28 +206,27 @@
    @Override
    public void handleAdd(final RequestContext requestContext,
        final AddRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      addProxiedAuthControl(request);
      final ConnectionCompletionHandler<Result> outerHandler =
        new ConnectionCompletionHandler<Result>(resultHandler)
          new ConnectionCompletionHandler<Result>(resultHandler)
      {
        @Override
        public void handleResult(
            final AsynchronousConnection connection)
        public void handleResult(final Connection connection)
        {
          final RequestCompletionHandler<Result> innerHandler =
            new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.add(request, innerHandler,
              intermediateResponseHandler);
              new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.addAsync(request, intermediateResponseHandler,
              innerHandler);
        }
      };
      factory.getAsynchronousConnection(outerHandler);
      factory.getConnectionAsync(outerHandler);
    }
@@ -246,8 +237,8 @@
    @Override
    public void handleBind(final RequestContext requestContext,
        final int version, final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException
    {
@@ -264,14 +255,14 @@
        // Authenticate using a separate bind connection pool, because we
        // don't want to change the state of the pooled connection.
        final ConnectionCompletionHandler<BindResult> outerHandler =
          new ConnectionCompletionHandler<BindResult>(resultHandler)
            new ConnectionCompletionHandler<BindResult>(resultHandler)
        {
          @Override
          public void handleResult(
              final AsynchronousConnection connection)
          public void handleResult(final Connection connection)
          {
            final ResultHandler<BindResult> innerHandler = new ResultHandler<BindResult>()
            final ResultHandler<BindResult> innerHandler =
                new ResultHandler<BindResult>()
            {
              @Override
@@ -293,14 +284,14 @@
                resultHandler.handleResult(result);
              }
            };
            connection.bind(request, innerHandler,
                intermediateResponseHandler);
            connection.bindAsync(request, intermediateResponseHandler,
                innerHandler);
          }
        };
        proxiedAuthControl = null;
        bindFactory.getAsynchronousConnection(outerHandler);
        bindFactory.getConnectionAsync(outerHandler);
      }
    }
@@ -312,28 +303,28 @@
    @Override
    public void handleCompare(final RequestContext requestContext,
        final CompareRequest request,
        final ResultHandler<? super CompareResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super CompareResult> resultHandler)
        throws UnsupportedOperationException
    {
      addProxiedAuthControl(request);
      final ConnectionCompletionHandler<CompareResult> outerHandler =
        new ConnectionCompletionHandler<CompareResult>(resultHandler)
          new ConnectionCompletionHandler<CompareResult>(resultHandler)
      {
        @Override
        public void handleResult(
            final AsynchronousConnection connection)
        public void handleResult(final Connection connection)
        {
          final RequestCompletionHandler<CompareResult> innerHandler =
            new RequestCompletionHandler<CompareResult>(connection, resultHandler);
          connection.compare(request, innerHandler,
              intermediateResponseHandler);
              new RequestCompletionHandler<CompareResult>(connection,
                  resultHandler);
          connection.compareAsync(request, intermediateResponseHandler,
              innerHandler);
        }
      };
      factory.getAsynchronousConnection(outerHandler);
      factory.getConnectionAsync(outerHandler);
    }
@@ -344,28 +335,27 @@
    @Override
    public void handleDelete(final RequestContext requestContext,
        final DeleteRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      addProxiedAuthControl(request);
      final ConnectionCompletionHandler<Result> outerHandler =
        new ConnectionCompletionHandler<Result>(resultHandler)
          new ConnectionCompletionHandler<Result>(resultHandler)
      {
        @Override
        public void handleResult(
            final AsynchronousConnection connection)
        public void handleResult(final Connection connection)
        {
          final RequestCompletionHandler<Result> innerHandler =
            new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.delete(request, innerHandler,
              intermediateResponseHandler);
              new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.deleteAsync(request, intermediateResponseHandler,
              innerHandler);
        }
      };
      factory.getAsynchronousConnection(outerHandler);
      factory.getConnectionAsync(outerHandler);
    }
@@ -375,10 +365,9 @@
     */
    @Override
    public <R extends ExtendedResult> void handleExtendedRequest(
        final RequestContext requestContext,
        final ExtendedRequest<R> request,
        final ResultHandler<? super R> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final RequestContext requestContext, final ExtendedRequest<R> request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super R> resultHandler)
        throws UnsupportedOperationException
    {
      if (request.getOID().equals(CancelExtendedRequest.OID))
@@ -401,22 +390,21 @@
        addProxiedAuthControl(request);
        final ConnectionCompletionHandler<R> outerHandler =
          new ConnectionCompletionHandler<R>(resultHandler)
            new ConnectionCompletionHandler<R>(resultHandler)
        {
          @Override
          public void handleResult(
              final AsynchronousConnection connection)
          public void handleResult(final Connection connection)
          {
            final RequestCompletionHandler<R> innerHandler =
              new RequestCompletionHandler<R>(connection, resultHandler);
            connection.extendedRequest(request, innerHandler,
                intermediateResponseHandler);
                new RequestCompletionHandler<R>(connection, resultHandler);
            connection.extendedRequestAsync(request,
                intermediateResponseHandler, innerHandler);
          }
        };
        factory.getAsynchronousConnection(outerHandler);
        factory.getConnectionAsync(outerHandler);
      }
    }
@@ -428,28 +416,27 @@
    @Override
    public void handleModify(final RequestContext requestContext,
        final ModifyRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      addProxiedAuthControl(request);
      final ConnectionCompletionHandler<Result> outerHandler =
        new ConnectionCompletionHandler<Result>(resultHandler)
          new ConnectionCompletionHandler<Result>(resultHandler)
      {
        @Override
        public void handleResult(
            final AsynchronousConnection connection)
        public void handleResult(final Connection connection)
        {
          final RequestCompletionHandler<Result> innerHandler =
            new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.modify(request, innerHandler,
              intermediateResponseHandler);
              new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.modifyAsync(request, intermediateResponseHandler,
              innerHandler);
        }
      };
      factory.getAsynchronousConnection(outerHandler);
      factory.getConnectionAsync(outerHandler);
    }
@@ -460,28 +447,27 @@
    @Override
    public void handleModifyDN(final RequestContext requestContext,
        final ModifyDNRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      addProxiedAuthControl(request);
      final ConnectionCompletionHandler<Result> outerHandler =
        new ConnectionCompletionHandler<Result>(resultHandler)
          new ConnectionCompletionHandler<Result>(resultHandler)
      {
        @Override
        public void handleResult(
            final AsynchronousConnection connection)
        public void handleResult(final Connection connection)
        {
          final RequestCompletionHandler<Result> innerHandler =
            new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.modifyDN(request, innerHandler,
              intermediateResponseHandler);
              new RequestCompletionHandler<Result>(connection, resultHandler);
          connection.modifyDNAsync(request, intermediateResponseHandler,
              innerHandler);
        }
      };
      factory.getAsynchronousConnection(outerHandler);
      factory.getConnectionAsync(outerHandler);
    }
@@ -492,28 +478,27 @@
    @Override
    public void handleSearch(final RequestContext requestContext,
        final SearchRequest request,
        final SearchResultHandler resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final SearchResultHandler resultHandler)
        throws UnsupportedOperationException
    {
      addProxiedAuthControl(request);
      final ConnectionCompletionHandler<Result> outerHandler =
        new ConnectionCompletionHandler<Result>(resultHandler)
          new ConnectionCompletionHandler<Result>(resultHandler)
      {
        @Override
        public void handleResult(
            final AsynchronousConnection connection)
        public void handleResult(final Connection connection)
        {
          final SearchRequestCompletionHandler innerHandler =
            new SearchRequestCompletionHandler(connection, resultHandler);
          connection.search(request, innerHandler,
              intermediateResponseHandler);
              new SearchRequestCompletionHandler(connection, resultHandler);
          connection.searchAsync(request, intermediateResponseHandler,
              innerHandler);
        }
      };
      factory.getAsynchronousConnection(outerHandler);
      factory.getConnectionAsync(outerHandler);
    }
@@ -552,8 +537,10 @@
    final int localPort = Integer.parseInt(args[1]);
    // Create load balancer.
    final List<ConnectionFactory> factories = new LinkedList<ConnectionFactory>();
    final List<ConnectionFactory> bindFactories = new LinkedList<ConnectionFactory>();
    final List<ConnectionFactory> factories =
        new LinkedList<ConnectionFactory>();
    final List<ConnectionFactory> bindFactories =
        new LinkedList<ConnectionFactory>();
    for (int i = 2; i < args.length; i += 2)
    {
      final String remoteAddress = args[i];
@@ -566,19 +553,18 @@
          new LDAPConnectionFactory(remoteAddress, remotePort),
          Integer.MAX_VALUE));
    }
    final RoundRobinLoadBalancingAlgorithm algorithm = new RoundRobinLoadBalancingAlgorithm(
        factories);
    final RoundRobinLoadBalancingAlgorithm bindAlgorithm = new RoundRobinLoadBalancingAlgorithm(
        bindFactories);
    final ConnectionFactory factory = Connections
        .newLoadBalancer(algorithm);
    final RoundRobinLoadBalancingAlgorithm algorithm =
        new RoundRobinLoadBalancingAlgorithm(factories);
    final RoundRobinLoadBalancingAlgorithm bindAlgorithm =
        new RoundRobinLoadBalancingAlgorithm(bindFactories);
    final ConnectionFactory factory = Connections.newLoadBalancer(algorithm);
    final ConnectionFactory bindFactory = Connections
        .newLoadBalancer(bindAlgorithm);
    // Create a server connection adapter.
    final ProxyBackend backend = new ProxyBackend(factory, bindFactory);
    final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler =
      Connections.newServerConnectionFactory(backend);
    final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler
      = Connections.newServerConnectionFactory(backend);
    // Create listener.
    final LDAPListenerOptions options = new LDAPListenerOptions()
@@ -586,15 +572,15 @@
    LDAPListener listener = null;
    try
    {
      listener = new LDAPListener(localAddress, localPort,
          connectionHandler, options);
      listener = new LDAPListener(localAddress, localPort, connectionHandler,
          options);
      System.out.println("Press any key to stop the server...");
      System.in.read();
    }
    catch (final IOException e)
    {
      System.out.println("Error listening on " + localAddress + ":"
          + localPort);
      System.out
          .println("Error listening on " + localAddress + ":" + localPort);
      e.printStackTrace();
    }
    finally
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/searchasync/Main.java
@@ -78,7 +78,7 @@
      // Bind succeeded: initiate search.
      final SearchRequest request = Requests.newSearchRequest(baseDN,
          scope, filter, attributes);
      connection.search(request, new SearchResultHandlerImpl());
      connection.searchAsync(request, null, new SearchResultHandlerImpl());
    }
  }
@@ -86,7 +86,7 @@
  private static final class ConnectResultHandlerImpl implements
      ResultHandler<AsynchronousConnection>
      ResultHandler<Connection>
  {
    /**
@@ -106,14 +106,14 @@
     * {@inheritDoc}
     */
    @Override
    public void handleResult(final AsynchronousConnection connection)
    public void handleResult(final Connection connection)
    {
      // Connect succeeded: save connection and initiate bind.
      Main.connection = connection;
      final BindRequest request = Requests.newSimpleBindRequest(
          userName, password.toCharArray());
      connection.bind(request, new BindResultHandlerImpl());
      connection.bindAsync(request, null, new BindResultHandlerImpl());
    }
  }
@@ -207,15 +207,10 @@
  private static String userName;
  private static String password;
  private static String baseDN;
  private static SearchScope scope;
  private static String filter;
  private static String[] attributes;
  private static AsynchronousConnection connection = null;
  private static Connection connection = null;
  private static int resultCode = 0;
@@ -280,7 +275,7 @@
    // Initiate the asynchronous connect, bind, and search.
    final LDAPConnectionFactory factory = new LDAPConnectionFactory(
        hostName, port);
    factory.getAsynchronousConnection(new ConnectResultHandlerImpl());
    factory.getConnectionAsync(new ConnectResultHandlerImpl());
    // Await completion.
    try
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/server/Main.java
@@ -68,8 +68,8 @@
      RequestHandler<RequestContext>
  {
    private final ConcurrentSkipListMap<DN, Entry> entries;
    private final ReentrantReadWriteLock entryLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock entryLock =
        new ReentrantReadWriteLock();
@@ -87,8 +87,8 @@
    @Override
    public void handleAdd(final RequestContext requestContext,
        final AddRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO: controls.
@@ -132,8 +132,8 @@
    @Override
    public void handleBind(final RequestContext requestContext,
        final int version, final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException
    {
      if (request.getAuthenticationType() != ((byte) 0x80))
@@ -160,8 +160,8 @@
    @Override
    public void handleCompare(final RequestContext requestContext,
        final CompareRequest request,
        final ResultHandler<? super CompareResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super CompareResult> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO:
@@ -175,8 +175,8 @@
    @Override
    public void handleDelete(final RequestContext requestContext,
        final DeleteRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO: controls.
@@ -213,8 +213,8 @@
    public <R extends ExtendedResult> void handleExtendedRequest(
        final RequestContext requestContext,
        final ExtendedRequest<R> request,
        final ResultHandler<? super R> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super R> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO: not implemented.
@@ -231,8 +231,8 @@
    @Override
    public void handleModify(final RequestContext requestContext,
        final ModifyRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO: controls.
@@ -272,8 +272,8 @@
          {
            resultHandler
                .handleErrorResult(newErrorResult(
                    ResultCode.PROTOCOL_ERROR,
                    "Modify request contains an unsupported modification type"));
                  ResultCode.PROTOCOL_ERROR,
                  "Modify request contains an unsupported modification type"));
            return;
          }
        }
@@ -296,8 +296,8 @@
    @Override
    public void handleModifyDN(final RequestContext requestContext,
        final ModifyDNRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO: not implemented.
@@ -314,8 +314,8 @@
    @Override
    public void handleSearch(final RequestContext requestContext,
        final SearchRequest request,
        final SearchResultHandler resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final SearchResultHandler resultHandler)
        throws UnsupportedOperationException
    {
      // TODO: controls, limits, etc.
@@ -458,12 +458,13 @@
    final String ldifFileName = args[2];
    // Create the memory backend.
    final ConcurrentSkipListMap<DN, Entry> entries = readEntriesFromLDIF(ldifFileName);
    final ConcurrentSkipListMap<DN, Entry> entries =
        readEntriesFromLDIF(ldifFileName);
    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()
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/AbstractLDAPFutureResultImpl.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap;
@@ -47,7 +48,7 @@
abstract class AbstractLDAPFutureResultImpl<S extends Result> extends
    AsynchronousFutureResult<S> implements IntermediateResponseHandler
{
  private final AsynchronousConnection connection;
  private final Connection connection;
  private final int requestID;
@@ -60,7 +61,7 @@
  AbstractLDAPFutureResultImpl(final int requestID,
      final ResultHandler<? super S> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler,
      final AsynchronousConnection connection)
      final Connection connection)
  {
    super(resultHandler);
    this.requestID = requestID;
@@ -113,7 +114,7 @@
  protected final ErrorResultException handleCancelRequest(
      final boolean mayInterruptIfRunning)
  {
    connection.abandon(Requests.newAbandonRequest(requestID));
    connection.abandonAsync(Requests.newAbandonRequest(requestID));
    return null;
  }
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/InternalConnection.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap;
@@ -60,7 +61,7 @@
        final BindRequest bindRequest,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler,
        final AsynchronousConnection connection)
        final Connection connection)
    {
      super(messageID, resultHandler, intermediateResponseHandler, connection);
      this.bindRequest = bindRequest;
@@ -120,7 +121,7 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Void> abandon(final AbandonRequest request)
  public FutureResult<Void> abandonAsync(final AbandonRequest request)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -135,9 +136,9 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Result> add(final AddRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> addAsync(final AddRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -167,9 +168,9 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<BindResult> bind(final BindRequest request,
      final ResultHandler<? super BindResult> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<BindResult> bindAsync(final BindRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super BindResult> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -198,9 +199,9 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<CompareResult> compare(final CompareRequest request,
      final ResultHandler<? super CompareResult> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<CompareResult> compareAsync(final CompareRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super CompareResult> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -217,9 +218,9 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Result> delete(final DeleteRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> deleteAsync(final DeleteRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -236,10 +237,10 @@
   * {@inheritDoc}
   */
  @Override
  public <R extends ExtendedResult> FutureResult<R> extendedRequest(
  public <R extends ExtendedResult> FutureResult<R> extendedRequestAsync(
      final ExtendedRequest<R> request,
      final ResultHandler<? super R> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super R> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -280,9 +281,9 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Result> modify(final ModifyRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> modifyAsync(final ModifyRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -299,9 +300,9 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Result> modifyDN(final ModifyDNRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> modifyDNAsync(final ModifyDNRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -331,9 +332,9 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Result> search(final SearchRequest request,
      final SearchResultHandler resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> searchAsync(final SearchRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final SearchResultHandler resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPBindFutureResultImpl.java
@@ -23,13 +23,14 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap;
import org.forgerock.opendj.ldap.AsynchronousConnection;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.IntermediateResponseHandler;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.ResultHandler;
@@ -52,7 +53,7 @@
  LDAPBindFutureResultImpl(final int requestID, final BindClient bindClient,
      final ResultHandler<? super BindResult> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler,
      final AsynchronousConnection connection)
      final Connection connection)
  {
    super(requestID, resultHandler, intermediateResponseHandler, connection);
    this.bindClient = bindClient;
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPCompareFutureResultImpl.java
@@ -23,13 +23,14 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap;
import org.forgerock.opendj.ldap.AsynchronousConnection;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.IntermediateResponseHandler;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.ResultHandler;
@@ -53,7 +54,7 @@
      final CompareRequest request,
      final ResultHandler<? super CompareResult> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler,
      final AsynchronousConnection connection)
      final Connection connection)
  {
    super(requestID, resultHandler, intermediateResponseHandler, connection);
    this.request = request;
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java
@@ -66,31 +66,21 @@
 * TODO: handle illegal state exceptions.
 */
final class LDAPConnection extends AbstractAsynchronousConnection implements
    AsynchronousConnection
    Connection
{
  private final org.glassfish.grizzly.Connection<?> connection;
  private Result connectionInvalidReason;
  private FilterChain customFilterChain;
  private boolean isClosed = false;
  private final List<ConnectionEventListener> listeners =
    new CopyOnWriteArrayList<ConnectionEventListener>();
      new CopyOnWriteArrayList<ConnectionEventListener>();
  private final AtomicInteger nextMsgID = new AtomicInteger(1);
  private final AtomicBoolean bindOrStartTLSInProgress =
      new AtomicBoolean(false);
  private final AtomicBoolean bindOrStartTLSInProgress = new AtomicBoolean(
      false);
  private final ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>> pendingRequests =
    new ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>>();
      new ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>>();
  private final Object stateLock = new Object();
  private final LDAPWriter ldapWriter = new LDAPWriter();
  private final LDAPOptions options;
@@ -115,7 +105,7 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Void> abandon(final AbandonRequest request)
  public FutureResult<Void> abandonAsync(final AbandonRequest request)
  {
    final AbstractLDAPFutureResultImpl<?> pendingRequest;
    final int messageID = nextMsgID.getAndIncrement();
@@ -132,8 +122,8 @@
        final Result errorResult = Responses.newResult(
            ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
            "Bind or Start TLS operation in progress");
        return new CompletedFutureResult<Void>(
            newErrorResult(errorResult), messageID);
        return new CompletedFutureResult<Void>(newErrorResult(errorResult),
            messageID);
      }
      // First remove the future associated with the request to be abandoned.
@@ -173,8 +163,8 @@
      final Result errorResult = Responses.newResult(
          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
      connectionErrorOccurred(errorResult);
      return new CompletedFutureResult<Void>(
          newErrorResult(errorResult), messageID);
      return new CompletedFutureResult<Void>(newErrorResult(errorResult),
          messageID);
    }
  }
@@ -183,9 +173,9 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> add(final AddRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> addAsync(final AddRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
@@ -253,9 +243,9 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<BindResult> bind(final BindRequest request,
      final ResultHandler<? super BindResult> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<BindResult> bindAsync(final BindRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super BindResult> resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
@@ -276,7 +266,8 @@
          .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
          .setDiagnosticMessage(
              "An error occurred while creating a bind context").setCause(e);
      final ErrorResultException error = ErrorResultException.newErrorResult(errorResult);
      final ErrorResultException error = ErrorResultException
          .newErrorResult(errorResult);
      if (resultHandler != null)
      {
        resultHandler.handleErrorResult(error);
@@ -371,9 +362,9 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<CompareResult> compare(final CompareRequest request,
      final ResultHandler<? super CompareResult> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<CompareResult> compareAsync(final CompareRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super CompareResult> resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
    final LDAPCompareFutureResultImpl future = new LDAPCompareFutureResultImpl(
@@ -429,9 +420,9 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> delete(final DeleteRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> deleteAsync(final DeleteRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
@@ -487,10 +478,10 @@
  /**
   * {@inheritDoc}
   */
  public <R extends ExtendedResult> FutureResult<R> extendedRequest(
  public <R extends ExtendedResult> FutureResult<R> extendedRequestAsync(
      final ExtendedRequest<R> request,
      final ResultHandler<? super R> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super R> resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
    final LDAPExtendedFutureResultImpl<R> future = new LDAPExtendedFutureResultImpl<R>(
@@ -522,8 +513,8 @@
        if (!bindOrStartTLSInProgress.compareAndSet(false, true))
        {
          future.setResultOrError(request.getResultDecoder()
                .newExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
                    "Bind or Start TLS operation in progress"));
              .newExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
                  "Bind or Start TLS operation in progress"));
          return future;
        }
      }
@@ -532,8 +523,8 @@
        if (bindOrStartTLSInProgress.get())
        {
          future.setResultOrError(request.getResultDecoder()
                .newExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
                    "Bind or Start TLS operation in progress"));
              .newExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
                  "Bind or Start TLS operation in progress"));
          return future;
        }
      }
@@ -594,9 +585,9 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> modify(final ModifyRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> modifyAsync(final ModifyRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
@@ -652,9 +643,9 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> modifyDN(final ModifyDNRequest request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> modifyDNAsync(final ModifyDNRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
@@ -722,9 +713,9 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> search(final SearchRequest request,
      final SearchResultHandler resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler)
  public FutureResult<Result> searchAsync(final SearchRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final SearchResultHandler resultHandler)
  {
    final int messageID = nextMsgID.getAndIncrement();
    final LDAPSearchFutureResultImpl future = new LDAPSearchFutureResultImpl(
@@ -831,7 +822,7 @@
                .newResult(ResultCode.CLIENT_SIDE_TIMEOUT);
            future.adaptErrorResult(result);
            abandon(Requests.newAbandonRequest(future.getRequestID()));
            abandonAsync(Requests.newAbandonRequest(future.getRequestID()));
          }
          else
          {
@@ -853,7 +844,8 @@
    synchronized (stateLock)
    {
      if (isClosed) {
      if (isClosed)
      {
        // Already closed.
        return;
      }
@@ -1051,10 +1043,10 @@
    sslEngineConfigurator = new SSLEngineConfigurator(sslContext, true, false,
        false);
    sslEngineConfigurator.setEnabledProtocols(protocols.isEmpty() ?
        null : protocols.toArray(new String[protocols.size()]));
    sslEngineConfigurator.setEnabledCipherSuites(cipherSuites.isEmpty() ?
        null : cipherSuites.toArray(new String[cipherSuites.size()]));
    sslEngineConfigurator.setEnabledProtocols(protocols.isEmpty() ? null
        : protocols.toArray(new String[protocols.size()]));
    sslEngineConfigurator.setEnabledCipherSuites(cipherSuites.isEmpty() ? null
        : cipherSuites.toArray(new String[cipherSuites.size()]));
    sslFilter = new SSLFilter(null, sslEngineConfigurator);
    installFilter(sslFilter);
    sslFilter.handshake(connection, completionHandler);
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java
@@ -44,14 +44,12 @@
import org.forgerock.opendj.ldap.responses.ExtendedResult;
import org.forgerock.opendj.ldap.responses.Result;
import org.glassfish.grizzly.CompletionHandler;
import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.EmptyCompletionHandler;
import org.glassfish.grizzly.filterchain.DefaultFilterChain;
import org.glassfish.grizzly.filterchain.FilterChain;
import org.glassfish.grizzly.filterchain.TransportFilter;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import com.forgerock.opendj.util.AbstractConnectionFactory;
import com.forgerock.opendj.util.CompletedFutureResult;
import com.forgerock.opendj.util.FutureResultTransformer;
import com.forgerock.opendj.util.RecursiveFutureResult;
@@ -61,25 +59,22 @@
/**
 * LDAP connection factory implementation.
 */
public final class LDAPConnectionFactoryImpl extends AbstractConnectionFactory
    implements ConnectionFactory
public final class LDAPConnectionFactoryImpl implements ConnectionFactory
{
  @SuppressWarnings("rawtypes")
  private final class FutureResultImpl implements CompletionHandler<Connection>
  private final class FutureResultImpl implements
      CompletionHandler<org.glassfish.grizzly.Connection>
  {
    private final FutureResultTransformer<Result, AsynchronousConnection> futureStartTLSResult;
    private final FutureResultTransformer<Result, Connection> futureStartTLSResult;
    private final RecursiveFutureResult<LDAPConnection, ExtendedResult> futureConnectionResult;
    private LDAPConnection connection;
    private FutureResultImpl(
        final ResultHandler<? super AsynchronousConnection> handler)
    private FutureResultImpl(final ResultHandler<? super Connection> handler)
    {
      this.futureStartTLSResult = new FutureResultTransformer<Result, AsynchronousConnection>(
      this.futureStartTLSResult = new FutureResultTransformer<Result, Connection>(
          handler)
      {
@@ -129,13 +124,11 @@
          {
            final StartTLSExtendedRequest startTLS = Requests
                .newStartTLSExtendedRequest(options.getSSLContext());
            startTLS.addEnabledCipherSuite(
                options.getEnabledCipherSuites().toArray(
                    new String[options.getEnabledCipherSuites().size()]));
            startTLS.addEnabledProtocol(
                options.getEnabledProtocols().toArray(
                    new String[options.getEnabledProtocols().size()]));
            return connection.extendedRequest(startTLS, handler);
            startTLS.addEnabledCipherSuite(options.getEnabledCipherSuites()
                .toArray(new String[options.getEnabledCipherSuites().size()]));
            startTLS.addEnabledProtocol(options.getEnabledProtocols().toArray(
                new String[options.getEnabledProtocols().size()]));
            return connection.extendedRequestAsync(startTLS, null, handler);
          }
          if (options.getSSLContext() != null)
@@ -167,8 +160,7 @@
            }
            catch (final IOException ioe)
            {
              throw newErrorResult(
                  ResultCode.CLIENT_SIDE_CONNECT_ERROR,
              throw newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR,
                  ioe.getMessage(), ioe);
            }
          }
@@ -187,6 +179,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public void cancelled()
    {
      // Ignore this.
@@ -197,7 +190,8 @@
    /**
     * {@inheritDoc}
     */
    public void completed(final Connection connection)
    @Override
    public void completed(final org.glassfish.grizzly.Connection connection)
    {
      futureConnectionResult.handleResult(adaptConnection(connection));
    }
@@ -207,6 +201,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public void failed(final Throwable throwable)
    {
      futureConnectionResult
@@ -218,7 +213,8 @@
    /**
     * {@inheritDoc}
     */
    public void updated(final Connection connection)
    @Override
    public void updated(final org.glassfish.grizzly.Connection connection)
    {
      // Ignore this.
    }
@@ -228,13 +224,9 @@
  private final SocketAddress socketAddress;
  private final TCPNIOTransport transport;
  private final FilterChain defaultFilterChain;
  private final LDAPClientFilter clientFilter;
  private final LDAPOptions options;
@@ -275,8 +267,20 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> handler)
  public Connection getConnection() throws ErrorResultException,
      InterruptedException
  {
    return getConnectionAsync(null).get();
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> handler)
  {
    final FutureResultImpl future = new FutureResultImpl(handler);
@@ -289,7 +293,7 @@
    catch (final IOException e)
    {
      final ErrorResultException result = adaptConnectionException(e);
      return new CompletedFutureResult<AsynchronousConnection>(result);
      return new CompletedFutureResult<Connection>(result);
    }
  }
@@ -310,6 +314,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public String toString()
  {
    final StringBuilder builder = new StringBuilder();
@@ -321,7 +326,8 @@
  private LDAPConnection adaptConnection(final Connection<?> connection)
  private LDAPConnection adaptConnection(
      final org.glassfish.grizzly.Connection<?> connection)
  {
    // Test shows that its much faster with non block writes but risk
    // running out of memory if the server is slow.
@@ -343,7 +349,7 @@
      t = t.getCause();
    }
    return newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR,
        t.getMessage(), t);
    return newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR, t.getMessage(),
        t);
  }
}
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPExtendedFutureResultImpl.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap;
@@ -53,7 +54,7 @@
      final ExtendedRequest<R> request,
      final ResultHandler<? super R> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler,
      final AsynchronousConnection connection)
      final Connection connection)
  {
    super(requestID, resultHandler, intermediateResponseHandler, connection);
    this.request = request;
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPFutureResultImpl.java
@@ -23,13 +23,14 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap;
import org.forgerock.opendj.ldap.AsynchronousConnection;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.IntermediateResponseHandler;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.ResultHandler;
@@ -51,7 +52,7 @@
  LDAPFutureResultImpl(final int requestID, final Request request,
      final ResultHandler<? super Result> resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler,
      final AsynchronousConnection connection)
      final Connection connection)
  {
    super(requestID, resultHandler, intermediateResponseHandler, connection);
    this.request = request;
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPSearchFutureResultImpl.java
@@ -23,13 +23,14 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap;
import org.forgerock.opendj.ldap.AsynchronousConnection;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.IntermediateResponseHandler;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchResultHandler;
@@ -57,7 +58,7 @@
  LDAPSearchFutureResultImpl(final int requestID, final SearchRequest request,
      final SearchResultHandler resultHandler,
      final IntermediateResponseHandler intermediateResponseHandler,
      final AsynchronousConnection connection)
      final Connection connection)
  {
    super(requestID, resultHandler, intermediateResponseHandler, connection);
    this.request = request;
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/AbstractConnectionFactory.java
File was deleted
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/AsynchronousConnectionDecorator.java
File was deleted
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/ConnectionDecorator.java
New file
@@ -0,0 +1,766 @@
/*
 * 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 2011 ForgeRock AS
 */
package com.forgerock.opendj.util;
import java.util.Collection;
import java.util.concurrent.BlockingQueue;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.*;
import org.forgerock.opendj.ldap.requests.*;
import org.forgerock.opendj.ldap.responses.*;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
/**
 * A base class from which connection decorators may be easily implemented. The
 * default implementation of each method is to delegate to the decorated
 * connection.
 */
public abstract class ConnectionDecorator implements Connection
{
  /**
   * The decorated connection.
   */
  protected final Connection connection;
  /**
   * Creates a new connection decorator.
   *
   * @param connection
   *          The connection to be decorated.
   */
  protected ConnectionDecorator(final Connection connection)
  {
    Validator.ensureNotNull(connection);
    this.connection = connection;
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<Void> abandonAsync(final AbandonRequest request)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.abandonAsync(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result add(final AddRequest request) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.add(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result add(final Entry entry) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.add(entry);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result add(final String... ldifLines) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      LocalizedIllegalArgumentException, IllegalStateException,
      NullPointerException
  {
    return connection.add(ldifLines);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<Result> addAsync(final AddRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.addAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public void addConnectionEventListener(final ConnectionEventListener listener)
      throws IllegalStateException, NullPointerException
  {
    connection.addConnectionEventListener(listener);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public BindResult bind(final BindRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.bind(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public BindResult bind(final String name, final char[] password)
      throws ErrorResultException, InterruptedException,
      LocalizedIllegalArgumentException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.bind(name, password);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<BindResult> bindAsync(final BindRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super BindResult> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.bindAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public void close()
  {
    connection.close();
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public void close(final UnbindRequest request, final String reason)
      throws NullPointerException
  {
    connection.close(request, reason);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public CompareResult compare(final CompareRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.compare(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public CompareResult compare(final String name,
      final String attributeDescription, final String assertionValue)
      throws ErrorResultException, InterruptedException,
      LocalizedIllegalArgumentException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.compare(name, attributeDescription, assertionValue);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<CompareResult> compareAsync(final CompareRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super CompareResult> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.compareAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result delete(final DeleteRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.delete(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result delete(final String name) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.delete(name);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<Result> deleteAsync(final DeleteRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.deleteAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public <R extends ExtendedResult> R extendedRequest(
      final ExtendedRequest<R> request) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.extendedRequest(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public <R extends ExtendedResult> R extendedRequest(
      final ExtendedRequest<R> request,
      final IntermediateResponseHandler handler) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.extendedRequest(request, handler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public GenericExtendedResult extendedRequest(final String requestName,
      final ByteString requestValue) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.extendedRequest(requestName, requestValue);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public <R extends ExtendedResult> FutureResult<R> extendedRequestAsync(
      final ExtendedRequest<R> request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super R> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.extendedRequestAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public boolean isClosed()
  {
    return connection.isClosed();
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public boolean isValid()
  {
    return connection.isValid();
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result modify(final ModifyRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.modify(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result modify(final String... ldifLines) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      LocalizedIllegalArgumentException, IllegalStateException,
      NullPointerException
  {
    return connection.modify(ldifLines);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<Result> modifyAsync(final ModifyRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.modifyAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result modifyDN(final ModifyDNRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.modifyDN(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result modifyDN(final String name, final String newRDN)
      throws ErrorResultException, LocalizedIllegalArgumentException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.modifyDN(name, newRDN);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<Result> modifyDNAsync(final ModifyDNRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.modifyDNAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public SearchResultEntry readEntry(final DN name,
      final String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.readEntry(name, attributeDescriptions);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public SearchResultEntry readEntry(final String name,
      final String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.readEntry(name, attributeDescriptions);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<SearchResultEntry> readEntryAsync(final DN name,
      final Collection<String> attributeDescriptions,
      final ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.readEntryAsync(name, attributeDescriptions, handler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public void removeConnectionEventListener(
      final ConnectionEventListener listener) throws NullPointerException
  {
    connection.removeConnectionEventListener(listener);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public ConnectionEntryReader search(final SearchRequest request,
      final BlockingQueue<Response> entries)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.search(request, entries);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result search(final SearchRequest request,
      final Collection<? super SearchResultEntry> entries)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.search(request, entries);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result search(final SearchRequest request,
      final Collection<? super SearchResultEntry> entries,
      final Collection<? super SearchResultReference> references)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.search(request, entries, references);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public Result search(final SearchRequest request,
      final SearchResultHandler handler) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return connection.search(request, handler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public ConnectionEntryReader search(final String baseObject,
      final SearchScope scope, final String filter,
      final String... attributeDescriptions)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.search(baseObject, scope, filter, attributeDescriptions);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<Result> searchAsync(final SearchRequest request,
      final IntermediateResponseHandler intermediateResponseHandler,
      final SearchResultHandler resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.searchAsync(request, intermediateResponseHandler,
        resultHandler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public SearchResultEntry searchSingleEntry(final SearchRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.searchSingleEntry(request);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public SearchResultEntry searchSingleEntry(final String baseObject,
      final SearchScope scope, final String filter,
      final String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.searchSingleEntry(baseObject, scope, filter,
        attributeDescriptions);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public FutureResult<SearchResultEntry> searchSingleEntryAsync(
      final SearchRequest request,
      final ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return connection.searchSingleEntryAsync(request, handler);
  }
  /**
   * {@inheritDoc}
   * <p>
   * The default implementation is to delegate.
   */
  @Override
  public String toString()
  {
    return connection.toString();
  }
}
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/SynchronousConnection.java
File was deleted
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnection.java
@@ -30,192 +30,23 @@
import static org.forgerock.opendj.ldap.CoreMessages.*;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.forgerock.opendj.ldap.requests.*;
import org.forgerock.opendj.ldap.responses.*;
import com.forgerock.opendj.util.SynchronousConnection;
import org.forgerock.opendj.ldap.responses.BindResult;
import org.forgerock.opendj.ldap.responses.CompareResult;
import org.forgerock.opendj.ldap.responses.ExtendedResult;
import org.forgerock.opendj.ldap.responses.Result;
/**
 * This class provides a skeletal implementation of the
 * {@code AsynchronousConnection} interface, to minimize the effort required to
 * implement this interface.
 * An abstract connection whose synchronous methods are implemented in terms of
 * asynchronous methods.
 */
public abstract class AbstractAsynchronousConnection implements
    AsynchronousConnection
public abstract class AbstractAsynchronousConnection extends AbstractConnection
{
  private static final class SingleEntryFuture implements
      FutureResult<SearchResultEntry>, SearchResultHandler
  {
    private final ResultHandler<? super SearchResultEntry> handler;
    private volatile SearchResultEntry firstEntry = null;
    private volatile SearchResultReference firstReference = null;
    private volatile int entryCount = 0;
    private volatile FutureResult<Result> future = null;
    private SingleEntryFuture(
        final ResultHandler<? super SearchResultEntry> handler)
    {
      this.handler = handler;
    }
    public boolean cancel(final boolean mayInterruptIfRunning)
    {
      return future.cancel(mayInterruptIfRunning);
    }
    public SearchResultEntry get() throws ErrorResultException,
        InterruptedException
    {
      future.get();
      return get0();
    }
    public SearchResultEntry get(final long timeout, final TimeUnit unit)
        throws ErrorResultException, TimeoutException, InterruptedException
    {
      future.get(timeout, unit);
      return get0();
    }
    public int getRequestID()
    {
      return future.getRequestID();
    }
    public boolean handleEntry(final SearchResultEntry entry)
    {
      if (firstEntry == null)
      {
        firstEntry = entry;
      }
      entryCount++;
      return true;
    }
    public void handleErrorResult(final ErrorResultException error)
    {
      if (handler != null)
      {
        handler.handleErrorResult(error);
      }
    }
    public boolean handleReference(final SearchResultReference reference)
    {
      if (firstReference == null)
      {
        firstReference = reference;
      }
      return true;
    }
    public void handleResult(final Result result)
    {
      if (handler != null)
      {
        try
        {
          handler.handleResult(get0());
        }
        catch (final ErrorResultException e)
        {
          handler.handleErrorResult(e);
        }
      }
    }
    public boolean isCancelled()
    {
      return future.isCancelled();
    }
    public boolean isDone()
    {
      return future.isDone();
    }
    private SearchResultEntry get0() throws ErrorResultException
    {
      if (entryCount == 0)
      {
        // Did not find any entries.
        throw newErrorResult(
            ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
            ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
      }
      else if (entryCount > 1)
      {
        // Got more entries than expected.
        throw newErrorResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
            ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(entryCount)
                .toString());
      }
      else if (firstReference != null)
      {
        // Got an unexpected search result reference.
        throw newErrorResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
            ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
                firstReference.getURIs().iterator().next())
                .toString());
      }
      else
      {
        return firstEntry;
      }
    }
    private void setResultFuture(final FutureResult<Result> future)
    {
      this.future = future;
    }
  }
  /**
   * Creates a new abstract connection.
   * Creates a new abstract asynchronous connection.
   */
  protected AbstractAsynchronousConnection()
  {
@@ -227,142 +58,21 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> add(final AddRequest request,
      final ResultHandler<? super Result> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return add(request, handler, null);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<BindResult> bind(final BindRequest request,
      final ResultHandler<? super BindResult> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return bind(request, handler, null);
  }
  /**
   * {@inheritDoc}
   */
  public void close()
  {
    close(Requests.newUnbindRequest(), null);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<CompareResult> compare(final CompareRequest request,
      final ResultHandler<? super CompareResult> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return compare(request, handler, null);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> delete(final DeleteRequest request,
      final ResultHandler<? super Result> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return delete(request, handler, null);
  }
  /**
   * {@inheritDoc}
   */
  public <R extends ExtendedResult> FutureResult<R> extendedRequest(
      final ExtendedRequest<R> request, final ResultHandler<? super R> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return extendedRequest(request, handler, null);
  }
  /**
   * {@inheritDoc}
   */
  public Connection getSynchronousConnection()
  {
    return new SynchronousConnection(this);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> modify(final ModifyRequest request,
      final ResultHandler<? super Result> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return modify(request, handler, null);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> modifyDN(final ModifyDNRequest request,
      final ResultHandler<? super Result> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return modifyDN(request, handler, null);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<SearchResultEntry> readEntry(final DN name,
      final Collection<String> attributeDescriptions,
      final ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SearchRequest request = Requests.newSearchRequest(name,
        SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter());
    if (attributeDescriptions != null)
    {
      request.getAttributes().addAll(attributeDescriptions);
    }
    return searchSingleEntry(request, handler);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> search(final SearchRequest request,
      final SearchResultHandler handler) throws UnsupportedOperationException,
  @Override
  public Result add(final AddRequest request) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return search(request, handler, null);
    final FutureResult<Result> future = addAsync(request, null, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
@@ -370,26 +80,161 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<SearchResultEntry> searchSingleEntry(
      final SearchRequest request,
      final ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
  @Override
  public BindResult bind(final BindRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SingleEntryFuture innerFuture = new SingleEntryFuture(handler);
    final FutureResult<Result> future = search(request, innerFuture);
    innerFuture.setResultFuture(future);
    return innerFuture;
    final FutureResult<BindResult> future = bindAsync(request, null, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
  /**
   * {@inheritDoc}
   * <p>
   * Sub-classes should provide an implementation which returns an appropriate
   * description of the connection which may be used for debugging purposes.
   */
  public abstract String toString();
  @Override
  public CompareResult compare(final CompareRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final FutureResult<CompareResult> future = compareAsync(request, null, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Result delete(final DeleteRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final FutureResult<Result> future = deleteAsync(request, null, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public <R extends ExtendedResult> R extendedRequest(
      final ExtendedRequest<R> request,
      final IntermediateResponseHandler handler) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    final FutureResult<R> future = extendedRequestAsync(request, handler, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Result modify(final ModifyRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final FutureResult<Result> future = modifyAsync(request, null, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Result modifyDN(final ModifyDNRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final FutureResult<Result> future = modifyDNAsync(request, null, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Result search(final SearchRequest request,
      final SearchResultHandler handler) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    final FutureResult<Result> future = searchAsync(request, null, handler);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnection.java
@@ -38,10 +38,11 @@
import java.util.Collection;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.requests.*;
import org.forgerock.opendj.ldap.responses.*;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
@@ -56,16 +57,66 @@
public abstract class AbstractConnection implements Connection
{
  private static final class SingleEntryHandler implements SearchResultHandler
  private static final class SingleEntryFuture implements
      FutureResult<SearchResultEntry>, SearchResultHandler
  {
    private final ResultHandler<? super SearchResultEntry> handler;
    private volatile SearchResultEntry firstEntry = null;
    private volatile SearchResultReference firstReference = null;
    private volatile int entryCount = 0;
    private volatile FutureResult<Result> future = null;
    private SingleEntryFuture(
        final ResultHandler<? super SearchResultEntry> handler)
    {
      this.handler = handler;
    }
    @Override
    public boolean cancel(final boolean mayInterruptIfRunning)
    {
      return future.cancel(mayInterruptIfRunning);
    }
    @Override
    public SearchResultEntry get() throws ErrorResultException,
        InterruptedException
    {
      future.get();
      return get0();
    }
    @Override
    public SearchResultEntry get(final long timeout, final TimeUnit unit)
        throws ErrorResultException, TimeoutException, InterruptedException
    {
      future.get(timeout, unit);
      return get0();
    }
    @Override
    public int getRequestID()
    {
      return future.getRequestID();
    }
    @Override
    public boolean handleEntry(final SearchResultEntry entry)
    {
      if (firstEntry == null)
@@ -78,6 +129,137 @@
    @Override
    public void handleErrorResult(final ErrorResultException error)
    {
      if (handler != null)
      {
        handler.handleErrorResult(error);
      }
    }
    @Override
    public boolean handleReference(final SearchResultReference reference)
    {
      if (firstReference == null)
      {
        firstReference = reference;
      }
      return true;
    }
    @Override
    public void handleResult(final Result result)
    {
      if (handler != null)
      {
        try
        {
          handler.handleResult(get0());
        }
        catch (final ErrorResultException e)
        {
          handler.handleErrorResult(e);
        }
      }
    }
    @Override
    public boolean isCancelled()
    {
      return future.isCancelled();
    }
    @Override
    public boolean isDone()
    {
      return future.isDone();
    }
    private SearchResultEntry get0() throws ErrorResultException
    {
      if (entryCount == 0)
      {
        // Did not find any entries.
        throw newErrorResult(ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
            ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
      }
      else if (entryCount > 1)
      {
        // Got more entries than expected.
        throw newErrorResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
            ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(entryCount).toString());
      }
      else if (firstReference != null)
      {
        // Got an unexpected search result reference.
        throw newErrorResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
            ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
                firstReference.getURIs().iterator().next()).toString());
      }
      else
      {
        return firstEntry;
      }
    }
    private void setResultFuture(final FutureResult<Result> future)
    {
      this.future = future;
    }
  }
  private static final class SingleEntryHandler implements SearchResultHandler
  {
    private volatile SearchResultEntry firstEntry = null;
    private volatile SearchResultReference firstReference = null;
    private volatile int entryCount = 0;
    @Override
    public boolean handleEntry(final SearchResultEntry entry)
    {
      if (firstEntry == null)
      {
        firstEntry = entry;
      }
      entryCount++;
      return true;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleErrorResult(final ErrorResultException error)
    {
      // Ignore.
    }
    @Override
    public boolean handleReference(final SearchResultReference reference)
    {
      if (firstReference == null)
@@ -92,17 +274,8 @@
    /**
     * {@inheritDoc}
     */
    public void handleErrorResult(ErrorResultException error)
    {
      // Ignore.
    }
    /**
     * {@inheritDoc}
     */
    public void handleResult(Result result)
    @Override
    public void handleResult(final Result result)
    {
      // Ignore.
    }
@@ -124,6 +297,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public Result add(final Entry entry) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
@@ -136,6 +310,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public Result add(final String... ldifLines) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      LocalizedIllegalArgumentException, IllegalStateException,
@@ -149,6 +324,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public BindResult bind(final String name, final char[] password)
      throws ErrorResultException, InterruptedException,
      LocalizedIllegalArgumentException, UnsupportedOperationException,
@@ -162,6 +338,18 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public void close()
  {
    close(Requests.newUnbindRequest(), null);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public CompareResult compare(final String name,
      final String attributeDescription, final String assertionValue)
      throws ErrorResultException, InterruptedException,
@@ -177,6 +365,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public Result delete(final String name) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
@@ -190,6 +379,21 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public <R extends ExtendedResult> R extendedRequest(
      final ExtendedRequest<R> request) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    return extendedRequest(request, null);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public GenericExtendedResult extendedRequest(final String requestName,
      final ByteString requestValue) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
@@ -204,6 +408,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public Result modify(final String... ldifLines) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      LocalizedIllegalArgumentException, IllegalStateException,
@@ -217,6 +422,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public Result modifyDN(final String name, final String newRDN)
      throws ErrorResultException, InterruptedException,
      LocalizedIllegalArgumentException, UnsupportedOperationException,
@@ -230,6 +436,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public SearchResultEntry readEntry(final DN baseObject,
      final String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
@@ -246,6 +453,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public SearchResultEntry readEntry(final String baseObject,
      final String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
@@ -260,6 +468,42 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<SearchResultEntry> readEntryAsync(final DN name,
      final Collection<String> attributeDescriptions,
      final ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SearchRequest request = Requests.newSearchRequest(name,
        SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter());
    if (attributeDescriptions != null)
    {
      request.getAttributes().addAll(attributeDescriptions);
    }
    return searchSingleEntryAsync(request, handler);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public ConnectionEntryReader search(final SearchRequest request,
      final BlockingQueue<Response> entries)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return new ConnectionEntryReader(this, request, entries);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Result search(final SearchRequest request,
      final Collection<? super SearchResultEntry> entries)
      throws ErrorResultException, InterruptedException,
@@ -274,6 +518,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public Result search(final SearchRequest request,
      final Collection<? super SearchResultEntry> entries,
      final Collection<? super SearchResultReference> references)
@@ -287,6 +532,7 @@
    final SearchResultHandler handler = new SearchResultHandler()
    {
      @Override
      public boolean handleEntry(final SearchResultEntry entry)
      {
        entries.add(entry);
@@ -295,6 +541,18 @@
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleErrorResult(final ErrorResultException error)
      {
        // Ignore.
      }
      @Override
      public boolean handleReference(final SearchResultReference reference)
      {
        if (references != null)
@@ -309,17 +567,8 @@
      /**
       * {@inheritDoc}
       */
      public void handleErrorResult(ErrorResultException error)
      {
        // Ignore.
      }
      /**
       * {@inheritDoc}
       */
      public void handleResult(Result result)
      @Override
      public void handleResult(final Result result)
      {
        // Ignore.
      }
@@ -333,6 +582,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public ConnectionEntryReader search(final String baseObject,
      final SearchScope scope, final String filter,
      final String... attributeDescriptions)
@@ -350,6 +600,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public SearchResultEntry searchSingleEntry(final SearchRequest request)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
@@ -361,17 +612,15 @@
    if (handler.entryCount == 0)
    {
      // Did not find any entries.
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
      throw newErrorResult(ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
          ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
    }
    else if (handler.entryCount > 1)
    {
      // Got more entries than expected.
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
          ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES
              .get(handler.entryCount).toString());
      throw newErrorResult(ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
          ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(handler.entryCount)
              .toString());
    }
    else if (handler.firstReference != null)
    {
@@ -379,8 +628,7 @@
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
          ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
              handler.firstReference.getURIs().iterator().next())
              .toString());
              handler.firstReference.getURIs().iterator().next()).toString());
    }
    else
    {
@@ -393,6 +641,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public SearchResultEntry searchSingleEntry(final String baseObject,
      final SearchScope scope, final String filter,
      final String... attributeDescriptions) throws ErrorResultException,
@@ -409,10 +658,29 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<SearchResultEntry> searchSingleEntryAsync(
      final SearchRequest request,
      final ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SingleEntryFuture innerFuture = new SingleEntryFuture(handler);
    final FutureResult<Result> future = searchAsync(request, null, innerFuture);
    innerFuture.setResultFuture(future);
    return innerFuture;
  }
  /**
   * {@inheritDoc}
   * <p>
   * Sub-classes should provide an implementation which returns an appropriate
   * description of the connection which may be used for debugging purposes.
   */
  @Override
  public abstract String toString();
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractLoadBalancingAlgorithm.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -40,7 +41,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import com.forgerock.opendj.util.AbstractConnectionFactory;
import com.forgerock.opendj.util.AsynchronousFutureResult;
import com.forgerock.opendj.util.StaticUtils;
import com.forgerock.opendj.util.Validator;
@@ -57,9 +57,8 @@
 */
abstract class AbstractLoadBalancingAlgorithm implements LoadBalancingAlgorithm
{
  private final class MonitoredConnectionFactory extends
      AbstractConnectionFactory implements
      ResultHandler<AsynchronousConnection>
  private final class MonitoredConnectionFactory implements ConnectionFactory,
      ResultHandler<Connection>
  {
    private final ConnectionFactory factory;
@@ -84,28 +83,53 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<AsynchronousConnection> getAsynchronousConnection(
        final ResultHandler<? super AsynchronousConnection> resultHandler)
    public Connection getConnection() throws ErrorResultException,
        InterruptedException
    {
      final AsynchronousFutureResult<AsynchronousConnection> future =
        new AsynchronousFutureResult<AsynchronousConnection>(resultHandler);
      final Connection connection;
      try
      {
        connection = factory.getConnection();
      }
      catch (ErrorResultException e)
      {
        // Attempt failed - try next factory.
        notifyOffline(e);
        final int nextIndex = (index + 1) % monitoredFactories.size();
        final MonitoredConnectionFactory nextFactory =
            getMonitoredConnectionFactory(nextIndex);
        return nextFactory.getConnection();
      }
      notifyOnline();
      return connection;
    }
      final ResultHandler<AsynchronousConnection> failoverHandler =
        new ResultHandler<AsynchronousConnection>()
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Connection> getConnectionAsync(
        final ResultHandler<? super Connection> resultHandler)
    {
      final AsynchronousFutureResult<Connection> future =
        new AsynchronousFutureResult<Connection>(resultHandler);
      final ResultHandler<Connection> failoverHandler =
        new ResultHandler<Connection>()
      {
        @Override
        public void handleErrorResult(final ErrorResultException error)
        {
          // Attempt failed - try next factory.
          notifyOffline(error);
          final int nextIndex = (index + 1) % monitoredFactories.size();
          try
          {
            final MonitoredConnectionFactory nextFactory =
              getMonitoredConnectionFactory(nextIndex);
            nextFactory.getAsynchronousConnection(future);
            nextFactory.getConnectionAsync(future);
          }
          catch (final ErrorResultException e)
          {
@@ -116,14 +140,14 @@
        @Override
        public void handleResult(final AsynchronousConnection result)
        public void handleResult(final Connection result)
        {
          notifyOnline();
          future.handleResult(result);
        }
      };
      factory.getAsynchronousConnection(failoverHandler);
      factory.getConnectionAsync(failoverHandler);
      return future;
    }
@@ -144,7 +168,7 @@
     * Handle monitoring connection request success.
     */
    @Override
    public void handleResult(final AsynchronousConnection connection)
    public void handleResult(final Connection connection)
    {
      notifyOnline();
@@ -179,7 +203,7 @@
          StaticUtils.DEBUG_LOG.fine(String
              .format("Attempting reconnect to offline factory " + this));
        }
        pendingConnectFuture = factory.getAsynchronousConnection(this);
        pendingConnectFuture = factory.getConnectionAsync(this);
      }
    }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AsynchronousConnection.java
File was deleted
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java
@@ -23,17 +23,18 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.requests.BindRequest;
import org.forgerock.opendj.ldap.responses.BindResult;
import com.forgerock.opendj.util.AbstractConnectionFactory;
import com.forgerock.opendj.util.AsynchronousConnectionDecorator;
import com.forgerock.opendj.util.ConnectionDecorator;
import com.forgerock.opendj.util.FutureResultTransformer;
import com.forgerock.opendj.util.RecursiveFutureResult;
@@ -51,19 +52,16 @@
 * the connection attempt will fail and an {@code ErrorResultException} will be
 * thrown.
 */
final class AuthenticatedConnectionFactory extends AbstractConnectionFactory
final class AuthenticatedConnectionFactory implements ConnectionFactory
{
  /**
   * An authenticated asynchronous connection supports all operations except
   * Bind operations.
   * An authenticated connection supports all operations except Bind operations.
   */
  public static final class AuthenticatedAsynchronousConnection extends
      AsynchronousConnectionDecorator
  public static final class AuthenticatedConnection extends ConnectionDecorator
  {
    private AuthenticatedAsynchronousConnection(
        final AsynchronousConnection connection)
    private AuthenticatedConnection(final Connection connection)
    {
      super(connection);
    }
@@ -74,8 +72,13 @@
     * Bind operations are not supported by pre-authenticated connections. This
     * method will always throw {@code UnsupportedOperationException}.
     */
    public FutureResult<BindResult> bind(final BindRequest request,
        final ResultHandler<? super BindResult> handler)
    /**
     * {@inheritDoc}
     */
    public FutureResult<BindResult> bindAsync(final BindRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
@@ -85,14 +88,24 @@
    /**
     * Bind operations are not supported by pre-authenticated connections. This
     * method will always throw {@code UnsupportedOperationException}.
     * {@inheritDoc}
     */
    public FutureResult<BindResult> bind(final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    public BindResult bind(BindRequest request) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      throw new UnsupportedOperationException();
    }
    /**
     * {@inheritDoc}
     */
    public BindResult bind(String name, char[] password)
        throws ErrorResultException, InterruptedException,
        LocalizedIllegalArgumentException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      throw new UnsupportedOperationException();
    }
@@ -117,21 +130,21 @@
  private static final class FutureResultImpl
  {
    private final FutureResultTransformer<BindResult, AsynchronousConnection> futureBindResult;
    private final FutureResultTransformer<BindResult, Connection> futureBindResult;
    private final RecursiveFutureResult<AsynchronousConnection, BindResult> futureConnectionResult;
    private final RecursiveFutureResult<Connection, BindResult> futureConnectionResult;
    private final BindRequest bindRequest;
    private AsynchronousConnection connection;
    private Connection connection;
    private FutureResultImpl(final BindRequest request,
        final ResultHandler<? super AsynchronousConnection> handler)
        final ResultHandler<? super Connection> handler)
    {
      this.bindRequest = request;
      this.futureBindResult = new FutureResultTransformer<BindResult, AsynchronousConnection>(
      this.futureBindResult = new FutureResultTransformer<BindResult, Connection>(
          handler)
      {
@@ -140,40 +153,33 @@
            final ErrorResultException errorResult)
        {
          // Ensure that the connection is closed.
          try
          {
            connection.close();
            connection = null;
          }
          catch (final Exception e)
          {
            // Ignore.
          }
          connection.close();
          connection = null;
          return errorResult;
        }
        @Override
        protected AsynchronousConnection transformResult(final BindResult result)
        protected Connection transformResult(final BindResult result)
            throws ErrorResultException
        {
          return new AuthenticatedAsynchronousConnection(connection);
          return new AuthenticatedConnection(connection);
        }
      };
      this.futureConnectionResult = new RecursiveFutureResult<AsynchronousConnection, BindResult>(
      this.futureConnectionResult = new RecursiveFutureResult<Connection, BindResult>(
          futureBindResult)
      {
        @Override
        protected FutureResult<? extends BindResult> chainResult(
            final AsynchronousConnection innerResult,
            final Connection innerResult,
            final ResultHandler<? super BindResult> handler)
            throws ErrorResultException
        {
          connection = innerResult;
          return connection.bind(bindRequest, handler);
          return connection.bindAsync(bindRequest, null, handler);
        }
      };
      futureBindResult.setFutureResult(futureConnectionResult);
@@ -214,13 +220,40 @@
  /**
   * {@inheritDoc}
   */
  public Connection getConnection() throws ErrorResultException,
      InterruptedException
  {
    final Connection connection = parentFactory.getConnection();
    boolean bindSucceeded = false;
    try
    {
      connection.bind(request);
      bindSucceeded = true;
    }
    finally
    {
      if (!bindSucceeded)
      {
        connection.close();
      }
    }
    // If the bind didn't succeed then an exception will have been thrown and
    // this line will not be reached.
    return new AuthenticatedConnection(connection);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> handler)
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> handler)
  {
    final FutureResultImpl future = new FutureResultImpl(request, handler);
    future.futureConnectionResult.setFutureResult(parentFactory
        .getAsynchronousConnection(future.futureConnectionResult));
        .getConnectionAsync(future.futureConnectionResult));
    return future.futureBindResult;
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connection.java
@@ -42,17 +42,78 @@
/**
 * A synchronous connection with a Directory Server over which read and update
 * operations may be performed. See RFC 4511 for the LDAPv3 protocol
 * specification and more information about the types of operations defined in
 * LDAP.
 * A connection with a Directory Server over which read and update operations
 * may be performed. See RFC 4511 for the LDAPv3 protocol specification and more
 * information about the types of operations defined in LDAP.
 * <p>
 * <h3>Operation processing</h3>
 * <p>
 * All operations are performed synchronously and return an appropriate
 * {@link Result} representing the final status of the operation. Operation
 * failures, for whatever reason, are signalled using an
 * {@link ErrorResultException}.
 * Operations may be performed synchronously or asynchronously depending on the
 * method chosen. Asynchronous methods can be identified by their {@code Async}
 * suffix.
 * <p>
 * <h4>Performing operations synchronously</h4>
 * <p>
 * Synchronous methods block until a response is received from the Directory
 * Server, at which point an appropriate {@link Result} object is returned if
 * the operation succeeded, or thrown as an {@link ErrorResultException} if the
 * operation failed.
 * <p>
 * Since synchronous operations block the calling thread, the only way to
 * abandon a long running operation is to interrupt the calling thread from
 * another thread. This will cause the calling thread unblock and throw an
 * {@link InterruptedException}.
 * <p>
 * <h4>Performing operations asynchronously</h4>
 * <p>
 * Asynchronous methods, identified by their {code Async} suffix, are
 * non-blocking, returning a {@link FutureResult} or sub-type thereof which can
 * be used for retrieving the result using the {@link FutureResult#get} method.
 * Operation failures, for whatever reason, are signalled by the
 * {@link FutureResult#get()} method throwing an {@link ErrorResultException}.
 * <p>
 * In addition to returning a {@code FutureResult}, all asynchronous methods
 * accept a {@link ResultHandler} which will be notified upon completion of the
 * operation.
 * <p>
 * Synchronous operations are easily simulated by immediately getting the
 * result:
 *
 * <pre>
 * Connection connection = ...;
 * AddRequest request = ...;
 * // Will block until operation completes, and
 * // throws exception on failure.
 * connection.add(request).get();
 * </pre>
 *
 * Operations can be performed in parallel while taking advantage of the
 * simplicity of a synchronous application design:
 *
 * <pre>
 * Connection connection1 = ...;
 * Connection connection2 = ...;
 * AddRequest request = ...;
 * // Add the entry to the first server (don't block).
 * FutureResult future1 = connection1.add(request);
 * // Add the entry to the second server (in parallel).
 * FutureResult future2 = connection2.add(request);
 * // Total time = is O(1) instead of O(n).
 * future1.get();
 * future2.get();
 * </pre>
 *
 * More complex client applications can take advantage of a fully asynchronous
 * event driven design using {@link ResultHandler}s:
 *
 * <pre>
 * Connection connection = ...;
 * SearchRequest request = ...;
 * // Process results in the search result handler
 * // in a separate thread.
 * SearchResponseHandler handle = ...;
 * connection.search(request, handler);
 * </pre>
 * <p>
 * <h3>Closing connections</h3>
 * <p>
@@ -80,6 +141,37 @@
{
  /**
   * Abandons the unfinished operation identified in the provided abandon
   * request.
   * <p>
   * Abandon requests do not have a response, so invoking the method get() on
   * the returned future will not block, nor return anything (it is Void), but
   * may throw an exception if a problem occurred while sending the abandon
   * request. In addition the returned future may be used in order to determine
   * the message ID of the abandon request.
   * <p>
   * <b>Note:</b> a more convenient approach to abandoning unfinished
   * asynchronous operations is provided via the
   * {@link FutureResult#cancel(boolean)} method.
   *
   * @param request
   *          The request identifying the operation to be abandoned.
   * @return A future whose result is Void.
   * @throws UnsupportedOperationException
   *           If this connection does not support abandon operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  FutureResult<Void> abandonAsync(AbandonRequest request)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Adds an entry to the Directory Server using the provided add request.
   *
   * @param request
@@ -93,8 +185,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support add operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -125,8 +217,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support add operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code entry} was {@code null} .
   */
@@ -161,8 +253,8 @@
   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
   *           could not be decoded using the default schema.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code ldifLines} was {@code null} .
   */
@@ -174,6 +266,35 @@
  /**
   * Asynchronously adds an entry to the Directory Server using the provided add
   * request.
   *
   * @param request
   *          The add request.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support add operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  FutureResult<Result> addAsync(AddRequest request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Registers the provided connection event listener so that it will be
   * notified when this connection is closed by the application, receives an
   * unsolicited notification, or experiences a fatal error.
@@ -182,8 +303,8 @@
   *          The listener which wants to be notified when events occur on this
   *          connection.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
@@ -206,8 +327,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support bind operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -245,8 +366,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support bind operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code name} or {@code password} was {@code null}.
   */
@@ -258,6 +379,35 @@
  /**
   * Asynchronously authenticates to the Directory Server using the provided
   * bind request.
   *
   * @param request
   *          The bind request.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support bind operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  FutureResult<BindResult> bindAsync(BindRequest request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super BindResult> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Releases any resources associated with this connection. For physical
   * connections to a Directory Server this will mean that an unbind request is
   * sent and the underlying socket is closed.
@@ -319,8 +469,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support compare operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -360,11 +510,11 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support compare operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code name}, {@code attributeDescription}, or {@code
   *           assertionValue} was {@code null}.
   *           If {@code name}, {@code attributeDescription}, or
   *           {@code assertionValue} was {@code null}.
   */
  CompareResult compare(String name, String attributeDescription,
      String assertionValue) throws ErrorResultException, InterruptedException,
@@ -374,6 +524,35 @@
  /**
   * Asynchronously compares an entry in the Directory Server using the provided
   * compare request.
   *
   * @param request
   *          The compare request.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support compare operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  FutureResult<CompareResult> compareAsync(CompareRequest request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super CompareResult> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Deletes an entry from the Directory Server using the provided delete
   * request.
   *
@@ -388,8 +567,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support delete operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -422,8 +601,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support delete operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code name} was {@code null}.
   */
@@ -434,6 +613,35 @@
  /**
   * Asynchronously deletes an entry from the Directory Server using the
   * provided delete request.
   *
   * @param request
   *          The delete request.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support delete operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  FutureResult<Result> deleteAsync(DeleteRequest request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Requests that the Directory Server performs the provided extended request.
   *
   * @param <R>
@@ -449,8 +657,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support extended operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -481,8 +689,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support extended operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -519,8 +727,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support extended operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code requestName} was {@code null}.
   */
@@ -532,13 +740,34 @@
  /**
   * Returns an asynchronous connection sharing the same underlying network
   * connection as this synchronous connection.
   * Asynchronously performs the provided extended request in the Directory
   * Server.
   *
   * @return An asynchronous connection sharing the same underlying network
   *         connection as this synchronous connection.
   * @param <R>
   *          The type of result returned by the extended request.
   * @param request
   *          The extended request.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support extended operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  AsynchronousConnection getAsynchronousConnection();
  <R extends ExtendedResult> FutureResult<R> extendedRequestAsync(
      ExtendedRequest<R> request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super R> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
@@ -556,9 +785,9 @@
  /**
   * Returns {@code true} if this connection has not been closed and no fatal
   * errors have been detected. This method is guaranteed to return {@code
   * false} only when it is called after the method {@code close} has been
   * called.
   * errors have been detected. This method is guaranteed to return
   * {@code false} only when it is called after the method {@code close} has
   * been called.
   *
   * @return {@code true} if this connection is valid, {@code false} otherwise.
   */
@@ -581,8 +810,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support modify operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -616,8 +845,8 @@
   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
   *           could not be decoded using the default schema.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code ldifLines} was {@code null} .
   */
@@ -629,6 +858,35 @@
  /**
   * Asynchronously modifies an entry in the Directory Server using the provided
   * modify request.
   *
   * @param request
   *          The modify request.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support modify operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  FutureResult<Result> modifyAsync(ModifyRequest request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Renames an entry in the Directory Server using the provided modify DN
   * request.
   *
@@ -643,8 +901,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support modify DN operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -680,8 +938,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support modify DN operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code name} or {@code newRDN} was {@code null}.
   */
@@ -693,6 +951,35 @@
  /**
   * Asynchronously renames an entry in the Directory Server using the provided
   * modify DN request.
   *
   * @param request
   *          The modify DN request.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support modify DN operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  FutureResult<Result> modifyDNAsync(ModifyDNRequest request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Reads the named entry from the Directory Server.
   * <p>
   * If the requested entry is not returned by the Directory Server then the
@@ -722,8 +1009,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code name} was {@code null}.
   */
@@ -765,8 +1052,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code name} was {@code null}.
   */
@@ -778,6 +1065,47 @@
  /**
   * Asynchronously reads the named entry from the Directory Server.
   * <p>
   * If the requested entry is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}. More
   * specifically, the returned future will never return {@code null}.
   * <p>
   * This method is equivalent to the following code:
   *
   * <pre>
   * SearchRequest request = new SearchRequest(name, SearchScope.BASE_OBJECT,
   *     &quot;(objectClass=*)&quot;, attributeDescriptions);
   * connection.searchSingleEntryAsync(request, resultHandler, p);
   * </pre>
   *
   * @param name
   *          The distinguished name of the entry to be read.
   * @param attributeDescriptions
   *          The names of the attributes to be included with the entry, which
   *          may be {@code null} or empty indicating that all user attributes
   *          should be returned.
   * @param handler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code name} was {@code null}.
   */
  FutureResult<SearchResultEntry> readEntryAsync(DN name,
      Collection<String> attributeDescriptions,
      ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Removes the provided connection event listener from this connection so that
   * it will no longer be notified when this connection is closed by the
   * application, receives an unsolicited notification, or experiences a fatal
@@ -795,6 +1123,34 @@
  /**
   * Searches the Directory Server using the provided search parameters. Any
   * matching entries returned by the search will be exposed through the
   * {@code EntryReader} interface.
   * <p>
   * <b>Warning:</b> When using a queue with an optional capacity bound, the
   * connection will stop reading responses and wait if necessary for space to
   * become available.
   *
   * @param request
   *          The search request.
   * @param entries
   *          The queue to which matching entries should be added.
   * @return The result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} or {@code entries} was {@code null}.
   */
  ConnectionEntryReader search(SearchRequest request,
      BlockingQueue<Response> entries) throws UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  /**
   * Searches the Directory Server using the provided search request. Any
   * matching entries returned by the search will be added to {@code entries},
   * even if the final search result indicates that the search failed. Search
@@ -802,8 +1158,8 @@
   * <p>
   * <b>Warning:</b> Usage of this method is discouraged if the search request
   * is expected to yield a large number of search results since the entire set
   * of results will be stored in memory, potentially causing an {@code
   * OutOfMemoryError}.
   * of results will be stored in memory, potentially causing an
   * {@code OutOfMemoryError}.
   * <p>
   * This method is equivalent to the following code:
   *
@@ -824,8 +1180,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} or {@code entries} was {@code null}.
   */
@@ -846,8 +1202,8 @@
   * <p>
   * <b>Warning:</b> Usage of this method is discouraged if the search request
   * is expected to yield a large number of search results since the entire set
   * of results will be stored in memory, potentially causing an {@code
   * OutOfMemoryError}.
   * of results will be stored in memory, potentially causing an
   * {@code OutOfMemoryError}.
   *
   * @param request
   *          The search request.
@@ -865,8 +1221,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} or {@code entries} was {@code null}.
   */
@@ -888,8 +1244,8 @@
   *          The search request.
   * @param handler
   *          A search result handler which can be used to process the search
   *          result entries and references as they are received, may be {@code
   *          null}.
   *          result entries and references as they are received, may be
   *          {@code null}.
   * @return The result of the operation.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for some
@@ -899,8 +1255,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
@@ -916,9 +1272,9 @@
   * matching entries returned by the search will be exposed through the
   * {@code EntryReader} interface.
   * <p>
   * <b>Warning:</b> When using a queue with an optional capacity bound,
   * the connection will stop reading responses and wait if necessary for
   * space to become available.
   * <b>Warning:</b> When using a queue with an optional capacity bound, the
   * connection will stop reading responses and wait if necessary for space to
   * become available.
   * <p>
   * This method is equivalent to the following code:
   *
@@ -942,44 +1298,46 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code baseObject}, {@code scope}, or {@code filter} were
   *           {@code null}.
   */
  ConnectionEntryReader search(String baseObject, SearchScope scope,
      String filter, String... attributeDescriptions)
      throws UnsupportedOperationException,
      IllegalStateException, NullPointerException;
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Searches the Directory Server using the provided search parameters. Any
   * matching entries returned by the search will be exposed through the
   * {@code EntryReader} interface.
   * <p>
   * <b>Warning:</b> When using a queue with an optional capacity bound,
   * the connection will stop reading responses and wait if necessary for
   * space to become available.
   * Asynchronously searches the Directory Server using the provided search
   * request.
   *
   * @param request
   *          The search request.
   * @param entries
   *          The queue to which matching entries should be added.
   * @return The result of the operation.
   * @param intermediateResponseHandler
   *          An intermediate response handler which can be used to process any
   *          intermediate responses as they are received, may be {@code null}.
   * @param resultHandler
   *          A search result handler which can be used to asynchronously
   *          process the search result entries and references as they are
   *          received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} or {@code entries} was {@code null}.
   *           If {@code request} was {@code null}.
   */
  ConnectionEntryReader search(SearchRequest request,
                               BlockingQueue<Response> entries)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  FutureResult<Result> searchAsync(SearchRequest request,
      IntermediateResponseHandler intermediateResponseHandler,
      SearchResultHandler resultHandler) throws UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  /**
@@ -1003,8 +1361,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code request} was {@code null}.
   */
@@ -1056,8 +1414,8 @@
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code baseObject}, {@code scope}, or {@code filter} were
   *           {@code null}.
@@ -1067,4 +1425,35 @@
      throws ErrorResultException, InterruptedException,
      LocalizedIllegalArgumentException, UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  /**
   * Asynchronously searches the Directory Server for a single entry using the
   * provided search request.
   * <p>
   * If the requested entry is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}. More
   * specifically, the returned future will never return {@code null}. If
   * multiple matching entries are returned by the Directory Server then the
   * request will fail with an {@link MultipleEntriesFoundException}.
   *
   * @param request
   *          The search request.
   * @param handler
   *          A result handler which can be used to asynchronously process the
   *          operation result when it is received, may be {@code null}.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code request} was {@code null}.
   */
  FutureResult<SearchResultEntry> searchSingleEntryAsync(SearchRequest request,
      ResultHandler<? super SearchResultEntry> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionFactory.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -54,19 +55,19 @@
public interface ConnectionFactory
{
  /**
   * Initiates an asynchronous connection request to the Directory Server
   * associated with this connection factory. The returned {@code FutureResult}
   * can be used to retrieve the completed asynchronous connection.
   * Alternatively, if a {@code ResultHandler} is provided, the handler will be
   * notified when the connection is available and ready for use.
   * Asynchronously obtains a connection to the Directory Server associated with
   * this connection factory. The returned {@code FutureResult} can be used to
   * retrieve the completed connection. Alternatively, if a
   * {@code ResultHandler} is provided, the handler will be notified when the
   * connection is available and ready for use.
   *
   * @param handler
   *          The completion handler, or {@code null} if no handler is to be
   *          used.
   * @return A future which can be used to retrieve the asynchronous connection.
   * @return A future which can be used to retrieve the connection.
   */
  FutureResult<AsynchronousConnection> getAsynchronousConnection(
      ResultHandler<? super AsynchronousConnection> handler);
  FutureResult<Connection> getConnectionAsync(
      ResultHandler<? super Connection> handler);
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ConnectionPool.java
@@ -64,11 +64,11 @@
  /**
   * Obtains an asynchronous connection from this connection pool, potentially
   * Asynchronously obtains a connection from this connection pool, potentially
   * opening a new connection if needed.
   * <p>
   * The returned {@code FutureResult} can be used to retrieve the pooled
   * asynchronous connection. Alternatively, if a {@code ResultHandler} is
   * connection. Alternatively, if a {@code ResultHandler} is
   * provided, the handler will be notified when the pooled connection is
   * available and ready for use.
   * <p>
@@ -78,13 +78,12 @@
   * @param handler
   *          The completion handler, or {@code null} if no handler is to be
   *          used.
   * @return A future which can be used to retrieve the pooled asynchronous
   *         connection.
   * @return A future which can be used to retrieve the pooled connection.
   * @throws IllegalStateException
   *           If this connection pool has already been closed.
   */
  FutureResult<AsynchronousConnection> getAsynchronousConnection(
      ResultHandler<? super AsynchronousConnection> handler);
  FutureResult<Connection> getConnectionAsync(
      ResultHandler<? super Connection> handler);
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java
@@ -151,9 +151,6 @@
  /**
   * Creates a new heart-beat connection factory which will create connections
   * using the provided connection factory and periodically ping any created
@@ -184,9 +181,6 @@
  /**
   * Creates a new heart-beat connection factory which will create connections
   * using the provided connection factory and periodically ping any created
@@ -304,10 +298,10 @@
    {
      @Override
      public FutureResult<AsynchronousConnection> getAsynchronousConnection(
          final ResultHandler<? super AsynchronousConnection> handler)
      public FutureResult<Connection> getConnectionAsync(
          final ResultHandler<? super Connection> handler)
      {
        return factory.getAsynchronousConnection(handler);
        return factory.getConnectionAsync(handler);
      }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/FixedConnectionPool.java
@@ -35,15 +35,21 @@
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.requests.*;
import org.forgerock.opendj.ldap.responses.*;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import com.forgerock.opendj.util.*;
import com.forgerock.opendj.util.AsynchronousFutureResult;
import com.forgerock.opendj.util.CompletedFutureResult;
import com.forgerock.opendj.util.StaticUtils;
import com.forgerock.opendj.util.Validator;
@@ -51,8 +57,7 @@
 * A simple connection pool implementation which maintains a fixed number of
 * connections.
 */
final class FixedConnectionPool extends AbstractConnectionFactory implements
    ConnectionPool
final class FixedConnectionPool implements ConnectionPool
{
  /**
@@ -60,7 +65,7 @@
   * the pool completes.
   */
  private final class ConnectionResultHandler implements
      ResultHandler<AsynchronousConnection>
      ResultHandler<Connection>
  {
    /**
     * {@inheritDoc}
@@ -102,7 +107,7 @@
     * {@inheritDoc}
     */
    @Override
    public void handleResult(final AsynchronousConnection connection)
    public void handleResult(final Connection connection)
    {
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
      {
@@ -124,77 +129,76 @@
   * the client application closes this connection. More specifically, pooled
   * connections are not actually stored in the internal queue.
   */
  private final class PooledConnection implements AsynchronousConnection
  private final class PooledConnection implements Connection
  {
    // Connection event listeners registed against this pooled connection should
    // have the same life time as the pooled connection.
    private final List<ConnectionEventListener> listeners =
      new CopyOnWriteArrayList<ConnectionEventListener>();
        new CopyOnWriteArrayList<ConnectionEventListener>();
    private final AsynchronousConnection connection;
    private final Connection connection;
    private final AtomicBoolean isClosed = new AtomicBoolean(false);
    PooledConnection(final AsynchronousConnection connection)
    PooledConnection(final Connection connection)
    {
      this.connection = connection;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Void> abandon(final AbandonRequest request)
    public FutureResult<Void> abandonAsync(final AbandonRequest request)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.abandon(request);
      return checkState().abandonAsync(request);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> add(final AddRequest request,
        final ResultHandler<? super Result> handler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    public Result add(final AddRequest request) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.add(request, handler);
      return checkState().add(request);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> add(final AddRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
    public Result add(final Entry entry) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      return checkState().add(entry);
    }
    @Override
    public Result add(final String... ldifLines) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        LocalizedIllegalArgumentException, IllegalStateException,
        NullPointerException
    {
      return checkState().add(ldifLines);
    }
    @Override
    public FutureResult<Result> addAsync(final AddRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection
          .add(request, resultHandler, intermediateResponseHandler);
      return checkState().addAsync(request, intermediateResponseHandler,
          resultHandler);
    }
@@ -208,49 +212,43 @@
        NullPointerException
    {
      Validator.ensureNotNull(listener);
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      checkState();
      listeners.add(listener);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<BindResult> bind(final BindRequest request,
        final ResultHandler<? super BindResult> handler)
        throws UnsupportedOperationException, IllegalStateException,
    public BindResult bind(final BindRequest request)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.bind(request, handler);
      return checkState().bind(request);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<BindResult> bind(final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
    public BindResult bind(final String name, final char[] password)
        throws ErrorResultException, InterruptedException,
        LocalizedIllegalArgumentException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      return checkState().bind(name, password);
    }
    @Override
    public FutureResult<BindResult> bindAsync(final BindRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.bind(request, resultHandler,
          intermediateResponseHandler);
      return checkState().bindAsync(request, intermediateResponseHandler,
          resultHandler);
    }
@@ -282,7 +280,7 @@
        connection.close();
        // Try to get a new connection to replace it.
        factory.getAsynchronousConnection(connectionResultHandler);
        factory.getConnectionAsync(connectionResultHandler);
        if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
        {
@@ -308,128 +306,122 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<CompareResult> compare(final CompareRequest request,
        final ResultHandler<? super CompareResult> handler)
        throws UnsupportedOperationException, IllegalStateException,
    public CompareResult compare(final CompareRequest request)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.compare(request, handler);
      return checkState().compare(request);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<CompareResult> compare(final CompareRequest request,
        final ResultHandler<? super CompareResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    public CompareResult compare(final String name,
        final String attributeDescription, final String assertionValue)
        throws ErrorResultException, InterruptedException,
        LocalizedIllegalArgumentException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.compare(request, resultHandler,
          intermediateResponseHandler);
      return checkState().compare(name, attributeDescription, assertionValue);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> delete(final DeleteRequest request,
        final ResultHandler<? super Result> handler)
    public FutureResult<CompareResult> compareAsync(
        final CompareRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super CompareResult> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.delete(request, handler);
      return checkState().compareAsync(request, intermediateResponseHandler,
          resultHandler);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> delete(final DeleteRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException, IllegalStateException,
    public Result delete(final DeleteRequest request)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.delete(request, resultHandler,
          intermediateResponseHandler);
      return checkState().delete(request);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
        final ExtendedRequest<R> request, final ResultHandler<? super R> handler)
        throws UnsupportedOperationException, IllegalStateException,
    public Result delete(final String name) throws ErrorResultException,
        InterruptedException, LocalizedIllegalArgumentException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.extendedRequest(request, handler);
      return checkState().delete(name);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
    public FutureResult<Result> deleteAsync(final DeleteRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().deleteAsync(request, intermediateResponseHandler,
          resultHandler);
    }
    @Override
    public <R extends ExtendedResult> R extendedRequest(
        final ExtendedRequest<R> request) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      return checkState().extendedRequest(request);
    }
    @Override
    public <R extends ExtendedResult> R extendedRequest(
        final ExtendedRequest<R> request,
        final ResultHandler<? super R> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
        final IntermediateResponseHandler handler) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.extendedRequest(request, resultHandler,
          intermediateResponseHandler);
      return checkState().extendedRequest(request, handler);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Connection getSynchronousConnection()
    public GenericExtendedResult extendedRequest(final String requestName,
        final ByteString requestValue) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      return new SynchronousConnection(this);
      return checkState().extendedRequest(requestName, requestValue);
    }
    @Override
    public <R extends ExtendedResult> FutureResult<R> extendedRequestAsync(
        final ExtendedRequest<R> request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super R> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().extendedRequestAsync(request,
          intermediateResponseHandler, resultHandler);
    }
@@ -456,97 +448,107 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> modify(final ModifyRequest request,
        final ResultHandler<? super Result> handler)
        throws UnsupportedOperationException, IllegalStateException,
    public Result modify(final ModifyRequest request)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.modify(request, handler);
      return checkState().modify(request);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> modify(final ModifyRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    public Result modify(final String... ldifLines)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, LocalizedIllegalArgumentException,
        IllegalStateException, NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.modify(request, resultHandler,
          intermediateResponseHandler);
      return checkState().modify(ldifLines);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
        final ResultHandler<? super Result> handler)
    public FutureResult<Result> modifyAsync(final ModifyRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.modifyDN(request, handler);
      return checkState().modifyAsync(request, intermediateResponseHandler,
          resultHandler);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException, IllegalStateException,
    public Result modifyDN(final ModifyDNRequest request)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.modifyDN(request, resultHandler,
          intermediateResponseHandler);
      return checkState().modifyDN(request);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<SearchResultEntry> readEntry(final DN name,
    public Result modifyDN(final String name, final String newRDN)
        throws ErrorResultException, LocalizedIllegalArgumentException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      return checkState().modifyDN(name, newRDN);
    }
    @Override
    public FutureResult<Result> modifyDNAsync(final ModifyDNRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().modifyDNAsync(request, intermediateResponseHandler,
          resultHandler);
    }
    @Override
    public SearchResultEntry readEntry(final DN name,
        final String... attributeDescriptions) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      return checkState().readEntry(name, attributeDescriptions);
    }
    @Override
    public SearchResultEntry readEntry(final String name,
        final String... attributeDescriptions) throws ErrorResultException,
        InterruptedException, LocalizedIllegalArgumentException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().readEntry(name, attributeDescriptions);
    }
    @Override
    public FutureResult<SearchResultEntry> readEntryAsync(final DN name,
        final Collection<String> attributeDescriptions,
        final ResultHandler<? super SearchResultEntry> resultHandler)
        final ResultHandler<? super SearchResultEntry> handler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.readEntry(name, attributeDescriptions, resultHandler);
      return checkState().readEntryAsync(name, attributeDescriptions, handler);
    }
@@ -559,68 +561,118 @@
        final ConnectionEventListener listener) throws NullPointerException
    {
      Validator.ensureNotNull(listener);
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      checkState();
      listeners.remove(listener);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> search(final SearchRequest request,
        final SearchResultHandler handler)
    public ConnectionEntryReader search(final SearchRequest request,
        final BlockingQueue<Response> entries)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.search(request, handler);
      return checkState().search(request, entries);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<Result> search(final SearchRequest request,
        final SearchResultHandler resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException, IllegalStateException,
    public Result search(final SearchRequest request,
        final Collection<? super SearchResultEntry> entries)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.search(request, resultHandler,
          intermediateResponseHandler);
      return checkState().search(request, entries);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public FutureResult<SearchResultEntry> searchSingleEntry(
    public Result search(final SearchRequest request,
        final Collection<? super SearchResultEntry> entries,
        final Collection<? super SearchResultReference> references)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().search(request, entries, references);
    }
    @Override
    public Result search(final SearchRequest request,
        final SearchResultHandler handler) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      return checkState().search(request, handler);
    }
    @Override
    public ConnectionEntryReader search(final String baseObject,
        final SearchScope scope, final String filter,
        final String... attributeDescriptions)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().search(baseObject, scope, filter,
          attributeDescriptions);
    }
    @Override
    public FutureResult<Result> searchAsync(final SearchRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final SearchResultHandler resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().searchAsync(request, intermediateResponseHandler,
          resultHandler);
    }
    @Override
    public SearchResultEntry searchSingleEntry(final SearchRequest request)
        throws ErrorResultException, InterruptedException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().searchSingleEntry(request);
    }
    @Override
    public SearchResultEntry searchSingleEntry(final String baseObject,
        final SearchScope scope, final String filter,
        final String... attributeDescriptions) throws ErrorResultException,
        InterruptedException, LocalizedIllegalArgumentException,
        UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return checkState().searchSingleEntry(baseObject, scope, filter,
          attributeDescriptions);
    }
    @Override
    public FutureResult<SearchResultEntry> searchSingleEntryAsync(
        final SearchRequest request,
        final ResultHandler<? super SearchResultEntry> resultHandler)
        final ResultHandler<? super SearchResultEntry> handler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection.searchSingleEntry(request, resultHandler);
      return checkState().searchSingleEntryAsync(request, handler);
    }
@@ -637,14 +689,27 @@
      builder.append(')');
      return builder.toString();
    }
    // Checks that this pooled connection has not been closed.
    private Connection checkState()
    {
      if (isClosed())
      {
        throw new IllegalStateException();
      }
      return connection;
    }
  }
  /**
   * A queue element is either a pending connection request future awaiting an
   * {@code AsynchronousConnection} or it is an unused
   * {@code AsynchronousConnection} awaiting a connection request.
   * {@code Connection} or it is an unused {@code Connection} awaiting a
   * connection request.
   */
  private static final class QueueElement
  {
@@ -652,16 +717,16 @@
    QueueElement(final AsynchronousConnection connection)
    QueueElement(final Connection connection)
    {
      this.value = connection;
    }
    QueueElement(final ResultHandler<? super AsynchronousConnection> handler)
    QueueElement(final ResultHandler<? super Connection> handler)
    {
      this.value = new AsynchronousFutureResult<AsynchronousConnection>(handler);
      this.value = new AsynchronousFutureResult<Connection>(handler);
    }
@@ -674,11 +739,11 @@
    AsynchronousConnection getWaitingConnection()
    Connection getWaitingConnection()
    {
      if (value instanceof AsynchronousConnection)
      if (value instanceof Connection)
      {
        return (AsynchronousConnection) value;
        return (Connection) value;
      }
      else
      {
@@ -689,11 +754,11 @@
    @SuppressWarnings("unchecked")
    AsynchronousFutureResult<AsynchronousConnection> getWaitingFuture()
    AsynchronousFutureResult<Connection> getWaitingFuture()
    {
      if (value instanceof AsynchronousFutureResult)
      {
        return (AsynchronousFutureResult<AsynchronousConnection>) value;
        return (AsynchronousFutureResult<Connection>) value;
      }
      else
      {
@@ -723,8 +788,7 @@
  private final Semaphore currentPoolSize;
  private final ResultHandler<AsynchronousConnection> connectionResultHandler =
    new ConnectionResultHandler();
  private final ResultHandler<Connection> connectionResultHandler = new ConnectionResultHandler();
@@ -752,7 +816,7 @@
  @Override
  public void close()
  {
    final LinkedList<AsynchronousConnection> idleConnections;
    final LinkedList<Connection> idleConnections;
    synchronized (queue)
    {
      if (isClosed)
@@ -763,7 +827,7 @@
      // Remove any connections which are waiting in the queue as these can be
      // closed immediately.
      idleConnections = new LinkedList<AsynchronousConnection>();
      idleConnections = new LinkedList<Connection>();
      while (!queue.isEmpty() && !queue.getFirst().isWaitingFuture())
      {
        final QueueElement holder = queue.removeFirst();
@@ -779,7 +843,7 @@
    }
    // Close the idle connections.
    for (final AsynchronousConnection connection : idleConnections)
    for (final Connection connection : idleConnections)
    {
      closeConnection(connection);
    }
@@ -791,8 +855,20 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> handler)
  public Connection getConnection() throws ErrorResultException,
      InterruptedException
  {
    return getConnectionAsync(null).get();
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> handler)
  {
    QueueElement holder;
    synchronized (queue)
@@ -816,22 +892,21 @@
    if (!holder.isWaitingFuture())
    {
      // There was a completed connection attempt.
      final AsynchronousConnection connection = holder.getWaitingConnection();
      final Connection connection = holder.getWaitingConnection();
      final PooledConnection pooledConnection = new PooledConnection(connection);
      if (handler != null)
      {
        handler.handleResult(pooledConnection);
      }
      return new CompletedFutureResult<AsynchronousConnection>(pooledConnection);
      return new CompletedFutureResult<Connection>(pooledConnection);
    }
    else
    {
      // Grow the pool if needed.
      final FutureResult<AsynchronousConnection> future = holder
          .getWaitingFuture();
      final FutureResult<Connection> future = holder.getWaitingFuture();
      if (!future.isDone() && currentPoolSize.tryAcquire())
      {
        factory.getAsynchronousConnection(connectionResultHandler);
        factory.getConnectionAsync(connectionResultHandler);
      }
      return future;
    }
@@ -869,7 +944,7 @@
  private void closeConnection(final AsynchronousConnection connection)
  private void closeConnection(final Connection connection)
  {
    // The connection will be closed, so decrease the pool size.
    currentPoolSize.release();
@@ -886,7 +961,7 @@
  private void publishConnection(final AsynchronousConnection connection)
  private void publishConnection(final Connection connection)
  {
    final QueueElement holder;
    boolean connectionPoolIsClosing = false;
@@ -941,4 +1016,5 @@
      holder.getWaitingFuture().handleResult(pooledConnection);
    }
  }
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactory.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -42,7 +43,10 @@
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.responses.SearchResultReference;
import com.forgerock.opendj.util.*;
import com.forgerock.opendj.util.ConnectionDecorator;
import com.forgerock.opendj.util.FutureResultTransformer;
import com.forgerock.opendj.util.StaticUtils;
import com.forgerock.opendj.util.Validator;
@@ -50,15 +54,13 @@
 * An heart beat connection factory can be used to create connections that sends
 * a periodic search request to a Directory Server.
 */
final class HeartBeatConnectionFactory extends AbstractConnectionFactory
final class HeartBeatConnectionFactory implements ConnectionFactory
{
  /**
   * An asynchronous connection that sends heart beats and supports all
   * operations.
   * A connection that sends heart beats and supports all operations.
   */
  private final class AsynchronousConnectionImpl extends
      AsynchronousConnectionDecorator implements ConnectionEventListener,
      SearchResultHandler
  private final class ConnectionImpl extends ConnectionDecorator implements
      ConnectionEventListener, SearchResultHandler
  {
    private long lastSuccessfulPing;
@@ -66,7 +68,7 @@
    private AsynchronousConnectionImpl(final AsynchronousConnection connection)
    private ConnectionImpl(final Connection connection)
    {
      super(connection);
    }
@@ -192,12 +194,11 @@
  private final class FutureResultImpl extends
      FutureResultTransformer<AsynchronousConnection, AsynchronousConnection>
      implements ResultHandler<AsynchronousConnection>
      FutureResultTransformer<Connection, Connection> implements
      ResultHandler<Connection>
  {
    private FutureResultImpl(
        final ResultHandler<? super AsynchronousConnection> handler)
    private FutureResultImpl(final ResultHandler<? super Connection> handler)
    {
      super(handler);
    }
@@ -208,23 +209,10 @@
     * {@inheritDoc}
     */
    @Override
    protected AsynchronousConnection transformResult(
        final AsynchronousConnection connection) throws ErrorResultException
    protected Connection transformResult(final Connection connection)
        throws ErrorResultException
    {
      final AsynchronousConnectionImpl heartBeatConnection = new AsynchronousConnectionImpl(
          connection);
      synchronized (activeConnections)
      {
        connection.addConnectionEventListener(heartBeatConnection);
        if (activeConnections.isEmpty())
        {
          // This is the first active connection, so start the heart beat.
          heartBeatFuture = scheduler.scheduleWithFixedDelay(
              new HeartBeatRunnable(), 0, interval, unit);
        }
        activeConnections.add(heartBeatConnection);
      }
      return heartBeatConnection;
      return adaptConnection(connection);
    }
  }
@@ -245,13 +233,13 @@
    {
      synchronized (activeConnections)
      {
        for (final AsynchronousConnectionImpl connection : activeConnections)
        for (final ConnectionImpl connection : activeConnections)
        {
          if (connection.lastPingFuture == null
              || connection.lastPingFuture.isDone())
          {
            connection.lastPingFuture = connection.search(heartBeat,
                connection, null);
            connection.lastPingFuture = connection.searchAsync(heartBeat, null,
                connection);
          }
        }
      }
@@ -268,7 +256,7 @@
  private final TimeUnit unit;
  private final List<AsynchronousConnectionImpl> activeConnections;
  private final List<ConnectionImpl> activeConnections;
  private final ConnectionFactory factory;
@@ -369,19 +357,34 @@
    this.heartBeat = heartBeat;
    this.interval = interval;
    this.unit = unit;
    this.activeConnections = new LinkedList<AsynchronousConnectionImpl>();
    this.activeConnections = new LinkedList<ConnectionImpl>();
    this.factory = factory;
    this.scheduler = scheduler;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> handler)
  public Connection getConnection() throws ErrorResultException,
      InterruptedException
  {
    return adaptConnection(factory.getConnection());
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> handler)
  {
    final FutureResultImpl future = new FutureResultImpl(handler);
    future.setFutureResult(factory.getAsynchronousConnection(future));
    future.setFutureResult(factory.getConnectionAsync(future));
    return future;
  }
@@ -399,4 +402,23 @@
    builder.append(')');
    return builder.toString();
  }
  private Connection adaptConnection(final Connection connection)
  {
    final ConnectionImpl heartBeatConnection = new ConnectionImpl(connection);
    synchronized (activeConnections)
    {
      connection.addConnectionEventListener(heartBeatConnection);
      if (activeConnections.isEmpty())
      {
        // This is the first active connection, so start the heart beat.
        heartBeatFuture = scheduler.scheduleWithFixedDelay(
            new HeartBeatRunnable(), 0, interval, unit);
      }
      activeConnections.add(heartBeatConnection);
    }
    return heartBeatConnection;
  }
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/IntermediateResponseHandler.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -38,12 +39,16 @@
 * extended operations, or other operations for which an appropriate control was
 * sent.
 * <p>
 * {@link Connection} objects support intermediate responses for extended
 * operations only via the {@link Connection#extendedRequest}
 * method. {@link AsynchronousConnection} objects support intermediate responses
 * for extended operations, and all other operation types for which appropriate
 * controls were used. When no handler is provided any intermediate responses
 * will be discarded.
 * Intermediate responses are rarely used in practice and are therefore only
 * supported in a few specialized cases where they are most likely to be
 * encountered:
 * <ul>
 * <li>when performing extended requests using the
 * {@link Connection#extendedRequest} methods
 * <li>when using the asynchronous operation methods, such as
 * {@link Connection#addAsync}
 * </ul>
 * When no handler is provided any intermediate responses will be discarded.
 * <p>
 * The {@link #handleIntermediateResponse} method is invoked each time a
 * Intermediate Response is returned from the Directory Server.
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/InternalConnectionFactory.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -30,7 +31,6 @@
import com.forgerock.opendj.ldap.InternalConnection;
import com.forgerock.opendj.util.AbstractConnectionFactory;
import com.forgerock.opendj.util.CompletedFutureResult;
@@ -54,7 +54,7 @@
 * @param <C>
 *          The type of client context.
 */
final class InternalConnectionFactory<C> extends AbstractConnectionFactory
final class InternalConnectionFactory<C> implements ConnectionFactory
{
  private final ServerConnectionFactory<C, Integer> factory;
@@ -72,9 +72,24 @@
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> handler)
  /**
   * {@inheritDoc}
   */
  public Connection getConnection() throws ErrorResultException,
      InterruptedException
  {
    final ServerConnection<Integer> serverConnection = factory
        .handleAccept(clientContext);
    return new InternalConnection(serverConnection);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> handler)
  {
    final ServerConnection<Integer> serverConnection;
    try
@@ -87,7 +102,7 @@
      {
        handler.handleErrorResult(e);
      }
      return new CompletedFutureResult<AsynchronousConnection>(e);
      return new CompletedFutureResult<Connection>(e);
    }
    final InternalConnection connection = new InternalConnection(
@@ -96,7 +111,7 @@
    {
      handler.handleResult(connection);
    }
    return new CompletedFutureResult<AsynchronousConnection>(connection);
    return new CompletedFutureResult<Connection>(connection);
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -44,9 +45,8 @@
 */
public final class LDAPConnectionFactory implements ConnectionFactory
{
  // We implement the factory using the pimpl idiom in order have
  // cleaner Javadoc which does not expose implementation methods from
  // AbstractConnectionFactory.
  // We implement the factory using the pimpl idiom in order to avoid making too
  // many implementation classes public.
  private final LDAPConnectionFactoryImpl impl;
@@ -157,10 +157,10 @@
   * {@inheritDoc}
   */
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> handler)
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> handler)
  {
    return impl.getAsynchronousConnection(handler);
    return impl.getConnectionAsync(handler);
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LoadBalancer.java
@@ -23,13 +23,13 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
import com.forgerock.opendj.util.AbstractConnectionFactory;
import com.forgerock.opendj.util.CompletedFutureResult;
import com.forgerock.opendj.util.Validator;
@@ -39,7 +39,7 @@
 * A load balancing connection factory allocates connections using the provided
 * algorithm.
 */
final class LoadBalancer extends AbstractConnectionFactory
final class LoadBalancer implements ConnectionFactory
{
  private final LoadBalancingAlgorithm algorithm;
@@ -63,9 +63,20 @@
  /**
   * {@inheritDoc}
   */
  public Connection getConnection() throws ErrorResultException,
      InterruptedException
  {
    return algorithm.getConnectionFactory().getConnection();
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> resultHandler)
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> resultHandler)
  {
    final ConnectionFactory factory;
@@ -79,10 +90,10 @@
      {
        resultHandler.handleErrorResult(e);
      }
      return new CompletedFutureResult<AsynchronousConnection>(e);
      return new CompletedFutureResult<Connection>(e);
    }
    return factory.getAsynchronousConnection(resultHandler);
    return factory.getConnectionAsync(resultHandler);
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandler.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -64,18 +65,18 @@
   *          The request context.
   * @param request
   *          The add request.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle add requests.
   */
  void handleAdd(C requestContext, AddRequest request,
      ResultHandler<? super Result> resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException;
@@ -89,18 +90,18 @@
   *          The protocol version included with the bind request.
   * @param request
   *          The bind request.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle bind requests.
   */
  void handleBind(C requestContext, int version, BindRequest request,
      ResultHandler<? super BindResult> resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super BindResult> resultHandler)
      throws UnsupportedOperationException;
@@ -112,18 +113,18 @@
   *          The request context.
   * @param request
   *          The compare request.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle compare requests.
   */
  void handleCompare(C requestContext, CompareRequest request,
      ResultHandler<? super CompareResult> resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super CompareResult> resultHandler)
      throws UnsupportedOperationException;
@@ -135,18 +136,18 @@
   *          The request context.
   * @param request
   *          The delete request.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle delete requests.
   */
  void handleDelete(C requestContext, DeleteRequest request,
      ResultHandler<? super Result> resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException;
@@ -160,18 +161,19 @@
   *          The request context.
   * @param request
   *          The extended request.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle extended requests.
   */
  <R extends ExtendedResult> void handleExtendedRequest(C requestContext,
      ExtendedRequest<R> request, ResultHandler<? super R> resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      ExtendedRequest<R> request,
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super R> resultHandler)
      throws UnsupportedOperationException;
@@ -183,18 +185,18 @@
   *          The request context.
   * @param request
   *          The modify request.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle modify requests.
   */
  void handleModify(C requestContext, ModifyRequest request,
      ResultHandler<? super Result> resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException;
@@ -206,18 +208,18 @@
   *          The request context.
   * @param request
   *          The modify DN request.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the result to the
   *          client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle modify DN requests.
   */
  void handleModifyDN(C requestContext, ModifyDNRequest request,
      ResultHandler<? super Result> resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      IntermediateResponseHandler intermediateResponseHandler,
      ResultHandler<? super Result> resultHandler)
      throws UnsupportedOperationException;
@@ -229,17 +231,16 @@
   *          The request context.
   * @param request
   *          The search request.
   * @param resultHandler
   *          The handler which should be used to send back the search results
   *          to the client.
   * @param intermediateResponseHandler
   *          The handler which should be used to send back any intermediate
   *          responses to the client.
   * @param resultHandler
   *          The handler which should be used to send back the search results
   *          to the client.
   * @throws UnsupportedOperationException
   *           If this request handler does not handle search requests.
   */
  void handleSearch(C requestContext, SearchRequest request,
      SearchResultHandler resultHandler,
      IntermediateResponseHandler intermediateResponseHandler)
      throws UnsupportedOperationException;
      IntermediateResponseHandler intermediateResponseHandler,
      SearchResultHandler resultHandler) throws UnsupportedOperationException;
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactoryAdapter.java
@@ -72,8 +72,7 @@
      private ExtendedResultHandlerHolder(
          final ExtendedRequest<R> request,
      private ExtendedResultHandlerHolder(final ExtendedRequest<R> request,
          final ResultHandler<? super R> resultHandler)
      {
        this.request = request;
@@ -148,9 +147,8 @@
    protected RequestContextImpl(
        final ServerConnectionImpl<?> clientConnection,
        final H resultHandler, final int messageID,
        final boolean isCancelSupported)
        final ServerConnectionImpl<?> clientConnection, final H resultHandler,
        final int messageID, final boolean isCancelSupported)
    {
      this.clientConnection = clientConnection;
      this.resultHandler = resultHandler;
@@ -164,8 +162,7 @@
     * {@inheritDoc}
     */
    @Override
    public void addCancelRequestListener(
        final CancelRequestListener listener)
    public void addCancelRequestListener(final CancelRequestListener listener)
        throws NullPointerException
    {
      Validator.ensureNotNull(listener);
@@ -224,8 +221,8 @@
          break;
        case CANCEL_REQUESTED:
          // Don't change state: let the handler ack the cancellation request.
          throw (CancelledResultException) newErrorResult(
              ResultCode.CANCELLED, cancelRequestReason.toString());
          throw (CancelledResultException) newErrorResult(ResultCode.CANCELLED,
              cancelRequestReason.toString());
        case TOO_LATE:
          // Already too late. Nothing to do.
          break;
@@ -294,8 +291,7 @@
     * {@inheritDoc}
     */
    @Override
    public void removeCancelRequestListener(
        final CancelRequestListener listener)
    public void removeCancelRequestListener(final CancelRequestListener listener)
        throws NullPointerException
    {
      Validator.ensureNotNull(listener);
@@ -325,8 +321,7 @@
        {
          final Result result = Responses
              .newGenericExtendedResult(ResultCode.CANNOT_CANCEL);
          cancelResultHandler
              .handleErrorResult(newErrorResult(result));
          cancelResultHandler.handleErrorResult(newErrorResult(result));
        }
        return;
      }
@@ -345,9 +340,8 @@
          if (cancelResultHandler != null)
          {
            cancelResultHandlers = new LinkedList<ExtendedResultHandlerHolder<?>>();
            cancelResultHandlers
                .add(new ExtendedResultHandlerHolder<R>(
                    cancelRequest, cancelResultHandler));
            cancelResultHandlers.add(new ExtendedResultHandlerHolder<R>(
                cancelRequest, cancelResultHandler));
          }
          tmpListeners = cancelRequestListeners;
          cancelRequestListeners = null;
@@ -362,9 +356,8 @@
            {
              cancelResultHandlers = new LinkedList<ExtendedResultHandlerHolder<?>>();
            }
            cancelResultHandlers
                .add(new ExtendedResultHandlerHolder<R>(
                    cancelRequest, cancelResultHandler));
            cancelResultHandlers.add(new ExtendedResultHandlerHolder<R>(
                cancelRequest, cancelResultHandler));
          }
          break;
        case TOO_LATE:
@@ -509,8 +502,7 @@
        final SearchResultHandler resultHandler, final int messageID,
        final boolean isCancelSupported)
    {
      super(clientConnection, resultHandler, messageID,
          isCancelSupported);
      super(clientConnection, resultHandler, messageID, isCancelSupported);
    }
@@ -530,8 +522,7 @@
     * {@inheritDoc}
     */
    @Override
    public boolean handleReference(
        final SearchResultReference reference)
    public boolean handleReference(final SearchResultReference reference)
    {
      return resultHandler.handleReference(reference);
    }
@@ -543,11 +534,9 @@
      ServerConnection<Integer>
  {
    private final RequestHandler<RequestContext> requestHandler;
    private final AtomicBoolean isClosed = new AtomicBoolean();
    private final ConcurrentHashMap<Integer, RequestContextImpl<?, ?>> pendingRequests =
      new ConcurrentHashMap<Integer, RequestContextImpl<?, ?>>();
        new ConcurrentHashMap<Integer, RequestContextImpl<?, ?>>();
@@ -564,8 +553,7 @@
     */
    @Override
    public void handleAbandon(final Integer messageID,
        final AbandonRequest request)
        throws UnsupportedOperationException
        final AbandonRequest request) throws UnsupportedOperationException
    {
      final RequestContextImpl<?, ?> abandonedRequest = getPendingRequest(request
          .getRequestID());
@@ -583,19 +571,18 @@
     * {@inheritDoc}
     */
    @Override
    public void handleAdd(final Integer messageID,
        final AddRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
    public void handleAdd(final Integer messageID, final AddRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleAdd(requestContext, request,
            requestContext, intermediateResponseHandler);
            intermediateResponseHandler, requestContext);
      }
    }
@@ -605,19 +592,19 @@
     * {@inheritDoc}
     */
    @Override
    public void handleBind(final Integer messageID,
        final int version, final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
    public void handleBind(final Integer messageID, final int version,
        final BindRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<BindResult, ResultHandler<? super BindResult>> requestContext =
        new RequestContextImpl<BindResult, ResultHandler<? super BindResult>>(
          new RequestContextImpl<BindResult, ResultHandler<? super BindResult>>(
          this, resultHandler, messageID, false);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleBind(requestContext, version, request,
            requestContext, intermediateResponseHandler);
            intermediateResponseHandler, requestContext);
      }
    }
@@ -629,17 +616,17 @@
    @Override
    public void handleCompare(final Integer messageID,
        final CompareRequest request,
        final ResultHandler<? super CompareResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super CompareResult> resultHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<CompareResult, ResultHandler<? super CompareResult>> requestContext =
        new RequestContextImpl<CompareResult, ResultHandler<? super CompareResult>>(
          new RequestContextImpl<CompareResult, ResultHandler<? super CompareResult>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleCompare(requestContext, request,
            requestContext, intermediateResponseHandler);
            intermediateResponseHandler, requestContext);
      }
    }
@@ -663,8 +650,8 @@
     * {@inheritDoc}
     */
    @Override
    public void handleConnectionDisconnected(
        final ResultCode resultCode, final String message)
    public void handleConnectionDisconnected(final ResultCode resultCode,
        final String message)
    {
      final LocalizableMessage cancelReason = INFO_CANCELED_BY_SERVER_DISCONNECT
          .get();
@@ -692,17 +679,17 @@
    @Override
    public void handleDelete(final Integer messageID,
        final DeleteRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleDelete(requestContext, request,
            requestContext, intermediateResponseHandler);
            intermediateResponseHandler, requestContext);
      }
    }
@@ -714,8 +701,8 @@
    @Override
    public <R extends ExtendedResult> void handleExtendedRequest(
        final Integer messageID, final ExtendedRequest<R> request,
        final ResultHandler<? super R> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super R> resultHandler)
        throws UnsupportedOperationException
    {
      if (request.getOID().equals(CancelExtendedRequest.OID))
@@ -724,8 +711,8 @@
        CancelExtendedRequest cancelRequest;
        try
        {
          cancelRequest = CancelExtendedRequest.DECODER
              .decodeExtendedRequest(request, new DecodeOptions());
          cancelRequest = CancelExtendedRequest.DECODER.decodeExtendedRequest(
              request, new DecodeOptions());
        }
        catch (final DecodeException e)
        {
@@ -739,7 +726,7 @@
        // this request cannot be cancelled, it is important to do this in
        // order to monitor the number of pending operations.
        final RequestContextImpl<R, ResultHandler<? super R>> requestContext =
          new RequestContextImpl<R, ResultHandler<? super R>>(
            new RequestContextImpl<R, ResultHandler<? super R>>(
            this, resultHandler, messageID, false);
        if (addPendingRequest(requestContext))
        {
@@ -750,8 +737,8 @@
          {
            final LocalizableMessage cancelReason = INFO_CANCELED_BY_CANCEL_REQUEST
                .get(messageID);
            cancelledRequest.cancel(cancelReason, request,
                requestContext, true);
            cancelledRequest
                .cancel(cancelReason, request, requestContext, true);
          }
          else
          {
@@ -779,8 +766,8 @@
        if (addPendingRequest(requestContext))
        {
          requestHandler.handleExtendedRequest(requestContext,
              request, requestContext, intermediateResponseHandler);
          requestHandler.handleExtendedRequest(requestContext, request,
              intermediateResponseHandler, requestContext);
        }
      }
    }
@@ -793,17 +780,17 @@
    @Override
    public void handleModify(final Integer messageID,
        final ModifyRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleModify(requestContext, request,
            requestContext, intermediateResponseHandler);
            intermediateResponseHandler, requestContext);
      }
    }
@@ -815,17 +802,17 @@
    @Override
    public void handleModifyDN(final Integer messageID,
        final ModifyDNRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleModifyDN(requestContext, request,
            requestContext, intermediateResponseHandler);
            intermediateResponseHandler, requestContext);
      }
    }
@@ -837,8 +824,8 @@
    @Override
    public void handleSearch(final Integer messageID,
        final SearchRequest request,
        final SearchResultHandler resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final SearchResultHandler resultHandler)
        throws UnsupportedOperationException
    {
      final SearchRequestContextImpl requestContext = new SearchRequestContextImpl(
@@ -846,7 +833,7 @@
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleSearch(requestContext, request,
            requestContext, intermediateResponseHandler);
            intermediateResponseHandler, requestContext);
      }
    }
@@ -859,8 +846,7 @@
      if (isClosed.get())
      {
        final LocalizableMessage message = INFO_CLIENT_CONNECTION_CLOSING
            .get();
        final LocalizableMessage message = INFO_CLIENT_CONNECTION_CLOSING.get();
        requestContext.handleErrorResult(newErrorResult(
            ResultCode.UNWILLING_TO_PERFORM, message.toString()));
        return false;
@@ -879,8 +865,7 @@
        // it will have only been notified for cancellation.
        pendingRequests.remove(messageID);
        final LocalizableMessage message = INFO_CLIENT_CONNECTION_CLOSING
            .get();
        final LocalizableMessage message = INFO_CLIENT_CONNECTION_CLOSING.get();
        requestContext.handleErrorResult(newErrorResult(
            ResultCode.UNWILLING_TO_PERFORM, message.toString()));
        return false;
@@ -906,8 +891,7 @@
            .values().iterator();
        while (iterator.hasNext())
        {
          final RequestContextImpl<?, ?> pendingRequest = iterator
              .next();
          final RequestContextImpl<?, ?> pendingRequest = iterator.next();
          pendingRequest.cancel(cancelReason, null, null, false);
          iterator.remove();
        }
@@ -923,8 +907,7 @@
     *          The message ID associated with the request context.
     * @return The pending request context.
     */
    private RequestContextImpl<?, ?> getPendingRequest(
        final Integer messageID)
    private RequestContextImpl<?, ?> getPendingRequest(final Integer messageID)
    {
      return pendingRequests.get(messageID);
    }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ResultHandler.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -34,7 +35,7 @@
 * connection attempts.
 * <p>
 * A result completion handler may be specified when performing asynchronous
 * operations using an {@link AsynchronousConnection} object or when connecting
 * operations using a {@link Connection} object or when connecting
 * asynchronously to a remote Directory Server using an
 * {@link ConnectionFactory}. The {@link #handleResult} method is invoked when
 * the operation or connection attempt completes successfully. The
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RootDSE.java
@@ -135,7 +135,8 @@
  /**
   * Reads the Root DSE from the Directory Server using the provided connection.
   * Asynchronously reads the Root DSE from the Directory Server using the
   * provided connection.
   * <p>
   * If the Root DSE is not returned by the Directory Server then the request
   * will fail with an {@link EntryNotFoundException}. More specifically, the
@@ -150,14 +151,13 @@
   * @throws UnsupportedOperationException
   *           If the connection does not support search operations.
   * @throws IllegalStateException
   *           If the connection has already been closed, i.e. if {@code
   *           isClosed() == true}.
   *           If the connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code connection} was {@code null}.
   */
  public static FutureResult<RootDSE> readRootDSE(
      final AsynchronousConnection connection,
      final ResultHandler<? super RootDSE> handler)
  public static FutureResult<RootDSE> readRootDSEAsync(
      final Connection connection, final ResultHandler<? super RootDSE> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
@@ -175,7 +175,7 @@
    };
    final FutureResult<SearchResultEntry> innerFuture = connection
        .searchSingleEntry(SEARCH_REQUEST, future);
        .searchSingleEntryAsync(SEARCH_REQUEST, future);
    future.setFutureResult(innerFuture);
    return future;
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/SearchResultHandler.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -38,7 +39,7 @@
/**
 * A completion handler for consuming the results of a Search operation.
 * <p>
 * {@link Connection} and {@link AsynchronousConnection} objects allow a search
 * {@link Connection} and {@link Connection} objects allow a search
 * result completion handler to be specified when sending Search operation
 * requests to a Directory Server. The {@link #handleEntry} method is invoked
 * each time a Search Result Entry is returned from the Directory Server. The
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -1718,7 +1718,7 @@
  /**
   * Reads the schema contained in the named subschema sub-entry.
   * Asynchronously reads the schema contained in the named subschema sub-entry.
   * <p>
   * If the requested schema is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}. More
@@ -1740,8 +1740,8 @@
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code null}.
   */
  public static FutureResult<Schema> readSchema(
      final AsynchronousConnection connection, final DN name,
  public static FutureResult<Schema> readSchemaAsync(
      final Connection connection, final DN name,
      final ResultHandler<? super Schema> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
@@ -1760,7 +1760,7 @@
    };
    final SchemaBuilder builder = new SchemaBuilder();
    final FutureResult<SchemaBuilder> innerFuture = builder.addSchema(
    final FutureResult<SchemaBuilder> innerFuture = builder.addSchemaAsync(
        connection, name, future, true);
    future.setFutureResult(innerFuture);
    return future;
@@ -1804,8 +1804,8 @@
  /**
   * Reads the schema contained in the subschema sub-entry which applies to the
   * named entry.
   * Asynchronously reads the schema contained in the subschema sub-entry which
   * applies to the named entry.
   * <p>
   * If the requested entry or its associated schema are not returned by the
   * Directory Server then the request will fail with an
@@ -1814,7 +1814,7 @@
   * <p>
   * This implementation first reads the {@code subschemaSubentry} attribute of
   * the entry in order to identify the schema and then invokes
   * {@link #readSchema(AsynchronousConnection, DN, ResultHandler)} to read the
   * {@link #readSchemaAsync(Connection, DN, ResultHandler)} to read the
   * schema.
   *
   * @param connection
@@ -1833,8 +1833,8 @@
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code null}.
   */
  public static FutureResult<Schema> readSchemaForEntry(
      final AsynchronousConnection connection, final DN name,
  public static FutureResult<Schema> readSchemaForEntryAsync(
      final Connection connection, final DN name,
      final ResultHandler<? super Schema> handler)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
@@ -1853,8 +1853,8 @@
    };
    final SchemaBuilder builder = new SchemaBuilder();
    final FutureResult<SchemaBuilder> innerFuture = builder.addSchemaForEntry(
        connection, name, future, true);
    final FutureResult<SchemaBuilder> innerFuture = builder
        .addSchemaForEntryAsync(connection, name, future, true);
    future.setFutureResult(innerFuture);
    return future;
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -2013,8 +2013,8 @@
  /**
   * Reads the schema elements contained in the named subschema sub-entry and
   * adds them to this schema builder.
   * Asynchronously reads the schema elements contained in the named subschema
   * sub-entry and adds them to this schema builder.
   * <p>
   * If the requested schema is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}.
@@ -2038,8 +2038,8 @@
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code null}.
   */
  public FutureResult<SchemaBuilder> addSchema(
      final AsynchronousConnection connection, final DN name,
  public FutureResult<SchemaBuilder> addSchemaAsync(
      final Connection connection, final DN name,
      final ResultHandler<? super SchemaBuilder> handler,
      final boolean overwrite) throws UnsupportedOperationException,
      IllegalStateException, NullPointerException
@@ -2062,7 +2062,7 @@
    };
    final FutureResult<SearchResultEntry> innerFuture = connection
        .searchSingleEntry(request, future);
        .searchSingleEntryAsync(request, future);
    future.setFutureResult(innerFuture);
    return future;
  }
@@ -2295,8 +2295,9 @@
  /**
   * Reads the schema elements contained in the subschema sub-entry which
   * applies to the named entry and adds them to this schema builder.
   * Asynchronously reads the schema elements contained in the subschema
   * sub-entry which applies to the named entry and adds them to this schema
   * builder.
   * <p>
   * If the requested entry or its associated schema are not returned by the
   * Directory Server then the request will fail with an
@@ -2304,7 +2305,7 @@
   * <p>
   * This implementation first reads the {@code subschemaSubentry} attribute of
   * the entry in order to identify the schema and then invokes
   * {@link #addSchema(AsynchronousConnection, DN, ResultHandler, boolean)} to
   * {@link #addSchemaAsync(Connection, DN, ResultHandler, boolean)} to
   * read the schema.
   *
   * @param connection
@@ -2326,8 +2327,8 @@
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code null}.
   */
  public FutureResult<SchemaBuilder> addSchemaForEntry(
      final AsynchronousConnection connection, final DN name,
  public FutureResult<SchemaBuilder> addSchemaForEntryAsync(
      final Connection connection, final DN name,
      final ResultHandler<? super SchemaBuilder> handler,
      final boolean overwrite) throws UnsupportedOperationException,
      IllegalStateException, NullPointerException
@@ -2344,14 +2345,14 @@
          throws ErrorResultException
      {
        final DN subschemaDN = getSubschemaSubentryDN(name, innerResult);
        return addSchema(connection, subschemaDN, handler, overwrite);
        return addSchemaAsync(connection, subschemaDN, handler, overwrite);
      }
    };
    final SearchRequest request = getReadSchemaForEntrySearchRequest(name);
    final FutureResult<SearchResultEntry> innerFuture = connection
        .searchSingleEntry(request, future);
        .searchSingleEntryAsync(request, future);
    future.setFutureResult(innerFuture);
    return future;
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/ConnectionEntryReader.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldif;
@@ -46,10 +47,10 @@
/**
 * A {@code ConnectionEntryReader} is a bridge from
 * {@code AsynchronousConnection}s to {@code EntryReader}s. A connection entry
 * reader allows applications to iterate over search results as they are
 * returned from the server during a search operation.
 * A {@code ConnectionEntryReader} is a bridge from {@code Connection}s to
 * {@code EntryReader}s. A connection entry reader allows applications to
 * iterate over search results as they are returned from the server during a
 * search operation.
 * <p>
 * The Search operation is performed synchronously, blocking until a search
 * result entry is received. If a search result indicates that the search
@@ -207,7 +208,7 @@
   * @throws NullPointerException
   *           If {@code connection} was {@code null}.
   */
  public ConnectionEntryReader(final AsynchronousConnection connection,
  public ConnectionEntryReader(final Connection connection,
      final SearchRequest searchRequest) throws NullPointerException
  {
    this(connection, searchRequest, new LinkedBlockingQueue<Response>());
@@ -229,13 +230,13 @@
   * @throws NullPointerException
   *           If {@code connection} was {@code null}.
   */
  public ConnectionEntryReader(final AsynchronousConnection connection,
  public ConnectionEntryReader(final Connection connection,
      final SearchRequest searchRequest, final BlockingQueue<Response> entries)
      throws NullPointerException
  {
    Validator.ensureNotNull(connection);
    buffer = new BufferHandler(entries);
    future = connection.search(searchRequest, buffer);
    future = connection.searchAsync(searchRequest, null, buffer);
  }
opendj3/opendj-ldap-sdk/src/test/java/com/forgerock/opendj/util/SynchronousConnectionTestCase.java
File was deleted
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnectionTestCase.java
New file
@@ -0,0 +1,605 @@
/*
 * 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 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.LinkedList;
import java.util.List;
import org.forgerock.opendj.ldap.requests.*;
import org.forgerock.opendj.ldap.responses.*;
import org.testng.annotations.Test;
import com.forgerock.opendj.util.CompletedFutureResult;
/**
 * Unit test for AbstractAsynchronousConnection. The tests verify that all
 * synchronous operation methods delegate to the equivalent asynchronous method.
 */
@SuppressWarnings("javadoc")
public class AbstractAsynchronousConnectionTestCase extends SdkTestCase
{
  private final class MockConnection extends AbstractAsynchronousConnection
  {
    private final ResultCode resultCode;
    private final SearchResultEntry entry;
    private MockConnection(ResultCode resultCode)
    {
      this(resultCode, null);
    }
    private MockConnection(ResultCode resultCode, SearchResultEntry entry)
    {
      this.resultCode = resultCode;
      this.entry = entry;
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<Void> abandonAsync(AbandonRequest request)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<Void>((Void) null);
      }
      else
      {
        return new CompletedFutureResult<Void>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<Result> addAsync(AddRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<Result>(
            Responses.newResult(resultCode));
      }
      else
      {
        return new CompletedFutureResult<Result>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public void addConnectionEventListener(ConnectionEventListener listener)
        throws IllegalStateException, NullPointerException
    {
      // Do nothing.
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<BindResult> bindAsync(BindRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<BindResult>(
            Responses.newBindResult(resultCode));
      }
      else
      {
        return new CompletedFutureResult<BindResult>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public void close(UnbindRequest request, String reason)
        throws NullPointerException
    {
      // Do nothing.
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<CompareResult> compareAsync(CompareRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super CompareResult> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<CompareResult>(
            Responses.newCompareResult(resultCode));
      }
      else
      {
        return new CompletedFutureResult<CompareResult>(
            newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<Result> deleteAsync(DeleteRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<Result>(
            Responses.newResult(resultCode));
      }
      else
      {
        return new CompletedFutureResult<Result>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public <R extends ExtendedResult> FutureResult<R> extendedRequestAsync(
        ExtendedRequest<R> request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super R> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<R>(request.getResultDecoder()
            .newExtendedErrorResult(resultCode, "", ""));
      }
      else
      {
        return new CompletedFutureResult<R>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public boolean isClosed()
    {
      return false;
    }
    /**
     * {@inheritDoc}
     */
    public boolean isValid()
    {
      return true;
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<Result> modifyAsync(ModifyRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<Result>(
            Responses.newResult(resultCode));
      }
      else
      {
        return new CompletedFutureResult<Result>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<Result> modifyDNAsync(ModifyDNRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<Result>(
            Responses.newResult(resultCode));
      }
      else
      {
        return new CompletedFutureResult<Result>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public void removeConnectionEventListener(ConnectionEventListener listener)
        throws NullPointerException
    {
      // Do nothing.
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<Result> searchAsync(SearchRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        SearchResultHandler resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (entry != null)
      {
        resultHandler.handleEntry(entry);
      }
      if (!resultCode.isExceptional())
      {
        return new CompletedFutureResult<Result>(
            Responses.newResult(resultCode));
      }
      else
      {
        return new CompletedFutureResult<Result>(newErrorResult(resultCode));
      }
    }
    /**
     * {@inheritDoc}
     */
    public String toString()
    {
      return "MockConnection";
    }
  }
  @Test()
  public void testAddRequestSuccess() throws Exception
  {
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS);
    final AddRequest addRequest = Requests.newAddRequest("cn=test");
    assertThat(mockConnection.add(addRequest).getResultCode()).isEqualTo(
        ResultCode.SUCCESS);
  }
  @Test()
  public void testAddRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final AddRequest addRequest = Requests.newAddRequest("cn=test");
    try
    {
      mockConnection.add(addRequest);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
    }
  }
  @Test()
  public void testBindRequestSuccess() throws Exception
  {
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS);
    final BindRequest bindRequest = Requests.newSimpleBindRequest();
    assertThat(mockConnection.bind(bindRequest).getResultCode()).isEqualTo(
        ResultCode.SUCCESS);
  }
  @Test()
  public void testBindRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final BindRequest bindRequest = Requests.newSimpleBindRequest();
    try
    {
      mockConnection.bind(bindRequest);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
    }
  }
  @Test()
  public void testCompareRequestSuccess() throws Exception
  {
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS);
    final CompareRequest compareRequest = Requests.newCompareRequest("cn=test",
        "cn", "test");
    assertThat(mockConnection.compare(compareRequest).getResultCode())
        .isEqualTo(ResultCode.SUCCESS);
  }
  @Test()
  public void testCompareRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final CompareRequest compareRequest = Requests.newCompareRequest("cn=test",
        "cn", "test");
    try
    {
      mockConnection.compare(compareRequest);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
    }
  }
  @Test()
  public void testDeleteRequestSuccess() throws Exception
  {
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS);
    final DeleteRequest deleteRequest = Requests.newDeleteRequest("cn=test");
    assertThat(mockConnection.delete(deleteRequest).getResultCode()).isEqualTo(
        ResultCode.SUCCESS);
  }
  @Test()
  public void testDeleteRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final DeleteRequest deleteRequest = Requests.newDeleteRequest("cn=test");
    try
    {
      mockConnection.delete(deleteRequest);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
    }
  }
  @Test()
  public void testExtendedRequestSuccess() throws Exception
  {
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS);
    final GenericExtendedRequest extendedRequest = Requests
        .newGenericExtendedRequest("test");
    assertThat(mockConnection.extendedRequest(extendedRequest).getResultCode())
        .isEqualTo(ResultCode.SUCCESS);
  }
  @Test()
  public void testExtendedRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final GenericExtendedRequest extendedRequest = Requests
        .newGenericExtendedRequest("test");
    try
    {
      mockConnection.extendedRequest(extendedRequest);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
    }
  }
  @Test()
  public void testModifyRequestSuccess() throws Exception
  {
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS);
    final ModifyRequest modifyRequest = Requests.newModifyRequest("cn=test");
    assertThat(mockConnection.modify(modifyRequest).getResultCode()).isEqualTo(
        ResultCode.SUCCESS);
  }
  @Test()
  public void testModifyRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final ModifyRequest modifyRequest = Requests.newModifyRequest("cn=test");
    try
    {
      mockConnection.modify(modifyRequest);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
    }
  }
  @Test()
  public void testModifyDNRequestSuccess() throws Exception
  {
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS);
    final ModifyDNRequest modifyDNRequest = Requests.newModifyDNRequest(
        "cn=test", "cn=newrdn");
    assertThat(mockConnection.modifyDN(modifyDNRequest).getResultCode())
        .isEqualTo(ResultCode.SUCCESS);
  }
  @Test()
  public void testModifyDNRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final ModifyDNRequest modifyDNRequest = Requests.newModifyDNRequest(
        "cn=test", "cn=newrdn");
    try
    {
      mockConnection.modifyDN(modifyDNRequest);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
    }
  }
  @Test()
  public void testSearchRequestSuccess() throws Exception
  {
    final SearchResultEntry entry = Responses.newSearchResultEntry("cn=test");
    final Connection mockConnection = new MockConnection(ResultCode.SUCCESS,
        entry);
    final SearchRequest searchRequest = Requests.newSearchRequest("cn=test",
        SearchScope.BASE_OBJECT, "(objectClass=*)");
    List<SearchResultEntry> entries = new LinkedList<SearchResultEntry>();
    assertThat(mockConnection.search(searchRequest, entries).getResultCode())
        .isEqualTo(ResultCode.SUCCESS);
    assertThat(entries.size()).isEqualTo(1);
    assertThat(entries.iterator().next()).isSameAs(entry);
  }
  @Test()
  public void testSearchRequestFail() throws Exception
  {
    final Connection mockConnection = new MockConnection(
        ResultCode.UNWILLING_TO_PERFORM);
    final SearchRequest searchRequest = Requests.newSearchRequest("cn=test",
        SearchScope.BASE_OBJECT, "(objectClass=*)");
    List<SearchResultEntry> entries = new LinkedList<SearchResultEntry>();
    try
    {
      mockConnection.search(searchRequest, entries);
      fail();
    }
    catch (ErrorResultException e)
    {
      assertThat(e.getResult().getResultCode()).isEqualTo(
          ResultCode.UNWILLING_TO_PERFORM);
      assertThat(entries.isEmpty());
    }
  }
}
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java
@@ -29,6 +29,7 @@
package org.forgerock.opendj.ldap;
import static org.fest.assertions.Assertions.assertThat;
import static org.testng.Assert.assertNotNull;
@@ -69,7 +70,7 @@
@SuppressWarnings("javadoc")
public class ConnectionFactoryTestCase extends SdkTestCase
{
  class MyResultHandler implements ResultHandler<AsynchronousConnection>
  class MyResultHandler implements ResultHandler<Connection>
  {
    // latch.
    private final CountDownLatch latch;
@@ -94,7 +95,7 @@
    public void handleResult(final AsynchronousConnection con)
    public void handleResult(final Connection con)
    {
      //
      latch.countDown();
@@ -166,8 +167,7 @@
    // AuthenticatedConnectionFactory with multi-stage SASL
    factories[3][0] = new AuthenticatedConnectionFactory(
        new LDAPConnectionFactory("localhost", TestCaseUtils.getLdapPort()),
        Requests.newCRAMMD5SASLBindRequest("id:user",
            "password".toCharArray()));
        Requests.newCRAMMD5SASLBindRequest("id:user", "password".toCharArray()));
    // LDAPConnectionFactory with default options
    factories[4][0] = new LDAPConnectionFactory("localhost",
@@ -267,12 +267,11 @@
  public void testBlockingFutureNoHandler(ConnectionFactory factory)
      throws Exception
  {
    final FutureResult<AsynchronousConnection> future = factory
        .getAsynchronousConnection(null);
    final AsynchronousConnection con = future.get();
    final FutureResult<Connection> future = factory.getConnectionAsync(null);
    final Connection con = future.get();
    // quickly check if it is a valid connection.
    // Don't use a result handler.
    assertNotNull(con.readEntry(DN.rootDN(), null, null).get());
    assertNotNull(con.readEntryAsync(DN.rootDN(), null, null).get());
    con.close();
  }
@@ -290,7 +289,7 @@
    // Use the handler to get the result asynchronously.
    final CountDownLatch latch = new CountDownLatch(1);
    final MyResultHandler handler = new MyResultHandler(latch);
    factory.getAsynchronousConnection(handler);
    factory.getConnectionAsync(handler);
    // Since we don't have anything to do, we would rather
    // be notified by the latch when the other thread calls our handler.
@@ -336,8 +335,8 @@
  {
    // Create a connection factory: this should always use the default schema,
    // even if it is updated.
    final ConnectionFactory factory = new LDAPConnectionFactory(
        "localhost", TestCaseUtils.getLdapPort());
    final ConnectionFactory factory = new LDAPConnectionFactory("localhost",
        TestCaseUtils.getLdapPort());
    final Schema defaultSchema = Schema.getDefaultSchema();
    final Connection connection = factory.getConnection();
@@ -346,14 +345,11 @@
      // Simulate a client which reads the schema from the server and then
      // sets it as the application default. We then want subsequent
      // operations to use this schema, not the original default.
      final SchemaBuilder builder = new SchemaBuilder(
          Schema.getCoreSchema());
      builder
          .addAttributeType(
              "( 0.9.2342.19200300.100.1.3 NAME 'mail' EQUALITY "
                  + "caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch "
                  + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )",
              false);
      final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
      builder.addAttributeType(
          "( 0.9.2342.19200300.100.1.3 NAME 'mail' EQUALITY "
              + "caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch "
              + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )", false);
      final Schema testSchema = builder.toSchema().asNonStrictSchema();
      assertThat(testSchema.getWarnings()).isEmpty();
      Schema.setDefaultSchema(testSchema);
@@ -364,8 +360,8 @@
      assertThat(e.getAttribute("mail")).isNotNull();
      assertThat(
          e.getAttribute(AttributeDescription.valueOf("mail",
              testSchema))).isNotNull();
          e.getAttribute(AttributeDescription.valueOf("mail", testSchema)))
          .isNotNull();
    }
    finally
    {
@@ -382,7 +378,8 @@
  /**
   * Tests connection pool closure.
   *
   * @throws Exception If an unexpected exception occurred.
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @SuppressWarnings("unchecked")
  @Test
@@ -398,19 +395,19 @@
    // Mock underlying connection factory which always succeeds.
    final ConnectionFactory mockFactory = mock(ConnectionFactory.class);
    when(mockFactory.getAsynchronousConnection(any(ResultHandler.class)))
        .thenAnswer(new Answer<FutureResult<AsynchronousConnection>>()
    when(mockFactory.getConnectionAsync(any(ResultHandler.class))).thenAnswer(
        new Answer<FutureResult<Connection>>()
        {
          public FutureResult<AsynchronousConnection> answer(
              InvocationOnMock invocation) throws Throwable
          public FutureResult<Connection> answer(InvocationOnMock invocation)
              throws Throwable
          {
            // Update state.
            final int connectionID = realConnectionCount.getAndIncrement();
            realConnectionIsClosed[connectionID] = false;
            // Mock connection decrements counter on close.
            AsynchronousConnection mockConnection = mock(AsynchronousConnection.class);
            Connection mockConnection = mock(Connection.class);
            doAnswer(new Answer<Void>()
            {
              public Void answer(InvocationOnMock invocation) throws Throwable
@@ -421,17 +418,17 @@
              }
            }).when(mockConnection).close();
            when(mockConnection.isValid()).thenReturn(true);
            when(mockConnection.toString()).thenReturn("Mock connection " + connectionID);
            when(mockConnection.toString()).thenReturn(
                "Mock connection " + connectionID);
            // Excecute handler and return future.
            ResultHandler<? super AsynchronousConnection> handler =
              (ResultHandler<? super AsynchronousConnection>) invocation.getArguments()[0];
            // Execute handler and return future.
            ResultHandler<? super Connection> handler = (ResultHandler<? super Connection>) invocation
                .getArguments()[0];
            if (handler != null)
            {
              handler.handleResult(mockConnection);
            }
            return new CompletedFutureResult<AsynchronousConnection>(
                mockConnection);
            return new CompletedFutureResult<Connection>(mockConnection);
          }
        });
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPListenerTestCase.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
@@ -122,8 +123,8 @@
    @Override
    public void handleAdd(final Integer requestContext,
        final AddRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
@@ -137,8 +138,8 @@
    @Override
    public void handleBind(final Integer requestContext, final int version,
        final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler.handleResult(Responses.newBindResult(ResultCode.SUCCESS));
@@ -152,8 +153,8 @@
    @Override
    public void handleCompare(final Integer requestContext,
        final CompareRequest request,
        final ResultHandler<? super CompareResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super CompareResult> resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler
@@ -203,8 +204,8 @@
    @Override
    public void handleDelete(final Integer requestContext,
        final DeleteRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
@@ -218,15 +219,14 @@
    @Override
    public <R extends ExtendedResult> void handleExtendedRequest(
        final Integer requestContext, final ExtendedRequest<R> request,
        final ResultHandler<? super R> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super R> resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler
          .handleErrorResult(ErrorResultException.newErrorResult(request
              .getResultDecoder().newExtendedErrorResult(
                  ResultCode.PROTOCOL_ERROR, "",
                  "Extended operation " + request.getOID() + " not supported")));
      resultHandler.handleErrorResult(ErrorResultException
          .newErrorResult(request.getResultDecoder().newExtendedErrorResult(
              ResultCode.PROTOCOL_ERROR, "",
              "Extended operation " + request.getOID() + " not supported")));
    }
@@ -237,8 +237,8 @@
    @Override
    public void handleModify(final Integer requestContext,
        final ModifyRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
@@ -252,8 +252,8 @@
    @Override
    public void handleModifyDN(final Integer requestContext,
        final ModifyDNRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
@@ -266,8 +266,9 @@
     */
    @Override
    public void handleSearch(final Integer requestContext,
        final SearchRequest request, final SearchResultHandler resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final SearchRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final SearchResultHandler resultHandler)
        throws UnsupportedOperationException
    {
      resultHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
@@ -382,7 +383,7 @@
   * @throws Exception
   *           If an unexpected error occurred.
   */
  @Test(enabled=false)
  @Test(enabled = false)
  public void testConnectionEventListenerDisconnect() throws Exception
  {
    final MockServerConnection onlineServerConnection = new MockServerConnection();
@@ -416,8 +417,8 @@
      connection.addConnectionEventListener(listener);
      Assert.assertEquals(listener.closeLatch.getCount(), 1);
      Assert.assertTrue(onlineServerConnection.isConnected
          .await(10, TimeUnit.SECONDS));
      Assert.assertTrue(onlineServerConnection.isConnected.await(10,
          TimeUnit.SECONDS));
      onlineServerConnection.context.disconnect();
      listener.closeLatch.await();
      Assert.assertNull(listener.errorMessage);
@@ -474,8 +475,8 @@
      connection.addConnectionEventListener(listener);
      Assert.assertEquals(listener.closeLatch.getCount(), 1);
      Assert.assertTrue(onlineServerConnection.isConnected
          .await(10, TimeUnit.SECONDS));
      Assert.assertTrue(onlineServerConnection.isConnected.await(10,
          TimeUnit.SECONDS));
      onlineServerConnection.context.disconnect(ResultCode.BUSY, "test");
      listener.closeLatch.await();
      Assert.assertNull(listener.errorMessage);
@@ -715,8 +716,8 @@
        @Override
        public void handleBind(final Integer requestContext, final int version,
            final BindRequest request,
            final ResultHandler<? super BindResult> resultHandler,
            final IntermediateResponseHandler intermediateResponseHandler)
            final IntermediateResponseHandler intermediateResponseHandler,
            final ResultHandler<? super BindResult> resultHandler)
            throws UnsupportedOperationException
        {
          // Get connection from load balancer, this should fail over twice
@@ -904,8 +905,8 @@
        @Override
        public void handleBind(final Integer requestContext, final int version,
            final BindRequest request,
            final ResultHandler<? super BindResult> resultHandler,
            final IntermediateResponseHandler intermediateResponseHandler)
            final IntermediateResponseHandler intermediateResponseHandler,
            final ResultHandler<? super BindResult> resultHandler)
            throws UnsupportedOperationException
        {
          // First attempt offline server.
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
@@ -137,8 +137,7 @@
  private class LDAPServerConnection implements
      ServerConnection<Integer>
  private class LDAPServerConnection implements ServerConnection<Integer>
  {
    private final LDAPClientContext clientContext;
@@ -187,9 +186,9 @@
     * @param intermediateResponseHandler
     * @throws UnsupportedOperationException
     */
    public void handleAdd(final Integer context,
        final AddRequest request, final ResultHandler<? super Result> handler,
        final IntermediateResponseHandler intermediateResponseHandler)
    public void handleAdd(final Integer context, final AddRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> handler)
        throws UnsupportedOperationException
    {
      Result result = null;
@@ -201,7 +200,8 @@
      {
        // duplicate entry.
        result = Responses.newResult(ResultCode.ENTRY_ALREADY_EXISTS);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        final ErrorResultException ere = ErrorResultException
            .newErrorResult(result);
        handler.handleErrorResult(ere);
        // doesn't matter if it was canceled.
        requestsInProgress.remove(context);
@@ -223,7 +223,8 @@
      if (abReq.isCanceled())
      {
        result = Responses.newResult(ResultCode.CANCELLED);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        final ErrorResultException ere = ErrorResultException
            .newErrorResult(result);
        handler.handleErrorResult(ere);
        requestsInProgress.remove(context);
        return;
@@ -247,8 +248,8 @@
     */
    public void handleBind(final Integer context, final int version,
        final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO: all bind types.
@@ -350,8 +351,8 @@
                  }
                  catch (SaslException e)
                  {
                    throw ErrorResultException.newErrorResult(Responses.newResult(
                        ResultCode.OPERATIONS_ERROR).setCause(e));
                    throw ErrorResultException.newErrorResult(Responses
                        .newResult(ResultCode.OPERATIONS_ERROR).setCause(e));
                  }
                }
@@ -366,8 +367,8 @@
                  }
                  catch (SaslException e)
                  {
                    throw ErrorResultException.newErrorResult(Responses.newResult(
                        ResultCode.OPERATIONS_ERROR).setCause(e));
                    throw ErrorResultException.newErrorResult(Responses
                        .newResult(ResultCode.OPERATIONS_ERROR).setCause(e));
                  }
                }
              };
@@ -385,9 +386,10 @@
        }
        catch (Exception e)
        {
          resultHandler.handleErrorResult(ErrorResultException.newErrorResult(Responses
              .newBindResult(ResultCode.OPERATIONS_ERROR).setCause(e)
              .setDiagnosticMessage(e.toString())));
          resultHandler.handleErrorResult(ErrorResultException
              .newErrorResult(Responses
                  .newBindResult(ResultCode.OPERATIONS_ERROR).setCause(e)
                  .setDiagnosticMessage(e.toString())));
        }
      }
      else
@@ -457,8 +459,8 @@
     */
    public void handleCompare(final Integer context,
        final CompareRequest request,
        final ResultHandler<? super CompareResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super CompareResult> resultHandler)
        throws UnsupportedOperationException
    {
      CompareResult result = null;
@@ -470,7 +472,8 @@
      {
        // entry not found.
        result = Responses.newCompareResult(ResultCode.NO_SUCH_ATTRIBUTE);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        final ErrorResultException ere = ErrorResultException
            .newErrorResult(result);
        resultHandler.handleErrorResult(ere);
        // doesn't matter if it was canceled.
        requestsInProgress.remove(context);
@@ -489,7 +492,8 @@
          if (abReq.isCanceled())
          {
            final Result r = Responses.newResult(ResultCode.CANCELLED);
            final ErrorResultException ere = ErrorResultException.newErrorResult(r);
            final ErrorResultException ere = ErrorResultException
                .newErrorResult(r);
            resultHandler.handleErrorResult(ere);
            requestsInProgress.remove(context);
            return;
@@ -519,8 +523,8 @@
     */
    public void handleDelete(final Integer context,
        final DeleteRequest request,
        final ResultHandler<? super Result> handler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> handler)
        throws UnsupportedOperationException
    {
      Result result = null;
@@ -532,7 +536,8 @@
      {
        // entry is not found.
        result = Responses.newResult(ResultCode.NO_SUCH_OBJECT);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        final ErrorResultException ere = ErrorResultException
            .newErrorResult(result);
        handler.handleErrorResult(ere);
        // doesn't matter if it was canceled.
        requestsInProgress.remove(context);
@@ -542,7 +547,8 @@
      if (abReq.isCanceled())
      {
        result = Responses.newResult(ResultCode.CANCELLED);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        final ErrorResultException ere = ErrorResultException
            .newErrorResult(result);
        handler.handleErrorResult(ere);
        requestsInProgress.remove(context);
        return;
@@ -563,8 +569,8 @@
     */
    public <R extends ExtendedResult> void handleExtendedRequest(
        final Integer context, final ExtendedRequest<R> request,
        final ResultHandler<? super R> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super R> resultHandler)
        throws UnsupportedOperationException
    {
      if (request.getOID().equals(StartTLSExtendedRequest.OID))
@@ -588,8 +594,8 @@
     */
    public void handleModify(final Integer context,
        final ModifyRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO:
@@ -606,8 +612,8 @@
     */
    public void handleModifyDN(final Integer context,
        final ModifyDNRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final IntermediateResponseHandler intermediateResponseHandler,
        final ResultHandler<? super Result> resultHandler)
        throws UnsupportedOperationException
    {
      // TODO
@@ -616,15 +622,16 @@
    /**
     * @param context
     * @param request
     * @param resultHandler
     * @param intermediateResponseHandler
     * @param resultHandler
     * @param context
     * @throws UnsupportedOperationException
     */
    public void handleSearch(final Integer context,
        final SearchRequest request, final SearchResultHandler resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        final SearchRequest request,
        final IntermediateResponseHandler intermediateResponseHandler,
        final SearchResultHandler resultHandler)
        throws UnsupportedOperationException
    {
      Result result = null;
@@ -636,7 +643,8 @@
      {
        // Entry not found.
        result = Responses.newResult(ResultCode.NO_SUCH_OBJECT);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        final ErrorResultException ere = ErrorResultException
            .newErrorResult(result);
        resultHandler.handleErrorResult(ere);
        // Should searchResultHandler handle anything?
@@ -648,7 +656,8 @@
      if (abReq.isCanceled())
      {
        result = Responses.newResult(ResultCode.CANCELLED);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        final ErrorResultException ere = ErrorResultException
            .newErrorResult(result);
        resultHandler.handleErrorResult(ere);
        requestsInProgress.remove(context);
        return;
@@ -685,8 +694,7 @@
  // The mapping between the message id and the requests the server is currently
  // handling.
  private final ConcurrentHashMap<Integer, AbandonableRequest> requestsInProgress =
    new ConcurrentHashMap<Integer, AbandonableRequest>();
  private final ConcurrentHashMap<Integer, AbandonableRequest> requestsInProgress = new ConcurrentHashMap<Integer, AbandonableRequest>();
  private SSLContext sslContext;
@@ -704,7 +712,8 @@
      final String sn = String.format("sn: %d", i);
      final String uid = String.format("uid: user.%d", i);
      // See org.forgerock.opendj.ldap.ConnectionFactoryTestCase.testSchemaUsage().
      // See
      // org.forgerock.opendj.ldap.ConnectionFactoryTestCase.testSchemaUsage().
      final String mail = String.format("mail: user.%d@example.com", i);
      final DN d = DN.valueOf(dn);
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java
@@ -134,7 +134,7 @@
      private BindWorkerThread(final AsynchronousConnection connection,
      private BindWorkerThread(final Connection connection,
          final ConnectionFactory connectionFactory)
      {
        super(connection, connectionFactory);
@@ -143,8 +143,7 @@
      @Override
      public FutureResult<?> performOperation(
          final AsynchronousConnection connection,
      public FutureResult<?> performOperation(final Connection connection,
          final DataSource[] dataSources, final long startTime)
      {
        if (dataSources != null)
@@ -179,7 +178,7 @@
          }
          final RecursiveFutureResult<SearchResultEntry, BindResult> future =
            new RecursiveFutureResult<SearchResultEntry, BindResult>(
              new RecursiveFutureResult<SearchResultEntry, BindResult>(
              new BindUpdateStatsResultHandler(startTime))
          {
            @Override
@@ -197,7 +196,7 @@
              return performBind(connection, data, resultHandler);
            }
          };
          connection.searchSingleEntry(sr, future);
          connection.searchSingleEntryAsync(sr, future);
          return future;
        }
        else
@@ -209,9 +208,8 @@
      private FutureResult<BindResult> performBind(
          final AsynchronousConnection connection, final Object[] data,
          final ResultHandler<? super BindResult> handler)
      private FutureResult<BindResult> performBind(final Connection connection,
          final Object[] data, final ResultHandler<? super BindResult> handler)
      {
        final boolean useInvalidPassword;
@@ -380,28 +378,20 @@
          }
        }
        return connection.bind(br, handler);
        return connection.bindAsync(br, null, handler);
      }
    }
    private final AtomicLong searchWaitRecentTime = new AtomicLong();
    private final AtomicInteger invalidCredRecentCount = new AtomicInteger();
    private String filter;
    private String baseDN;
    private SearchScope scope;
    private DereferenceAliasesPolicy dereferencesAliasesPolicy;
    private String[] attributes;
    private BindRequest bindRequest;
    private int invalidCredPercent;
@@ -415,8 +405,7 @@
    @Override
    WorkerThread newWorkerThread(
        final AsynchronousConnection connection,
    WorkerThread newWorkerThread(final Connection connection,
        final ConnectionFactory connectionFactory)
    {
      return new BindWorkerThread(connection, connectionFactory);
@@ -449,7 +438,6 @@
  private BooleanArgument verbose;
  private BooleanArgument scriptFriendly;
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthenticatedConnectionFactory.java
@@ -23,12 +23,14 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap.tools;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.*;
import org.forgerock.opendj.ldap.requests.BindRequest;
import org.forgerock.opendj.ldap.responses.BindResult;
@@ -57,16 +59,13 @@
 * the connection attempt will fail and an {@code ErrorResultException} will be
 * thrown.
 */
final class AuthenticatedConnectionFactory extends AbstractConnectionFactory
    implements ConnectionFactory
final class AuthenticatedConnectionFactory implements ConnectionFactory
{
  /**
   * An authenticated asynchronous connection supports all operations except
   * Bind operations.
   * An authenticated connection supports all operations except Bind operations.
   */
  public static final class AuthenticatedAsynchronousConnection extends
      AsynchronousConnectionDecorator
  public static final class AuthenticatedConnection extends ConnectionDecorator
  {
    private final BindRequest request;
@@ -75,9 +74,8 @@
    private AuthenticatedAsynchronousConnection(
        final AsynchronousConnection connection, final BindRequest request,
        final BindResult result)
    private AuthenticatedConnection(final Connection connection,
        final BindRequest request, final BindResult result)
    {
      super(connection);
      this.request = request;
@@ -90,10 +88,13 @@
     * Bind operations are not supported by pre-authenticated connections. This
     * method will always throw {@code UnsupportedOperationException}.
     */
    public FutureResult<BindResult> bind(final BindRequest request,
        final ResultHandler<? super BindResult> handler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    /**
     * {@inheritDoc}
     */
    public BindResult bind(BindRequest request) throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      throw new UnsupportedOperationException();
    }
@@ -101,12 +102,24 @@
    /**
     * Bind operations are not supported by pre-authenticated connections. This
     * method will always throw {@code UnsupportedOperationException}.
     * {@inheritDoc}
     */
    public FutureResult<BindResult> bind(final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
    public BindResult bind(String name, char[] password)
        throws ErrorResultException, InterruptedException,
        LocalizedIllegalArgumentException, UnsupportedOperationException,
        IllegalStateException, NullPointerException
    {
      throw new UnsupportedOperationException();
    }
    /**
     * {@inheritDoc}
     */
    public FutureResult<BindResult> bindAsync(BindRequest request,
        IntermediateResponseHandler intermediateResponseHandler,
        ResultHandler<? super BindResult> resultHandler)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
@@ -144,7 +157,7 @@
     *           If this connection has already been closed, i.e. if
     *           {@code isClosed() == true}.
     */
    public FutureResult<BindResult> rebind(
    public FutureResult<BindResult> rebindAsync(
        final ResultHandler<? super BindResult> handler)
        throws UnsupportedOperationException, IllegalStateException
    {
@@ -177,7 +190,7 @@
        public void handleResult(final BindResult result)
        {
          // Save the result.
          AuthenticatedAsynchronousConnection.this.result = result;
          AuthenticatedConnection.this.result = result;
          if (clientHandler != null)
          {
@@ -187,7 +200,7 @@
      };
      return connection.bind(request, handlerWrapper);
      return connection.bindAsync(request, null, handlerWrapper);
    }
@@ -208,115 +221,20 @@
  /**
   * An authenticated synchronous connection supports all operations except Bind
   * operations.
   */
  public static final class AuthenticatedConnection extends
      SynchronousConnection
  {
    private final AuthenticatedAsynchronousConnection connection;
    private AuthenticatedConnection(
        final AuthenticatedAsynchronousConnection connection)
    {
      super(connection);
      this.connection = connection;
    }
    /**
     * Bind operations are not supported by pre-authenticated connections. This
     * method will always throw {@code UnsupportedOperationException}.
     */
    @Override
    public BindResult bind(final BindRequest request)
        throws UnsupportedOperationException
    {
      throw new UnsupportedOperationException();
    }
    /**
     * Bind operations are not supported by pre-authenticated connections. This
     * method will always throw {@code UnsupportedOperationException}.
     */
    @Override
    public BindResult bind(final String name, final char[] password)
        throws UnsupportedOperationException
    {
      throw new UnsupportedOperationException();
    }
    /**
     * Returns an unmodifiable view of the Bind result which was returned from
     * the server after authentication.
     *
     * @return The Bind result which was returned from the server after
     *         authentication.
     */
    public BindResult getAuthenticatedBindResult()
    {
      return connection.getAuthenticatedBindResult();
    }
    /**
     * Re-authenticates to the Directory Server using the bind request
     * associated with this connection. If re-authentication fails for some
     * reason then this connection will be automatically closed.
     *
     * @return The result of the operation.
     * @throws ErrorResultException
     *           If the result code indicates that the request failed for some
     *           reason.
     * @throws InterruptedException
     *           If the current thread was interrupted while waiting.
     * @throws UnsupportedOperationException
     *           If this connection does not support rebind operations.
     * @throws IllegalStateException
     *           If this connection has already been closed, i.e. if
     *           {@code isClosed() == true}.
     */
    public BindResult rebind() throws ErrorResultException,
        InterruptedException, UnsupportedOperationException,
        IllegalStateException
    {
      if (connection.request == null)
      {
        throw new UnsupportedOperationException();
      }
      return super.bind(connection.request);
    }
  }
  private static final class FutureResultImpl
  {
    private final FutureResultTransformer<BindResult, AsynchronousConnection> futureBindResult;
    private final RecursiveFutureResult<AsynchronousConnection, BindResult> futureConnectionResult;
    private final FutureResultTransformer<BindResult, Connection> futureBindResult;
    private final RecursiveFutureResult<Connection, BindResult> futureConnectionResult;
    private final BindRequest bindRequest;
    private AsynchronousConnection connection;
    private Connection connection;
    private FutureResultImpl(final BindRequest request,
        final ResultHandler<? super AsynchronousConnection> handler)
        final ResultHandler<? super Connection> handler)
    {
      this.bindRequest = request;
      this.futureBindResult = new FutureResultTransformer<BindResult, AsynchronousConnection>(
      this.futureBindResult = new FutureResultTransformer<BindResult, Connection>(
          handler)
      {
@@ -340,27 +258,26 @@
        @Override
        protected AuthenticatedAsynchronousConnection transformResult(
        protected AuthenticatedConnection transformResult(
            final BindResult result) throws ErrorResultException
        {
          // FIXME: should make the result unmodifiable.
          return new AuthenticatedAsynchronousConnection(connection,
              bindRequest, result);
          return new AuthenticatedConnection(connection, bindRequest, result);
        }
      };
      this.futureConnectionResult = new RecursiveFutureResult<AsynchronousConnection, BindResult>(
      this.futureConnectionResult = new RecursiveFutureResult<Connection, BindResult>(
          futureBindResult)
      {
        @Override
        protected FutureResult<? extends BindResult> chainResult(
            final AsynchronousConnection innerResult,
            final Connection innerResult,
            final ResultHandler<? super BindResult> handler)
            throws ErrorResultException
        {
          connection = innerResult;
          return connection.bind(bindRequest, handler);
          return connection.bindAsync(bindRequest, null, handler);
        }
      };
      futureBindResult.setFutureResult(futureConnectionResult);
@@ -371,9 +288,7 @@
  private final BindRequest request;
  private final ConnectionFactory parentFactory;
  private boolean allowRebinds = false;
@@ -403,13 +318,41 @@
  @Override
  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
      final ResultHandler<? super AsynchronousConnection> handler)
  /**
   * {@inheritDoc}
   */
  public Connection getConnection() throws ErrorResultException,
      InterruptedException
  {
    final Connection connection = parentFactory.getConnection();
    BindResult bindResult = null;
    try
    {
      bindResult = connection.bind(request);
    }
    finally
    {
      if (bindResult == null)
      {
        connection.close();
      }
    }
    // If the bind didn't succeed then an exception will have been thrown and
    // this line will not be reached.
    return new AuthenticatedConnection(connection, request, bindResult);
  }
  /**
   * {@inheritDoc}
   */
  public FutureResult<Connection> getConnectionAsync(
      final ResultHandler<? super Connection> handler)
  {
    final FutureResultImpl future = new FutureResultImpl(request, handler);
    future.futureConnectionResult.setFutureResult(parentFactory
        .getAsynchronousConnection(future.futureConnectionResult));
        .getConnectionAsync(future.futureConnectionResult));
    return future.futureBindResult;
  }
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java
@@ -57,7 +57,7 @@
      private ModifyWorkerThread(final AsynchronousConnection connection,
      private ModifyWorkerThread(final Connection connection,
          final ConnectionFactory connectionFactory)
      {
        super(connection, connectionFactory);
@@ -66,8 +66,7 @@
      @Override
      public FutureResult<?> performOperation(
          final AsynchronousConnection connection,
      public FutureResult<?> performOperation(final Connection connection,
          final DataSource[] dataSources, final long startTime)
      {
        if (dataSources != null)
@@ -75,7 +74,7 @@
          data = DataSource.generateData(dataSources, data);
        }
        mr = newModifyRequest(data);
        return connection.modify(mr,
        return connection.modifyAsync(mr, null,
            new UpdateStatsResultHandler<Result>(startTime));
      }
@@ -119,7 +118,6 @@
    private String baseDN;
    private String[] modStrings;
@@ -133,8 +131,7 @@
    @Override
    WorkerThread newWorkerThread(
        final AsynchronousConnection connection,
    WorkerThread newWorkerThread(final Connection connection,
        final ConnectionFactory connectionFactory)
    {
      return new ModifyWorkerThread(connection, connectionFactory);
@@ -167,7 +164,6 @@
  private BooleanArgument verbose;
  private BooleanArgument scriptFriendly;
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS.
 */
package com.forgerock.opendj.ldap.tools;
@@ -458,14 +459,12 @@
  abstract class WorkerThread extends Thread
  {
    private int count;
    private final AsynchronousConnection connection;
    private final Connection connection;
    private final ConnectionFactory connectionFactory;
    WorkerThread(final AsynchronousConnection connection,
    WorkerThread(final Connection connection,
        final ConnectionFactory connectionFactory)
    {
      super("Worker Thread");
@@ -475,9 +474,8 @@
    public abstract FutureResult<?> performOperation(
        AsynchronousConnection connection, DataSource[] dataSources,
        long startTime);
    public abstract FutureResult<?> performOperation(Connection connection,
        DataSource[] dataSources, long startTime);
@@ -485,10 +483,10 @@
    public void run()
    {
      FutureResult<?> future;
      AsynchronousConnection connection;
      Connection connection;
      final double targetTimeInMS =
        (1000.0 / (targetThroughput / (double) (numThreads * numConnections)));
      final double targetTimeInMS = (1000.0 / (targetThroughput /
          (double) (numThreads * numConnections)));
      double sleepTimeInMS = 0;
      long start;
      while (!stopRequested && !(maxIterations > 0 && count >= maxIterations))
@@ -497,8 +495,7 @@
        {
          try
          {
            connection = connectionFactory.getAsynchronousConnection(null)
                .get();
            connection = connectionFactory.getConnectionAsync(null).get();
          }
          catch (final InterruptedException e)
          {
@@ -520,14 +517,12 @@
        else
        {
          connection = this.connection;
          if (!noRebind
              && connection instanceof AuthenticatedAsynchronousConnection)
          if (!noRebind && connection instanceof AuthenticatedConnection)
          {
            final AuthenticatedAsynchronousConnection ac =
              (AuthenticatedAsynchronousConnection) connection;
            final AuthenticatedConnection ac = (AuthenticatedConnection) connection;
            try
            {
              ac.rebind(null).get();
              ac.rebindAsync(null).get();
            }
            catch (final InterruptedException e)
            {
@@ -869,10 +864,9 @@
      throws ArgumentException
  {
    this.app = app;
    numThreadsArgument = new IntegerArgument("numThreads", 't',
        "numThreads", false, false, true,
        LocalizableMessage.raw("{numThreads}"), 1, null, true, 1,
        false, 0,
    numThreadsArgument = new IntegerArgument("numThreads", 't', "numThreads",
        false, false, true, LocalizableMessage.raw("{numThreads}"), 1, null,
        true, 1, false, 0,
        LocalizableMessage.raw("Number of worker threads per connection"));
    numThreadsArgument.setPropertyName("numThreads");
    if (!alwaysSingleThreaded)
@@ -1003,8 +997,8 @@
  {
    numConnections = numConnectionsArgument.getIntValue();
    numThreads = numThreadsArgument.getIntValue();
    maxIterations = maxIterationsArgument.getIntValue()
        / numConnections / numThreads;
    maxIterations = maxIterationsArgument.getIntValue() / numConnections
        / numThreads;
    statsInterval = statsIntervalArgument.getIntValue() * 1000;
    targetThroughput = targetThroughputArgument.getIntValue();
@@ -1042,8 +1036,7 @@
  abstract WorkerThread newWorkerThread(
      final AsynchronousConnection connection,
  abstract WorkerThread newWorkerThread(final Connection connection,
      final ConnectionFactory connectionFactory);
@@ -1055,17 +1048,16 @@
  final int run(final ConnectionFactory connectionFactory)
  {
    final List<Thread> threads = new ArrayList<Thread>();
    final List<AsynchronousConnection> connections =
      new ArrayList<AsynchronousConnection>();
    final List<Connection> connections = new ArrayList<Connection>();
    AsynchronousConnection connection = null;
    Connection connection = null;
    try
    {
      for (int i = 0; i < numConnections; i++)
      {
        if (keepConnectionsOpen.isPresent() || noRebindArgument.isPresent())
        {
          connection = connectionFactory.getAsynchronousConnection(null).get();
          connection = connectionFactory.getConnectionAsync(null).get();
          connection.addConnectionEventListener(this);
          connections.add(connection);
        }
@@ -1098,7 +1090,7 @@
    }
    finally
    {
      for (final AsynchronousConnection c : connections)
      for (final Connection c : connections)
      {
        c.close();
      }
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java
@@ -121,12 +121,11 @@
    private final class SearchWorkerThread extends WorkerThread
    {
      private SearchRequest sr;
      private Object[] data;
      private SearchWorkerThread(final AsynchronousConnection connection,
      private SearchWorkerThread(final Connection connection,
          final ConnectionFactory connectionFactory)
      {
        super(connection, connectionFactory);
@@ -135,8 +134,7 @@
      @Override
      public FutureResult<?> performOperation(
          final AsynchronousConnection connection,
      public FutureResult<?> performOperation(final Connection connection,
          final DataSource[] dataSources, final long startTime)
      {
        if (sr == null)
@@ -159,20 +157,17 @@
          sr.setFilter(String.format(filter, data));
          sr.setName(String.format(baseDN, data));
        }
        return connection.search(sr, new SearchStatsHandler(startTime));
        return connection.searchAsync(sr, null, new SearchStatsHandler(
            startTime));
      }
    }
    private String filter;
    private String baseDN;
    private SearchScope scope;
    private DereferenceAliasesPolicy dereferencesAliasesPolicy;
    private String[] attributes;
@@ -186,8 +181,7 @@
    @Override
    WorkerThread newWorkerThread(
        final AsynchronousConnection connection,
    WorkerThread newWorkerThread(final Connection connection,
        final ConnectionFactory connectionFactory)
    {
      return new SearchWorkerThread(connection, connectionFactory);