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

Matthew Swift
02.01.2011 6385fb6984cb076c5a4a3ef5233deed798dc81c2
Fix OPENDJ-183: Add support for RequestContext and RequestHandlers

Added the following APIs:

* RequestContext
* CancelRequestListener
* RequestHandlerFactory
* Connections.newServerConnectionFactory(RequestHandler)
* Connections.newServerConnectionFactory(RequestHandlerFactory)

Updated example proxy and server.

4 files added
26 files modified
2101 ■■■■ changed files
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/proxy/Main.java 161 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/server/Main.java 252 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/AbstractLDAPFutureResultImpl.java 2 ●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java 14 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java 25 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/AsynchronousFutureResult.java 8 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnection.java 24 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnection.java 22 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractLoadBalancingAlgorithm.java 9 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/CancelRequestListener.java 64 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java 77 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ErrorResultException.java 84 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestContext.java 118 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactory.java 61 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactoryAdapter.java 983 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java 7 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java 22 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java 7 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java 37 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java 6 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/responses/AbstractExtendedResultDecoder.java 8 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java 20 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/ConnectionEntryReader.java 5 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/main/resources/org/forgerock/opendj/ldap/core.properties 16 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPListenerTestCase.java 2 ●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java 22 ●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java 7 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java 23 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java 8 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java 7 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/proxy/Main.java
@@ -62,18 +62,25 @@
 */
