From 911b4d52497cf4a285779bb5cd4a92d548935215 Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Fri, 27 Mar 2015 14:10:47 +0000
Subject: [PATCH] OPENDJ-1714 (CR-6442) Refactor ConfigureDS.java

---
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java | 1800 +++++++++++++++++++++++++++--------------------------------
 1 files changed, 820 insertions(+), 980 deletions(-)

diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
index d4dc5da..6c64b67 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
@@ -76,6 +76,7 @@
 import org.opends.server.types.NullOutputStream;
 import org.opends.server.util.LDIFReader;
 
+import com.forgerock.opendj.cli.Argument;
 import com.forgerock.opendj.cli.ArgumentException;
 import com.forgerock.opendj.cli.ArgumentParser;
 import com.forgerock.opendj.cli.BooleanArgument;
@@ -102,63 +103,121 @@
  */
 public class ConfigureDS
 {
+  private static final boolean WRONG_USAGE = true;
+
+  /** Private exception class to handle error message printing. */
+  @SuppressWarnings("serial")
+  private class ConfigureDSException extends Exception
+  {
+    private final int returnedErrorCode;
+    private final LocalizableMessage errorMessage;
+    private final boolean wrongUsage;
+
+    ConfigureDSException(final LocalizableMessage errorMessage)
+    {
+      this(new Exception("An error occured in ConfigureDS: " + errorMessage), errorMessage, false);
+    }
+
+    ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage)
+    {
+      this(parentException, errorMessage, false);
+    }
+
+    ConfigureDSException(final LocalizableMessage errorMessage, final boolean showUsage)
+    {
+      this(new Exception("An error occured in ConfigureDS: " + errorMessage), errorMessage, showUsage);
+    }
+
+    ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage,
+        final boolean showUsage)
+    {
+      this(parentException, errorMessage, showUsage, ERROR);
+    }
+
+    ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage,
+        final boolean wrongUsage, final int retCode)
+    {
+      super(parentException);
+      this.errorMessage = errorMessage;
+      this.wrongUsage = wrongUsage;
+      returnedErrorCode = retCode;
+    }
+
+    private LocalizableMessage getErrorMessage()
+    {
+      return errorMessage;
+    }
+
+    private boolean isWrongUsage()
+    {
+      return wrongUsage;
+    }
+
+    private int getErrorCode()
+    {
+      return returnedErrorCode;
+    }
+  }
+
+  //FIXME: Find a better way to do to prevent hardcoded ldif entries.
+  private static final String NEW_LINE = System.getProperty("line.separator");
+
+  private static final String JCKES_KEY_MANAGER_DN = "cn=JCEKS,cn=Key Manager Providers,cn=config";
+  private static final String JCKES_KEY_MANAGER_LDIF_ENTRY =
+        "dn: " + JCKES_KEY_MANAGER_DN + NEW_LINE
+      + "objectClass: top" + NEW_LINE
+      + "objectClass: ds-cfg-key-manager-provider" + NEW_LINE
+      + "objectClass: ds-cfg-file-based-key-manager-provider" + NEW_LINE
+      + "cn: JCEKS" + NEW_LINE
+      + "ds-cfg-java-class: org.opends.server.extensions.FileBasedKeyManagerProvider" + NEW_LINE
+      + "ds-cfg-enabled: true" + NEW_LINE
+      + "ds-cfg-key-store-type: JCEKS" + NEW_LINE
+      + "ds-cfg-key-store-file: config/keystore.jceks" + NEW_LINE
+      + "ds-cfg-key-store-pin-file: config/keystore.pin" + NEW_LINE;
+
+  private static final String JCKES_TRUST_MANAGER_DN = "cn=JCEKS,cn=Trust Manager Providers,cn=config";
+  private static final String JCKES_TRUST_MANAGER_LDIF_ENTRY =
+        "dn: " + JCKES_TRUST_MANAGER_DN + NEW_LINE
+      + "objectClass: top" + NEW_LINE
+      + "objectClass: ds-cfg-trust-manager-provider" + NEW_LINE
+      + "objectClass: ds-cfg-file-based-trust-manager-provider" + NEW_LINE
+      + "cn: JCEKS" + NEW_LINE
+      + "ds-cfg-java-class: org.opends.server.extensions.FileBasedTrustManagerProvider" + NEW_LINE
+      + "ds-cfg-enabled: false" + NEW_LINE
+      + "ds-cfg-trust-store-type: JCEKS" + NEW_LINE
+      + "ds-cfg-trust-store-file: config/truststore" + NEW_LINE;
+
   /** The fully-qualified name of this class. */
-  private static final String CLASS_NAME =
-       "org.opends.server.tools.ConfigureDS";
+  private static final String CLASS_NAME = "org.opends.server.tools.ConfigureDS";
 
+  /** The DN of the configuration entry defining the JE database backend. */
+  private static final String DN_JE_BACKEND = ATTR_BACKEND_ID + "=userRoot," + DN_BACKEND_BASE;
 
+  /** The DN of the configuration entry defining the LDAP connection handler. */
+  public static final String DN_LDAP_CONNECTION_HANDLER = "cn=LDAP Connection Handler," + DN_CONNHANDLER_BASE;
 
-  /**
-   * The DN of the configuration entry defining the JE database backend.
-   */
-  private static final String DN_JE_BACKEND =
-       ATTR_BACKEND_ID + "=userRoot," + DN_BACKEND_BASE;
+  /** The DN of the configuration entry defining the Administration connector. */
+  public static final String DN_ADMIN_CONNECTOR = "cn=Administration Connector," + DN_CONFIG_ROOT;
 
+  /** The DN of the configuration entry defining the LDAPS connection handler. */
+  private static final String DN_LDAPS_CONNECTION_HANDLER = "cn=LDAPS Connection Handler," + DN_CONNHANDLER_BASE;
 
+  /** The DN of the configuration entry defining the JMX connection handler. */
+  private static final String DN_JMX_CONNECTION_HANDLER = "cn=JMX Connection Handler," + DN_CONNHANDLER_BASE;
 
-  /**
-   * The DN of the configuration entry defining the LDAP connection handler.
-   */
-  public static final String DN_LDAP_CONNECTION_HANDLER =
-       "cn=LDAP Connection Handler," + DN_CONNHANDLER_BASE;
+  /** The DN of the configuration entry defining the initial root user. */
+  public static final String DN_ROOT_USER = "cn=Directory Manager," + DN_ROOT_DN_CONFIG_BASE;
 
-  /**
-   * The DN of the configuration entry defining the Administration connector.
-   */
-  public static final String DN_ADMIN_CONNECTOR =
-       "cn=Administration Connector," + DN_CONFIG_ROOT;
-
-  /**
-   * The DN of the configuration entry defining the LDAPS connection handler.
-   */
-  private static final String DN_LDAPS_CONNECTION_HANDLER =
-       "cn=LDAPS Connection Handler," + DN_CONNHANDLER_BASE;
-
-  /**
-   * The DN of the configuration entry defining the JMX connection handler.
-   */
-  private static final String DN_JMX_CONNECTION_HANDLER =
-       "cn=JMX Connection Handler," + DN_CONNHANDLER_BASE;
-
-
-  /**
-   * The DN of the configuration entry defining the initial root user.
-   */
-  public static final String DN_ROOT_USER =
-       "cn=Directory Manager," + DN_ROOT_DN_CONFIG_BASE;
-
-  /**
-   * The DN of the Crypto Manager.
-   */
+  /** The DN of the Crypto Manager. */
   public static final String DN_CRYPTO_MANAGER = "cn=Crypto Manager,cn=config";
 
