From 9020a676bbe359cb158e96761ef6f1a3c32c80e5 Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <yannick.lecaillez@forgerock.com>
Date: Tue, 10 May 2016 16:42:27 +0000
Subject: [PATCH] REST2LDAP Refactoring

---
 opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Adapters.java |  449 +++++++++++++++++++++++++++++---------------------------
 1 files changed, 233 insertions(+), 216 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Adapters.java b/opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Adapters.java
index 71875e6..eab6f55 100644
--- a/opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Adapters.java
+++ b/opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Adapters.java
@@ -17,6 +17,8 @@
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.List;
 
 import org.forgerock.opendj.ldap.AbstractSynchronousConnection;
 import org.forgerock.opendj.ldap.ByteString;
@@ -51,17 +53,19 @@
 import org.forgerock.opendj.ldap.responses.Responses;
 import org.forgerock.opendj.ldap.responses.Result;
 import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.PromiseImpl;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.BindOperation;
 import org.opends.server.core.CompareOperation;
 import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ExtendedOperation;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchListener;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.Requests;
-import org.opends.server.types.AuthenticationInfo;
 import org.opends.server.types.DirectoryException;
+import org.opends.server.types.OperationType;
 import org.opends.server.types.SearchFilter;
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.types.SearchResultReference;
@@ -69,7 +73,6 @@
 import static org.forgerock.opendj.adapter.server3x.Converters.*;
 import static org.forgerock.opendj.ldap.ByteString.*;
 import static org.forgerock.opendj.ldap.LdapException.*;
