From 7c02aa90fad0f4eaf27856ad1afcf2ffd90b64fc Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Thu, 02 Apr 2015 15:08:02 +0000
Subject: [PATCH] OPENDJ-1714 (CR-6533) Add backend type choice in setup cli

---
 opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java |  202 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 181 insertions(+), 21 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
index 6c64b67..22484b7 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
@@ -26,9 +26,6 @@
  */
 package org.opends.server.tools;
 
-import static com.forgerock.opendj.cli.ArgumentConstants.*;
-import static com.forgerock.opendj.cli.Utils.*;
-
 import static org.opends.messages.ConfigMessages.*;
 import static org.opends.messages.ExtensionMessages.*;
 import static org.opends.messages.ProtocolMessages.*;
@@ -37,7 +34,14 @@
 import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
+import static com.forgerock.opendj.cli.ArgumentConstants.*;
+import static com.forgerock.opendj.cli.Utils.*;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.io.StringReader;
@@ -45,12 +49,39 @@
 import java.security.GeneralSecurityException;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Set;
 
 import javax.crypto.Cipher;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.LDAPProfile;
+import org.forgerock.opendj.config.ManagedObjectDefinition;
+import org.forgerock.opendj.config.client.ManagementContext;
+import org.forgerock.opendj.config.client.ldap.LDAPManagementContext;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.Connections;
+import org.forgerock.opendj.ldap.MemoryBackend;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldif.LDIF;
+import org.forgerock.opendj.ldif.LDIFEntryReader;
+import org.forgerock.opendj.ldif.LDIFEntryWriter;
+import org.forgerock.opendj.server.config.client.BackendCfgClient;
+import org.forgerock.opendj.server.config.client.BackendIndexCfgClient;
+import org.forgerock.opendj.server.config.client.LocalDBBackendCfgClient;
+import org.forgerock.opendj.server.config.client.LocalDBIndexCfgClient;
+import org.forgerock.opendj.server.config.client.PluggableBackendCfgClient;
+import org.forgerock.opendj.server.config.client.RootCfgClient;
+import org.forgerock.opendj.server.config.meta.BackendCfgDefn.WritabilityMode;
+import org.forgerock.opendj.server.config.meta.BackendIndexCfgDefn;
+import org.forgerock.opendj.server.config.meta.BackendIndexCfgDefn.IndexType;
+import org.forgerock.opendj.server.config.meta.LocalDBBackendCfgDefn;
+import org.forgerock.opendj.server.config.meta.LocalDBIndexCfgDefn;
+import org.forgerock.opendj.server.config.server.BackendCfg;
+import org.opends.quicksetup.Installation;
+import org.opends.quicksetup.installer.Installer;
 import org.opends.server.admin.DefaultBehaviorProvider;
 import org.opends.server.admin.DefinedDefaultBehaviorProvider;
 import org.opends.server.admin.StringPropertyDefinition;
@@ -214,6 +245,40 @@
   /** The DN of the DIGEST-MD5 SASL mechanism handler. */
   public static final String DN_DIGEST_MD5_SASL_MECHANISM = "cn=DIGEST-MD5,cn=SASL Mechanisms,cn=config";
 
+  /** Describes an attribute index which should be created during installation. */
+  private static final class DefaultIndex
+  {
+    private final String name;
+    private final boolean shouldCreateSubstringIndex;
+
+    private DefaultIndex(final String name, final boolean substringIndex)
+    {
+      this.name = name;
+      this.shouldCreateSubstringIndex = substringIndex;
+    }
+
+    private static DefaultIndex withEqualityAndSubstring(final String name)
+    {
+      return new DefaultIndex(name, true);
+    }
+
+    private static DefaultIndex withEquality(final String name)
+    {
+      return new DefaultIndex(name, false);
+    }
+  }
+
+  private static final DefaultIndex[] DEFAULT_INDEXES = {
+    DefaultIndex.withEqualityAndSubstring("cn"),
+    DefaultIndex.withEqualityAndSubstring("givenName"),
+    DefaultIndex.withEqualityAndSubstring("mail"),
+    DefaultIndex.withEqualityAndSubstring("member"),
+    DefaultIndex.withEqualityAndSubstring("sn"),
+    DefaultIndex.withEqualityAndSubstring("telephoneNumber"),
+    DefaultIndex.withEquality("uid"),
+    DefaultIndex.withEquality("uniqueMember")
+  };
+
 
   private static int SUCCESS = 0;
   private static int ERROR = 1;