-  /**
-   * 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";
+  /** 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";
 
 
+  private static int SUCCESS = 0;
+  private static int ERROR = 1;
+
   /**
    * Provides the command-line arguments to the <CODE>configMain</CODE> method
    * for processing.
@@ -167,8 +226,8 @@
    */
   public static void main(String[] args)
   {
-    int exitCode = configMain(args, System.out, System.err);
-    if (exitCode != 0)
+    final int exitCode = configMain(args, System.out, System.err);
+    if (exitCode != SUCCESS)
     {
       System.exit(filterExitCode(exitCode));
     }
@@ -186,50 +245,134 @@
    *          indicates that there was some kind of problem during the
    *          configuration processing.
    */
-  public static int configMain(String[] args,
-    OutputStream outStream, OutputStream errStream)
+  public static int configMain(final String[] args, final OutputStream outStream, final OutputStream errStream)
   {
-    BooleanArgument   showUsage;
-    BooleanArgument   enableStartTLS;
-    FileBasedArgument rootPasswordFile;
-    StringArgument    hostName;
-    IntegerArgument   ldapPort;
-    IntegerArgument   adminConnectorPort;
-    IntegerArgument   ldapsPort;
-    IntegerArgument   jmxPort;
-    StringArgument    baseDNString;
-    StringArgument    configClass;
-    StringArgument    configFile;
-    StringArgument    rootDNString;
-    StringArgument    rootPassword;
-    StringArgument    keyManagerProviderDN;
-    StringArgument    trustManagerProviderDN;
-    StringArgument    certNickName;
-    StringArgument    keyManagerPath;
-    StringArgument    serverRoot;
-    PrintStream out = NullOutputStream.wrapOrNullStream(outStream);
-    PrintStream err = NullOutputStream.wrapOrNullStream(errStream);
+    final ConfigureDS tool = new ConfigureDS(args, outStream, errStream);
+    return tool.run();
+  }
 
+  private final String[] arguments;
+  private final OutputStream outputStream;
+  private final OutputStream errorStream;
+  private final PrintStream out;
+  private final PrintStream err;
+
+  private final ArgumentParser argParser;
+
+  private BooleanArgument showUsage;
+  private BooleanArgument enableStartTLS;
+  private FileBasedArgument rootPasswordFile;
+  private StringArgument hostName;
+  private IntegerArgument ldapPort;
+  private IntegerArgument adminConnectorPort;
+  private IntegerArgument ldapsPort;
+  private IntegerArgument jmxPort;
+  private StringArgument baseDNString;
+  private StringArgument configClass;
+  private StringArgument configFile;
+  private StringArgument rootDNString;
+  private StringArgument rootPassword;
+  private StringArgument keyManagerProviderDN;
+  private StringArgument trustManagerProviderDN;
+  private StringArgument certNickName;
+  private StringArgument keyManagerPath;
+  private StringArgument serverRoot;
+
+  private final String serverLockFileName = LockFileManager.getServerLockFileName();
+  private final StringBuilder failureReason = new StringBuilder();
+  private ConfigHandler<?> configHandler;
+
+  private ConfigureDS(final String[] args, final OutputStream outStream, final OutputStream errStream)
+  {
+    arguments = args;
+    outputStream = outStream;
+    errorStream = errStream;
+    out = NullOutputStream.wrapOrNullStream(outputStream);
+    err = NullOutputStream.wrapOrNullStream(errorStream);
+    argParser = new ArgumentParser(CLASS_NAME, INFO_CONFIGDS_TOOL_DESCRIPTION.get(), false);
+  }
+
+  private int run()
+  {
     JDKLogging.disableLogging();
-
-    LocalizableMessage toolDescription = INFO_CONFIGDS_TOOL_DESCRIPTION.get();
-    ArgumentParser argParser = new ArgumentParser(CLASS_NAME, toolDescription,
-                                                  false);
     try
     {
-      configFile = new StringArgument("configfile", 'c', "configFile", true,
-                                      false, true,
-                                      INFO_CONFIGFILE_PLACEHOLDER.get(), null,
-                                      null,
-                                      INFO_DESCRIPTION_CONFIG_FILE.get());
+      initializeArguments();
+      parseArguments();
+      if (argParser.usageOrVersionDisplayed())
+      {
+        return SUCCESS;
+      }
+
+      checkArgumentsConsistency();
+      checkPortArguments();
+
+      initializeDirectoryServer();
+      tryAcquireExclusiveLocks();
+
+      final LinkedList<DN> baseDNs = parseProvidedBaseDNs();
+      final DN rootDN = parseRootDN();
+      final String rootPW = parseRootDNPassword();
+
+      // Get the Directory Server configuration handler and use it to make the
+      // appropriate configuration changes.
+      configHandler = DirectoryServer.getConfigHandler();
+
+      checkManagerProvider(keyManagerProviderDN, JCKES_KEY_MANAGER_DN, JCKES_KEY_MANAGER_LDIF_ENTRY, true);
+      checkManagerProvider(trustManagerProviderDN, JCKES_TRUST_MANAGER_DN, JCKES_TRUST_MANAGER_LDIF_ENTRY, false);
+      // Check that the keystore path values are valid.
+      if (keyManagerPath.isPresent() && !keyManagerProviderDN.isPresent())
+      {
+        final LocalizableMessage message = ERR_CONFIGDS_KEYMANAGER_PROVIDER_DN_REQUIRED.get(
+            keyManagerProviderDN.getLongIdentifier(), keyManagerPath.getLongIdentifier());
+        throw new ConfigureDSException(message);
+      }
+
+      updateBaseDNs(baseDNs);
+      updateLdapPort();
+      updateAdminConnectorPort();
+      updateLdapSecurePort();
+      updateJMXport();
+      updateStartTLS();
+      updateKeyManager();
+      updateTrustManager();
+      updateRootUser(rootDN, rootPW);
+      addFQDNDigestMD5();
+      updateCryptoCipher();
+      writeUpdatedConfiguration();
+
+      return SUCCESS;
+    }
+    catch (final ConfigureDSException e)
+    {
+     if (e.isWrongUsage())
+     {
+       err.println(argParser.getUsage());
+     }
+     err.println(e.getErrorMessage());
+     return e.getErrorCode();
+    }
+    finally
+    {
+      LockFileManager.releaseLock(serverLockFileName, failureReason);
+    }
+  }
+
+  private void initializeArguments() throws ConfigureDSException
+  {
+    try
+    {
+      configFile = new StringArgument(
+          "configfile", 'c', "configFile",
+          true, false, true, INFO_CONFIGFILE_PLACEHOLDER.get(),
+          null, null, INFO_DESCRIPTION_CONFIG_FILE.get());
       configFile.setHidden(true);
       argParser.addArgument(configFile);
 
-      configClass = new StringArgument("configclass", OPTION_SHORT_CONFIG_CLASS,
-                             OPTION_LONG_CONFIG_CLASS, false,
-                             false, true, INFO_CONFIGCLASS_PLACEHOLDER.get(),
-                             ConfigFileHandler.class.getName(), null,
-                             INFO_DESCRIPTION_CONFIG_CLASS.get());
+      configClass = new StringArgument(
+          "configclass", OPTION_SHORT_CONFIG_CLASS, OPTION_LONG_CONFIG_CLASS,
+          false, false, true, INFO_CONFIGCLASS_PLACEHOLDER.get(),
+          ConfigFileHandler.class.getName(), null, INFO_DESCRIPTION_CONFIG_CLASS.get());
       configClass.setHidden(true);
       argParser.addArgument(configClass);
 
@@ -238,1041 +381,738 @@
       {
         defaultHostName = InetAddress.getLocalHost().getHostName();
       }
-      catch (Exception e)
+      catch (final Exception e)
       {
         // Not much we can do here.
         defaultHostName = "localhost";
       }
-      hostName = new StringArgument(OPTION_LONG_HOST.toLowerCase(),
-                                    OPTION_SHORT_HOST,
-                                    OPTION_LONG_HOST, false, false, true,
-                                    INFO_HOST_PLACEHOLDER.get(),
-                                    defaultHostName,
-                                    null,
-                                    INFO_INSTALLDS_DESCRIPTION_HOST_NAME.get());
+
+      hostName = new StringArgument(
+          OPTION_LONG_HOST.toLowerCase(), OPTION_SHORT_HOST, OPTION_LONG_HOST,
+          false, false, true, INFO_HOST_PLACEHOLDER.get(),
+          defaultHostName, null, INFO_INSTALLDS_DESCRIPTION_HOST_NAME.get());
       argParser.addArgument(hostName);
 
-      ldapPort = new IntegerArgument("ldapport", OPTION_SHORT_PORT,
-                                    "ldapPort", false, false,
-                                     true, INFO_LDAPPORT_PLACEHOLDER.get(), 389,
-                                     null, true, 1,
-                                     true, 65535,
-                                     INFO_CONFIGDS_DESCRIPTION_LDAP_PORT.get());
+      ldapPort = new IntegerArgument(
+          "ldapport", OPTION_SHORT_PORT, "ldapPort",
+          false, false, true, INFO_LDAPPORT_PLACEHOLDER.get(),
+          389, null, true, 1, true, 65535, INFO_CONFIGDS_DESCRIPTION_LDAP_PORT.get());
       argParser.addArgument(ldapPort);
 
       adminConnectorPort = new IntegerArgument(
-          "adminConnectorPort".toLowerCase(), null,
-          "adminConnectorPort", false, false,
-          true, INFO_PORT_PLACEHOLDER.get(), 4444,
-          "adminConnectorPort", true, 1, true, 65535,
-          INFO_INSTALLDS_DESCRIPTION_ADMINCONNECTORPORT.get());
+          "adminConnectorPort".toLowerCase(), null, "adminConnectorPort",
+          false, false, true, INFO_PORT_PLACEHOLDER.get(),
+          4444, "adminConnectorPort", true, 1, true, 65535, INFO_INSTALLDS_DESCRIPTION_ADMINCONNECTORPORT.get());
       argParser.addArgument(adminConnectorPort);
 
-      ldapsPort = new IntegerArgument("ldapsPort", 'P', "ldapsPort", false,
-          false, true, INFO_LDAPPORT_PLACEHOLDER.get(), 636, null, true, 1,
-          true, 65535,
-          INFO_CONFIGDS_DESCRIPTION_LDAPS_PORT.get());
+      ldapsPort = new IntegerArgument(
+          "ldapsPort", 'P', "ldapsPort",
+          false, false, true, INFO_LDAPPORT_PLACEHOLDER.get(),
+          636, null, true, 1, true, 65535, INFO_CONFIGDS_DESCRIPTION_LDAPS_PORT.get());
       argParser.addArgument(ldapsPort);
 
-      enableStartTLS = new BooleanArgument("enableStartTLS",
-          OPTION_SHORT_START_TLS, "enableStartTLS",
+      enableStartTLS = new BooleanArgument(
+          "enableStartTLS", OPTION_SHORT_START_TLS, "enableStartTLS",
           INFO_CONFIGDS_DESCRIPTION_ENABLE_START_TLS.get());
       argParser.addArgument(enableStartTLS);
 
-      jmxPort = new IntegerArgument("jmxport", 'x', "jmxPort", false, false,
-          true, INFO_JMXPORT_PLACEHOLDER.get(), CliConstants.DEFAULT_JMX_PORT,
-          null, true, 1,
-          true, 65535,
-          INFO_CONFIGDS_DESCRIPTION_JMX_PORT.get());
+      jmxPort = new IntegerArgument(
+          "jmxport", 'x', "jmxPort",
+          false, false, true, INFO_JMXPORT_PLACEHOLDER.get(),
+          CliConstants.DEFAULT_JMX_PORT, null, true, 1, true, 65535, INFO_CONFIGDS_DESCRIPTION_JMX_PORT.get());
       argParser.addArgument(jmxPort);
 
-      keyManagerProviderDN = new StringArgument("keymanagerproviderdn",
-          'k',
-          "keyManagerProviderDN",
-          false, false,
-          true, INFO_KEY_MANAGER_PROVIDER_DN_PLACEHOLDER.get(),
-          null,
-          null,
-          INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PROVIDER_DN.get());
+      keyManagerProviderDN = new StringArgument(
+          "keymanagerproviderdn", 'k', "keyManagerProviderDN",
+          false, false, true, INFO_KEY_MANAGER_PROVIDER_DN_PLACEHOLDER.get(),
+          null, null, INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PROVIDER_DN.get());
       argParser.addArgument(keyManagerProviderDN);
 
-      trustManagerProviderDN = new StringArgument("trustmanagerproviderdn",
-          't',
-          "trustManagerProviderDN",
-          false, false,
-          true, INFO_TRUST_MANAGER_PROVIDER_DN_PLACEHOLDER.get(),
-          null,
-          null,
-          INFO_CONFIGDS_DESCRIPTION_TRUSTMANAGER_PROVIDER_DN.get());
+      trustManagerProviderDN = new StringArgument(
+          "trustmanagerproviderdn", 't', "trustManagerProviderDN",
+          false, false, true, INFO_TRUST_MANAGER_PROVIDER_DN_PLACEHOLDER.get(),
+          null, null, INFO_CONFIGDS_DESCRIPTION_TRUSTMANAGER_PROVIDER_DN.get());
       argParser.addArgument(trustManagerProviderDN);
 
-      keyManagerPath = new StringArgument("keymanagerpath",
-          'm',
-          "keyManagerPath",
-          false, false, true,
-          INFO_KEY_MANAGER_PATH_PLACEHOLDER.get(),
-          null,
-          null,
-          INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PATH.get());
+      keyManagerPath = new StringArgument(
+          "keymanagerpath", 'm', "keyManagerPath",
+          false, false, true, INFO_KEY_MANAGER_PATH_PLACEHOLDER.get(),
+          null, null, INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PATH.get());
       argParser.addArgument(keyManagerPath);
 
-      certNickName = new StringArgument("certnickname",
-          'a',
-          "certNickName",
-          false, false,
-          true, INFO_NICKNAME_PLACEHOLDER.get(),
-          null,
-          null,
-          INFO_CONFIGDS_DESCRIPTION_CERTNICKNAME.get());
+      certNickName = new StringArgument(
+          "certnickname", 'a', "certNickName",
+          false, false, true, INFO_NICKNAME_PLACEHOLDER.get(),
+          null, null, INFO_CONFIGDS_DESCRIPTION_CERTNICKNAME.get());
       argParser.addArgument(certNickName);
 
       baseDNString = new StringArgument(
-          "basedn", OPTION_SHORT_BASEDN,
-          OPTION_LONG_BASEDN, false, true,
-          true, INFO_BASEDN_PLACEHOLDER.get(),
-          "dc=example,dc=com",
-          null,
-          INFO_CONFIGDS_DESCRIPTION_BASE_DN.get());
+          "basedn", OPTION_SHORT_BASEDN, OPTION_LONG_BASEDN,
+          false, true, true, INFO_BASEDN_PLACEHOLDER.get(),
+          "dc=example,dc=com", null, INFO_CONFIGDS_DESCRIPTION_BASE_DN.get());
       argParser.addArgument(baseDNString);
 
       rootDNString = new StringArgument(
-          "rootdn", OPTION_SHORT_ROOT_USER_DN,
-          OPTION_LONG_ROOT_USER_DN, false, false,
-          true, INFO_ROOT_USER_DN_PLACEHOLDER.get(),
-          "cn=Directory Manager", null,
-          INFO_CONFIGDS_DESCRIPTION_ROOT_DN.get());
+          "rootdn", OPTION_SHORT_ROOT_USER_DN, OPTION_LONG_ROOT_USER_DN,
+          false, false, true, INFO_ROOT_USER_DN_PLACEHOLDER.get(),
+          "cn=Directory Manager", null, INFO_CONFIGDS_DESCRIPTION_ROOT_DN.get());
       argParser.addArgument(rootDNString);
 
       rootPassword = new StringArgument(
-          "rootpw", OPTION_SHORT_BINDPWD,
-          "rootPassword", false,
-          false, true, INFO_ROOT_USER_PWD_PLACEHOLDER.get(), null, null,
-          INFO_CONFIGDS_DESCRIPTION_ROOT_PW.get());
+          "rootpw", OPTION_SHORT_BINDPWD, "rootPassword",
+          false, false, true, INFO_ROOT_USER_PWD_PLACEHOLDER.get(),
+          null, null, INFO_CONFIGDS_DESCRIPTION_ROOT_PW.get());
       argParser.addArgument(rootPassword);
 
       rootPasswordFile = new FileBasedArgument(
-          "rootpwfile",
-          OPTION_SHORT_BINDPWD_FILE,
-          "rootPasswordFile", false, false,
-          INFO_FILE_PLACEHOLDER.get(), null, null,
-          INFO_CONFIGDS_DESCRIPTION_ROOT_PW_FILE.get());
+          "rootpwfile", OPTION_SHORT_BINDPWD_FILE, "rootPasswordFile",
+          false, false, INFO_FILE_PLACEHOLDER.get(),
+          null, null, INFO_CONFIGDS_DESCRIPTION_ROOT_PW_FILE.get());
       argParser.addArgument(rootPasswordFile);
 
       showUsage = CommonArguments.getShowUsage();
       argParser.addArgument(showUsage);
       argParser.setUsageArgument(showUsage);
 