public final class Main
{
  /**
   * Proxy server connection factory implementation.
   */
  private static final class Proxy implements
      ServerConnectionFactory<LDAPClientContext, Integer>
  private static final class ProxyBackend implements
      RequestHandler<RequestContext>
  {
    private final class ServerConnectionImpl implements
        ServerConnection<Integer>
    {
    private final ConnectionFactory factory;
    private final ConnectionFactory bindFactory;
      private abstract class AbstractRequestCompletionHandler<R extends Result,
                                                              H extends ResultHandler<? super R>>
    private ProxyBackend(final ConnectionFactory factory,
        final ConnectionFactory bindFactory)
    {
      this.factory = factory;
      this.bindFactory = bindFactory;
    }
    private abstract class AbstractRequestCompletionHandler
        <R extends Result, H extends ResultHandler<? super R>>
          implements ResultHandler<R>
      {
        final H resultHandler;
@@ -158,8 +165,7 @@
      private final class SearchRequestCompletionHandler
          extends
    private final class SearchRequestCompletionHandler extends
          AbstractRequestCompletionHandler<Result, SearchResultHandler>
          implements SearchResultHandler
      {
@@ -202,33 +208,11 @@
      private ServerConnectionImpl(
          final LDAPClientContext clientContext)
      {
        // Nothing to do.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleAbandon(final Integer requestContext,
          final AbandonRequest request)
          throws UnsupportedOperationException
      {
        // Not implemented.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleAdd(
          final Integer requestContext,
    public void handleAdd(final RequestContext requestContext,
          final AddRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -260,10 +244,8 @@
       * {@inheritDoc}
       */
      @Override
      public void handleBind(
          final Integer requestContext,
          final int version,
          final BindRequest request,
    public void handleBind(final RequestContext requestContext,
        final int version, final BindRequest request,
          final ResultHandler<? super BindResult> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
          throws UnsupportedOperationException
@@ -289,8 +271,7 @@
            public void handleResult(
                final AsynchronousConnection connection)
            {
              final ResultHandler<BindResult> innerHandler =
                new ResultHandler<BindResult>()
            final ResultHandler<BindResult> innerHandler = new ResultHandler<BindResult>()
              {
                @Override
@@ -329,8 +310,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleCompare(
          final Integer requestContext,
    public void handleCompare(final RequestContext requestContext,
          final CompareRequest request,
          final ResultHandler<? super CompareResult> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -362,43 +342,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleConnectionClosed(
          final Integer requestContext, final UnbindRequest request)
      {
        // Client connection closed.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleConnectionDisconnected(
          final ResultCode resultCode, final String message)
      {
        // Client disconnected by server.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleConnectionError(final Throwable error)
      {
        // Client connection failed.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleDelete(
          final Integer requestContext,
    public void handleDelete(final RequestContext requestContext,
          final DeleteRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -431,7 +375,7 @@
       */
      @Override
      public <R extends ExtendedResult> void handleExtendedRequest(
          final Integer requestContext,
        final RequestContext requestContext,
          final ExtendedRequest<R> request,
          final ResultHandler<? super R> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -482,8 +426,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleModify(
          final Integer requestContext,
    public void handleModify(final RequestContext requestContext,
          final ModifyRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -515,8 +458,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleModifyDN(
          final Integer requestContext,
    public void handleModifyDN(final RequestContext requestContext,
          final ModifyDNRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -548,8 +490,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleSearch(
          final Integer requestContext,
    public void handleSearch(final RequestContext requestContext,
          final SearchRequest request,
          final SearchResultHandler resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -590,35 +531,6 @@
    private final ConnectionFactory factory;
    private final ConnectionFactory bindFactory;
    private Proxy(final ConnectionFactory factory,
        final ConnectionFactory bindFactory)
    {
      this.factory = factory;
      this.bindFactory = bindFactory;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public ServerConnection<Integer> handleAccept(
        final LDAPClientContext clientContext)
        throws ErrorResultException
    {
      return new ServerConnectionImpl(clientContext);
    }
  }
  /**
   * Main method.
   *
@@ -654,23 +566,28 @@
          new LDAPConnectionFactory(remoteAddress, remotePort),
          Integer.MAX_VALUE));
    }
    final RoundRobinLoadBalancingAlgorithm algorithm =
      new RoundRobinLoadBalancingAlgorithm(factories);
    final RoundRobinLoadBalancingAlgorithm bindAlgorithm =
      new RoundRobinLoadBalancingAlgorithm(bindFactories);
    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);
    // Create listener.
    final LDAPListenerOptions options = new LDAPListenerOptions()
        .setBacklog(4096);
    LDAPListener listener = null;
    try
    {
      listener = new LDAPListener(localAddress, localPort, new Proxy(
          factory, bindFactory), options);
      listener = new LDAPListener(localAddress, localPort,
          connectionHandler, options);
      System.out.println("Press any key to stop the server...");
      System.in.read();
    }
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/server/Main.java
@@ -64,20 +64,19 @@
 */
public final class Main
{
  /**
   * Proxy server connection factory implementation.
   */
  private static final class Store implements
      ServerConnectionFactory<LDAPClientContext, Integer>
  private static final class MemoryBackend implements
      RequestHandler<RequestContext>
  {
    private final class ServerConnectionImpl implements
        ServerConnection<Integer>
    {
    private final ConcurrentSkipListMap<DN, Entry> entries;
      private ServerConnectionImpl(
          final LDAPClientContext clientContext)
    private final ReentrantReadWriteLock entryLock = new ReentrantReadWriteLock();
    private MemoryBackend(
        final ConcurrentSkipListMap<DN, Entry> entries)
      {
        // Nothing to do.
      this.entries = entries;
      }
@@ -86,21 +85,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleAbandon(final Integer requestContext,
          final AbandonRequest request)
          throws UnsupportedOperationException
      {
        // Not implemented.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleAdd(
          final Integer requestContext,
    public void handleAdd(final RequestContext requestContext,
          final AddRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -113,11 +98,9 @@
          DN dn = request.getName();
          if (entries.containsKey(dn))
          {
            resultHandler
                .handleErrorResult(ErrorResultException
          resultHandler.handleErrorResult(ErrorResultException
                    .newErrorResult(ResultCode.ENTRY_ALREADY_EXISTS,
                        "The entry " + dn.toString()
                            + " already exists"));
                  "The entry " + dn.toString() + " already exists"));
          }
          DN parent = dn.parent();
@@ -147,10 +130,8 @@
       * {@inheritDoc}
       */
      @Override
      public void handleBind(
          final Integer requestContext,
          final int version,
          final BindRequest request,
    public void handleBind(final RequestContext requestContext,
        final int version, final BindRequest request,
          final ResultHandler<? super BindResult> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
          throws UnsupportedOperationException
@@ -177,8 +158,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleCompare(
          final Integer requestContext,
    public void handleCompare(final RequestContext requestContext,
          final CompareRequest request,
          final ResultHandler<? super CompareResult> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -193,43 +173,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleConnectionClosed(
          final Integer requestContext, final UnbindRequest request)
      {
        // Nothing to do.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleConnectionDisconnected(
          final ResultCode resultCode, final String message)
      {
        // Nothing to do.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleConnectionError(final Throwable error)
      {
        // Nothing to do.
      }
      /**
       * {@inheritDoc}
       */
      @Override
      public void handleDelete(
          final Integer requestContext,
    public void handleDelete(final RequestContext requestContext,
          final DeleteRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -243,11 +187,9 @@
          DN dn = request.getName();
          if (!entries.containsKey(dn))
          {
            resultHandler
                .handleErrorResult(ErrorResultException
                    .newErrorResult(ResultCode.NO_SUCH_OBJECT,
                        "The entry " + dn.toString()
                            + " does not exist"));
          resultHandler.handleErrorResult(ErrorResultException
              .newErrorResult(ResultCode.NO_SUCH_OBJECT, "The entry "
                  + dn.toString() + " does not exist"));
          }
          else
          {
@@ -269,7 +211,7 @@
       */
      @Override
      public <R extends ExtendedResult> void handleExtendedRequest(
          final Integer requestContext,
        final RequestContext requestContext,
          final ExtendedRequest<R> request,
          final ResultHandler<? super R> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -287,8 +229,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleModify(
          final Integer requestContext,
    public void handleModify(final RequestContext requestContext,
          final ModifyRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -304,11 +245,9 @@
          Entry entry = entries.get(dn);
          if (entry == null)
          {
            resultHandler
                .handleErrorResult(ErrorResultException
                    .newErrorResult(ResultCode.NO_SUCH_OBJECT,
                        "The entry " + dn.toString()
                            + " does not exist"));
          resultHandler.handleErrorResult(ErrorResultException
              .newErrorResult(ResultCode.NO_SUCH_OBJECT, "The entry "
                  + dn.toString() + " does not exist"));
          }
          Entry newEntry = new LinkedHashMapEntry(entry);
@@ -355,8 +294,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleModifyDN(
          final Integer requestContext,
    public void handleModifyDN(final RequestContext requestContext,
          final ModifyDNRequest request,
          final ResultHandler<? super Result> resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -374,8 +312,7 @@
       * {@inheritDoc}
       */
      @Override
      public void handleSearch(
          final Integer requestContext,
    public void handleSearch(final RequestContext requestContext,
          final SearchRequest request,
          final SearchResultHandler resultHandler,
          final IntermediateResponseHandler intermediateResponseHandler)
@@ -389,11 +326,9 @@
          Entry baseEntry = entries.get(dn);
          if (baseEntry == null)
          {
            resultHandler
                .handleErrorResult(ErrorResultException
                    .newErrorResult(ResultCode.NO_SUCH_OBJECT,
                        "The entry " + dn.toString()
                            + " does not exist"));
          resultHandler.handleErrorResult(ErrorResultException
              .newErrorResult(ResultCode.NO_SUCH_OBJECT, "The entry "
                  + dn.toString() + " does not exist"));
          }
          SearchScope scope = request.getScope();
@@ -411,10 +346,13 @@
          {
            sendEntry(request, resultHandler, baseEntry);
            NavigableMap<DN, Entry> subtree = entries.tailMap(dn,
                false);
          NavigableMap<DN, Entry> subtree = entries
              .tailMap(dn, false);
            for (Entry entry : subtree.values())
            {
            // Check for cancellation.
            requestContext.checkIfCancelled(false);
              DN childDN = entry.getName();
              if (childDN.isChildOf(dn))
              {
@@ -441,6 +379,9 @@
            NavigableMap<DN, Entry> subtree = entries.tailMap(dn);
            for (Entry entry : subtree.values())
            {
            // Check for cancellation.
            requestContext.checkIfCancelled(false);
              DN childDN = entry.getName();
              if (childDN.isSubordinateOrEqualTo(dn))
              {
@@ -464,8 +405,7 @@
          }
          else
          {
            resultHandler
                .handleErrorResult(newErrorResult(
          resultHandler.handleErrorResult(newErrorResult(
                    ResultCode.PROTOCOL_ERROR,
                    "Search request contains an unsupported search scope"));
            return;
@@ -474,6 +414,10 @@
          resultHandler.handleResult(Responses
              .newResult(ResultCode.SUCCESS));
        }
      catch (CancelledResultException e)
      {
        resultHandler.handleErrorResult(e);
      }
        finally
        {
          entryLock.readLock().unlock();
@@ -493,34 +437,6 @@
    private final ConcurrentSkipListMap<DN, Entry> entries;
    private final ReentrantReadWriteLock entryLock = new ReentrantReadWriteLock();
    private Store(final ConcurrentSkipListMap<DN, Entry> entries)
    {
      this.entries = entries;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public ServerConnection<Integer> handleAccept(
        final LDAPClientContext clientContext)
        throws ErrorResultException
    {
      return new ServerConnectionImpl(clientContext);
    }
  }
  /**
   * Main method.
   *
@@ -538,22 +454,70 @@
    // Parse command line arguments.
    final String localAddress = args[0];
    final int localPort = Integer.parseInt(args[1]);
    final String ldifFileName = args[2];
    // Create the memory backend.
    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);
    // Create listener.
    final LDAPListenerOptions options = new LDAPListenerOptions()
        .setBacklog(4096);
    LDAPListener listener = null;
    try
    {
      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);
      e.printStackTrace();
    }
    finally
    {
      if (listener != null)
      {
        listener.close();
      }
    }
  }
  /**
   * Reads the entries from the named LDIF file.
   *
   * @param ldifFileName
   *          The name of the LDIF file.
   * @return The entries.
   */
  private static ConcurrentSkipListMap<DN, Entry> readEntriesFromLDIF(
      final String ldifFileName)
  {
    final ConcurrentSkipListMap<DN, Entry> entries;
    // Read the LDIF.
    InputStream ldif;
    try
    {
      ldif = new FileInputStream(args[2]);
      ldif = new FileInputStream(ldifFileName);
    }
    catch (final FileNotFoundException e)
    {
      System.err.println(e.getMessage());
      System.exit(ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue());
      return;
      return null; // Satisfy compiler.
    }
    entries = new ConcurrentSkipListMap<DN, Entry>();
    final LDIFEntryReader reader = new LDIFEntryReader(ldif);
    ConcurrentSkipListMap<DN, Entry> entries = new ConcurrentSkipListMap<DN, Entry>();
    try
    {
      while (reader.hasNext())
@@ -566,7 +530,7 @@
    {
      System.err.println(e.getMessage());
      System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
      return;
      return null; // Satisfy compiler.
    }
    finally
    {
@@ -600,31 +564,7 @@
    {
      System.exit(1);
    }
    // Create listener.
    final LDAPListenerOptions options = new LDAPListenerOptions()
        .setBacklog(4096);
    LDAPListener listener = null;
    try
    {
      listener = new LDAPListener(localAddress, localPort, new Store(
          entries), 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);
      e.printStackTrace();
    }
    finally
    {
      if (listener != null)
      {
        listener.close();
      }
    }
    return entries;
  }
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/AbstractLDAPFutureResultImpl.java
@@ -156,7 +156,7 @@
  {
    if (result.getResultCode().isExceptional())
    {
      handleErrorResult(ErrorResultException.wrap(result));
      handleErrorResult(ErrorResultException.newErrorResult(result));
    }
    else
    {
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java
@@ -29,6 +29,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.List;
@@ -122,7 +124,7 @@
      if (connectionInvalidReason != null)
      {
        return new CompletedFutureResult<Void>(
            ErrorResultException.wrap(connectionInvalidReason), messageID);
            newErrorResult(connectionInvalidReason), messageID);
      }
      if (bindOrStartTLSInProgress.get())
      {
@@ -130,7 +132,7 @@
            ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
            "Bind or Start TLS operation in progress");
        return new CompletedFutureResult<Void>(
            ErrorResultException.wrap(errorResult), messageID);
            newErrorResult(errorResult), messageID);
      }
      // First remove the future associated with the request to be abandoned.
@@ -171,7 +173,7 @@
          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
      connectionErrorOccurred(errorResult);
      return new CompletedFutureResult<Void>(
          ErrorResultException.wrap(errorResult), messageID);
          newErrorResult(errorResult), messageID);
    }
  }
@@ -273,7 +275,7 @@
          .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
          .setDiagnosticMessage(
              "An error occurred while creating a bind context").setCause(e);
      final ErrorResultException error = ErrorResultException.wrap(errorResult);
      final ErrorResultException error = ErrorResultException.newErrorResult(errorResult);
      if (resultHandler != null)
      {
        resultHandler.handleErrorResult(error);
@@ -783,7 +785,7 @@
    {
      if (connectionInvalidReason != null)
      {
        throw ErrorResultException.wrap(connectionInvalidReason);
        throw newErrorResult(connectionInvalidReason);
      }
      pendingRequests.put(newMsgID, request);
    }
@@ -920,7 +922,7 @@
      for (final ConnectionEventListener listener : listeners)
      {
        listener.handleConnectionError(isDisconnectNotification,
            ErrorResultException.wrap(reason));
            newErrorResult(reason));
      }
    }
  }
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java
@@ -30,6 +30,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.io.IOException;
import java.net.SocketAddress;
import java.util.concurrent.ExecutionException;
@@ -40,7 +42,6 @@
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.StartTLSExtendedRequest;
import org.forgerock.opendj.ldap.responses.ExtendedResult;
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
import org.glassfish.grizzly.CompletionHandler;
import org.glassfish.grizzly.Connection;
@@ -156,22 +157,18 @@
                    @Override
                    public void failed(final Throwable throwable)
                    {
                      final Result errorResult = Responses
                          .newResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR)
                          .setCause(throwable)
                          .setDiagnosticMessage(throwable.getMessage());
                      handler.handleErrorResult(ErrorResultException
                          .wrap(errorResult));
                      handler.handleErrorResult(newErrorResult(
                          ResultCode.CLIENT_SIDE_CONNECT_ERROR,
                          throwable.getMessage(), throwable));
                    }
                  });
              return null;
            }
            catch (final IOException ioe)
            {
              final Result errorResult = Responses
                  .newResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR)
                  .setCause(ioe).setDiagnosticMessage(ioe.getMessage());
              throw ErrorResultException.wrap(errorResult);
              throw newErrorResult(
                  ResultCode.CLIENT_SIDE_CONNECT_ERROR,
                  ioe.getMessage(), ioe);
            }
          }
          handler.handleResult(null);
@@ -345,9 +342,7 @@
      t = t.getCause();
    }
    final Result result = Responses
        .newResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(t)
        .setDiagnosticMessage(t.getMessage());
    return ErrorResultException.wrap(result);
    return newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR,
        t.getMessage(), t);
  }
}
opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/util/AsynchronousFutureResult.java
@@ -29,13 +29,13 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import org.forgerock.opendj.ldap.*;
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
@@ -134,9 +134,7 @@
      ErrorResultException errorResult = handleCancelRequest(mayInterruptIfRunning);
      if (errorResult == null)
      {
        final Result result = Responses
            .newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED);
        errorResult = ErrorResultException.wrap(result);
        errorResult = newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED);
      }
      this.errorResult = errorResult;
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnection.java
@@ -32,6 +32,7 @@
import static org.forgerock.opendj.ldap.CoreMessages.ERR_NO_SEARCH_RESULT_ENTRIES;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
@@ -176,29 +177,26 @@
      if (entryCount == 0)
      {
        // Did not find any entries.
        final Result result = Responses.newResult(
            ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
        throw newErrorResult(
            ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
            ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
        throw ErrorResultException.wrap(result);
      }
      else if (entryCount > 1)
      {
        // Got more entries than expected.
        final Result result = Responses
            .newResult(ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
            .setDiagnosticMessage(
                ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(entryCount).toString());
        throw ErrorResultException.wrap(result);
        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.
        final Result result = Responses.newResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
            .setDiagnosticMessage(
        throw newErrorResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
                ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
                    firstReference.getURIs().iterator().next()).toString());
        throw ErrorResultException.wrap(result);
                firstReference.getURIs().iterator().next())
                .toString());
      }
      else
      {
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractConnection.java
@@ -32,6 +32,7 @@
import static org.forgerock.opendj.ldap.CoreMessages.ERR_NO_SEARCH_RESULT_ENTRIES;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.Collection;
import java.util.concurrent.BlockingQueue;
@@ -433,31 +434,26 @@
    if (handler.entryCount == 0)
    {
      // Did not find any entries.
      final Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
          ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
      throw ErrorResultException.wrap(result);
    }
    else if (handler.entryCount > 1)
    {
      // Got more entries than expected.
      final Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
          .setDiagnosticMessage(
              ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(handler.entryCount)
                  .toString());
      throw ErrorResultException.wrap(result);
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
          ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES
              .get(handler.entryCount).toString());
    }
    else if (handler.firstReference != null)
    {
      // Got an unexpected search result reference.
      final Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
          .setDiagnosticMessage(
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
              ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
                  handler.firstReference.getURIs().iterator().next())
                  .toString());
      throw ErrorResultException.wrap(result);
    }
    else
    {
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractLoadBalancingAlgorithm.java
@@ -29,6 +29,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -38,8 +40,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import org.forgerock.opendj.ldap.responses.Responses;
import com.forgerock.opendj.util.AsynchronousFutureResult;
import com.forgerock.opendj.util.StaticUtils;
import com.forgerock.opendj.util.Validator;
@@ -439,8 +439,7 @@
    // All factories are offline so give up. We could have a
    // configurable policy here such as waiting indefinitely, or for a
    // configurable timeout period.
    throw ErrorResultException.wrap(Responses.newResult(
        ResultCode.CLIENT_SIDE_CONNECT_ERROR).setDiagnosticMessage(
        "No operational connection factories available"));
    throw newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR,
        "No operational connection factories available");
  }
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/CancelRequestListener.java
New file
@@ -0,0 +1,64 @@
/*
 * 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 2011 ForgeRock AS
 */
package org.forgerock.opendj.ldap;
import java.util.EventListener;
import org.forgerock.i18n.LocalizableMessage;
/**
 * An object that registers to be notified when a cancellation request has been
 * received and processing of the request should be aborted if possible.
 * <p>
 * Requests may be cancelled as a result of an abandon request or a cancel
 * extended request sent from the client, or by the server itself (e.g. during
 * server shutdown).
 */
public interface CancelRequestListener extends EventListener
{
  /**
   * Invoked when a cancellation request has been received and processing of the
   * request should be aborted if possible.
   * <p>
   * Requests may be cancelled as a result of an abandon request or a cancel
   * extended request sent from the client, or by the server itself (e.g. during
   * server shutdown).
   * <p>
   * Implementations should, if possible, abort further processing of the
   * request and return an appropriate cancellation result.
   *
   * @param cancellationReason
   *          A message describing the reason why the request is being
   *          cancelled.
   */
  void handleCancelRequest(LocalizableMessage cancellationReason);
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Connections.java
@@ -334,6 +334,83 @@
  /**
   * Creates a new server connection factory using the provided
   * {@link RequestHandler}. The returned factory will manage connection and
   * request life-cycle, including request cancellation.
   * <p>
   * When processing requests, {@link RequestHandler} implementations are passed
   * a {@link RequestContext} as the first parameter which may be used for
   * detecting whether or not the request should be aborted due to cancellation
   * requests or other events, such as connection failure.
   * <p>
   * The returned factory maintains state information which includes a table of
   * active requests. Therefore, {@code RequestHandler} implementations are
   * required to always return results in order to avoid potential memory leaks.
   *
   * @param <C>
   *          The type of client context.
   * @param requestHandler
   *          The request handler which will be used for all client connections.
   * @return The new server connection factory.
   * @throws NullPointerException
   *           If {@code requestHandler} was {@code null}.
   */
  public static <C> ServerConnectionFactory<C, Integer> newServerConnectionFactory(
      final RequestHandler<RequestContext> requestHandler)
      throws NullPointerException
  {
    Validator.ensureNotNull(requestHandler);
    final RequestHandlerFactory<C, RequestContext> factory =
      new RequestHandlerFactory<C, RequestContext>()
    {
      public RequestHandler<RequestContext> handleAccept(
          C clientContext) throws ErrorResultException
      {
        return requestHandler;
      }
    };
    return new RequestHandlerFactoryAdapter<C>(factory);
  }
  /**
   * Creates a new server connection factory using the provided
   * {@link RequestHandlerFactory}. The returned factory will manage connection
   * and request life-cycle, including request cancellation.
   * <p>
   * When processing requests, {@link RequestHandler} implementations are passed
   * a {@link RequestContext} as the first parameter which may be used for
   * detecting whether or not the request should be aborted due to cancellation
   * requests or other events, such as connection failure.
   * <p>
   * The returned factory maintains state information which includes a table of
   * active requests. Therefore, {@code RequestHandler} implementations are
   * required to always return results in order to avoid potential memory leaks.
   *
   * @param <C>
   *          The type of client context.
   * @param factory
   *          The request handler factory to use for associating request
   *          handlers with client connections.
   * @return The new server connection factory.
   * @throws NullPointerException
   *           If {@code factory} was {@code null}.
   */
  public static <C> ServerConnectionFactory<C, Integer> newServerConnectionFactory(
      final RequestHandlerFactory<C, RequestContext> factory)
      throws NullPointerException
  {
    Validator.ensureNotNull(factory);
    return new RequestHandlerFactoryAdapter<C>(factory);
  }
  // Prevent instantiation.
  private Connections()
  {
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ErrorResultException.java
@@ -45,6 +45,27 @@
{
  /**
   * Creates a new error result exception with the provided result code and an
   * empty diagnostic message.
   *
   * @param resultCode
   *          The result code.
   * @return The new error result exception.
   * @throws IllegalArgumentException
   *           If the provided result code does not represent a failure.
   * @throws NullPointerException
   *           If {@code resultCode} was {@code null}.
   */
  public static ErrorResultException newErrorResult(
      ResultCode resultCode) throws IllegalArgumentException,
      NullPointerException
  {
    return newErrorResult(resultCode, null, null);
  }
  /**
   * Creates a new error result exception with the provided result code and
   * diagnostic message.
   *
@@ -59,9 +80,9 @@
   * @throws NullPointerException
   *           If {@code resultCode} was {@code null}.
   */
  public static ErrorResultException newErrorResult(ResultCode resultCode,
      String diagnosticMessage) throws IllegalArgumentException,
      NullPointerException
  public static ErrorResultException newErrorResult(
      ResultCode resultCode, String diagnosticMessage)
      throws IllegalArgumentException, NullPointerException
  {
    return newErrorResult(resultCode, diagnosticMessage, null);
  }
@@ -69,6 +90,30 @@
  /**
   * Creates a new error result exception with the provided result code and
   * cause. The diagnostic message will be taken from the cause, if provided.
   *
   * @param resultCode
   *          The result code.
   * @param cause
   *          The throwable cause, which may be {@code null} indicating that
   *          none was provided.
   * @return The new error result exception.
   * @throws IllegalArgumentException
   *           If the provided result code does not represent a failure.
   * @throws NullPointerException
   *           If {@code resultCode} was {@code null}.
   */
  public static ErrorResultException newErrorResult(
      ResultCode resultCode, Throwable cause)
      throws IllegalArgumentException, NullPointerException
  {
    return newErrorResult(resultCode, null, cause);
  }
  /**
   * Creates a new error result exception with the provided result code,
   * diagnostic message, and cause.
   *
@@ -78,28 +123,35 @@
   *          The diagnostic message, which may be empty or {@code null}
   *          indicating that none was provided.
   * @param cause
   *          The throwable cause, which may be null indicating that none was
   *          provided.
   *          The throwable cause, which may be {@code null} indicating that
   *          none was provided.
   * @return The new error result exception.
   * @throws IllegalArgumentException
   *           If the provided result code does not represent a failure.
   * @throws NullPointerException
   *           If {@code resultCode} was {@code null}.
   */
  public static ErrorResultException newErrorResult(ResultCode resultCode,
      String diagnosticMessage, Throwable cause)
  public static ErrorResultException newErrorResult(
      ResultCode resultCode, String diagnosticMessage, Throwable cause)
      throws IllegalArgumentException, NullPointerException
  {
    Result result = Responses.newResult(resultCode)
        .setDiagnosticMessage(diagnosticMessage).setCause(cause);
    return wrap(result);
    final Result result = Responses.newResult(resultCode);
    if (diagnosticMessage != null)
    {
      result.setDiagnosticMessage(diagnosticMessage);
    }
    else if (cause != null)
    {
      result.setDiagnosticMessage(cause.getLocalizedMessage());
    }
    result.setCause(cause);
    return newErrorResult(result);
  }
  /**
   * Wraps the provided result in an appropriate error result exception. The
   * type of error result exception used depends on the underlying result code.
   * Creates a new error result exception using the provided result.
   *
   * @param result
   *          The result whose result code indicates a failure.
@@ -109,8 +161,9 @@
   * @throws NullPointerException
   *           If {@code result} was {@code null}.
   */
  public static ErrorResultException wrap(final Result result)
      throws IllegalArgumentException, NullPointerException
  public static ErrorResultException newErrorResult(
      final Result result) throws IllegalArgumentException,
      NullPointerException
  {
    if (!result.getResultCode().isExceptional())
    {
@@ -199,7 +252,8 @@
   */
  ErrorResultException(final Result result)
  {
    super(result.getResultCode() + ": " + result.getDiagnosticMessage());
    super(result.getResultCode() + ": "
        + result.getDiagnosticMessage());
    this.result = result;
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestContext.java
New file
@@ -0,0 +1,118 @@
/*
 * 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 2011 ForgeRock AS
 */
package org.forgerock.opendj.ldap;
/**
 * The context associated with a request currently being processed by a request
 * handler. A request context can be used to query state information about the
 * request, such as whether or not it has been cancelled, as well as registering
 * to be notified if the request has been cancelled. Implementations may provide
 * additional information, such as the associated schema, time-stamp
 * information, etc.
 */
public interface RequestContext
{
  /**
   * Registers the provided cancellation listener with this request context so
   * that it can be notified if a cancellation request is received and
   * processing of the request should be aborted if possible.
   * <p>
   * Requests may be cancelled as a result of an abandon request or a cancel
   * extended request sent from the client, or by the server itself (e.g. during
   * server shutdown).
   * <p>
   * This method provides a event notification mechanism which can be used by
   * asynchronous request handler implementations to detect cancellation of
   * requests.
   *
   * @param listener
   *          The listener which wants to be notified if a cancellation request
   *          is received and processing of the request should be aborted if
   *          possible.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   * @see #checkIfCancelled
   */
  void addCancelRequestListener(CancelRequestListener listener)
      throws NullPointerException;
  /**
   * Throws {@link CancelledResultException} if a cancellation request has been
   * received and processing of the request should be aborted if possible.
   * <p>
   * Requests may be cancelled as a result of an abandon request or a cancel
   * extended request sent from the client, or by the server itself (e.g. during
   * server shutdown).
   * <p>
   * This method provides a polling mechanism which can be used by synchronous
   * request handler implementations to detect cancellation of requests.
   *
   * @param signalTooLate
   *          {@code true} to signal that, after this method returns, processing
   *          of the request will have proceeded too far for it to be aborted by
   *          subsequent cancellation requests.
   * @throws CancelledResultException
   *           If a cancellation request has been received and processing of the
   *           request should be aborted if possible.
   * @see #addCancelRequestListener
   */
  void checkIfCancelled(boolean signalTooLate)
      throws CancelledResultException;
  /**
   * Returns the message ID of the request, if available. Protocols, such as
   * LDAP and internal connections, include a unique message ID with each
   * request which may be useful for logging and auditing.
   *
   * @return The message ID of the request, or {@code -1} if there is no message
   *         ID associated with the request.
   */
  int getMessageID();
  /**
   * Removes the provided cancellation listener from this request context so
   * that it will not be notified if a cancellation request has been received.
   *
   * @param listener
   *          The listener which no longer wants to be notified if a
   *          cancellation request has been received.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
  void removeCancelRequestListener(CancelRequestListener listener)
      throws NullPointerException;
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactory.java
New file
@@ -0,0 +1,61 @@
/*
 * 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 2011 ForgeRock AS
 */
package org.forgerock.opendj.ldap;
/**
 * A handler interface for accepting new connections from clients.
 *
 * @param <C>
 *          The type of client context.
 * @param <R>
 *          The type of request context.
 */
public interface RequestHandlerFactory<C, R extends RequestContext>
{
  /**
   * Invoked when a new client connection is accepted by the associated
   * listener. Implementations should return a {@code RequestHandler} which will
   * be used to handle requests from the client connection.
   *
   * @param clientContext
   *          The protocol dependent context information associated with the
   *          client connection. Depending on the protocol this may contain
   *          information about the client such as their address and level
   *          connection security. It may also be used to manage the state of
   *          the client's connection.
   * @return A {@code RequestHandler} which will be used to handle requests from
   *         a client connection.
   * @throws ErrorResultException
   *           If this request handler factory cannot accept the client
   *           connection.
   */
  RequestHandler<R> handleAccept(C clientContext)
      throws ErrorResultException;
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactoryAdapter.java
New file
@@ -0,0 +1,983 @@
/*
 * 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 2011 ForgeRock AS
 */
package org.forgerock.opendj.ldap;
import static org.forgerock.opendj.ldap.CoreMessages.*;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.requests.*;
import org.forgerock.opendj.ldap.responses.*;
import com.forgerock.opendj.util.Validator;
/**
 * An adapter which converts a {@code RequestHandlerFactory} into a
 * {@code ServerConnectionFactory}.
 *
 * @param <C>
 *          The type of client context.
 */
final class RequestHandlerFactoryAdapter<C> implements
    ServerConnectionFactory<C, Integer>
{
  /**
   * Request context implementation.
   */
  private static class RequestContextImpl<S extends Result, H extends ResultHandler<? super S>>
      implements RequestContext, ResultHandler<S>
  {
    // Adapter class which invokes cancel result handlers with correct result
    // type.
    private static final class ExtendedResultHandlerHolder<R extends ExtendedResult>
    {
      private final ExtendedRequest<R> request;
      private final ResultHandler<? super R> resultHandler;
      private ExtendedResultHandlerHolder(
          final ExtendedRequest<R> request,
          final ResultHandler<? super R> resultHandler)
      {
        this.request = request;
        this.resultHandler = resultHandler;
      }
      private void handleSuccess()
      {
        final R cancelResult = request.getResultDecoder()
            .newExtendedErrorResult(ResultCode.SUCCESS, "", "");
        resultHandler.handleResult(cancelResult);
      }
      private void handleTooLate()
      {
        final R cancelResult = request.getResultDecoder()
            .newExtendedErrorResult(ResultCode.TOO_LATE, "", "");
        resultHandler.handleErrorResult(ErrorResultException
            .newErrorResult(cancelResult));
      }
    }
    private static enum RequestState
    {
      // Request active
      PENDING,
      // Request active, cancel requested
      CANCEL_REQUESTED,
      // Request active, too late to cancel
      TOO_LATE,
      // Result sent, not cancelled
      RESULT_SENT,
      // Result sent, was cancelled
      CANCELLED;
    }
    private final int messageID;
    // Cancellation state guarded by lock.
    private final Object stateLock = new Object();
    // These should be notified when a cancel request arrives, at most once.
    private List<CancelRequestListener> cancelRequestListeners = null;
    // These should be notified when the result is set.
    private List<ExtendedResultHandlerHolder<?>> cancelResultHandlers = null;
    private RequestState state = RequestState.PENDING;
    private LocalizableMessage cancelRequestReason = null;
    private boolean sendResult = true;
    private final boolean isCancelSupported;
    private final ServerConnectionImpl<?> clientConnection;
    protected final H resultHandler;
    protected RequestContextImpl(
        final ServerConnectionImpl<?> clientConnection,
        final H resultHandler, final int messageID,
        final boolean isCancelSupported)
    {
      this.clientConnection = clientConnection;
      this.resultHandler = resultHandler;
      this.messageID = messageID;
      this.isCancelSupported = isCancelSupported;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void addCancelRequestListener(
        final CancelRequestListener listener)
        throws NullPointerException
    {
      Validator.ensureNotNull(listener);
      boolean invokeImmediately = false;
      synchronized (stateLock)
      {
        switch (state)
        {
        case PENDING:
          if (cancelRequestListeners == null)
          {
            cancelRequestListeners = new LinkedList<CancelRequestListener>();
          }
          cancelRequestListeners.add(listener);
          break;
        case CANCEL_REQUESTED:
          // Signal immediately outside lock.
          invokeImmediately = true;
          break;
        case TOO_LATE:
        case RESULT_SENT:
        case CANCELLED:
          // No point in registering the callback since the request can never be
          // cancelled now.
          break;
        }
      }
      if (invokeImmediately)
      {
        listener.handleCancelRequest(cancelRequestReason);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void checkIfCancelled(final boolean signalTooLate)
        throws CancelledResultException
    {
      synchronized (stateLock)
      {
        switch (state)
        {
        case PENDING:
          // No cancel request, so no handlers, just switch state.
          if (signalTooLate)
          {
            cancelRequestListeners = null;
            state = RequestState.TOO_LATE;
          }
          break;
        case CANCEL_REQUESTED:
          // Don't change state: let the handler ack the cancellation request.
          throw (CancelledResultException) newErrorResult(
              ResultCode.CANCELLED, cancelRequestReason.toString());
        case TOO_LATE:
          // Already too late. Nothing to do.
          break;
        case RESULT_SENT:
        case CANCELLED:
          // This should not happen - could throw an illegal state exception?
          break;
        }
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public int getMessageID()
    {
      return messageID;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleErrorResult(final ErrorResultException error)
    {
      if (clientConnection.removePendingRequest(this))
      {
        if (setResult(error.getResult()))
        {
          // FIXME: we must invoke the result handler even when abandoned so
          // that chained result handlers may clean up, log, etc. We really need
          // to signal that the result must not be sent to the client.
        }
        resultHandler.handleErrorResult(error);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleResult(final S result)
    {
      if (clientConnection.removePendingRequest(this))
      {
        if (setResult(result))
        {
          // FIXME: we must invoke the result handler even when abandoned so
          // that chained result handlers may clean up, log, etc. We really need
          // to signal that the result must not be sent to the client.
        }
        resultHandler.handleResult(result);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void removeCancelRequestListener(
        final CancelRequestListener listener)
        throws NullPointerException
    {
      Validator.ensureNotNull(listener);
      synchronized (stateLock)
      {
        if (cancelRequestListeners != null)
        {
          cancelRequestListeners.remove(listener);
        }
      }
    }
    private <R extends ExtendedResult> void cancel(
        final LocalizableMessage reason,
        final ExtendedRequest<R> cancelRequest,
        final ResultHandler<? super R> cancelResultHandler,
        final boolean sendResult)
    {
      Validator.ensureNotNull(reason);
      if (!isCancelSupported)
      {
        if (cancelResultHandler != null)
        {
          final Result result = Responses
              .newGenericExtendedResult(ResultCode.CANNOT_CANCEL);
          cancelResultHandler
              .handleErrorResult(newErrorResult(result));
        }
        return;
      }
      List<CancelRequestListener> tmpListeners = null;
      boolean invokeResultHandler = false;
      boolean resultHandlerIsSuccess = false;
      synchronized (stateLock)
      {
        switch (state)
        {
        case PENDING:
          // Switch to CANCEL_REQUESTED state.
          cancelRequestReason = reason;
          if (cancelResultHandler != null)
          {
            cancelResultHandlers = new LinkedList<ExtendedResultHandlerHolder<?>>();
            cancelResultHandlers
                .add(new ExtendedResultHandlerHolder<R>(
                    cancelRequest, cancelResultHandler));
          }
          tmpListeners = cancelRequestListeners;
          cancelRequestListeners = null;
          state = RequestState.CANCEL_REQUESTED;
          this.sendResult &= sendResult;
          break;
        case CANCEL_REQUESTED:
          // Cancel already request so listeners already invoked.
          if (cancelResultHandler != null)
          {
            if (cancelResultHandlers == null)
            {
              cancelResultHandlers = new LinkedList<ExtendedResultHandlerHolder<?>>();
            }
            cancelResultHandlers
                .add(new ExtendedResultHandlerHolder<R>(
                    cancelRequest, cancelResultHandler));
          }
          break;
        case TOO_LATE:
        case RESULT_SENT:
          // Cannot cancel, so invoke result handler immediately outside of
          // lock.
          if (cancelResultHandler != null)
          {
            invokeResultHandler = true;
            resultHandlerIsSuccess = false;
          }
          break;
        case CANCELLED:
          // Multiple cancellation attempts. Clients should not do this, but the
          // cancel will effectively succeed immediately, so invoke result
          // handler immediately outside of lock.
          if (cancelResultHandler != null)
          {
            invokeResultHandler = true;
            resultHandlerIsSuccess = true;
          }
          break;
        }
      }
      // Invoke listeners outside of lock.
      if (tmpListeners != null)
      {
        for (final CancelRequestListener listener : tmpListeners)
        {
          listener.handleCancelRequest(reason);
        }
      }
      if (invokeResultHandler)
      {
        if (resultHandlerIsSuccess)
        {
          final R result = cancelRequest.getResultDecoder()
              .newExtendedErrorResult(ResultCode.SUCCESS, "", "");
          cancelResultHandler.handleResult(result);
        }
        else
        {
          final Result result = Responses
              .newGenericExtendedResult(ResultCode.TOO_LATE);
          cancelResultHandler.handleErrorResult(ErrorResultException
              .newErrorResult(result));
        }
      }
    }
    /**
     * Sets the result associated with this request context and updates the
     * state accordingly.
     *
     * @param result
     *          The result.
     */
    private boolean setResult(final Result result)
    {
      List<ExtendedResultHandlerHolder<?>> tmpHandlers = null;
      boolean isCancelled = false;
      boolean maySendResult;
      synchronized (stateLock)
      {
        maySendResult = sendResult;
        switch (state)
        {
        case PENDING:
        case TOO_LATE:
          // Switch to appropriate final state.
          if (!result.getResultCode().equals(ResultCode.CANCELLED))
          {
            state = RequestState.RESULT_SENT;
          }
          else
          {
            state = RequestState.CANCELLED;
          }
          break;
        case CANCEL_REQUESTED:
          // Switch to appropriate final state and invoke any cancel request
          // handlers.
          if (!result.getResultCode().equals(ResultCode.CANCELLED))
          {
            state = RequestState.RESULT_SENT;
          }
          else
          {
            state = RequestState.CANCELLED;
          }
          isCancelled = (state == RequestState.CANCELLED);
          tmpHandlers = cancelResultHandlers;
          cancelResultHandlers = null;
          break;
        case RESULT_SENT:
        case CANCELLED:
          // This should not happen - could throw an illegal state exception?
          maySendResult = false; // Prevent sending multiple results.
          break;
        }
      }
      // Invoke handlers outside of lock.
      if (tmpHandlers != null)
      {
        for (final ExtendedResultHandlerHolder<?> handler : tmpHandlers)
        {
          if (isCancelled)
          {
            handler.handleSuccess();
          }
          else
          {
            handler.handleTooLate();
          }
        }
      }
      return maySendResult;
    }
  }
  /**
   * Search request context implementation.
   */
  private final static class SearchRequestContextImpl extends
      RequestContextImpl<Result, SearchResultHandler> implements
      SearchResultHandler
  {
    private SearchRequestContextImpl(
        final ServerConnectionImpl<?> clientConnection,
        final SearchResultHandler resultHandler, final int messageID,
        final boolean isCancelSupported)
    {
      super(clientConnection, resultHandler, messageID,
          isCancelSupported);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean handleEntry(final SearchResultEntry entry)
    {
      return resultHandler.handleEntry(entry);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean handleReference(
        final SearchResultReference reference)
    {
      return resultHandler.handleReference(reference);
    }
  }
  private static final class ServerConnectionImpl<C> implements
      ServerConnection<Integer>
  {
    private final RequestHandler<RequestContext> requestHandler;
    private final AtomicBoolean isClosed = new AtomicBoolean();
    private final ConcurrentHashMap<Integer, RequestContextImpl<?, ?>> pendingRequests =
      new ConcurrentHashMap<Integer, RequestContextImpl<?, ?>>();
    private ServerConnectionImpl(
        final RequestHandler<RequestContext> requestHandler)
    {
      this.requestHandler = requestHandler;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleAbandon(final Integer messageID,
        final AbandonRequest request)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<?, ?> abandonedRequest = getPendingRequest(request
          .getRequestID());
      if (abandonedRequest != null)
      {
        final LocalizableMessage abandonReason = INFO_CANCELED_BY_ABANDON_REQUEST
            .get(messageID);
        abandonedRequest.cancel(abandonReason, null, null, false);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleAdd(final Integer messageID,
        final AddRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleAdd(requestContext, request,
            requestContext, intermediateResponseHandler);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleBind(final Integer messageID,
        final int version, final BindRequest request,
        final ResultHandler<? super BindResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<BindResult, ResultHandler<? super BindResult>> requestContext =
        new RequestContextImpl<BindResult, ResultHandler<? super BindResult>>(
          this, resultHandler, messageID, false);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleBind(requestContext, version, request,
            requestContext, intermediateResponseHandler);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleCompare(final Integer messageID,
        final CompareRequest request,
        final ResultHandler<? super CompareResult> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<CompareResult, ResultHandler<? super CompareResult>> requestContext =
        new RequestContextImpl<CompareResult, ResultHandler<? super CompareResult>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleCompare(requestContext, request,
            requestContext, intermediateResponseHandler);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleConnectionClosed(final Integer messageID,
        final UnbindRequest request)
    {
      final LocalizableMessage cancelReason = INFO_CANCELED_BY_CLIENT_DISCONNECT
          .get();
      doClose(cancelReason);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleConnectionDisconnected(
        final ResultCode resultCode, final String message)
    {
      final LocalizableMessage cancelReason = INFO_CANCELED_BY_SERVER_DISCONNECT
          .get();
      doClose(cancelReason);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleConnectionError(final Throwable error)
    {
      final LocalizableMessage cancelReason = INFO_CANCELED_BY_CLIENT_ERROR
          .get();
      doClose(cancelReason);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleDelete(final Integer messageID,
        final DeleteRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleDelete(requestContext, request,
            requestContext, intermediateResponseHandler);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public <R extends ExtendedResult> void handleExtendedRequest(
        final Integer messageID, final ExtendedRequest<R> request,
        final ResultHandler<? super R> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      if (request.getOID().equals(CancelExtendedRequest.OID))
      {
        // Decode the request as a cancel request.
        CancelExtendedRequest cancelRequest;
        try
        {
          cancelRequest = CancelExtendedRequest.DECODER
              .decodeExtendedRequest(request, new DecodeOptions());
        }
        catch (final DecodeException e)
        {
          // Couldn't decode a cancel request.
          resultHandler.handleErrorResult(newErrorResult(
              ResultCode.PROTOCOL_ERROR, e.getLocalizedMessage()));
          return;
        }
        // Register the request in the pending requests table. Even though
        // 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>>(
            this, resultHandler, messageID, false);
        if (addPendingRequest(requestContext))
        {
          // Find and cancel the request.
          final RequestContextImpl<?, ?> cancelledRequest = getPendingRequest(cancelRequest
              .getRequestID());
          if (cancelledRequest != null)
          {
            final LocalizableMessage cancelReason = INFO_CANCELED_BY_CANCEL_REQUEST
                .get(messageID);
            cancelledRequest.cancel(cancelReason, request,
                requestContext, true);
          }
          else
          {
            // Couldn't find the request. Invoke on context in order to remove
            // pending request.
            requestContext
                .handleErrorResult(newErrorResult(ResultCode.NO_SUCH_OPERATION));
          }
        }
      }
      else
      {
        final RequestContextImpl<R, ResultHandler<? super R>> requestContext;
        if (request.getOID().equals(StartTLSExtendedRequest.OID))
        {
          // StartTLS requests cannot be cancelled.
          requestContext = new RequestContextImpl<R, ResultHandler<? super R>>(
              this, resultHandler, messageID, false);
        }
        else
        {
          requestContext = new RequestContextImpl<R, ResultHandler<? super R>>(
              this, resultHandler, messageID, true);
        }
        if (addPendingRequest(requestContext))
        {
          requestHandler.handleExtendedRequest(requestContext,
              request, requestContext, intermediateResponseHandler);
        }
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleModify(final Integer messageID,
        final ModifyRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleModify(requestContext, request,
            requestContext, intermediateResponseHandler);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleModifyDN(final Integer messageID,
        final ModifyDNRequest request,
        final ResultHandler<? super Result> resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      final RequestContextImpl<Result, ResultHandler<? super Result>> requestContext =
        new RequestContextImpl<Result, ResultHandler<? super Result>>(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleModifyDN(requestContext, request,
            requestContext, intermediateResponseHandler);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void handleSearch(final Integer messageID,
        final SearchRequest request,
        final SearchResultHandler resultHandler,
        final IntermediateResponseHandler intermediateResponseHandler)
        throws UnsupportedOperationException
    {
      final SearchRequestContextImpl requestContext = new SearchRequestContextImpl(
          this, resultHandler, messageID, true);
      if (addPendingRequest(requestContext))
      {
        requestHandler.handleSearch(requestContext, request,
            requestContext, intermediateResponseHandler);
      }
    }
    private boolean addPendingRequest(
        final RequestContextImpl<?, ?> requestContext)
    {
      final Integer messageID = requestContext.getMessageID();
      if (isClosed.get())
      {
        final LocalizableMessage message = INFO_CLIENT_CONNECTION_CLOSING
            .get();
        requestContext.handleErrorResult(newErrorResult(
            ResultCode.UNWILLING_TO_PERFORM, message.toString()));
        return false;
      }
      else if (pendingRequests.putIfAbsent(messageID, requestContext) != null)
      {
        final LocalizableMessage message = WARN_CLIENT_DUPLICATE_MESSAGE_ID
            .get(requestContext.getMessageID());
        requestContext.handleErrorResult(newErrorResult(
            ResultCode.PROTOCOL_ERROR, message.toString()));
        return false;
      }
      else if (isClosed.get())
      {
        // A concurrent close may have already removed the pending request but
        // it will have only been notified for cancellation.
        pendingRequests.remove(messageID);
        final LocalizableMessage message = INFO_CLIENT_CONNECTION_CLOSING
            .get();
        requestContext.handleErrorResult(newErrorResult(
            ResultCode.UNWILLING_TO_PERFORM, message.toString()));
        return false;
      }
      else
      {
        // If the connection is closed now then we just have to pay the cost of
        // invoking the request in the request handler.
        return true;
      }
    }
    private void doClose(final LocalizableMessage cancelReason)
    {
      if (!isClosed.getAndSet(true))
      {
        // At this point if any pending requests are added then we may end up
        // cancelling them, but this does not matter since addPendingRequest
        // will fail the request immediately.
        final Iterator<RequestContextImpl<?, ?>> iterator = pendingRequests
            .values().iterator();
        while (iterator.hasNext())
        {
          final RequestContextImpl<?, ?> pendingRequest = iterator
              .next();
          pendingRequest.cancel(cancelReason, null, null, false);
          iterator.remove();
        }
      }
    }
    /**
     * Returns the pending request context having the specified message ID.
     *
     * @param messageID
     *          The message ID associated with the request context.
     * @return The pending request context.
     */
    private RequestContextImpl<?, ?> getPendingRequest(
        final Integer messageID)
    {
      return pendingRequests.get(messageID);
    }
    /**
     * Deregister a request context once it has completed.
     *
     * @param requestContext
     *          The request context.
     * @return {@code true} if the request context was found and removed.
     */
    private boolean removePendingRequest(
        final RequestContextImpl<?, ?> requestContext)
    {
      return pendingRequests.remove(requestContext.getMessageID()) != null;
    }
  }
  private final RequestHandlerFactory<C, RequestContext> factory;
  /**
   * Creates a new server connection factory using the provided request handler
   * factory.
   *
   * @param factory
   *          The request handler factory to be adapted into a server connection
   *          factory.
   */
  RequestHandlerFactoryAdapter(
      final RequestHandlerFactory<C, RequestContext> factory)
  {
    this.factory = factory;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public ServerConnection<Integer> handleAccept(final C clientContext)
      throws ErrorResultException
  {
    final RequestHandler<RequestContext> requestHandler = factory
        .handleAccept(clientContext);
    return new ServerConnectionImpl<C>(requestHandler);
  }
}
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java
@@ -29,6 +29,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
@@ -85,8 +87,7 @@
      }
      catch (final SaslException e)
      {
        throw ErrorResultException.wrap(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR, e);
      }
    }
@@ -122,7 +123,7 @@
      {
        // FIXME: I18N need to have a better error message.
        // FIXME: Is this the best result code?
        throw ErrorResultException.wrap(Responses.newResult(
        throw ErrorResultException.newErrorResult(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
            "An error occurred during multi-stage authentication")
            .setCause(e));
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java
@@ -32,6 +32,7 @@
import static com.forgerock.opendj.util.StaticUtils.getExceptionMessage;
import static com.forgerock.opendj.util.StaticUtils.joinCollection;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_SASL_PROTOCOL_ERROR;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.*;
@@ -49,7 +50,6 @@
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.responses.BindResult;
import org.forgerock.opendj.ldap.responses.Responses;
import com.forgerock.opendj.util.Validator;
@@ -154,8 +154,7 @@
      }
      catch (final SaslException e)
      {
        throw ErrorResultException.wrap(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR, e);
      }
    }
@@ -191,11 +190,8 @@
      {
        // FIXME: I18N need to have a better error message.
        // FIXME: Is this the best result code?
        throw ErrorResultException.wrap(Responses
            .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
            .setDiagnosticMessage(
                "An error occurred during multi-stage authentication")
            .setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR,
            "An error occurred during multi-stage authentication", e);
      }
    }
@@ -229,9 +225,8 @@
      {
        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
            SASL_MECHANISM_NAME, getExceptionMessage(e));
        throw ErrorResultException.wrap(Responses
            .newResult(ResultCode.CLIENT_SIDE_DECODING_ERROR)
            .setDiagnosticMessage(msg.toString()).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_DECODING_ERROR,
            msg.toString(), e);
      }
    }
@@ -249,9 +244,8 @@
      {
        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
            SASL_MECHANISM_NAME, getExceptionMessage(e));
        throw ErrorResultException.wrap(Responses
            .newResult(ResultCode.CLIENT_SIDE_ENCODING_ERROR)
            .setDiagnosticMessage(msg.toString()).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_ENCODING_ERROR,
            msg.toString(), e);
      }
    }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java
@@ -29,6 +29,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
@@ -76,8 +78,7 @@
      }
      catch (final SaslException e)
      {
        throw ErrorResultException.wrap(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR, e);
      }
    }
@@ -113,7 +114,7 @@
      {
        // FIXME: I18N need to have a better error message.
        // FIXME: Is this the best result code?
        throw ErrorResultException.wrap(Responses.newResult(
        throw ErrorResultException.newErrorResult(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
            "An error occurred during multi-stage authentication")
            .setCause(e));
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java
@@ -32,6 +32,7 @@
import static com.forgerock.opendj.util.StaticUtils.getExceptionMessage;
import static com.forgerock.opendj.util.StaticUtils.joinCollection;
import static org.forgerock.opendj.ldap.CoreMessages.*;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@@ -61,6 +62,7 @@
/**
 * GSSAPI SASL bind request implementation.
 */
@SuppressWarnings("restriction")
final class GSSAPISASLBindRequestImpl extends
    AbstractSASLBindRequest<GSSAPISASLBindRequest> implements
    GSSAPISASLBindRequest
@@ -75,7 +77,7 @@
      {
        // FIXME: I18N need to have a better error message.
        // FIXME: Is this the best result code?
        throw ErrorResultException.wrap(Responses.newResult(
        throw ErrorResultException.newErrorResult(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
            "No authentication ID specified for GSSAPI SASL authentication"));
      }
@@ -84,7 +86,7 @@
      {
        // FIXME: I18N need to have a better error message.
        // FIXME: Is this the best result code?
        throw ErrorResultException.wrap(Responses.newResult(
        throw ErrorResultException.newErrorResult(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
            "No password specified for GSSAPI SASL authentication"));
      }
@@ -119,7 +121,7 @@
        // FIXME: Is this the best result code?
        final LocalizableMessage message = ERR_LDAPAUTH_GSSAPI_LOCAL_AUTHENTICATION_FAILED
            .get(StaticUtils.getExceptionMessage(e));
        throw ErrorResultException.wrap(Responses
        throw ErrorResultException.newErrorResult(Responses
            .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
            .setDiagnosticMessage(message.toString()).setCause(e));
      }
@@ -151,7 +153,7 @@
        {
          // FIXME: I18N need to have a better error message.
          // FIXME: Is this the best result code?
          throw ErrorResultException.wrap(Responses
          throw ErrorResultException.newErrorResult(Responses
              .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
              .setDiagnosticMessage(
                  "An error occurred during multi-stage authentication")
@@ -239,8 +241,7 @@
                }
                catch (final SaslException e)
                {
                  throw ErrorResultException.wrap(Responses.newResult(
                      ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
                  throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR, e);
                }
              }
            });
@@ -254,11 +255,10 @@
        else
        {
          // This should not happen. Must be a bug.
          final LocalizableMessage msg = ERR_SASL_CONTEXT_CREATE_ERROR.get(
              SASL_MECHANISM_NAME, getExceptionMessage(e));
          throw ErrorResultException.wrap(Responses
              .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
              .setDiagnosticMessage(msg.toString()).setCause(e));
          final LocalizableMessage msg = ERR_SASL_CONTEXT_CREATE_ERROR
              .get(SASL_MECHANISM_NAME, getExceptionMessage(e));
          throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR,
              msg.toString(), e);
        }
      }
    }
@@ -300,9 +300,8 @@
          // This should not happen. Must be a bug.
          final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
              SASL_MECHANISM_NAME, getExceptionMessage(e));
          throw ErrorResultException.wrap(Responses
              .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
              .setDiagnosticMessage(msg.toString()).setCause(e));
          throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR,
              msg.toString(), e);
        }
      }
    }
@@ -337,9 +336,8 @@
      {
        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
            SASL_MECHANISM_NAME, getExceptionMessage(e));
        throw ErrorResultException.wrap(Responses
            .newResult(ResultCode.CLIENT_SIDE_DECODING_ERROR)
            .setDiagnosticMessage(msg.toString()).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_DECODING_ERROR,
            msg.toString(), e);
      }
    }
@@ -357,9 +355,8 @@
      {
        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
            SASL_MECHANISM_NAME, getExceptionMessage(e));
        throw ErrorResultException.wrap(Responses
            .newResult(ResultCode.CLIENT_SIDE_ENCODING_ERROR)
            .setDiagnosticMessage(msg.toString()).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_ENCODING_ERROR,
            msg.toString(), e);
      }
    }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java
@@ -29,6 +29,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
@@ -40,7 +42,6 @@
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.responses.BindResult;
import org.forgerock.opendj.ldap.responses.Responses;
import com.forgerock.opendj.util.Validator;
@@ -87,8 +88,7 @@
      }
      catch (final SaslException e)
      {
        throw ErrorResultException.wrap(Responses.newResult(
            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
        throw newErrorResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR, e);
      }
    }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/responses/AbstractExtendedResultDecoder.java
@@ -29,6 +29,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import org.forgerock.opendj.ldap.*;
import org.forgerock.opendj.ldap.requests.ExtendedRequest;
@@ -89,8 +91,7 @@
            .newExtendedErrorResult(result.getResultCode(),
                result.getMatchedDN(), result.getDiagnosticMessage());
        adaptedResult.setCause(result.getCause());
        resultHandler.handleErrorResult(ErrorResultException
            .wrap(adaptedResult));
        resultHandler.handleErrorResult(newErrorResult(adaptedResult));
      }
@@ -108,8 +109,7 @@
        {
          final R adaptedResult = request.getResultDecoder()
              .adaptDecodeException(e);
          resultHandler.handleErrorResult(ErrorResultException
              .wrap(adaptedResult));
          resultHandler.handleErrorResult(newErrorResult(adaptedResult));
        }
      }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -29,6 +29,7 @@
import static org.forgerock.opendj.ldap.CoreMessages.*;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.util.Collection;
import java.util.Collections;
@@ -40,8 +41,6 @@
import org.forgerock.opendj.ldap.*;
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import com.forgerock.opendj.util.FutureResultTransformer;
@@ -1829,10 +1828,10 @@
    if (subentryAttr == null || subentryAttr.isEmpty())
    {
      // Did not get the subschema sub-entry attribute.
      final Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
          ERR_NO_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString()).toString());
      throw ErrorResultException.wrap(result);
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
          ERR_NO_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString())
              .toString());
    }
    final String dnString = subentryAttr.iterator().next().toString();
@@ -1843,11 +1842,10 @@
    }
    catch (final LocalizedIllegalArgumentException e)
    {
      final Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
          ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString(), dnString,
              e.getMessageObject()).toString());
      throw ErrorResultException.wrap(result);
      throw newErrorResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED,
          ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString(),
              dnString, e.getMessageObject()).toString());
    }
    return subschemaDN;
  }
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/ConnectionEntryReader.java
@@ -29,6 +29,8 @@
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.io.InterruptedIOException;
import java.util.NoSuchElementException;
import java.util.concurrent.BlockingQueue;
@@ -273,8 +275,7 @@
      return false;
    }
    final ErrorResultException e = ErrorResultException.wrap(result);
    throw new ErrorResultIOException(e);
    throw new ErrorResultIOException(newErrorResult(result));
  }
opendj3/opendj-ldap-sdk/src/main/resources/org/forgerock/opendj/ldap/core.properties
@@ -1269,6 +1269,22 @@
 contained the OID '%s', when '%s' was expected
ERR_VIRTUAL_ATTRS_ONLY_INVALID_CONTROL_VALUE=Cannot decode the provided \
 virtual attributes only control because it contains a value
WARN_CLIENT_DUPLICATE_MESSAGE_ID=The operation was rejected because there is \
 already another request on the same client connection with the same message \
 ID of %d
INFO_CANCELED_BY_ABANDON_REQUEST=The operation was canceled because the client \
 issued an abandon request (message ID %d) for this operation
INFO_CANCELED_BY_CANCEL_REQUEST=The operation was canceled because the client \
 issued a cancel request (message ID %d) for this operation
INFO_CANCELED_BY_CLIENT_DISCONNECT=The operation was canceled because the \
 client has disconnected from the server
INFO_CANCELED_BY_SERVER_DISCONNECT=The operation was canceled because the \
 server has disconnected from the client
INFO_CANCELED_BY_CLIENT_ERROR=The operation was canceled because the \
 client connection failed
INFO_CLIENT_CONNECTION_CLOSING=The operation was rejected because the \
 client connection is closing
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPListenerTestCase.java
@@ -223,7 +223,7 @@
        throws UnsupportedOperationException
    {
      resultHandler
          .handleErrorResult(ErrorResultException.wrap(request
          .handleErrorResult(ErrorResultException.newErrorResult(request
              .getResultDecoder().newExtendedErrorResult(
                  ResultCode.PROTOCOL_ERROR, "",
                  "Extended operation " + request.getOID() + " not supported")));
opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
@@ -200,7 +200,7 @@
      {
        // duplicate entry.
        result = Responses.newResult(ResultCode.ENTRY_ALREADY_EXISTS);
        final ErrorResultException ere = ErrorResultException.wrap(result);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        handler.handleErrorResult(ere);
        // doesn't matter if it was canceled.
        requestsInProgress.remove(context);
@@ -222,7 +222,7 @@
      if (abReq.isCanceled())
      {
        result = Responses.newResult(ResultCode.CANCELLED);
        final ErrorResultException ere = ErrorResultException.wrap(result);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        handler.handleErrorResult(ere);
        requestsInProgress.remove(context);
        return;
@@ -349,7 +349,7 @@
                  }
                  catch (SaslException e)
                  {
                    throw ErrorResultException.wrap(Responses.newResult(
                    throw ErrorResultException.newErrorResult(Responses.newResult(
                        ResultCode.OPERATIONS_ERROR).setCause(e));
                  }
                }
@@ -365,7 +365,7 @@
                  }
                  catch (SaslException e)
                  {
                    throw ErrorResultException.wrap(Responses.newResult(
                    throw ErrorResultException.newErrorResult(Responses.newResult(
                        ResultCode.OPERATIONS_ERROR).setCause(e));
                  }
                }
@@ -384,7 +384,7 @@
        }
        catch (Exception e)
        {
          resultHandler.handleErrorResult(ErrorResultException.wrap(Responses
          resultHandler.handleErrorResult(ErrorResultException.newErrorResult(Responses
              .newBindResult(ResultCode.OPERATIONS_ERROR).setCause(e)
              .setDiagnosticMessage(e.toString())));
        }
@@ -469,7 +469,7 @@
      {
        // entry not found.
        result = Responses.newCompareResult(ResultCode.NO_SUCH_ATTRIBUTE);
        final ErrorResultException ere = ErrorResultException.wrap(result);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        resultHandler.handleErrorResult(ere);
        // doesn't matter if it was canceled.
        requestsInProgress.remove(context);
@@ -488,7 +488,7 @@
          if (abReq.isCanceled())
          {
            final Result r = Responses.newResult(ResultCode.CANCELLED);
            final ErrorResultException ere = ErrorResultException.wrap(r);
            final ErrorResultException ere = ErrorResultException.newErrorResult(r);
            resultHandler.handleErrorResult(ere);
            requestsInProgress.remove(context);
            return;
@@ -529,7 +529,7 @@
      {
        // entry is not found.
        result = Responses.newResult(ResultCode.NO_SUCH_OBJECT);
        final ErrorResultException ere = ErrorResultException.wrap(result);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        handler.handleErrorResult(ere);
        // doesn't matter if it was canceled.
        requestsInProgress.remove(context);
@@ -539,7 +539,7 @@
      if (abReq.isCanceled())
      {
        result = Responses.newResult(ResultCode.CANCELLED);
        final ErrorResultException ere = ErrorResultException.wrap(result);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        handler.handleErrorResult(ere);
        requestsInProgress.remove(context);
        return;
@@ -633,7 +633,7 @@
      {
        // Entry not found.
        result = Responses.newResult(ResultCode.NO_SUCH_OBJECT);
        final ErrorResultException ere = ErrorResultException.wrap(result);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        resultHandler.handleErrorResult(ere);
        // Should searchResultHandler handle anything?
@@ -645,7 +645,7 @@
      if (abReq.isCanceled())
      {
        result = Responses.newResult(ResultCode.CANCELLED);
        final ErrorResultException ere = ErrorResultException.wrap(result);
        final ErrorResultException ere = ErrorResultException.newErrorResult(result);
        resultHandler.handleErrorResult(ere);
        requestsInProgress.remove(context);
        return;
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java
@@ -32,6 +32,7 @@
import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
import static com.forgerock.opendj.ldap.tools.ToolConstants.*;
import static com.forgerock.opendj.ldap.tools.Utils.filterExitCode;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.io.*;
import java.util.ArrayList;
@@ -44,7 +45,6 @@
import org.forgerock.opendj.ldap.controls.ProxiedAuthV2RequestControl;
import org.forgerock.opendj.ldap.requests.CompareRequest;
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
import com.forgerock.opendj.util.Base64;
@@ -229,9 +229,8 @@
        {
          // This shouldn't happen because there are no other threads to
          // interrupt this one.
          result = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
              .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
          throw ErrorResultException.wrap(result);
          throw newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED,
              e.getLocalizedMessage(), e);
        }
        if (result.getResultCode() == ResultCode.COMPARE_FALSE)
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java
@@ -32,6 +32,7 @@
import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
import static com.forgerock.opendj.ldap.tools.ToolConstants.*;
import static com.forgerock.opendj.ldap.tools.Utils.filterExitCode;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.io.FileInputStream;
import java.io.IOException;
@@ -50,7 +51,6 @@
import org.forgerock.opendj.ldap.requests.DeleteRequest;
import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldif.*;
@@ -87,9 +87,9 @@
          {
            // This shouldn't happen because there are no other threads
            // to interrupt this one.
            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
            throw ErrorResultException.wrap(r);
            throw newErrorResult(
                ResultCode.CLIENT_SIDE_USER_CANCELLED,
                e.getLocalizedMessage(), e);
          }
          printResult(opType, change.getName().toString(), r);
          return r.getResultCode().intValue();
@@ -127,9 +127,8 @@
          {
            // This shouldn't happen because there are no other threads
            // to interrupt this one.
            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
            throw ErrorResultException.wrap(r);
            throw newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED,
                e.getLocalizedMessage(), e);
          }
          printResult(opType, change.getName().toString(), r);
          return r.getResultCode().intValue();
@@ -167,9 +166,8 @@
          {
            // This shouldn't happen because there are no other threads
            // to interrupt this one.
            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
            throw ErrorResultException.wrap(r);
            throw newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED,
                e.getLocalizedMessage(), e);
          }
          printResult(opType, change.getName().toString(), r);
          return r.getResultCode().intValue();
@@ -207,9 +205,8 @@
          {
            // This shouldn't happen because there are no other threads
            // to interrupt this one.
            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
            throw ErrorResultException.wrap(r);
            throw newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED,
                e.getLocalizedMessage(), e);
          }
          printResult(opType, change.getName().toString(), r);
          return r.getResultCode().intValue();
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java
@@ -32,6 +32,7 @@
import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
import static com.forgerock.opendj.ldap.tools.ToolConstants.*;
import static com.forgerock.opendj.ldap.tools.Utils.filterExitCode;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.io.InputStream;
import java.io.OutputStream;
@@ -42,7 +43,6 @@
import org.forgerock.opendj.ldap.requests.PasswordModifyExtendedRequest;
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.responses.PasswordModifyExtendedResult;
import org.forgerock.opendj.ldap.responses.Responses;
@@ -446,10 +446,8 @@
      {
        // This shouldn't happen because there are no other threads to
        // interrupt this one.
        result = Responses.newPasswordModifyExtendedResult(
            ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
            .setDiagnosticMessage(e.getLocalizedMessage());
        throw ErrorResultException.wrap(result);
        throw newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED,
            e.getLocalizedMessage(), e);
      }
    }
    catch (final ErrorResultException e)
opendj3/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java
@@ -32,6 +32,7 @@
import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
import static com.forgerock.opendj.ldap.tools.ToolConstants.*;
import static com.forgerock.opendj.ldap.tools.Utils.filterExitCode;
import static org.forgerock.opendj.ldap.ErrorResultException.newErrorResult;
import java.io.*;
import java.util.*;
@@ -42,7 +43,6 @@
import org.forgerock.opendj.ldap.controls.*;
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.responses.SearchResultReference;
@@ -1168,9 +1168,8 @@
        {
          // This shouldn't happen because there are no other threads to
          // interrupt this one.
          result = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
              .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
          throw ErrorResultException.wrap(result);
          throw newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED,
              e.getLocalizedMessage(), e);
        }
        try