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/InstallDS.java |  182 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 177 insertions(+), 5 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java
index 86d57a7..4c42af9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java
@@ -27,15 +27,15 @@
  */
 package org.opends.server.tools;
 
-import static com.forgerock.opendj.cli.Utils.*;
-import static com.forgerock.opendj.util.OperatingSystem.*;
-
 import static org.forgerock.util.Utils.*;
 import static org.opends.messages.AdminToolMessages.*;
 import static org.opends.messages.QuickSetupMessages.*;
 import static org.opends.messages.ToolMessages.*;
 import static org.opends.messages.UtilityMessages.*;
 
+import static com.forgerock.opendj.cli.Utils.*;
+import static com.forgerock.opendj.util.OperatingSystem.*;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
@@ -50,6 +50,8 @@
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.naming.ldap.LdapName;
 
@@ -57,6 +59,14 @@
 import org.forgerock.i18n.LocalizableMessageDescriptor.Arg0;
 import org.forgerock.i18n.LocalizableMessageDescriptor.Arg1;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.AbstractManagedObjectDefinition;
+import org.forgerock.opendj.config.ConfigurationFramework;
+import org.forgerock.opendj.config.ManagedObjectDefinition;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.server.config.client.BackendCfgClient;
+import org.forgerock.opendj.server.config.meta.LocalDBBackendCfgDefn;
+import org.forgerock.opendj.server.config.meta.PluggableBackendCfgDefn;
+import org.forgerock.opendj.server.config.server.BackendCfg;
 import org.opends.messages.QuickSetupMessages;
 import org.opends.messages.ToolMessages;
 import org.opends.quicksetup.ApplicationException;
@@ -207,6 +217,7 @@
 
   /** Different variables we use when the user decides to provide data again. */
   private NewSuffixOptions.Type lastResetPopulateOption;
+  private String lastResetBackendType;
 
   private String lastResetImportFile;
   private String lastResetRejectedFile;
@@ -222,6 +233,8 @@
   private Boolean lastResetEnableWindowsService;
   private Boolean lastResetStartServer;
 
+  private List<ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>> availableBackendTypes;
+
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
   /** The argument parser. */
@@ -366,6 +379,9 @@
       return InstallReturnCode.ERROR_LICENSE_NOT_ACCEPTED.getReturnCode();
     }
 
+    initializeConfigurationFramework();
+    availableBackendTypes = getBackendTypes();
+
     final UserData uData = new UserData();
     InstallReturnCode fillUserDataRC;
     try
@@ -410,6 +426,24 @@
     return InstallReturnCode.SUCCESSFUL.getReturnCode();
   }
 
+  private void initializeConfigurationFramework()
+  {
+    if (!ConfigurationFramework.getInstance().isInitialized())
+    {
+        try
+        {
+          ConfigurationFramework.getInstance().initialize();
+        }
+        catch (ConfigException e)
+        {
+          final LocalizableMessage message = LocalizableMessage.raw(
+              "Error occured while loading the configuration framework: " + e.getLocalizedMessage());
+          logger.error(message);
+          throw new RuntimeException(message.toString());
+        }
+    }
+  }
+
   private InstallReturnCode fillUserData(UserData uData, String[] args) throws UserDataException
   {
     if (!isInteractive())
@@ -685,6 +719,7 @@
     uData.setConnectTimeout(getConnectTimeout());
 
     final List<LocalizableMessage> errorMessages = new LinkedList<LocalizableMessage>();
+    setBackendType(uData, errorMessages);
     final List<String> baseDNs = checkBaseDNs(errorMessages);
     setDirectoryManagerData(uData, errorMessages);
     setPorts(uData, errorMessages);
@@ -698,6 +733,19 @@
     }
   }
 