-      serverRoot = new StringArgument("serverRoot",
-              OPTION_SHORT_SERVER_ROOT,
-              OPTION_LONG_SERVER_ROOT,
-              false, false, true, INFO_SERVER_ROOT_DIR_PLACEHOLDER.get(), null,
-              null, null);
+      serverRoot = new StringArgument(
+          "serverRoot", OPTION_SHORT_SERVER_ROOT, OPTION_LONG_SERVER_ROOT,
+          false, false, true, INFO_SERVER_ROOT_DIR_PLACEHOLDER.get(),
+          null, null, null);
       serverRoot.setHidden(true);
       argParser.addArgument(serverRoot);
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      return 1;
+      throw new ConfigureDSException(ae, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
     }
+  }
 
-
-    // Parse the command-line arguments provided to the program.
+  private int parseArguments() throws ConfigureDSException
+  {
     try
     {
-      argParser.parseArguments(args);
+      argParser.parseArguments(arguments);
+      return SUCCESS;
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
-
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      err.println(argParser.getUsage());
-      return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+      throw new ConfigureDSException(ae, ERR_ERROR_PARSING_ARGS.get(ae.getMessage()),
+          WRONG_USAGE, LDAPResultCode.CLIENT_SIDE_PARAM_ERROR);
     }
+  }
 
-
-    // If we should just display usage or version information,
-    // then print it and exit.
-    if (argParser.usageOrVersionDisplayed())
-    {
-      return 0;
-    }
-
-
-    // Make sure that the user actually tried to configure something.
+  /** Make sure that the user actually tried to configure something. */
+  private void checkArgumentsConsistency() throws ConfigureDSException
+  {
     if (!baseDNString.isPresent()
         && !ldapPort.isPresent()
         && !jmxPort.isPresent()
         && !rootDNString.isPresent())
     {
-      LocalizableMessage message = ERR_CONFIGDS_NO_CONFIG_CHANGES.get();
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      err.println(argParser.getUsage());
-      return 1;
+      throw new ConfigureDSException(ERR_CONFIGDS_NO_CONFIG_CHANGES.get(), WRONG_USAGE);
     }
+  }
 