@@ -277,6 +342,7 @@
   private StringArgument certNickName;
   private StringArgument keyManagerPath;
   private StringArgument serverRoot;
+  private StringArgument backendType;
 
   private final String serverLockFileName = LockFileManager.getServerLockFileName();
   private final StringBuilder failureReason = new StringBuilder();
@@ -307,10 +373,11 @@
       checkArgumentsConsistency();
       checkPortArguments();
 
-      initializeDirectoryServer();
       tryAcquireExclusiveLocks();
+      updateBaseDNs(parseProvidedBaseDNs());
 
-      final LinkedList<DN> baseDNs = parseProvidedBaseDNs();
+      initializeDirectoryServer();
+
       final DN rootDN = parseRootDN();
       final String rootPW = parseRootDNPassword();
 
@@ -328,7 +395,6 @@
         throw new ConfigureDSException(message);
       }
 
-      updateBaseDNs(baseDNs);
       updateLdapPort();
       updateAdminConnectorPort();
       updateLdapSecurePort();
@@ -480,6 +546,13 @@
           null, null, null);
       serverRoot.setHidden(true);
       argParser.addArgument(serverRoot);
+
+      backendType = new StringArgument(
+          OPTION_LONG_BACKEND_TYPE.toLowerCase(), null, OPTION_LONG_BACKEND_TYPE,
+          false, false, true, INFO_INSTALLDS_BACKEND_TYPE_PLACEHOLDER.get(),
+          null, OPTION_LONG_BACKEND_TYPE, INFO_INSTALLDS_DESCRIPTION_BACKEND_TYPE.get()
+      );
+      argParser.addArgument(backendType);
     }
     catch (final ArgumentException ae)
     {
@@ -601,21 +674,20 @@
     }
   }
 
-  private LinkedList<DN> parseProvidedBaseDNs() throws ConfigureDSException
+  private LinkedList<org.forgerock.opendj.ldap.DN> parseProvidedBaseDNs() throws ConfigureDSException
   {
-    LinkedList<DN> baseDNs = null;
+    LinkedList<org.forgerock.opendj.ldap.DN> baseDNs = new LinkedList<org.forgerock.opendj.ldap.DN>();
     if (baseDNString.isPresent())
     {
-      baseDNs = new LinkedList<DN>();
       for (final String dnString : baseDNString.getValues())
       {
         try
         {
-          baseDNs.add(DN.valueOf(dnString));
+          baseDNs.add(org.forgerock.opendj.ldap.DN.valueOf(dnString));
         }
-        catch (final DirectoryException de)
+        catch (final Exception e)
         {
-          throw new ConfigureDSException(de, ERR_CONFIGDS_CANNOT_PARSE_BASE_DN.get(dnString, de.getMessageObject()));
+          throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_PARSE_BASE_DN.get(dnString, e.getMessage()));
         }
       }
     }
@@ -727,24 +799,112 @@
     }
   }
 
