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

Matthew Swift
29.31.2011 32034d853f3a284424ccfa87b6de210f1ca814e1
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);