+  private void checkPortArguments() throws ConfigureDSException
+  {
     try
     {
-      Set<Integer> ports = new HashSet<Integer>();
-      if (ldapPort.isPresent())
-      {
-        ports.add(ldapPort.getIntValue());
-      }
-      if (adminConnectorPort.isPresent())
-      {
-        if (ports.contains(adminConnectorPort.getIntValue()))
-        {
-          LocalizableMessage message = ERR_CONFIGDS_PORT_ALREADY_SPECIFIED.get(adminConnectorPort.getIntValue());
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          err.println(argParser.getUsage());
-          return 1;
-        }
-        else
-        {
-          ports.add(adminConnectorPort.getIntValue());
-        }
-      }
-      if (ldapsPort.isPresent())
-      {
-        if (ports.contains(ldapsPort.getIntValue()))
-        {
-          LocalizableMessage message = ERR_CONFIGDS_PORT_ALREADY_SPECIFIED.get(ldapsPort.getIntValue());
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          err.println(argParser.getUsage());
-          return 1;
-        }
-        else
-        {
-          ports.add(ldapsPort.getIntValue());
-        }
-      }
-      if (jmxPort.isPresent())
-      {
-        if (ports.contains(jmxPort.getIntValue()))
-        {
-          LocalizableMessage message = ERR_CONFIGDS_PORT_ALREADY_SPECIFIED.get(jmxPort.getIntValue());
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          err.println(argParser.getUsage());
-          return 1;
-        }
-        else
-        {
-          ports.add(jmxPort.getIntValue());
-        }
-      }
-    }
-    catch (ArgumentException ae)
-    {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      return 1;
-    }
+      final IntegerArgument[] portArgs = {ldapPort, adminConnectorPort, ldapsPort, jmxPort};
+      final Set<Integer> portsAdded = new HashSet<Integer>();
 
+      for (final IntegerArgument portArg : portArgs)
+      {
+        if (portArg.isPresent())
+        {
+          final int portNumber = portArg.getIntValue();
+          if (portsAdded.contains(portNumber))
+          {
+            throw new ConfigureDSException(ERR_CONFIGDS_PORT_ALREADY_SPECIFIED.get(portArg.getIntValue()), WRONG_USAGE);
+          }
+          portsAdded.add(portNumber);
+        }
+      }
+    }
+    catch (final ArgumentException ae)
+    {
+      throw new ConfigureDSException(ae, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
+    }
+  }
+
+  private void initializeDirectoryServer() throws ConfigureDSException
+  {
     if (serverRoot.isPresent()) {
-      DirectoryEnvironmentConfig env = DirectoryServer.getEnvironmentConfig();
-      String root = serverRoot.getValue();
+      final DirectoryEnvironmentConfig env = DirectoryServer.getEnvironmentConfig();
+      final String root = serverRoot.getValue();
       try {
         env.setServerRoot(new File(serverRoot.getValue()));
-      } catch (InitializationException e) {
+      } catch (final InitializationException e) {
         ERR_INITIALIZE_SERVER_ROOT.get(root, e.getMessageObject());
       }
     }
 
     // Initialize the Directory Server configuration handler using the
     // information that was provided.
-    DirectoryServer directoryServer = DirectoryServer.getInstance();
+    final DirectoryServer directoryServer = DirectoryServer.getInstance();
     DirectoryServer.bootstrapClient();
 
     try
     {
       DirectoryServer.initializeJMX();
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      LocalizableMessage message = ERR_CONFIGDS_CANNOT_INITIALIZE_JMX.get(configFile.getValue(), e.getMessage());
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      return 1;
+      final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_JMX.get(configFile.getValue(), e.getMessage());
+      throw new ConfigureDSException(e, msg);
     }
 
     try
     {
-      directoryServer.initializeConfiguration(configClass.getValue(),
-                                              configFile.getValue());
+      directoryServer.initializeConfiguration(configClass.getValue(), configFile.getValue());
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      LocalizableMessage message = ERR_CONFIGDS_CANNOT_INITIALIZE_CONFIG.get(configFile.getValue(), e.getMessage());
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      return 1;
+      final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_CONFIG.get(configFile.getValue(), e.getMessage());
+      throw new ConfigureDSException(e, msg);
     }
 
     try
     {
       directoryServer.initializeSchema();
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      LocalizableMessage message = ERR_CONFIGDS_CANNOT_INITIALIZE_SCHEMA.get(configFile.getValue(), e.getMessage());
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      return 1;
+      final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_SCHEMA.get(configFile.getValue(), e.getMessage());
+      throw new ConfigureDSException(e, msg);
+    }
+  }
+
+  /**
+   * Make sure that we can get an exclusive lock for the Directory Server, so
+   * that no other operation will be allowed while this is in progress.
+   *
+   * @throws ConfigureDSException
+   */
+  private void tryAcquireExclusiveLocks() throws ConfigureDSException
+  {
+    if (! LockFileManager.acquireExclusiveLock(serverLockFileName, failureReason))
+    {
+      throw new ConfigureDSException(ERR_CONFIGDS_CANNOT_ACQUIRE_SERVER_LOCK.get(serverLockFileName, failureReason));
+    }
+  }
+
+  private LinkedList<DN> parseProvidedBaseDNs() throws ConfigureDSException
+  {
+    LinkedList<DN> baseDNs = null;
+    if (baseDNString.isPresent())
+    {
+      baseDNs = new LinkedList<DN>();
+      for (final String dnString : baseDNString.getValues())
+      {
+        try
+        {
+          baseDNs.add(DN.valueOf(dnString));
+        }
+        catch (final DirectoryException de)
+        {
+          throw new ConfigureDSException(de, ERR_CONFIGDS_CANNOT_PARSE_BASE_DN.get(dnString, de.getMessageObject()));
+        }
+      }
     }
 
+    return baseDNs;
+  }
 
-    // Make sure that we can get an exclusive lock for the Directory Server, so
-    // that no other operation will be allowed while this is in progress.
-    String serverLockFileName = LockFileManager.getServerLockFileName();
-    StringBuilder failureReason = new StringBuilder();
-    if (! LockFileManager.acquireExclusiveLock(serverLockFileName,
-                                               failureReason))
+  private DN parseRootDN() throws ConfigureDSException
+  {
+    DN rootDN = null;
+    if (rootDNString.isPresent())
     {
-      LocalizableMessage message = ERR_CONFIGDS_CANNOT_ACQUIRE_SERVER_LOCK.get(serverLockFileName, failureReason);
-      err.println(wrapText(message, MAX_LINE_WIDTH));
-      return 1;
+      try
+      {
+        rootDN = DN.valueOf(rootDNString.getValue());
+      }
+      catch (final DirectoryException de)
+      {
+        final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_PARSE_ROOT_DN.get(
+            rootDNString.getValue(), de.getMessageObject());
+        throw new ConfigureDSException(de, msg);
+      }
     }
+    return rootDN;
+  }
 