-  private void updateBaseDNs(final LinkedList<DN> baseDNs) throws ConfigureDSException
+  @SuppressWarnings("unchecked")
+  private void updateBaseDNs(final List<org.forgerock.opendj.ldap.DN> baseDNs) throws ConfigureDSException
   {
-    if (baseDNs != null)
+    if (!baseDNs.isEmpty())
     {
+      final String backendTypeName = backendType.getValue();
+      final ManagedObjectDefinition<?, ?> backend = InstallDS.retrieveBackendTypeFromName(backendTypeName);
+      if (backend == null)
+      {
+        throw new ConfigureDSException(
+            ERR_CONFIGDS_BACKEND_TYPE_UNKNOWN.get(backendTypeName, InstallDS.getBackendTypeNames()));
+      }
+
+      BufferedReader configReader = null;
+      BufferedWriter configWriter = null;
       try
       {
-        final DN jeBackendDN = DN.valueOf(DN_JE_BACKEND);
-        final ConfigEntry configEntry = configHandler.getConfigEntry(jeBackendDN);
+          final File configurationFile = Installation.getLocal().getCurrentConfigurationFile();
+          configReader = new BufferedReader(new FileReader(configurationFile));
 
-        final DNConfigAttribute baseDNAttr = new DNConfigAttribute(
-            ATTR_BACKEND_BASE_DN, INFO_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS.get(),
-            true, true, false, baseDNs);
-        configEntry.putConfigAttribute(baseDNAttr);
+          final MemoryBackend memoryBackend = new MemoryBackend(new LDIFEntryReader(configReader));
+          final Connection co = Connections.newInternalConnection(memoryBackend);
+          // We need to add the root dse entry to make the configuration framework work.
+          co.add(LDIFEntryReader.valueOfLDIFEntry("dn:", "objectClass:top", "objectClass:ds-root-dse"));
+
+          final ManagementContext context = LDAPManagementContext.newManagementContext(co, LDAPProfile.getInstance());
+          createBackend(context.getRootConfiguration(), baseDNs,
+                        (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>) backend);
+
+
+          final Iterator<org.forgerock.opendj.ldap.Entry> entries = memoryBackend.getAll().iterator();
+          entries.next(); // skip RootDSE
+          configWriter = new BufferedWriter(new FileWriter(configurationFile));
+          LDIF.copyTo(LDIF.newEntryIteratorReader(entries), new LDIFEntryWriter(configWriter));
       }
       catch (final Exception e)
       {
-        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_BASE_DN.get(e));
+        throw new ConfigureDSException(ERR_CONFIGDS_SET_BACKEND_TYPE.get(backendTypeName, e.getMessage()));
       }
+      finally
+      {
+        close(configReader, configWriter);
+      }
+    }
+  }
+
+  private void createBackend(final RootCfgClient rootConfiguration, final List<org.forgerock.opendj.ldap.DN> baseDNs,
+      final ManagedObjectDefinition<?, ?> backend) throws Exception
+  {
+      final BackendCfgClient backendCfgClient = rootConfiguration.createBackend(
+                      (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>) backend,
+                      Installer.ROOT_BACKEND_NAME, null);
+      backendCfgClient.setEnabled(true);
+      backendCfgClient.setBaseDN(baseDNs);
+      backendCfgClient.setWritabilityMode(WritabilityMode.ENABLED);
+      backendCfgClient.commit();
+
+      //FIXME: Remove once local-db backend will be pluggable.
+      if (backend instanceof LocalDBBackendCfgDefn)
+      {
+        addJEIndexes((LocalDBBackendCfgClient) backendCfgClient);
+        return;
+      }
+
+      addBackendIndexes((PluggableBackendCfgClient) backendCfgClient);
+  }
+
+  private void addBackendIndexes(PluggableBackendCfgClient backendCfgClient) throws Exception
+  {
+    for (DefaultIndex defaultIndex : DEFAULT_INDEXES)
+    {
+      final BackendIndexCfgClient index =
+          backendCfgClient.createBackendIndex(BackendIndexCfgDefn.getInstance(), defaultIndex.name, null);
+      index.setAttribute(Schema.getCoreSchema().getAttributeType(defaultIndex.name));
+
+      final List<IndexType> indexTypes = new LinkedList<IndexType>();
+      indexTypes.add(IndexType.EQUALITY);
+      if (defaultIndex.shouldCreateSubstringIndex)
+      {
+        indexTypes.add(IndexType.SUBSTRING);
+      }
+      index.setIndexType(indexTypes);
+
+      index.commit();
+    }
+  }
+
+  // FIXME: Remove once local-db backend will be pluggable.
+  private void addJEIndexes(final LocalDBBackendCfgClient jeBackendCfgClient) throws Exception
+  {
+    for (DefaultIndex defaultIndex : DEFAULT_INDEXES)
+    {
+      final LocalDBIndexCfgClient jeIndex =
+          jeBackendCfgClient.createLocalDBIndex(LocalDBIndexCfgDefn.getInstance(), defaultIndex.name, null);
+      jeIndex.setAttribute(Schema.getCoreSchema().getAttributeType(defaultIndex.name));
+
+      final List<org.forgerock.opendj.server.config.meta.LocalDBIndexCfgDefn.IndexType> indexTypes =
+          new LinkedList<org.forgerock.opendj.server.config.meta.LocalDBIndexCfgDefn.IndexType>();
+      indexTypes.add(org.forgerock.opendj.server.config.meta.LocalDBIndexCfgDefn.IndexType.EQUALITY);
+      if (defaultIndex.shouldCreateSubstringIndex)
+      {
+        indexTypes.add(org.forgerock.opendj.server.config.meta.LocalDBIndexCfgDefn.IndexType.SUBSTRING);
+      }
+      jeIndex.setIndexType(indexTypes);
+
+      jeIndex.commit();
     }
   }
 

--
Gitblit v1.10.0