+  private void setBackendType(final UserData uData, final List<LocalizableMessage> errorMessages)
+  {
+    final String filledBackendType = argParser.backendTypeArg.getValue();
+    if (retrieveBackendTypeFromName(filledBackendType) != null)
+    {
+      uData.setBackendType(filledBackendType);
+    }
+    else
+    {
+      errorMessages.add(ERR_INSTALLDS_NO_SUCH_BACKEND_TYPE.get(filledBackendType, getBackendTypeNames()));
+    }
+  }
+
   private List<String> checkBaseDNs(List<LocalizableMessage> errorMessages)
   {
     final List<String> baseDNs = argParser.baseDNArg.getValues();
@@ -940,7 +988,7 @@
 
     promptIfRequiredForDirectoryManager(uData);
     promptIfRequiredForPortData(uData);
-    uData.setNewSuffixOptions(promptIfRequiredForImportData());
+    uData.setNewSuffixOptions(promptIfRequiredForImportData(uData));
     uData.setSecurityOptions(promptIfRequiredForSecurityData(uData));
     uData.setEnableWindowsService(promptIfRequiredForWindowsService());
     uData.setStartServer(promptIfRequiredForStartServer());
@@ -1217,11 +1265,13 @@
    * some data or if the provided data is not valid, it prompts the user to
    * provide it.
    *
+   * @param uData
+   *          The UserData object to be updated.
    * @return the NewSuffixOptions telling how to import data
    * @throws UserDataException
    *           if something went wrong checking the data.
    */
-  private NewSuffixOptions promptIfRequiredForImportData() throws UserDataException
+  private NewSuffixOptions promptIfRequiredForImportData(final UserData uData) throws UserDataException
   {
     boolean prompt = true;
     if (!argParser.baseDNArg.isPresent())
@@ -1243,6 +1293,8 @@
       return NewSuffixOptions.createEmpty(new LinkedList<String>());
     }
 
+    uData.setBackendType(getOrPromptForBackendType());
+
     // Add default value for base DN on first prompt
     if (argParser.baseDNArg.getDefaultValue() == null)
     {
@@ -1254,6 +1306,63 @@
 
   }
 
+  private String getOrPromptForBackendType()
+  {
+    if (argParser.backendTypeArg.isPresent())
+    {
+      if (retrieveBackendTypeFromName(argParser.backendTypeArg.getValue().toLowerCase()) != null)
+      {
+        return argParser.backendTypeArg.getValue();
+      }
+      println();
+      println(ERR_INSTALLDS_NO_SUCH_BACKEND_TYPE.get(argParser.backendTypeArg.getValue(), getBackendTypeNames()));
+    }
+
+    int backendTypeIndex = 1;
+    try
+    {
+      final MenuResult<Integer> m = getBackendTypeMenu().run();
+      if (m.isSuccess())
+      {
+        backendTypeIndex = m.getValue();
+      }
+    }
+    catch (final ClientException ce)
+    {
+      logger.warn(LocalizableMessage.raw("Error reading input: " + ce, ce));
+    }
+
+    return availableBackendTypes.get(backendTypeIndex - 1).getName();
+  }
+
+  private Menu<Integer> getBackendTypeMenu()
+  {
+    final MenuBuilder<Integer> builder = new MenuBuilder<Integer>(this);
+    builder.setPrompt(INFO_INSTALLDS_PROMPT_BACKEND_TYPE.get());
+    int index = 1;
+    for (AbstractManagedObjectDefinition<?, ?> backendType : availableBackendTypes)
+    {
+      final String printableBackendName = filterSchemaBackendName(backendType.getName());
+      builder.addNumberedOption(LocalizableMessage.raw(printableBackendName), MenuResult.success(index++));
+    }
+
+    final int printableIndex = getPromptedBackendTypeIndex();
+    builder.setDefault(LocalizableMessage.raw(Integer.toString(printableIndex)), MenuResult.success(printableIndex));
+    final Menu<Integer> menu = builder.toMenu();
+    return menu;
+  }
+
+  private int getPromptedBackendTypeIndex()
+  {
+    if (lastResetBackendType != null)
+    {
+      ManagedObjectDefinition<?, ?> backend = InstallDS.retrieveBackendTypeFromName(lastResetBackendType);
+      return availableBackendTypes.indexOf(backend) + 1;
+    }
+
+    return 1;
+  }
+
   private NewSuffixOptions promptIfRequiredForDataOptions(List<String> baseDNs)
   {
     NewSuffixOptions dataOptions;
@@ -2507,6 +2616,7 @@
 
       lastResetEnableWindowsService = uData.getEnableWindowsService();
       lastResetStartServer = uData.getStartServer();
+      lastResetBackendType = uData.getBackendType();
     }
     catch (final Throwable t)
     {
@@ -2551,4 +2661,66 @@
     return argParser.getConnectTimeout();
   }
 
+  static ManagedObjectDefinition<?, ?> retrieveBackendTypeFromName(final String backendTypeStr)
+  {
+    for (ManagedObjectDefinition<?, ?> backendType : getBackendTypes())
+    {
+      final String name = backendType.getName();
+      if (backendTypeStr.equalsIgnoreCase(name)
+          || backendTypeStr.equalsIgnoreCase(filterSchemaBackendName(name)))
+      {
+        return backendType;
+      }
+    }
+
+    return null;
+  }
+
+  @SuppressWarnings("unchecked")
+  static List<ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>> getBackendTypes()
+  {
+    final List<ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>> backendTypes =
+        new LinkedList<ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>>();
+    backendTypes.add(LocalDBBackendCfgDefn.getInstance());
+
+    for (AbstractManagedObjectDefinition<?, ?> backendType : PluggableBackendCfgDefn.getInstance().getAllChildren())
+    {
+      // Filtering out only the non-abstract backends to avoid users attempt to create abstract ones
+      if (backendType instanceof ManagedObjectDefinition)
+      {
+        backendTypes.add((ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>) backendType);
+      }
+    }
+
+    return backendTypes;
+  }
+
+  static String getBackendTypeNames()
+  {
+    String backendTypeNames = "";
+    for (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType : getBackendTypes())
+    {
+      backendTypeNames += filterSchemaBackendName(backendType.getName()) + ", ";
+    }
+
+    if (backendTypeNames.isEmpty())
+    {
+      return "Impossible to retrieve supported backend type list";
+    }
+
+    return backendTypeNames.substring(0, backendTypeNames.length() - 2);
+  }
+
+  static String filterSchemaBackendName(final String dsCfgBackendName)
+  {
+    final String cfgNameRegExp = "(.*)-backend.*";
+    final Matcher regExpMatcher = Pattern.compile(cfgNameRegExp, Pattern.CASE_INSENSITIVE).matcher(dsCfgBackendName);
+    if (regExpMatcher.matches())
+    {
+      return regExpMatcher.group(1);
+    }
+
+    return dsCfgBackendName;
+  }
+
 }

--
Gitblit v1.10.0