-
-    try
+  private String parseRootDNPassword() throws ConfigureDSException
+  {
+    String rootPW = null;
+    if (rootDNString.isPresent())
     {
-      // If one or more base DNs were provided, then make sure that they can be
-      // parsed as valid DNs.
-      LinkedList<DN> baseDNs = null;
-      if (baseDNString.isPresent())
+      if (rootPassword.isPresent())
       {
-        baseDNs = new LinkedList<DN>();
-        for (String dnString : baseDNString.getValues())
-        {
-          try
-          {
-            baseDNs.add(DN.valueOf(dnString));
-          }
-          catch (DirectoryException de)
-          {
-            LocalizableMessage message = ERR_CONFIGDS_CANNOT_PARSE_BASE_DN.get(dnString, de.getMessageObject());
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
-          }
-        }
+        rootPW = rootPassword.getValue();
+      }
+      else if (rootPasswordFile.isPresent())
+      {
+        rootPW = rootPasswordFile.getValue();
+      }
+      else
+      {
+        throw new ConfigureDSException(ERR_CONFIGDS_NO_ROOT_PW.get());
+      }
+    }
+    return rootPW;
+  }
+
+  private void checkManagerProvider(final Argument arg, final String jckesDN, final String ldifEntry,
+      final boolean isKeyManager) throws ConfigureDSException
+  {
+    if (arg.isPresent())
+    {
+      DN dn = null;
+      DN JCEKSManagerDN = null;
+      try
+      {
+        dn = DN.valueOf(trustManagerProviderDN.getValue());
+        JCEKSManagerDN = DN.valueOf(jckesDN);
+      }
+      catch (final DirectoryException de)
+      {
+        final String value = trustManagerProviderDN.getValue();
+        final LocalizableMessage errorMessage = de.getMessageObject();
+        final LocalizableMessage message =
+            isKeyManager ? ERR_CONFIGDS_CANNOT_PARSE_KEYMANAGER_PROVIDER_DN.get(value, errorMessage)
+                         : ERR_CONFIGDS_CANNOT_PARSE_TRUSTMANAGER_PROVIDER_DN.get(value, errorMessage);
+        throw new ConfigureDSException(de, message);
       }
 
-
-      // If a root user DN was provided, then make sure it can be parsed.  Also,
-      // make sure that either a password or password file was specified.
-      DN     rootDN = null;
-      String rootPW = null;
-      if (rootDNString.isPresent())
+      if (dn.equals(JCEKSManagerDN))
       {
+        LDIFReader reader = null;
         try
         {
-          rootDN = DN.valueOf(rootDNString.getValue());
-        }
-        catch (DirectoryException de)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_PARSE_ROOT_DN.get(
-              rootDNString.getValue(), de.getMessageObject());
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
 
-        if (rootPassword.isPresent())
-        {
-          rootPW = rootPassword.getValue();
-        }
-        else if (rootPasswordFile.isPresent())
-        {
-          rootPW = rootPasswordFile.getValue();
-        }
-        else
-        {
-          LocalizableMessage message = ERR_CONFIGDS_NO_ROOT_PW.get();
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-
-      // Get the Directory Server configuration handler and use it to make the
-      // appropriate configuration changes.
-      ConfigHandler configHandler = DirectoryServer.getConfigHandler();
-
-
-      // Check that the key manager provided is valid.
-      if (keyManagerProviderDN.isPresent())
-      {
-        DN dn = null;
-        DN JCEKSProviderDN = null;
-        try
-        {
-          dn = DN.valueOf(keyManagerProviderDN.getValue());
-          JCEKSProviderDN =
-            DN.valueOf("cn=JCEKS,cn=Key Manager Providers,cn=config");
-        }
-        catch (DirectoryException de)
-        {
-          LocalizableMessage message =
-                  ERR_CONFIGDS_CANNOT_PARSE_KEYMANAGER_PROVIDER_DN.get(
-                          keyManagerProviderDN.getValue(),
-                          de.getMessageObject());
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-
-        if (dn.equals(JCEKSProviderDN))
-        {
-          // Create the JCEKSProvider entry
-          try
+          final String ldif = ldifEntry;
+          final LDIFImportConfig ldifImportConfig = new LDIFImportConfig(new StringReader(ldif));
+          reader = new LDIFReader(ldifImportConfig);
+          Entry mangerConfigEntry;
+          while ((mangerConfigEntry = reader.readEntry()) != null)
           {
-            String ldif = "dn: cn=JCEKS,cn=Key Manager Providers,cn=config\n"+
-            "objectClass: top\n"+
-            "objectClass: ds-cfg-key-manager-provider\n"+
-            "objectClass: ds-cfg-file-based-key-manager-provider\n"+
-            "cn: JCEKS\n"+
-            "ds-cfg-java-class: org.opends.server.extensions."+
-                 "FileBasedKeyManagerProvider\n"+
-            "ds-cfg-enabled: true\n"+
-            "ds-cfg-key-store-type: JCEKS\n"+
-            "ds-cfg-key-store-file: config/keystore.jceks\n"+
-            "ds-cfg-key-store-pin-file: config/keystore.pin";
-
-            LDIFImportConfig ldifImportConfig =
-              new LDIFImportConfig(new StringReader(ldif));
-            LDIFReader reader = new LDIFReader(ldifImportConfig);
-            Entry providerConfigEntry;
-            while ((providerConfigEntry = reader.readEntry()) != null)
-            {
-              configHandler.addEntry(providerConfigEntry, null);
-            }
-          }
-          catch (Exception e)
-          {
-            LocalizableMessage message = ERR_CONFIG_KEYMANAGER_CANNOT_CREATE_JCEKS_PROVIDER.get(e);
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
+            configHandler.addEntry(mangerConfigEntry, null);
           }
         }
-        else
+        catch (final Exception e)
         {
-          try
-          {
-            configHandler.getConfigEntry(dn);
-          }
-          catch (Exception e)
-          {
-            LocalizableMessage message = ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e);
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
-          }
+          final LocalizableMessage message = isKeyManager ? ERR_CONFIG_KEYMANAGER_CANNOT_CREATE_JCEKS_PROVIDER.get(e)
+                                                          : ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e);
+          throw new ConfigureDSException(e, message);
         }
-      }
-
-      // Check that the trust manager provided is valid.
-      if (trustManagerProviderDN.isPresent())
-      {
-        DN dn = null;
-        DN JCEKSTrustManagerDN = null;
-        try
+        finally
         {
-          dn = DN.valueOf(trustManagerProviderDN.getValue());
-          JCEKSTrustManagerDN =
-            DN.valueOf("cn=JCEKS,cn=Trust Manager Providers,cn=config");
-        }
-        catch (DirectoryException de)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_PARSE_TRUSTMANAGER_PROVIDER_DN.
-                  get(trustManagerProviderDN.getValue(), de.getMessageObject());
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-
-        if (dn.equals(JCEKSTrustManagerDN))
-        {
-          try
-          {
-            String ldif = "dn: cn=JCEKS,cn=Trust Manager Providers,cn=config\n"+
-            "objectClass: top\n"+
-            "objectClass: ds-cfg-trust-manager-provider\n"+
-            "objectClass: ds-cfg-file-based-trust-manager-provider\n"+
-            "cn: JCEKS\n"+
-            "ds-cfg-java-class: org.opends.server.extensions."+
-            "FileBasedTrustManagerProvider\n"+
-            "ds-cfg-enabled: false\n"+
-            "ds-cfg-trust-store-type: JCEKS\n"+
-            "ds-cfg-trust-store-file: config/truststore\n";
-
-            LDIFImportConfig ldifImportConfig =
-              new LDIFImportConfig(new StringReader(ldif));
-            LDIFReader reader = new LDIFReader(ldifImportConfig);
-            Entry trustManagerConfigEntry;
-            while ((trustManagerConfigEntry = reader.readEntry()) != null)
-            {
-              configHandler.addEntry(trustManagerConfigEntry, null);
-            }
-          }
-          catch (Exception e)
-          {
-            LocalizableMessage message = ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e);
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
-          }
-        }
-        else
-        {
-          try
-          {
-            configHandler.getConfigEntry(dn);
-          }
-          catch (Exception e)
-          {
-            LocalizableMessage message = ERR_CONFIG_TRUSTMANAGER_CANNOT_GET_BASE.get(e);
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
-          }
-        }
-      }
-
-      // Check that the keystore path values are valid.
-      if (keyManagerPath.isPresent() && !keyManagerProviderDN.isPresent())
-      {
-        LocalizableMessage message = ERR_CONFIGDS_KEYMANAGER_PROVIDER_DN_REQUIRED.get(
-            keyManagerProviderDN.getLongIdentifier(), keyManagerPath.getLongIdentifier());
-        err.println(wrapText(message, MAX_LINE_WIDTH));
-        return 1;
-      }
-
-      // If one or more base DNs were specified, then update the config
-      // accordingly.
-      if (baseDNs != null)
-      {
-        try
-        {
-          DN jeBackendDN = DN.valueOf(DN_JE_BACKEND);
-          ConfigEntry configEntry = configHandler.getConfigEntry(jeBackendDN);
-
-          DNConfigAttribute baseDNAttr =
-               new DNConfigAttribute(
-                       ATTR_BACKEND_BASE_DN,
-                       INFO_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS.get(),
-                                     true, true, false, baseDNs);
-          configEntry.putConfigAttribute(baseDNAttr);
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_BASE_DN.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-
-      // If an LDAP port was specified, then update the config accordingly.
-      if (ldapPort.isPresent())
-      {
-        try
-        {
-          DN ldapListenerDN = DN.valueOf(DN_LDAP_CONNECTION_HANDLER);
-          ConfigEntry configEntry =
-               configHandler.getConfigEntry(ldapListenerDN);
-
-
-          IntegerConfigAttribute portAttr =
-               new IntegerConfigAttribute(ATTR_LISTEN_PORT,
-                       INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
-                                          true, false, true, true, 1, true,
-                                          65535, ldapPort.getIntValue());
-          configEntry.putConfigAttribute(portAttr);
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_LDAP_PORT.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-      // If an Admin Connector port was specified, then update the config
-      // accordingly.
-      if (adminConnectorPort.isPresent())
-      {
-        try
-        {
-          DN adminConnectorDN = DN.valueOf(DN_ADMIN_CONNECTOR);
-          ConfigEntry configEntry =
-               configHandler.getConfigEntry(adminConnectorDN);
-
-
-          IntegerConfigAttribute portAttr =
-               new IntegerConfigAttribute(ATTR_LISTEN_PORT,
-                       INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
-                                          true, false, true, true, 1, true,
-                                          65535,
-                                          adminConnectorPort.getIntValue());
-          configEntry.putConfigAttribute(portAttr);
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_ADMIN_CONNECTOR_PORT.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-//    If an LDAPS port was specified, then update the config accordingly.
-      if (ldapsPort.isPresent())
-      {
-        try
-        {
-          DN ldapListenerDN = DN.valueOf(DN_LDAPS_CONNECTION_HANDLER);
-          ConfigEntry configEntry =
-               configHandler.getConfigEntry(ldapListenerDN);
-
-
-          IntegerConfigAttribute portAttr =
-               new IntegerConfigAttribute(ATTR_LISTEN_PORT,
-                       INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
-                                          true, false, true, true, 1, true,
-                                          65535, ldapsPort.getIntValue());
-          configEntry.putConfigAttribute(portAttr);
-
-          BooleanConfigAttribute enablePortAttr =
-            new BooleanConfigAttribute(ATTR_CONNECTION_HANDLER_ENABLED,
-                INFO_LDAPS_CONNHANDLER_DESCRIPTION_ENABLE.get(),
-                    true, true);
-          configEntry.putConfigAttribute(enablePortAttr);
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_LDAPS_PORT.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-//    If an JMX port was specified, then update the config accordingly.
-      if (jmxPort.isPresent())
-      {
-        try
-        {
-          DN jmxListenerDN = DN.valueOf(DN_JMX_CONNECTION_HANDLER);
-          ConfigEntry configEntry =
-               configHandler.getConfigEntry(jmxListenerDN);
-
-          IntegerConfigAttribute portAttr =
-               new IntegerConfigAttribute(
-                       ATTR_LISTEN_PORT,
-                       INFO_JMX_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
-                       true, false, true, true, 1, true,
-                       65535, jmxPort.getIntValue());
-          configEntry.putConfigAttribute(portAttr);
-
-          BooleanConfigAttribute enablePortAttr =
-            new BooleanConfigAttribute(ATTR_CONNECTION_HANDLER_ENABLED,
-                INFO_JMX_CONNHANDLER_DESCRIPTION_ENABLE.get(),
-                    true, true);
-          configEntry.putConfigAttribute(enablePortAttr);
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_JMX_PORT.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-      // Start TLS configuration
-      if (enableStartTLS.isPresent())
-      {
-        try
-        {
-          DN ldapListenerDN = DN.valueOf(DN_LDAP_CONNECTION_HANDLER);
-          ConfigEntry configEntry =
-               configHandler.getConfigEntry(ldapListenerDN);
-
-
-          BooleanConfigAttribute startTLS =
-            new BooleanConfigAttribute(ATTR_ALLOW_STARTTLS,
-                INFO_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS.get(),
-                    true, true);
-          configEntry.putConfigAttribute(startTLS);
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_ENABLE_STARTTLS.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-      // Key manager provider
-      if (keyManagerProviderDN.isPresent())
-      {
-        if (enableStartTLS.isPresent() || ldapsPort.isPresent())
-        {
-          try
-          {
-            // Enable the key manager
-            DN dn = DN.valueOf(keyManagerProviderDN.getValue());
-            ConfigEntry configEntry = configHandler.getConfigEntry(dn);
-
-            BooleanConfigAttribute enableAttr =
-              new BooleanConfigAttribute(ATTR_KEYMANAGER_ENABLED,
-                  INFO_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED.get(),
-                      true, true);
-            configEntry.putConfigAttribute(enableAttr);
-          }
-          catch (Exception e)
-          {
-            LocalizableMessage message = ERR_CONFIGDS_CANNOT_ENABLE_KEYMANAGER.get(e);
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
-          }
-        }
-
-        try
-        {
-          if (enableStartTLS.isPresent())
-          {
-            // Use the key manager specified for the LDAP connection handler.
-            DN ldapListenerDN = DN.valueOf(DN_LDAP_CONNECTION_HANDLER);
-            ConfigEntry configEntry =
-              configHandler.getConfigEntry(ldapListenerDN);
-
-            StringConfigAttribute keyManagerProviderAttr =
-              new StringConfigAttribute(ATTR_KEYMANAGER_DN,
-                      INFO_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN.get(),
-                  false, false, true, keyManagerProviderDN.getValue());
-            configEntry.putConfigAttribute(keyManagerProviderAttr);
-          }
-
-          if (ldapsPort.isPresent())
-          {
-            // Use the key manager specified for the LDAPS connection handler.
-            DN ldapsListenerDN = DN.valueOf(DN_LDAPS_CONNECTION_HANDLER);
-            ConfigEntry configEntry =
-              configHandler.getConfigEntry(ldapsListenerDN);
-
-            StringConfigAttribute keyManagerProviderAttr =
-              new StringConfigAttribute(ATTR_KEYMANAGER_DN,
-                  INFO_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN.get(),
-                      false, false,
-                  true, keyManagerProviderDN.getValue());
-            configEntry.putConfigAttribute(keyManagerProviderAttr);
-          }
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_KEYMANAGER_REFERENCE.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-
-        if (keyManagerPath.isPresent())
-        {
-          try
-          {
-            // Enable the key manager
-            DN dn = DN.valueOf(keyManagerProviderDN.getValue());
-            ConfigEntry configEntry = configHandler.getConfigEntry(dn);
-
-            StringConfigAttribute pathAttr =
-              new StringConfigAttribute(ATTR_KEYSTORE_FILE,
-                  INFO_FILE_KEYMANAGER_DESCRIPTION_FILE.get(), true, true, true,
-                  keyManagerPath.getValue());
-            configEntry.putConfigAttribute(pathAttr);
-          }
-          catch (Exception e)
-          {
-            String message = String.valueOf(e);
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
-          }
-        }
-      }
-      if (trustManagerProviderDN.isPresent())
-      {
-        if (enableStartTLS.isPresent() || ldapsPort.isPresent())
-        {
-          // Enable the trust manager
-          try
-          {
-            DN dn = DN.valueOf(trustManagerProviderDN.getValue());
-            ConfigEntry configEntry = configHandler.getConfigEntry(dn);
-
-            BooleanConfigAttribute enableAttr =
-              new BooleanConfigAttribute(ATTR_TRUSTMANAGER_ENABLED,
-                  ERR_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED.get(),
-                      true, true);
-            configEntry.putConfigAttribute(enableAttr);
-          }
-          catch (Exception e)
-          {
-            LocalizableMessage message = ERR_CONFIGDS_CANNOT_ENABLE_TRUSTMANAGER.get(e);
-            err.println(wrapText(message, MAX_LINE_WIDTH));
-            return 1;
-          }
-        }
-
-        try
-        {
-          if (enableStartTLS.isPresent())
-          {
-            // Use the trust manager specified for the LDAP connection handler.
-            DN ldapListenerDN = DN.valueOf(DN_LDAP_CONNECTION_HANDLER);
-            ConfigEntry configEntry =
-              configHandler.getConfigEntry(ldapListenerDN);
-
-            StringConfigAttribute trustManagerProviderAttr =
-              new StringConfigAttribute(ATTR_TRUSTMANAGER_DN,
-                  INFO_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN.get(),
-                      false, false,
-                  true, trustManagerProviderDN.getValue());
-            configEntry.putConfigAttribute(trustManagerProviderAttr);
-          }
-
-          if (ldapsPort.isPresent())
-          {
-            // Use the trust manager specified for the LDAPS connection handler.
-            DN ldapsListenerDN = DN.valueOf(DN_LDAPS_CONNECTION_HANDLER);
-            ConfigEntry configEntry =
-              configHandler.getConfigEntry(ldapsListenerDN);
-
-            StringConfigAttribute trustManagerProviderAttr =
-              new StringConfigAttribute(ATTR_TRUSTMANAGER_DN,
-                  INFO_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN.get(),
-                      false, false,
-                  true, trustManagerProviderDN.getValue());
-            configEntry.putConfigAttribute(trustManagerProviderAttr);
-          }
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_TRUSTMANAGER_REFERENCE.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-      if (certNickName.isPresent())
-      {
-        try
-        {
-          StringConfigAttribute certNickNameAttr =
-            new StringConfigAttribute(
-                    ATTR_SSL_CERT_NICKNAME,
-                    INFO_LDAP_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(),
-                false, false, true, certNickName.getValue());
-
-          DN ldapListenerDN = DN.valueOf(DN_LDAP_CONNECTION_HANDLER);
-          ConfigEntry configEntry =
-            configHandler.getConfigEntry(ldapListenerDN);
-          if (ldapPort.isPresent())
-          {
-            // Use the key manager specified for the LDAP connection handler.
-            configEntry.putConfigAttribute(certNickNameAttr);
-          }
-          else
-          {
-            configEntry.removeConfigAttribute(
-                ATTR_SSL_CERT_NICKNAME.toLowerCase());
-          }
-
-          // Use the key manager specified for the LDAPS connection handler.
-          DN ldapsListenerDN = DN.valueOf(DN_LDAPS_CONNECTION_HANDLER);
-          configEntry = configHandler.getConfigEntry(ldapsListenerDN);
-          if (ldapsPort.isPresent())
-          {
-            configEntry.putConfigAttribute(certNickNameAttr);
-          }
-          else
-          {
-            configEntry.removeConfigAttribute(
-                ATTR_SSL_CERT_NICKNAME.toLowerCase());
-          }
-
-          certNickNameAttr = new StringConfigAttribute(ATTR_SSL_CERT_NICKNAME,
-              INFO_JMX_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(),
-                  false, false, true, certNickName.getValue());
-
-          // Use the key manager specified for the JMX connection handler.
-          DN jmxListenerDN = DN.valueOf(DN_JMX_CONNECTION_HANDLER);
-          configEntry = configHandler.getConfigEntry(jmxListenerDN);
-          if (jmxPort.isPresent())
-          {
-            configEntry.putConfigAttribute(certNickNameAttr);
-          }
-          else
-          {
-            configEntry.removeConfigAttribute(
-                ATTR_SSL_CERT_NICKNAME.toLowerCase());
-          }
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
+          close(reader);
         }
       }
       else
       {
         try
         {
-          // Use the key manager specified for the LDAP connection handler.
-          DN ldapListenerDN = DN.valueOf(DN_LDAP_CONNECTION_HANDLER);
-          ConfigEntry configEntry =
-            configHandler.getConfigEntry(ldapListenerDN);
-
-          configEntry.removeConfigAttribute(
-              ATTR_SSL_CERT_NICKNAME.toLowerCase());
-
-          // Use the key manager specified for the LDAPS connection handler.
-          DN ldapsListenerDN = DN.valueOf(DN_LDAPS_CONNECTION_HANDLER);
-          configEntry = configHandler.getConfigEntry(ldapsListenerDN);
-
-          configEntry.removeConfigAttribute(
-              ATTR_SSL_CERT_NICKNAME.toLowerCase());
-
-          // Use the key manager specified for the JMX connection handler.
-          DN jmxListenerDN = DN.valueOf(DN_JMX_CONNECTION_HANDLER);
-          configEntry = configHandler.getConfigEntry(jmxListenerDN);
-
-          configEntry.removeConfigAttribute(
-              ATTR_SSL_CERT_NICKNAME.toLowerCase());
+          configHandler.getConfigEntry(dn);
         }
-        catch (Exception e)
+        catch (final Exception e)
         {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
+          final LocalizableMessage message = isKeyManager ? ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e)
+                                                          : ERR_CONFIG_TRUSTMANAGER_CANNOT_GET_BASE.get(e);
+          throw new ConfigureDSException(e, message);
         }
       }
+    }
+  }
 
-      // If a root user DN and password were specified, then update the config
-      // accordingly.
-      if (rootDN != null)
-      {
-        try
-        {
-          DN rootUserDN = DN.valueOf(DN_ROOT_USER);
-          ConfigEntry configEntry = configHandler.getConfigEntry(rootUserDN);
-
-          DNConfigAttribute bindDNAttr =
-               new DNConfigAttribute(
-                       ATTR_ROOTDN_ALTERNATE_BIND_DN,
-                       INFO_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN.get(),
-                       false, true, false,
-                                     rootDN);
-          configEntry.putConfigAttribute(bindDNAttr);
-
-          byte[] rootPWBytes = getBytes(rootPW);
-          String encodedPassword =
-               SaltedSHA512PasswordStorageScheme.encodeOffline(rootPWBytes);
-          StringConfigAttribute bindPWAttr =
-               new StringConfigAttribute(ATTR_USER_PASSWORD, LocalizableMessage.EMPTY,
-                                         false, false, false, encodedPassword);
-          configEntry.putConfigAttribute(bindPWAttr);
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_ROOT_USER.get(e);
-          err.println(wrapText(message, MAX_LINE_WIDTH));
-          return 1;
-        }
-      }
-
-      // Set the FQDN for the DIGEST-MD5 SASL mechanism.
+  private void updateBaseDNs(final LinkedList<DN> baseDNs) throws ConfigureDSException
+  {
+    if (baseDNs != null)
+    {
       try
       {
-        DN digestMD5DN = DN.valueOf(DN_DIGEST_MD5_SASL_MECHANISM);
-        ConfigEntry configEntry = configHandler.getConfigEntry(digestMD5DN);
-        StringConfigAttribute fqdnAttr = new StringConfigAttribute(
-            "ds-cfg-server-fqdn", LocalizableMessage.EMPTY, false, false, false,
-            hostName.getValue());
-        configEntry.putConfigAttribute(fqdnAttr);
-      }
-      catch (Exception e)
-      {
-        LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_DIGEST_MD5_FQDN.get(e);
-        err.println(wrapText(message, MAX_LINE_WIDTH));
-        return 1;
-      }
+        final DN jeBackendDN = DN.valueOf(DN_JE_BACKEND);
+        final ConfigEntry configEntry = configHandler.getConfigEntry(jeBackendDN);
 
-      // Check that the cipher specified is supported.  This is intended to
-      // fix issues with JVM that do not support the default cipher (see
-      // issue 3075 for instance).
-      CryptoManagerCfgDefn cryptoManager = CryptoManagerCfgDefn.getInstance();
-      StringPropertyDefinition prop =
-        cryptoManager.getKeyWrappingTransformationPropertyDefinition();
-      String defaultCipher = null;
-      DefaultBehaviorProvider<?> p = prop.getDefaultBehaviorProvider();
-      if (p instanceof DefinedDefaultBehaviorProvider)
-      {
-        Collection<?> defaultValues =
-          ((DefinedDefaultBehaviorProvider<?>)p).getDefaultValues();
-        if (!defaultValues.isEmpty())
-        {
-          defaultCipher = defaultValues.iterator().next().toString();
-        }
+        final DNConfigAttribute baseDNAttr = new DNConfigAttribute(
+            ATTR_BACKEND_BASE_DN, INFO_CONFIG_BACKEND_ATTR_DESCRIPTION_BASE_DNS.get(),
+            true, true, false, baseDNs);
+        configEntry.putConfigAttribute(baseDNAttr);
       }
-      if (defaultCipher != null)
+      catch (final Exception e)
       {
-        // Check that the default cipher is supported by the JVM.
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_BASE_DN.get(e));
+      }
+    }
+  }
+
+  private void updateLdapPort() throws ConfigureDSException
+  {
+    if (ldapPort.isPresent())
+    {
+      try
+      {
+        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
+            ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
+            true, false, true, true, 1, true, 65535, ldapPort.getIntValue());
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAP_CONNECTION_HANDLER));
+        configEntry.putConfigAttribute(portAttr);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_LDAP_PORT.get(e));
+      }
+    }
+  }
+
+  private void updateAdminConnectorPort() throws ConfigureDSException
+  {
+    if (adminConnectorPort.isPresent())
+    {
+      try
+      {
+        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
+            ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
+            true, false, true, true, 1, true, 65535, adminConnectorPort.getIntValue());
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_ADMIN_CONNECTOR));
+        configEntry.putConfigAttribute(portAttr);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_ADMIN_CONNECTOR_PORT.get(e));
+      }
+    }
+  }
+
+  private void updateLdapSecurePort() throws ConfigureDSException
+  {
+    if (ldapsPort.isPresent())
+    {
+      try
+      {
+        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
+            ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
+            true, false, true, true, 1, true, 65535, ldapsPort.getIntValue());
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAPS_CONNECTION_HANDLER));
+        configEntry.putConfigAttribute(portAttr);
+
+        final BooleanConfigAttribute enablePortAttr = new BooleanConfigAttribute(
+            ATTR_CONNECTION_HANDLER_ENABLED, INFO_LDAPS_CONNHANDLER_DESCRIPTION_ENABLE.get(), true, true);
+        configEntry.putConfigAttribute(enablePortAttr);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_LDAPS_PORT.get(e));
+      }
+    }
+  }
+
+  private void updateJMXport() throws ConfigureDSException
+  {
+    if (jmxPort.isPresent())
+    {
+      try
+      {
+
+        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
+            ATTR_LISTEN_PORT, INFO_JMX_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
+            true, false, true, true, 1, true, 65535, jmxPort.getIntValue());
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_JMX_CONNECTION_HANDLER));
+        configEntry.putConfigAttribute(portAttr);
+
+        final BooleanConfigAttribute enablePortAttr = new BooleanConfigAttribute(
+            ATTR_CONNECTION_HANDLER_ENABLED, INFO_JMX_CONNHANDLER_DESCRIPTION_ENABLE.get(), true, true);
+        configEntry.putConfigAttribute(enablePortAttr);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_JMX_PORT.get(e));
+      }
+    }
+  }
+
+  private void updateStartTLS() throws ConfigureDSException
+  {
+    if (enableStartTLS.isPresent())
+    {
+      try
+      {
+        final BooleanConfigAttribute startTLS = new BooleanConfigAttribute(
+            ATTR_ALLOW_STARTTLS, INFO_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS.get(), true, true);
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAP_CONNECTION_HANDLER));
+        configEntry.putConfigAttribute(startTLS);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_STARTTLS.get(e));
+      }
+    }
+  }
+
+  private void updateKeyManager() throws ConfigureDSException
+  {
+    if (keyManagerProviderDN.isPresent())
+    {
+      if (enableStartTLS.isPresent() || ldapsPort.isPresent())
+      {
         try
         {
-          Cipher.getInstance(defaultCipher);
+          // Enable the key manager
+          final BooleanConfigAttribute enableAttr = new BooleanConfigAttribute(
+              ATTR_KEYMANAGER_ENABLED, INFO_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED.get(), true, true);
+          final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(keyManagerProviderDN.getValue()));
+          configEntry.putConfigAttribute(enableAttr);
         }
-        catch (GeneralSecurityException ex)
+        catch (final Exception e)
         {
-          // The cipher is not supported: try to find an alternative one.
-          String alternativeCipher = getAlternativeCipher();
-          if (alternativeCipher != null)
-          {
-            try
-            {
-              DN cipherDN = DN.valueOf(DN_CRYPTO_MANAGER);
-              ConfigEntry configEntry = configHandler.getConfigEntry(cipherDN);
+          throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_KEYMANAGER.get(e));
+        }
+      }
 
-              // Set the alternative cipher
-              StringConfigAttribute keyWrappingTransformation =
-                new StringConfigAttribute(
-                    ATTR_CRYPTO_CIPHER_KEY_WRAPPING_TRANSFORMATION,
-                    LocalizableMessage.EMPTY, false, false, true, alternativeCipher);
-              configEntry.putConfigAttribute(keyWrappingTransformation);
-            }
-            catch (Exception e)
-            {
-              LocalizableMessage message = ERR_CONFIGDS_CANNOT_UPDATE_CRYPTO_MANAGER.get(e);
-              err.println(wrapText(message, MAX_LINE_WIDTH));
-              return 1;
-            }
+      putKeyManagerConfigAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER);
+      putKeyManagerConfigAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER);
+
+      if (keyManagerPath.isPresent())
+      {
+        try
+        {
+          final StringConfigAttribute pathAttr = new StringConfigAttribute(
+              ATTR_KEYSTORE_FILE, INFO_FILE_KEYMANAGER_DESCRIPTION_FILE.get(),
+              true, true, true, keyManagerPath.getValue());
+          final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(keyManagerProviderDN.getValue()));
+          configEntry.putConfigAttribute(pathAttr);
+        }
+        catch (final Exception e)
+        {
+          throw new ConfigureDSException(e, LocalizableMessage.raw(e.toString()));
+        }
+      }
+    }
+  }
+
+  private void putKeyManagerConfigAttribute(final Argument arg, final String attributeDN)
+      throws ConfigureDSException
+  {
+    if (arg.isPresent())
+    {
+      try
+      {
+        final StringConfigAttribute keyManagerProviderAttr = new StringConfigAttribute(
+            ATTR_KEYMANAGER_DN, INFO_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN.get(),
+            false, false, true, keyManagerProviderDN.getValue());
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
+        configEntry.putConfigAttribute(keyManagerProviderAttr);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_KEYMANAGER_REFERENCE.get(e));
+      }
+    }
+  }
+
+  private void updateTrustManager() throws ConfigureDSException
+  {
+    if (trustManagerProviderDN.isPresent())
+    {
+      if (enableStartTLS.isPresent() || ldapsPort.isPresent())
+      {
+        try
+        {
+          final BooleanConfigAttribute enableAttr = new BooleanConfigAttribute(
+              ATTR_TRUSTMANAGER_ENABLED, ERR_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED.get(), true, true);
+          final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(trustManagerProviderDN.getValue()));
+          configEntry.putConfigAttribute(enableAttr);
+        }
+        catch (final Exception e)
+        {
+          throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_TRUSTMANAGER.get(e));
+        }
+      }
+      putTrustManagerAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER);
+      putTrustManagerAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER);
+    }
+
+    if (certNickName.isPresent())
+    {
+      final StringConfigAttribute certNickNameAttr = new StringConfigAttribute(
+          ATTR_SSL_CERT_NICKNAME, INFO_LDAP_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(),
+          false, false, true, certNickName.getValue());
+      updateCertNicknameEntry(ldapPort, DN_LDAP_CONNECTION_HANDLER, certNickNameAttr);
+      updateCertNicknameEntry(ldapsPort, DN_LDAPS_CONNECTION_HANDLER, certNickNameAttr);
+
+      final StringConfigAttribute certNickNameJmxAttr = new StringConfigAttribute(
+          ATTR_SSL_CERT_NICKNAME, INFO_JMX_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(),
+          false, false, true, certNickName.getValue());
+      updateCertNicknameEntry(jmxPort, DN_JMX_CONNECTION_HANDLER, certNickNameJmxAttr);
+    }
+    else
+    {
+      // Use the key manager specified for connection handlers
+      removeSSLCertNicknameAttribute(DN_LDAP_CONNECTION_HANDLER);
+      removeSSLCertNicknameAttribute(DN_LDAPS_CONNECTION_HANDLER);
+      removeSSLCertNicknameAttribute(DN_JMX_CONNECTION_HANDLER);
+    }
+  }
+
+  private void putTrustManagerAttribute(final Argument arg, final String attributeDN) throws ConfigureDSException
+  {
+    if (arg.isPresent())
+    {
+      try
+      {
+        final StringConfigAttribute trustManagerProviderAttr = new StringConfigAttribute(
+            ATTR_TRUSTMANAGER_DN, INFO_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN.get(),
+            false, false, true, trustManagerProviderDN.getValue());
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
+        configEntry.putConfigAttribute(trustManagerProviderAttr);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_TRUSTMANAGER_REFERENCE.get(e));
+      }
+    }
+  }
+
+  private void updateCertNicknameEntry(final Argument arg, final String attributeDN,
+      final StringConfigAttribute configAttr) throws ConfigureDSException
+  {
+    try
+    {
+      ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
+      if (arg.isPresent())
+      {
+        configEntry.putConfigAttribute(configAttr);
+      }
+      else
+      {
+        configEntry.removeConfigAttribute(ATTR_SSL_CERT_NICKNAME);
+      }
+    }
+    catch (final Exception e)
+    {
+      throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e));
+    }
+  }
+
+  private void removeSSLCertNicknameAttribute(final String attributeDN) throws ConfigureDSException
+  {
+    try
+    {
+      final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
+      configEntry.removeConfigAttribute(ATTR_SSL_CERT_NICKNAME.toLowerCase());
+    }
+    catch (final Exception e)
+    {
+      throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e));
+    }
+  }
+
+  private void updateRootUser(final DN rootDN, final String rootPW) throws ConfigureDSException
+  {
+    if (rootDN != null)
+    {
+      try
+      {
+        final DNConfigAttribute bindDNAttr = new DNConfigAttribute(
+            ATTR_ROOTDN_ALTERNATE_BIND_DN, INFO_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN.get(),
+            false, true, false, rootDN);
+        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_ROOT_USER));
+        configEntry.putConfigAttribute(bindDNAttr);
+
+        final String encodedPassword = SaltedSHA512PasswordStorageScheme.encodeOffline(getBytes(rootPW));
+        final StringConfigAttribute bindPWAttr = new StringConfigAttribute(
+            ATTR_USER_PASSWORD, LocalizableMessage.EMPTY, false, false, false, encodedPassword);
+        configEntry.putConfigAttribute(bindPWAttr);
+      }
+      catch (final Exception e)
+      {
+        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_ROOT_USER.get(e));
+      }
+    }
+  }
+
+  /** Set the FQDN for the DIGEST-MD5 SASL mechanism. */
+  private void addFQDNDigestMD5() throws ConfigureDSException
+  {
+    try
+    {
+      final StringConfigAttribute fqdnAttr = new StringConfigAttribute(
+            "ds-cfg-server-fqdn", LocalizableMessage.EMPTY, false, false, false, hostName.getValue());
+      final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_DIGEST_MD5_SASL_MECHANISM));
+      configEntry.putConfigAttribute(fqdnAttr);
+    }
+    catch (final Exception e)
+    {
+      throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_DIGEST_MD5_FQDN.get(e));
+    }
+  }
+
+  /**
+   * Check that the cipher specified is supported. This is intended to fix
+   * issues with JVM that do not support the default cipher (see issue 3075 for
+   * instance).
+   *
+   * @throws ConfigureDSException
+   */
+  private void updateCryptoCipher() throws ConfigureDSException
+  {
+    final CryptoManagerCfgDefn cryptoManager = CryptoManagerCfgDefn.getInstance();
+    final StringPropertyDefinition prop = cryptoManager.getKeyWrappingTransformationPropertyDefinition();
+    String defaultCipher = null;
+
+    final DefaultBehaviorProvider<?> p = prop.getDefaultBehaviorProvider();
+    if (p instanceof DefinedDefaultBehaviorProvider)
+    {
+      final Collection<?> defaultValues = ((DefinedDefaultBehaviorProvider<?>) p).getDefaultValues();
+      if (!defaultValues.isEmpty())
+      {
+        defaultCipher = defaultValues.iterator().next().toString();
+      }
+    }
+
+    if (defaultCipher != null)
+    {
+      // Check that the default cipher is supported by the JVM.
+      try
+      {
+        Cipher.getInstance(defaultCipher);
+      }
+      catch (final GeneralSecurityException ex)
+      {
+        // The cipher is not supported: try to find an alternative one.
+        final String alternativeCipher = getAlternativeCipher();
+        if (alternativeCipher != null)
+        {
+          try
+          {
+            final StringConfigAttribute keyWrappingTransformation = new StringConfigAttribute(
+                ATTR_CRYPTO_CIPHER_KEY_WRAPPING_TRANSFORMATION, LocalizableMessage.EMPTY,
+                false, false, true, alternativeCipher);
+            final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_CRYPTO_MANAGER));
+            configEntry.putConfigAttribute(keyWrappingTransformation);
+          }
+          catch (final Exception e)
+          {
+            throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CRYPTO_MANAGER.get(e));
           }
         }
       }
