From 15469de4b9253a7f84cf5634019c6d94fa94393c Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 07 Nov 2016 15:05:30 +0000
Subject: [PATCH] OPENDJ-3417 Add abstract Backend class as superior of LocalBackend

---
 opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java |  265 ++++++-----------------------
 opendj-server-legacy/src/main/java/org/opends/server/api/Backend.java      |  268 +++++++++++++++++++++++++++++
 2 files changed, 322 insertions(+), 211 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/Backend.java b/opendj-server-legacy/src/main/java/org/opends/server/api/Backend.java
new file mode 100644
index 0000000..d3b63f1
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/Backend.java
@@ -0,0 +1,268 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2016 ForgeRock AS.
+ */
+package org.opends.server.api;
+
+import java.util.List;
+import java.util.Set;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.Configuration;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.DN;
+import org.opends.server.core.ServerContext;
+import org.opends.server.monitors.BackendMonitor;
+import org.opends.server.types.InitializationException;
+
+/**
+ * Represents a directory server backend, which can be either local or remote (proxy).
+ * A backend is a LDAP endpoint.
+ *
+ * @param <C>
+ *          the type of the BackendCfg for the current backend
+ */
+public abstract class Backend<C extends Configuration>
+  //implements ReactiveHandler<LdapClientConnection, Request, Response>
+{
+
+  /** The backend monitor associated with this backend. */
+  private BackendMonitor backendMonitor;
+
+  /** The unique identifier for this backend. */
+  private String backendID;
+
+  /**
+   * Performs the provided request on this backend.
+   *
+   * @return a stream of response
+   */
+  //public abstract Stream<Response> handle(final LDAPClientConnection clientContext, final Request request)
+  //   throws Exception;
+
+  /**
+   * Configure this backend based on the information in the provided configuration.
+   * When the method returns, the backend will have been configured (ready to be opened) but still unable
+   * to process operations.
+   *
+   * @param  cfg          The configuration of this backend.
+   * @param  serverContext The server context for this instance
+   * @throws  ConfigException
+   *                      If there is an error in the configuration.
+   */
+  public abstract void configureBackend(C cfg, ServerContext serverContext) throws ConfigException;
+
+  /**
+   * Opens this backend based on the information provided when the backend was configured.
+   * It also should open any underlying storage and register all suffixes with the server.
+   *
+   * @see #configureBackend
+   *
+   * @throws  ConfigException  If an unrecoverable problem arises while opening the backend.
+   *
+   * @throws  InitializationException  If a problem occurs during opening that is not
+   *                                   related to the server configuration.
+   */
+  public abstract void openBackend() throws ConfigException, InitializationException;
+
+  /**
+   * Performs any necessary work to finalize this backend. The backend must be an opened backend,
+   * so do not use this method on backends where only <code>configureBackend()</code> has been called.
+   * This may be called during the Directory Server shutdown process or if a backend is disabled
+   * with the server online.
+   * It must not return until the backend is closed.
+   * <p>
+   * This method may not throw any exceptions. If any problems are encountered,
+   * then they may be logged but the closure should progress as completely as
+   * possible.
+   * <p>
+   */
+  public abstract void finalizeBackend();
+
+  /**
+   * Retrieves the unique identifier for this backend.
+   *
+   * @return  The unique identifier for this backend.
+   */
+  public final String getBackendID()
+  {
+    return backendID;
+  }
+
+  /**
+   * Retrieves the backend monitor that is associated with this
+   * backend.
+   *
+   * @return  The backend monitor that is associated with this
+   *          backend, or {@code null} if none has been assigned.
+   */
+  public final BackendMonitor getBackendMonitor()
+  {
+    return backendMonitor;
+  }
+
+  /**
+   * Retrieves the set of base-level DNs that may be used within this
+   * backend.
+   *
+   * @return  The set of base-level DNs that may be used within this
+   *          backend.
+   */
+  public abstract Set<DN> getBaseDNs();
+
+  /**
+   * Retrieves the parent backend for this backend.
+   *
+   * @return  The parent backend for this backend, or {@code null} if
+   *          there is none.
+   */
+  public abstract LocalBackend<?> getParentBackend();
+
+  /**
+   * Retrieve the password storage schemes defined for this backend.
+   */
+  public abstract Set<PasswordStorageScheme<?>> getPasswordStorageSchemes();
+
+  /**
+   * Retrieves the set of subordinate backends for this backend.
+   *
+   * @return  The set of subordinate backends for this backend, or an
+   *          empty array if none exist.
+   */
+  public abstract Backend<?>[] getSubordinateBackends();
+
+  /**
+   * Retrieves the OIDs of the controls that may be supported by this
+   * backend.
+   *
+   * @return  The OIDs of the controls that may be supported by this
+   *          backend.
+   */
+  public abstract Set<String> getSupportedControls();
+
+  /**
+   * Retrieves the OIDs of the features that may be supported by this
+   * backend.
+   *
+   * @return  The OIDs of the features that may be supported by this
+   *          backend.
+   */
+  public abstract Set<String> getSupportedFeatures();
+
+  /**
+   * Indicates whether the provided configuration is acceptable for
+   * this backend.  It should be possible to call this method on an
+   * uninitialized backend instance in order to determine whether the
+   * backend would be able to use the provided configuration.
+   * <BR><BR>
+   * Note that implementations which use a subclass of the provided
+   * configuration class will likely need to cast the configuration
+   * to the appropriate subclass type.
+   *
+   * @param  configuration        The backend configuration for which
+   *                              to make the determination.
+   * @param  unacceptableReasons  A list that may be used to hold the
+   *                              reasons that the provided
+   *                              configuration is not acceptable.
+   * @param serverContext         this Directory Server instance's server context
+   * @return  {@code true} if the provided configuration is acceptable
+   *          for this backend, or {@code false} if not.
+   */
+  public boolean isConfigurationAcceptable(
+                      C configuration,
+                      List<LocalizableMessage> unacceptableReasons, ServerContext serverContext)
+  {
+    // This default implementation does not perform any special
+    // validation.  It should be overridden by backend implementations
+    // that wish to perform more detailed validation.
+    return true;
+  }
+
+  /**
+   * Indicates whether this backend should be considered a default (wild-card) route.
+   *
+   * @return {@code true} if the backend should be considered as the default route, {@code false} otherwise
+   */
+  public abstract boolean isDefaultRoute();
+
+  /**
+   * Indicates whether this backend holds private data or user data.
+   *
+   * @return  {@code true} if this backend holds private data, or
+   *          {@code false} if it holds user data.
+   */
+  public abstract boolean isPrivateBackend();
+
+  /**
+   * Indicates whether this backend supports the specified control.
+   *
+   * @param  controlOID  The OID of the control for which to make the
+   *                     determination.
+   *
+   * @return  {@code true} if this backends supports the control with
+   *          the specified OID, or {@code false} if it does not.
+   */
+  public final boolean supportsControl(String controlOID)
+  {
+    Set<String> supportedControls = getSupportedControls();
+    return supportedControls != null && supportedControls.contains(controlOID);
+  }
+
+  /**
+   * Adds the provided backend to the set of subordinate backends for
+   * this backend.
+   *
+   * @param  subordinateBackend  The backend to add to the set of
+   *                             subordinate backends for this
+   *                             backend.
+   */
+  public abstract void addSubordinateBackend(Backend<?> subordinateBackend);
+
+  /**
+   * Removes the provided backend from the set of subordinate backends
+   * for this backend.
+   *
+   * @param  subordinateBackend  The backend to remove from the set of
+   *                             subordinate backends for this
+   *                             backend.
+   */
+  public abstract void removeSubordinateBackend(Backend<?> subordinateBackend);
+
+  /**
+   * Specifies the unique identifier for this backend.
+   *
+   * @param  backendID  The unique identifier for this backend.
+   */
+  public final void setBackendID(String backendID)
+  {
+    this.backendID = backendID;
+  }
+
+  /**
+   * Sets the backend monitor for this backend.
+   *
+   * @param  backendMonitor  The backend monitor for this backend.
+   */
+  public final void setBackendMonitor(BackendMonitor backendMonitor)
+  {
+    this.backendMonitor = backendMonitor;
+  }
+
+  /**
+   * Specifies the parent backend for this backend.
+   *
+   * @param  parentBackend  The parent backend for this backend.
+   */
+  public abstract void setParentBackend(Backend<?> parentBackend);
+
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java
index e0de700..8ac6bd3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java
@@ -21,13 +21,12 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
-import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.config.Configuration;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ConditionResult;
@@ -47,7 +46,6 @@
 import org.opends.server.core.PersistentSearch.CancellationCallback;
 import org.opends.server.core.SearchOperation;
 import org.opends.server.core.ServerContext;
-import org.opends.server.monitors.BackendMonitor;
 import org.opends.server.types.BackupConfig;
 import org.opends.server.types.BackupDirectory;
 import org.opends.server.types.CanceledOperationException;
@@ -73,7 +71,7 @@
      mayInstantiate=false,
      mayExtend=true,
      mayInvoke=false)