-import static org.forgerock.util.promise.Promises.*;
 
 /** This class provides a connection factory and an adapter for the OpenDJ 2.x server. */
 public final class Adapters {
@@ -90,33 +93,6 @@
     }
 
     /**
-     * Returns a new anonymous connection factory.
-     *
-     * @return A new anonymous connection factory.
-     */
-    public static ConnectionFactory newAnonymousConnectionFactory() {
-        InternalClientConnection icc = new InternalClientConnection(new AuthenticationInfo());
-        return newConnectionFactory(icc);
-    }
-
-    /**
-     * Returns a new connection factory for a specified user.
-     *
-     * @param userDN
-     *            The specified user's DN.
-     * @return a new connection factory.
-     */
-    public static ConnectionFactory newConnectionFactoryForUser(final DN userDN) {
-        InternalClientConnection icc = null;
-        try {
-            icc = new InternalClientConnection(userDN);
-        } catch (DirectoryException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-        return newConnectionFactory(icc);
-    }
-
-    /**
      * Returns a new connection factory.
      *
      * @param icc
@@ -125,7 +101,6 @@
      */
     public static ConnectionFactory newConnectionFactory(final InternalClientConnection icc) {
         return new ConnectionFactory() {
-
             @Override
             public void close() {
                 // Nothing to do.
@@ -133,8 +108,30 @@
 
             @Override
             public Promise<Connection, LdapException> getConnectionAsync() {
-                // TODO change the path...
-                return newResultPromise(newConnection(icc));
+                final PromiseImpl<Connection, LdapException> promise = PromiseImpl.create();
+                try
+                {
+                  DirectoryServer.getWorkQueue().submitOperation(new AsyncOperation<>(icc, new Runnable()
+                  {
+                    @Override
+                    public void run()
+                    {
+                      try
+                      {
+                        promise.handleResult(getConnection());
+                      }
+                      catch (LdapException e)
+                      {
+                        promise.handleException(e);
+                      }
+                    }
+                  }));
+                }
+                catch (DirectoryException e)
+                {
+                  promise.handleException(LdapException.newLdapException(e.getResultCode()));
+                }
+                return promise;
             }
 
             @Override
@@ -144,214 +141,234 @@
         };
     }
 
-    /**
-     * Returns a new root connection.
-     *
-     * @return A new root connection.
-     */
-    public static Connection newRootConnection() {
-        return newConnection(InternalClientConnection.getRootConnection());
-    }
-
-    /**
-     * Returns a new connection for an anonymous user.
-     *
-     * @return A new connection.
-     */
-    public static Connection newAnonymousConnection() {
-        return newConnection(new InternalClientConnection(new AuthenticationInfo()));
-    }
-
-    /**
-     * Returns a new connection for a specified user.
-     *
-     * @param dn
-     *            The DN of the user.
-     * @return A new connection for a specified user.
-     * @throws LdapException
-     *             If no such object.
-     */
-    public static Connection newConnectionForUser(final DN dn) throws LdapException {
-        try {
-            return newConnection(new InternalClientConnection(dn));
-        } catch (DirectoryException e) {
-            throw newLdapException(Responses.newResult(ResultCode.NO_SUCH_OBJECT));
-        }
-    }
-
     private static Connection newConnection(final InternalClientConnection icc) {
-        return new AbstractSynchronousConnection() {
+      return new AbstractSynchronousConnection() {
 
-            @Override
-            public Result search(final SearchRequest request, final SearchResultHandler handler)
-                    throws LdapException {
-                InternalSearchListener internalSearchListener = new InternalSearchListener() {
+          @Override
+          public Result search(final SearchRequest request, final SearchResultHandler handler)
+                  throws LdapException {
+              InternalSearchListener internalSearchListener = new InternalSearchListener() {
 
-                    @Override
-                    public void handleInternalSearchReference(
-                            InternalSearchOperation searchOperation,
-                            SearchResultReference searchReference) throws DirectoryException {
-                        handler.handleReference(from(searchReference));
-                    }
+                  @Override
+                  public void handleInternalSearchReference(
+                          InternalSearchOperation searchOperation,
+                          SearchResultReference searchReference) throws DirectoryException {
+                      handler.handleReference(from(searchReference));
+                  }
 
-                    @Override
-                    public void handleInternalSearchEntry(InternalSearchOperation searchOperation,
-                            SearchResultEntry searchEntry) throws DirectoryException {
-                        handler.handleEntry(from(searchEntry));
-                    }
-                };
+                  @Override
+                  public void handleInternalSearchEntry(InternalSearchOperation searchOperation,
+                          SearchResultEntry searchEntry) throws DirectoryException {
+                      handler.handleEntry(from(searchEntry));
+                  }
+              };
 
-                final SearchFilter filter = toSearchFilter(request.getFilter());
-                final org.opends.server.protocols.internal.SearchRequest sr =
-                    Requests.newSearchRequest(request.getName(), request.getScope(), filter)
-                        .setDereferenceAliasesPolicy(request.getDereferenceAliasesPolicy())
-                        .setSizeLimit(request.getSizeLimit())
-                        .setTimeLimit(request.getTimeLimit())
-                        .setTypesOnly(request.isTypesOnly())
-                        .addAttribute(request.getAttributes())
-                        .addControl(to(request.getControls()));
-                return getResponseResult(icc.processSearch(sr, internalSearchListener));
-            }
+              final SearchFilter filter = toSearchFilter(request.getFilter());
+              final org.opends.server.protocols.internal.SearchRequest sr =
+                  Requests.newSearchRequest(request.getName(), request.getScope(), filter)
+                      .setDereferenceAliasesPolicy(request.getDereferenceAliasesPolicy())
+                      .setSizeLimit(request.getSizeLimit())
+                      .setTimeLimit(request.getTimeLimit())
+                      .setTypesOnly(request.isTypesOnly())
+                      .addAttribute(request.getAttributes())
+                      .addControl(to(request.getControls()));
+              return getResponseResult(icc.processSearch(sr, internalSearchListener));
+          }
 
-            @Override
-            public void removeConnectionEventListener(ConnectionEventListener listener) {
-                // Internal client connection don't have any connection events.
-            }
+          @Override
+          public void removeConnectionEventListener(ConnectionEventListener listener) {
+              // Internal client connection don't have any connection events.
+          }
 
-            @Override
-            public Result modifyDN(final ModifyDNRequest request) throws LdapException {
-                return getResponseResult(icc.processModifyDN(request));
-            }
+          @Override
+          public Result modifyDN(final ModifyDNRequest request) throws LdapException {
+              return getResponseResult(icc.processModifyDN(request));
+          }
 
-            @Override
-            public Result modify(final ModifyRequest request) throws LdapException {
-                return getResponseResult(icc.processModify(request));
-            }
+          @Override
+          public Result modify(final ModifyRequest request) throws LdapException {
+              return getResponseResult(icc.processModify(request));
+          }
 
-            @Override
-            public boolean isValid() {
-                // Always true.
-                return true;
-            }
+          @Override
+          public boolean isValid() {
+              // Always true.
+              return true;
+          }
 
-            @Override
-            public boolean isClosed() {
-                return false;
-            }
+          @Override
+          public boolean isClosed() {
+              return false;
+          }
 
-            @Override
-            public <R extends ExtendedResult> R extendedRequest(final ExtendedRequest<R> request,
-                    final IntermediateResponseHandler handler) throws LdapException {
+          @Override
+          public <R extends ExtendedResult> R extendedRequest(final ExtendedRequest<R> request,
+                  final IntermediateResponseHandler handler) throws LdapException {
 
-                final ExtendedOperation extendedOperation =
-                        icc.processExtendedOperation(request.getOID(), request.getValue(),
-                                to(request.getControls()));
+              final ExtendedOperation extendedOperation =
+                      icc.processExtendedOperation(request.getOID(), request.getValue(),
+                              to(request.getControls()));
 
-                final Result result = getResponseResult(extendedOperation);
-                final GenericExtendedResult genericExtendedResult =
-                        Responses.newGenericExtendedResult(result.getResultCode())
-                                .setDiagnosticMessage(result.getDiagnosticMessage()).setMatchedDN(
-                                        result.getMatchedDN()).setValue(
-                                        extendedOperation.getResponseValue().toByteString());
-                try {
-                    R extendedResult =
-                            request.getResultDecoder().decodeExtendedResult(genericExtendedResult,
-                                    new DecodeOptions());
-                    for (final Control control : result.getControls()) {
-                        extendedResult.addControl(control);
-                    }
-                    return extendedResult;
+              final Result result = getResponseResult(extendedOperation);
+              final GenericExtendedResult genericExtendedResult =
+                      Responses.newGenericExtendedResult(result.getResultCode())
+                              .setDiagnosticMessage(result.getDiagnosticMessage()).setMatchedDN(
+                                      result.getMatchedDN()).setValue(
+                                      extendedOperation.getResponseValue().toByteString());
+              try {
+                  R extendedResult =
+                          request.getResultDecoder().decodeExtendedResult(genericExtendedResult,
+                                  new DecodeOptions());
+                  for (final Control control : result.getControls()) {
+                      extendedResult.addControl(control);
+                  }
+                  return extendedResult;
 
-                } catch (DecodeException e) {
-                    DN matchedDN = extendedOperation.getMatchedDN();
-                    return request.getResultDecoder().newExtendedErrorResult(
-                            extendedOperation.getResultCode(),
-                            matchedDN != null ? matchedDN.toString() : null,
-                            extendedOperation.getErrorMessage().toString());
-                }
-            }
+              } catch (DecodeException e) {
+                  DN matchedDN = extendedOperation.getMatchedDN();
+                  return request.getResultDecoder().newExtendedErrorResult(
+                          extendedOperation.getResultCode(),
+                          matchedDN != null ? matchedDN.toString() : null,
+                          extendedOperation.getErrorMessage().toString());
+              }
+          }
 
-            @Override
-            public Result delete(final DeleteRequest request) throws LdapException {
-                final DeleteOperation deleteOperation =
-                        icc.processDelete(valueOfObject(request.getName()), to(request.getControls()));
-                return getResponseResult(deleteOperation);
-            }
+          @Override
+          public Result delete(final DeleteRequest request) throws LdapException {
+              final DeleteOperation deleteOperation =
+                      icc.processDelete(valueOfObject(request.getName()), to(request.getControls()));
+              return getResponseResult(deleteOperation);
+          }
 
-            @Override
-            public CompareResult compare(final CompareRequest request) throws LdapException {
-                final CompareOperation compareOperation =
-                        icc.processCompare(valueOfObject(request.getName()),
-                                request.getAttributeDescription().toString(),
-                                request.getAssertionValue(), to(request.getControls()));
+          @Override
+          public CompareResult compare(final CompareRequest request) throws LdapException {
+              final CompareOperation compareOperation =
+                      icc.processCompare(valueOfObject(request.getName()),
+                              request.getAttributeDescription().toString(),
+                              request.getAssertionValue(), to(request.getControls()));
 
-                CompareResult result = Responses.newCompareResult(compareOperation.getResultCode());
-                return getResponseResult(compareOperation, result);
-            }
+              CompareResult result = Responses.newCompareResult(compareOperation.getResultCode());
+              return getResponseResult(compareOperation, result);
+          }
 
-            @Override
-            public void close(final UnbindRequest request, final String reason) {
-                // no implementation in open-ds.
-            }
+          @Override
+          public void close(final UnbindRequest request, final String reason) {
+              // no implementation in open-ds.
+          }
 
-            @Override
-            public BindResult bind(final BindRequest request) throws LdapException {
-                BindOperation bindOperation = null;
-                if (request instanceof SimpleBindRequest) {
-                    bindOperation =
-                            icc.processSimpleBind(valueOfUtf8(request.getName()),
-                                    ByteString.wrap(((SimpleBindRequest) request).getPassword()),
-                                    to(request.getControls()));
-                } else if (request instanceof SASLBindRequest) {
-                    String serverName = null;
-                    try {
-                        serverName = InetAddress.getByName(null).getCanonicalHostName();
-                    } catch (UnknownHostException e) {
-                        // nothing to do.
-                    }
-                    BindClient bindClient = request.createBindClient(serverName);
-                    do {
-                        final GenericBindRequest genericBindRequest = bindClient.nextBindRequest();
-                        bindOperation =
-                                icc.processSASLBind(
-                                        valueOfUtf8(request.getName()),
-                                        ((SASLBindRequest) request).getSASLMechanism(),
-                                        getCredentials(genericBindRequest.getAuthenticationValue()),
-                                        to(request.getControls()));
-                    } while (bindOperation.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS);
+          @Override
+          public BindResult bind(final BindRequest request) throws LdapException {
+              BindOperation bindOperation = null;
+              if (request instanceof SimpleBindRequest) {
+                  bindOperation =
+                          icc.processSimpleBind(valueOfUtf8(request.getName()),
+                                  ByteString.wrap(((SimpleBindRequest) request).getPassword()),
+                                  to(request.getControls()));
+              } else if (request instanceof SASLBindRequest) {
+                  String serverName = null;
+                  try {
+                      serverName = InetAddress.getByName(null).getCanonicalHostName();
+                  } catch (UnknownHostException e) {
+                      // nothing to do.
+                  }
+                  BindClient bindClient = request.createBindClient(serverName);
+                  do {
+                      final GenericBindRequest genericBindRequest = bindClient.nextBindRequest();
+                      bindOperation =
+                              icc.processSASLBind(
+                                      valueOfUtf8(request.getName()),
+                                      ((SASLBindRequest) request).getSASLMechanism(),
+                                      getCredentials(genericBindRequest.getAuthenticationValue()),
+                                      to(request.getControls()));
+                  } while (bindOperation.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS);
 
-                    bindClient.dispose();
+                  bindClient.dispose();
 
-                } else { // not supported
-                    throw newLdapException(Responses.newResult(ResultCode.AUTH_METHOD_NOT_SUPPORTED));
-                }
-                BindResult result = Responses.newBindResult(bindOperation.getResultCode());
-                result.setServerSASLCredentials(bindOperation.getSASLCredentials());
+              } else { // not supported
+                  throw newLdapException(Responses.newResult(ResultCode.AUTH_METHOD_NOT_SUPPORTED));
+              }
+              BindResult result = Responses.newBindResult(bindOperation.getResultCode());
+              result.setServerSASLCredentials(bindOperation.getSASLCredentials());
 
-                if (result.isSuccess()) {
-                    return result;
-                } else {
-                    throw newLdapException(result);
-                }
-            }
+              if (result.isSuccess()) {
+                  return result;
+              } else {
+                  throw newLdapException(result);
+              }
+          }
 
-            @Override
-            public void addConnectionEventListener(ConnectionEventListener listener) {
-                // Internal client connection don't have any connection events.
-            }
+          @Override
+          public void addConnectionEventListener(ConnectionEventListener listener) {
+              // Internal client connection don't have any connection events.
+          }
 
-            @Override
-            public Result add(final AddRequest request) throws LdapException {
-                final AddOperation addOperation =
-                        icc.processAdd(valueOfObject(request.getName()), to(request
-                                .getAllAttributes()), to(request.getControls()));
-                return getResponseResult(addOperation);
-            }
+          @Override
+          public Result add(final AddRequest request) throws LdapException {
+              final AddOperation addOperation =
+                      icc.processAdd(valueOfObject(request.getName()), to(request
+                              .getAllAttributes()), to(request.getControls()));
+              return getResponseResult(addOperation);
+          }
 
-            @Override
-            public String toString() {
-                return icc.toString();
-            }
-        };
+          @Override
+          public String toString() {
+              return icc.toString();
+          }
+      };
+  }
+
+  /**
+   * This operation is hack to be able to execute a {@link Runnable} in a
+   * Directory Server's worker thread.
+   */
+  private static final class AsyncOperation<V> extends org.opends.server.types.AbstractOperation
+  {
+    private final Runnable runnable;
+
+    AsyncOperation(InternalClientConnection icc, Runnable runnable)
+    {
+      super(icc, icc.nextOperationID(), icc.nextMessageID(), Collections.<org.opends.server.types.Control> emptyList());
+      this.setInternalOperation(true);
+      this.runnable = runnable;
     }
+
+    @Override
+    public void run()
+    {
+      runnable.run();
+    }
+
+    @Override
+    public OperationType getOperationType()
+    {
+      return null;
+    }
+    @Override
+    public List<org.opends.server.types.Control> getResponseControls()
+    {
+      return Collections.emptyList();
+    }
+    @Override
+    public void addResponseControl(org.opends.server.types.Control control)
+    {
+    }
+    @Override
+    public void removeResponseControl(org.opends.server.types.Control control)
+    {
+    }
+    @Override
+    public DN getProxiedAuthorizationDN()
+    {
+      return null;
+    }
+    @Override
+    public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+    {
+    }
+    @Override
+    public void toString(StringBuilder buffer)
+    {
+      buffer.append(AsyncOperation.class.getSimpleName());
+    }
+  }
 }

--
Gitblit v1.10.0