-
-      // Write the updated configuration.
-      try
-      {
-        configHandler.writeUpdatedConfig();
-
-        LocalizableMessage message = INFO_CONFIGDS_WROTE_UPDATED_CONFIG.get();
-        out.println(wrapText(message, MAX_LINE_WIDTH));
-      }
-      catch (DirectoryException de)
-      {
-        LocalizableMessage message = ERR_CONFIGDS_CANNOT_WRITE_UPDATED_CONFIG.get(
-                de.getMessageObject());
-        err.println(wrapText(message, MAX_LINE_WIDTH));
-        return 1;
-      }
     }
-    finally
+  }
+
+  private void writeUpdatedConfiguration() throws ConfigureDSException
+  {
+    try
     {
-      LockFileManager.releaseLock(serverLockFileName, failureReason);
+      configHandler.writeUpdatedConfig();
+      out.println(wrapText(INFO_CONFIGDS_WROTE_UPDATED_CONFIG.get(), MAX_LINE_WIDTH));
     }
-
-
-    // If we've gotten here, then everything was successful.
-    return 0;
+    catch (final DirectoryException de)
+    {
+      throw new ConfigureDSException(de, ERR_CONFIGDS_CANNOT_WRITE_UPDATED_CONFIG.get(de.getMessageObject()));
+    }
   }
 
   /**
@@ -1288,7 +1128,7 @@
         "RSA/ECB/PKCS1Padding"
     };
     String alternativeCipher = null;
-    for (String cipher : preferredAlternativeCiphers)
+    for (final String cipher : preferredAlternativeCiphers)
     {
       try
       {
@@ -1296,7 +1136,7 @@
         alternativeCipher = cipher;
         break;
       }
-      catch (Throwable t)
+      catch (final Throwable t)
       {
       }
     }

--
Gitblit v1.10.0