-public abstract class LocalBackend<C extends Configuration>
+public abstract class LocalBackend<C extends Configuration> extends Backend<C>
 // should have been BackendCfg instead of Configuration
 {
   /**
@@ -88,60 +86,22 @@
    */
   private LocalBackend<?>[] subordinateBackends = new LocalBackend[0];
 
-  /** The backend monitor associated with this backend. */
-  private BackendMonitor backendMonitor;
-
   /** Indicates whether this is a private backend or one that holds user data. */
   private boolean isPrivateBackend;
 
-  /** The unique identifier for this backend. */
-  private String backendID;
-
   /** The writability mode for this backend. */
   private WritabilityMode writabilityMode = WritabilityMode.ENABLED;
 
   /** The set of persistent searches registered with this backend. */
   private final ConcurrentLinkedQueue<PersistentSearch> persistentSearches = new ConcurrentLinkedQueue<>();
 
-  /**
-   * Configure this backend based on the information in the provided configuration.
-   * When the method returns, the backend will have been configured (ready to be opened) but still unable
-   * to process operations.
-   *
-   * @param  cfg          The configuration of this backend.
-   * @param  serverContext The server context for this instance
-   * @throws  ConfigException
-   *                      If there is an error in the configuration.
-   */
-  public abstract void configureBackend(C cfg, ServerContext serverContext) throws ConfigException;
-
-  /**
-   * Indicates whether the provided configuration is acceptable for
-   * this backend.  It should be possible to call this method on an
-   * uninitialized backend instance in order to determine whether the
-   * backend would be able to use the provided configuration.
-   * <BR><BR>
-   * Note that implementations which use a subclass of the provided
-   * configuration class will likely need to cast the configuration
-   * to the appropriate subclass type.
-   *
-   * @param  configuration        The backend configuration for which
-   *                              to make the determination.
-   * @param  unacceptableReasons  A list that may be used to hold the
-   *                              reasons that the provided
-   *                              configuration is not acceptable.
-   * @param serverContext         this Directory Server instance's server context
-   * @return  {@code true} if the provided configuration is acceptable
-   *          for this backend, or {@code false} if not.
-   */
-  public boolean isConfigurationAcceptable(
-                      C configuration,
-                      List<LocalizableMessage> unacceptableReasons, ServerContext serverContext)
+  public static LocalBackend<?> asLocalBackend(Backend<?> backend)
   {
-    // This default implementation does not perform any special
-    // validation.  It should be overridden by backend implementations
-    // that wish to perform more detailed validation.
-    return true;
+    if (backend instanceof LocalBackend)
+    {
+      return (LocalBackend<?>) backend;
+    }
+    throw new IllegalArgumentException("Backend " + backend.getBackendID() + " is not a local backend");
   }
 
   /**
@@ -155,20 +115,10 @@
    * @throws  InitializationException  If a problem occurs during opening that is not
    *                                   related to the server configuration.
    */
+  @Override
   public abstract void openBackend() throws ConfigException, InitializationException;
 
-  /**
-   * Performs any necessary work to finalize this backend. The backend must be an opened backend,
-   * so do not use this method on backends where only <code>configureBackend()</code> has been called.
-   * This may be called during the Directory Server shutdown process or if a backend is disabled
-   * with the server online.
-   * It must not return until the backend is closed.
-   * <p>
-   * This method may not throw any exceptions. If any problems are encountered,
-   * then they may be logged but the closure should progress as completely as
-   * possible.
-   * <p>
-   */
+  @Override
   public final void finalizeBackend()
   {
     for (PersistentSearch psearch : persistentSearches)
@@ -193,15 +143,6 @@
   }
 
   /**
-   * Retrieves the set of base-level DNs that may be used within this
-   * backend.
-   *
-   * @return  The set of base-level DNs that may be used within this
-   *          backend.
-   */
-  public abstract Set<DN> getBaseDNs();
-
-  /**
    * Indicates whether search operations which target the specified
    * attribute in the indicated manner would be considered indexed
    * in this backend.  The operation should be considered indexed only
@@ -351,18 +292,6 @@
   }
 
   /**
-   * Retrieves the requested entry from this backend. The caller is not required to hold any locks
-   * on the specified DN.
-   *
-   * @param entryDN
-   *          The distinguished name of the entry to retrieve.
-   * @return The requested entry, or {@code null} if the entry does not exist.
-   * @throws DirectoryException
-   *           If a problem occurs while trying to retrieve the entry.
-   */
-  public abstract Entry getEntry(DN entryDN) throws DirectoryException;
-
-  /**
    * Indicates whether the requested entry has any subordinates.
    *
    * @param entryDN The distinguished name of the entry.
@@ -424,6 +353,18 @@
   }
 
   /**
+   * Retrieves the requested entry from this backend. The caller is not required to hold any locks
+   * on the specified DN.
+   *
+   * @param entryDN
+   *          The distinguished name of the entry to retrieve.
+   * @return The requested entry, or {@code null} if the entry does not exist.
+   * @throws DirectoryException
+   *           If a problem occurs while trying to retrieve the entry.
+   */
+  public abstract Entry getEntry(DN entryDN) throws DirectoryException;
+
+  /**
    * Adds the provided entry to this backend.  This method must ensure
    * that the entry is appropriate for the backend and that no entry
    * already exists with the same DN.  The caller must hold a write
@@ -540,39 +481,6 @@
   public abstract void search(SearchOperation searchOperation)
          throws DirectoryException, CanceledOperationException;
 
-  /**
-   * Retrieves the OIDs of the controls that may be supported by this
-   * backend.
-   *
-   * @return  The OIDs of the controls that may be supported by this
-   *          backend.
-   */
-  public abstract Set<String> getSupportedControls();
-
-  /**
-   * Indicates whether this backend supports the specified control.
-   *
-   * @param  controlOID  The OID of the control for which to make the
-   *                     determination.
-   *
-   * @return  {@code true} if this backends supports the control with
-   *          the specified OID, or {@code false} if it does not.
-   */
-  public final boolean supportsControl(String controlOID)
-  {
-    Set<String> supportedControls = getSupportedControls();
-    return supportedControls != null && supportedControls.contains(controlOID);
-  }
-
-  /**
-   * Retrieves the OIDs of the features that may be supported by this
-   * backend.
-   *
-   * @return  The OIDs of the features that may be supported by this
-   *          backend.
-   */
-  public abstract Set<String> getSupportedFeatures();
-
   /** Enumeration of optional backend operations. */
   public static enum BackendOperation
   {
@@ -726,48 +634,6 @@
   public abstract void restoreBackup(RestoreConfig restoreConfig) throws DirectoryException;
 
   /**
-   * Retrieves the unique identifier for this backend.
-   *
-   * @return  The unique identifier for this backend.
-   */
-  public final String getBackendID()
-  {
-    return backendID;
-  }
-
-  /**
-   * Specifies the unique identifier for this backend.
-   *
-   * @param  backendID  The unique identifier for this backend.
-   */
-  public final void setBackendID(String backendID)
-  {
-    this.backendID = backendID;
-  }
-
-  /**
-   * Indicates whether this backend holds private data or user data.
-   *
-   * @return  {@code true} if this backend holds private data, or
-   *          {@code false} if it holds user data.
-   */
-  public final boolean isPrivateBackend()
-  {
-    return isPrivateBackend;
-  }
-
-  /**
-   * Specifies whether this backend holds private data or user data.
-   *
-   * @param  isPrivateBackend  Specifies whether this backend holds
-   *                           private data or user data.
-   */
-  public final void setPrivateBackend(boolean isPrivateBackend)
-  {
-    this.isPrivateBackend = isPrivateBackend;
-  }
-
-  /**
    * Retrieves the writability mode for this backend.
    *
    * @return  The writability mode for this backend.
@@ -787,16 +653,27 @@
     this.writabilityMode = writabilityMode != null ? writabilityMode : WritabilityMode.ENABLED;
   }
 
-  /**
-   * Retrieves the backend monitor that is associated with this
-   * backend.
-   *
-   * @return  The backend monitor that is associated with this
-   *          backend, or {@code null} if none has been assigned.
-   */
-  public final BackendMonitor getBackendMonitor()
+  @Override
+  public final boolean isPrivateBackend()
   {
-    return backendMonitor;
+    return isPrivateBackend;
+  }
+
+  /**
+   * Specifies whether this backend holds private data or user data.
+   *
+   * @param  isPrivateBackend  Specifies whether this backend holds
+   *                           private data or user data.
+   */
+  public final void setPrivateBackend(boolean isPrivateBackend)
+  {
+    this.isPrivateBackend = isPrivateBackend;
+  }
+
+  @Override
+  public final boolean isDefaultRoute()
+  {
+    return false;
   }
 
   /**
@@ -835,14 +712,8 @@
     return persistentSearches;
   }
 
-  /**
-   * Sets the backend monitor for this backend.
-   *
-   * @param  backendMonitor  The backend monitor for this backend.
-   */
-  public final void setBackendMonitor(BackendMonitor backendMonitor)
-  {
-    this.backendMonitor = backendMonitor;
+  public Set<PasswordStorageScheme<?>> getPasswordStorageSchemes() {
+    return new HashSet<PasswordStorageScheme<?>>(DirectoryServer.getPasswordStorageSchemes());
   }
 
   /**
@@ -854,66 +725,38 @@
    */
   public abstract long getEntryCount();
 
-  /**
-   * Retrieves the parent backend for this backend.
-   *
-   * @return  The parent backend for this backend, or {@code null} if
-   *          there is none.
-   */
+  @Override
   public final LocalBackend<?> getParentBackend()
   {
     return parentBackend;
   }
 
-  /**
-   * Specifies the parent backend for this backend.
-   *
-   * @param  parentBackend  The parent backend for this backend.
-   */
-  public final synchronized void setParentBackend(LocalBackend<?> parentBackend)
+  @Override
+  public final synchronized void setParentBackend(Backend<?> parentBackend)
   {
-    this.parentBackend = parentBackend;
+    this.parentBackend = (LocalBackend<?>) parentBackend;
   }
 
-  /**
-   * Retrieves the set of subordinate backends for this backend.
-   *
-   * @return  The set of subordinate backends for this backend, or an
-   *          empty array if none exist.
-   */
+  @Override
   public final LocalBackend<?>[] getSubordinateBackends()
   {
     return subordinateBackends;
   }
 
-  /**
-   * Adds the provided backend to the set of subordinate backends for
-   * this backend.
-   *
-   * @param  subordinateBackend  The backend to add to the set of
-   *                             subordinate backends for this
-   *                             backend.
-   */
-  public final synchronized void addSubordinateBackend(LocalBackend<?> subordinateBackend)
+  @Override
+  public final synchronized void addSubordinateBackend(Backend<?> subordinateBackend)
   {
     LinkedHashSet<LocalBackend<?>> backendSet = new LinkedHashSet<>();
     Collections.addAll(backendSet, subordinateBackends);
 
-    if (backendSet.add(subordinateBackend))
+    if (backendSet.add((LocalBackend<?>) subordinateBackend))
     {
       subordinateBackends = backendSet.toArray(new LocalBackend[backendSet.size()]);
     }
   }
 
-  /**
-   * Removes the provided backend from the set of subordinate backends
-   * for this backend.
-   *
-   * @param  subordinateBackend  The backend to remove from the set of
-   *                             subordinate backends for this
-   *                             backend.
-   */
-  public final synchronized void removeSubordinateBackend(LocalBackend<?> subordinateBackend)
+  @Override
+  public final synchronized void removeSubordinateBackend(Backend<?> subordinateBackend)
   {
     ArrayList<LocalBackend<?>> backendList = new ArrayList<>(subordinateBackends.length);
 

--
Gitblit v1.10.0