mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Gaetan Boismal
16.59.2016 1932d41262099a16f43749a90677366818b3664c
OPENDJ-2701 Code cleanup

Refactor LDAPConnectionConsoleInteraction

* Split very long methods (run(), getKeyManagerInternal() and
getTrustManagerInternal()) in smaller ones, trying to keep the following
pattern for each parameter to resolve:
1. Initialize the parameter value with command line (if present)
2. Interactive prompt for the argument value (if the application is
interactive and the argument has not been given in the command line)
3. Store the argument value in the CommandBuilder

* Make public fields private and create getters in
SecureConnectionCliArgs
* Other minor cleanup actions
12 files modified
2957 ■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/guitools/uninstaller/UninstallCliHelper.java 71 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/uninstaller/Uninstaller.java 9 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/uninstaller/UninstallerArgumentParser.java 17 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/admin/client/cli/SecureConnectionCliArgs.java 295 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/admin/client/cli/SecureConnectionCliParser.java 120 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliArgumentParser.java 92 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java 20 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java 8 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCliArgumentParser.java 10 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/util/args/LDAPConnectionArgumentParser.java 78 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java 2227 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/messages/org/opends/messages/tool.properties 10 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/uninstaller/UninstallCliHelper.java
@@ -791,39 +791,37 @@
    while (!couldConnect && accepted)
    {
      // This is done because we do not need to ask the user about these
      // parameters.  If we force their presence the class
      // LDAPConnectionConsoleInteraction will not prompt the user for
      // them.
      // This is done because we do not need to ask the user about these parameters.
      // If we force their presence the class LDAPConnectionConsoleInteraction will not prompt the user for them.
      SecureConnectionCliArgs secureArgsList = parser.getSecureArgsList();
      secureArgsList.hostNameArg.setPresent(true);
      secureArgsList.portArg.setPresent(true);
      secureArgsList.hostNameArg.clearValues();
      secureArgsList.hostNameArg.addValue(
          secureArgsList.hostNameArg.getDefaultValue());
      secureArgsList.portArg.clearValues();
      secureArgsList.portArg.addValue(
          secureArgsList.portArg.getDefaultValue());
      secureArgsList.bindDnArg.clearValues();
      secureArgsList.getHostNameArg().setPresent(true);
      secureArgsList.getPortArg().setPresent(true);
      secureArgsList.getHostNameArg().clearValues();
      secureArgsList.getHostNameArg().addValue(
          secureArgsList.getHostNameArg().getDefaultValue());
      secureArgsList.getPortArg().clearValues();
      secureArgsList.getPortArg().addValue(
          secureArgsList.getPortArg().getDefaultValue());
      secureArgsList.getBindDnArg().clearValues();
      if (uid != null)
      {
        secureArgsList.bindDnArg.addValue(ADSContext.getAdministratorDN(uid));
        secureArgsList.bindDnArg.setPresent(true);
        secureArgsList.getBindDnArg().addValue(ADSContext.getAdministratorDN(uid));
        secureArgsList.getBindDnArg().setPresent(true);
      }
      else
      {
        secureArgsList.bindDnArg.setPresent(false);
        secureArgsList.getBindDnArg().setPresent(false);
      }
      secureArgsList.bindPasswordArg.clearValues();
      secureArgsList.getBindPasswordArg().clearValues();
      if (pwd != null)
      {
        secureArgsList.bindPasswordArg.addValue(pwd);
        secureArgsList.bindPasswordArg.setPresent(true);
        secureArgsList.getBindPasswordArg().addValue(pwd);
        secureArgsList.getBindPasswordArg().setPresent(true);
      }
      else
      {
        secureArgsList.bindPasswordArg.setPresent(false);
        secureArgsList.getBindPasswordArg().setPresent(false);
      }
      if (ci == null)
@@ -853,8 +851,8 @@
        {
          URI uri = new URI(adminConnectorUrl);
          int port = uri.getPort();
          secureArgsList.portArg.clearValues();
          secureArgsList.portArg.addValue(String.valueOf(port));
          secureArgsList.getPortArg().clearValues();
          secureArgsList.getPortArg().addValue(String.valueOf(port));
          ci.setPortNumber(port);
        }
        catch (Throwable t)
@@ -1256,9 +1254,9 @@
        {
          println();
          printErrorMessage(ERR_UNINSTALL_ERROR_UPDATING_REMOTE_FORCE.get(
              "--"+parser.getSecureArgsList().adminUidArg.getLongIdentifier(),
              "--"+OPTION_LONG_BINDPWD,
              "--"+OPTION_LONG_BINDPWD_FILE,
              "--" + parser.getSecureArgsList().getAdminUidArg().getLongIdentifier(),
              "--" + OPTION_LONG_BINDPWD,
              "--" + OPTION_LONG_BINDPWD_FILE,
              exceptionMsg));
        }
        else
@@ -1266,11 +1264,10 @@
          println();
          throw new UserDataException(null,
              ERR_UNINSTALL_ERROR_UPDATING_REMOTE_NO_FORCE.get(
                  "--"+
                  parser.getSecureArgsList().adminUidArg.getLongIdentifier(),
                  "--"+OPTION_LONG_BINDPWD,
                  "--"+OPTION_LONG_BINDPWD_FILE,
                  "--"+parser.forceOnErrorArg.getLongIdentifier(),
                  "--" + parser.getSecureArgsList().getAdminUidArg().getLongIdentifier(),
                  "--" + OPTION_LONG_BINDPWD,
                  "--" + OPTION_LONG_BINDPWD_FILE,
                  "--" + parser.forceOnErrorArg.getLongIdentifier(),
                  exceptionMsg));
        }
      }
@@ -1420,13 +1417,11 @@
        {
          LocalizableMessage msg =
            ERR_UNINSTALL_ERROR_UPDATING_REMOTE_NO_FORCE.get(
              "--"+
              parser.getSecureArgsList().adminUidArg.getLongIdentifier(),
              "--"+OPTION_LONG_BINDPWD,
              "--"+OPTION_LONG_BINDPWD_FILE,
              "--"+parser.forceOnErrorArg.getLongIdentifier(),
              Utils.getMessageFromCollection(exceptionMsgs,
                  Constants.LINE_SEPARATOR));
              "--" + parser.getSecureArgsList().getAdminUidArg().getLongIdentifier(),
              "--" + OPTION_LONG_BINDPWD,
              "--" + OPTION_LONG_BINDPWD_FILE,
              "--" + parser.forceOnErrorArg.getLongIdentifier(),
              Utils.getMessageFromCollection(exceptionMsgs, Constants.LINE_SEPARATOR));
          throw new ClientException(ReturnCode.APPLICATION_ERROR, msg);
        }
      }
@@ -1549,7 +1544,7 @@
   {
     try
     {
       return parser.getSecureArgsList().connectTimeoutArg.getIntValue();
       return parser.getSecureArgsList().getConnectTimeoutArg().getIntValue();
     }
     catch (ArgumentException ae)
     {
opendj-server-legacy/src/main/java/org/opends/guitools/uninstaller/Uninstaller.java
@@ -1951,11 +1951,10 @@
        {
          LocalizableMessage msg =
            ERR_UNINSTALL_ERROR_UPDATING_REMOTE_NO_FORCE.get(
              "--"+
              parser.getSecureArgsList().adminUidArg.getLongIdentifier(),
              "--"+OPTION_LONG_BINDPWD,
              "--"+OPTION_LONG_BINDPWD_FILE,
              "--"+parser.forceOnErrorArg.getLongIdentifier(),
              "--" + parser.getSecureArgsList().getAdminUidArg().getLongIdentifier(),
              "--" + OPTION_LONG_BINDPWD,
              "--" + OPTION_LONG_BINDPWD_FILE,
              "--" + parser.forceOnErrorArg.getLongIdentifier(),
              ae.getMessageObject());
          throw new ApplicationException(ae.getType(), msg, ae);
        }
opendj-server-legacy/src/main/java/org/opends/guitools/uninstaller/UninstallerArgumentParser.java
@@ -25,6 +25,7 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
@@ -159,20 +160,20 @@
    quietArg = quietArgument();
    args.add(quietArg);
    ArrayList<Argument> defaultArgs = new ArrayList<>(createGlobalArguments(outStream, alwaysSSL));
    final List<Argument> defaultArgs = new ArrayList<>(createGlobalArguments(outStream, alwaysSSL));
    secureArgsList.createVisibleAdminUidArgument(INFO_DESCRIPTION_ADMIN_UID.get());
    int index = defaultArgs.indexOf(secureArgsList.bindDnArg);
    int index = defaultArgs.indexOf(secureArgsList.getBindDnArg());
    if (index != -1)
    {
      defaultArgs.add(index, secureArgsList.adminUidArg);
      defaultArgs.remove(secureArgsList.bindDnArg);
      defaultArgs.add(index, secureArgsList.getAdminUidArg());
      defaultArgs.remove(secureArgsList.getBindDnArg());
    }
    else
    {
      defaultArgs.add(secureArgsList.adminUidArg);
      defaultArgs.add(secureArgsList.getAdminUidArg());
    }
    defaultArgs.remove(secureArgsList.hostNameArg);
    defaultArgs.remove(secureArgsList.portArg);
    defaultArgs.remove(secureArgsList.getHostNameArg());
    defaultArgs.remove(secureArgsList.getPortArg());
    referencedHostNameArg =
            StringArgument.builder(OPTION_LONG_REFERENCED_HOST_NAME)
                    .shortIdentifier(OPTION_SHORT_HOST)
@@ -314,7 +315,7 @@
   */
  public String getDefaultAdministratorUID()
  {
    return secureArgsList.adminUidArg.getDefaultValue();
    return secureArgsList.getAdminUidArg().getDefaultValue();
  }
  /**
opendj-server-legacy/src/main/java/org/opends/server/admin/client/cli/SecureConnectionCliArgs.java
@@ -68,42 +68,24 @@
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  /** The 'hostName' global argument. */
  public StringArgument hostNameArg;
  /** The 'port' global argument. */
  public IntegerArgument portArg;
  /** The 'bindDN' global argument. */
  public StringArgument bindDnArg;
  /** The 'adminUID' global argument. */
  public StringArgument adminUidArg;
  /** The 'bindPasswordFile' global argument. */
  public FileBasedArgument bindPasswordFileArg;
  /** The 'bindPassword' global argument. */
  public StringArgument bindPasswordArg;
  /** The 'trustAllArg' global argument. */
  public BooleanArgument trustAllArg;
  /** The 'trustStore' global argument. */
  public StringArgument trustStorePathArg;
  /** The 'trustStorePassword' global argument. */
  public StringArgument trustStorePasswordArg;
  /** The 'trustStorePasswordFile' global argument. */
  public FileBasedArgument trustStorePasswordFileArg;
  /** The 'keyStore' global argument. */
  public StringArgument keyStorePathArg;
  /** The 'keyStorePassword' global argument. */
  public StringArgument keyStorePasswordArg;
  /** The 'keyStorePasswordFile' global argument. */
  public FileBasedArgument keyStorePasswordFileArg;
  /** The 'certNicknameArg' global argument. */
  public StringArgument certNicknameArg;
  /** The 'useSSLArg' global argument. */
  public BooleanArgument useSSLArg;
  /** The 'useStartTLSArg' global argument. */
  public BooleanArgument useStartTLSArg;
  /** Argument indicating a SASL option. */
  public StringArgument saslOptionArg;
  /** Argument to specify the connection timeout. */
  public IntegerArgument connectTimeoutArg;
  private StringArgument hostNameArg;
  private IntegerArgument portArg;
  private StringArgument bindDnArg;
  private StringArgument adminUidArg;
  private FileBasedArgument bindPasswordFileArg;
  private StringArgument bindPasswordArg;
  private BooleanArgument trustAllArg;
  private StringArgument trustStorePathArg;
  private StringArgument trustStorePasswordArg;
  private FileBasedArgument trustStorePasswordFileArg;
  private StringArgument keyStorePathArg;
  private StringArgument keyStorePasswordArg;
  private FileBasedArgument keyStorePasswordFileArg;
  private StringArgument certNicknameArg;
  private BooleanArgument useSSLArg;
  private BooleanArgument useStartTLSArg;
  private StringArgument saslOptionArg;
  private IntegerArgument connectTimeoutArg;
  /** Private container for global arguments. */
  private Set<Argument> argList;
@@ -165,18 +147,6 @@
  }
  /**
   * Tells whether this parser uses the Administrator UID (instead of the bind
   * DN) or not.
   *
   * @return {@code true} if this parser uses the Administrator UID and
   *         {@code false} otherwise.
   */
  public boolean useAdminUID()
  {
    return !adminUidArg.isHidden();
  }
  /**
   * Get the bindDN which has to be used for the command.
   *
   * @return The bindDN specified by the command line argument, or the default
@@ -229,7 +199,7 @@
    bindDnArg = bindDNArgument(CliConstants.DEFAULT_ROOT_USER_DN);
    argList.add(bindDnArg);
    // Classes that required admin UID to be not hidden must use CommonsArguments.adminUid().
    // Classes that required admin UID to be not hidden must call createVisibleAdminUidArgument(localizedDescription)
    adminUidArg = adminUidHiddenArgument(INFO_DESCRIPTION_ADMIN_UID.get());
    bindPasswordArg = bindPasswordArgument();
@@ -376,26 +346,6 @@
  }
  /**
   * Indicate if the SSL mode is required.
   *
   * @return True if SSL mode is required
   */
  public boolean useSSL()
  {
    return useSSLArg.isPresent() || alwaysSSL();
  }
  /**
   * Indicate if the startTLS mode is required.
   *
   * @return True if startTLS mode is required
   */
  public boolean useStartTLS()
  {
    return useStartTLSArg.isPresent();
  }
  /**
   * Indicate if the SSL mode is always used.
   *
   * @return True if SSL mode is always used.
@@ -658,9 +608,9 @@
    {
      this.adminUidArg = adminUid(description);
    }
    catch (ArgumentException e)
    catch (final ArgumentException unexpected)
    {
      // Will never append.
      throw new RuntimeException("Unexpected");
    }
  }
@@ -669,4 +619,207 @@
    return portArgument(
            defaultValue, alwaysSSL ? INFO_DESCRIPTION_ADMIN_PORT.get() : INFO_DESCRIPTION_PORT.get());
  }
  /**
   * Return the 'keyStore' global argument.
   *
   * @return The 'keyStore' global argument.
   */
  public StringArgument getKeyStorePathArg() {
    return keyStorePathArg;
  }
  /**
   * Return the 'hostName' global argument.
   *
   * @return The 'hostName' global argument.
   */
  public StringArgument getHostNameArg() {
    return hostNameArg;
  }
  /**
   * Return the 'port' global argument.
   *
   * @return The 'port' global argument.
   */
  public IntegerArgument getPortArg() {
    return portArg;
  }
  /**
   * Return the 'bindDN' global argument.
   *
   * @return The 'bindDN' global argument.
   */
  public StringArgument getBindDnArg() {
    return bindDnArg;
  }
  /**
   * Return the 'adminUID' global argument.
   *
   * @return The 'adminUID' global argument.
   */
  public StringArgument getAdminUidArg() {
    return adminUidArg;
  }
  /**
   * Return the 'bindPasswordFile' global argument.
   *
   * @return The 'bindPasswordFile' global argument.
   */
  public FileBasedArgument getBindPasswordFileArg() {
    return bindPasswordFileArg;
  }
  /**
   * Return the 'bindPassword' global argument.
   *
   * @return The 'bindPassword' global argument.
   */
  public StringArgument getBindPasswordArg() {
    return bindPasswordArg;
  }
  /**
   * Return the 'trustAllArg' global argument.
   *
   * @return The 'trustAllArg' global argument.
   */
  public BooleanArgument getTrustAllArg() {
    return trustAllArg;
  }
  /**
   * Return the 'trustStore' global argument.
   *
   * @return The 'trustStore' global argument.
   */
  public StringArgument getTrustStorePathArg() {
    return trustStorePathArg;
  }
  /**
   * Return the 'trustStorePassword' global argument.
   *
   * @return The 'trustStorePassword' global argument.
   */
  public StringArgument getTrustStorePasswordArg() {
    return trustStorePasswordArg;
  }
  /**
   * Return the 'trustStorePasswordFile' global argument.
   *
   * @return The 'trustStorePasswordFile' global argument.
   */
  public FileBasedArgument getTrustStorePasswordFileArg() {
    return trustStorePasswordFileArg;
  }
  /**
   * Return the 'keyStorePassword' global argument.
   *
   * @return The 'keyStorePassword' global argument.
   */
  public StringArgument getKeyStorePasswordArg() {
    return keyStorePasswordArg;
  }
  /**
   * Return the 'keyStorePasswordFile' global argument.
   *
   * @return The 'keyStorePasswordFile' global argument.
   */
  public FileBasedArgument getKeyStorePasswordFileArg() {
    return keyStorePasswordFileArg;
  }
  /**
   * Return the 'certNicknameArg' global argument.
   *
   * @return The 'certNicknameArg' global argument.
   */
  public StringArgument getCertNicknameArg() {
    return certNicknameArg;
  }
  /**
   * Return the 'useSSLArg' global argument.
   *
   * @return The 'useSSLArg' global argument.
   */
  public BooleanArgument getUseSSLArg() {
    return useSSLArg;
  }
  /**
   * Return the 'useStartTLSArg' global argument.
   *
   * @return The 'useStartTLSArg' global argument.
   */
  public BooleanArgument getUseStartTLSArg() {
    return useStartTLSArg;
  }
  /**
   * Return the 'saslOption' argument.
   *
   * @return the 'saslOption' argument.
   */
  public StringArgument getSaslOptionArg() {
    return saslOptionArg;
  }
  /**
   * Return the 'connectTimeout' argument.
   *
   * @return the 'connectTimeout' argument.
   */
  public IntegerArgument getConnectTimeoutArg() {
    return connectTimeoutArg;
  }
  /**
   * Set the bind DN argument with the provided description.
   * Note that this method will create a new {@link Argument} instance replacing the current one.
   *
   * @param description
   *         The localized description which will be used in help messages.
   */
  public void setBindDnArgDescription(final LocalizableMessage description)
  {
    try
    {
      this.bindDnArg = bindDNArgument(CliConstants.DEFAULT_ROOT_USER_DN, description);
    }
    catch (final ArgumentException unexpected)
    {
      throw new RuntimeException("unexpected");
    }
  }
  /**
   * Set the bind password argument.
   *
   * @param bindPasswordArg
   *         The argument which will replace the current one.
   */
  public void setBindPasswordArgument(final StringArgument bindPasswordArg)
  {
    this.bindPasswordArg = bindPasswordArg;
  }
  /**
   * Set the bind password file argument.
   *
   * @param bindPasswordFileArg
   *         The argument which will replace the current one.
   */
  public void setBindPasswordFileArgument(final FileBasedArgument bindPasswordFileArg)
  {
    this.bindPasswordFileArg = bindPasswordFileArg;
  }
}
opendj-server-legacy/src/main/java/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
@@ -22,7 +22,6 @@
import static com.forgerock.opendj.cli.Utils.*;
import static com.forgerock.opendj.cli.CommonArguments.*;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Collection;
@@ -37,9 +36,6 @@
import com.forgerock.opendj.cli.ArgumentException;
import com.forgerock.opendj.cli.ArgumentGroup;
import com.forgerock.opendj.cli.BooleanArgument;
import com.forgerock.opendj.cli.ClientException;
import com.forgerock.opendj.cli.ConsoleApplication;
import com.forgerock.opendj.cli.FileBasedArgument;
import com.forgerock.opendj.cli.StringArgument;
import com.forgerock.opendj.cli.SubCommandArgumentParser;
@@ -53,18 +49,12 @@
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  /** The 'showUsage' global argument. */
  protected BooleanArgument showUsageArg;
  /** The 'verbose' global argument. */
  protected BooleanArgument verboseArg;
  /** The secure args list object. */
  protected SecureConnectionCliArgs secureArgsList;
  /** Argument indicating a properties file argument. */
  protected StringArgument propertiesFileArg;
  /** The argument which should be used to indicate that we will not look for properties file. */
  protected BooleanArgument noPropertiesFileArg;
@@ -99,7 +89,6 @@
    return secureArgsList.getBindDN();
  }
  /**
   * Returns the Administrator UID provided in the command-line.
   * @return the Administrator UID provided in the command-line.
@@ -110,86 +99,6 @@
  }
  /**
   * Get the password which has to be used for the command.
   *
   * @param dn
   *          The user DN for which to password could be asked.
   * @param out
   *          The input stream to used if we have to prompt to the
   *          user.
   * @param err
   *          The error stream to used if we have to prompt to the
   *          user.
   * @param pwdArg
   *          The password StringArgument argument.
   * @param fileArg
   *          The password FileBased argument.
   * @return The password stored into the specified file on by the
   *         command line argument, or prompts it if not specified.
   */
  protected String getBindPassword(String dn, OutputStream out,
      OutputStream err, StringArgument pwdArg, FileBasedArgument fileArg)
  {
    if (fileArg.isPresent())
    {
      return fileArg.getValue();
    }
    String bindPasswordValue = pwdArg.isPresent() ? pwdArg.getValue() : null;
    if (bindPasswordValue == null || "-".equals(bindPasswordValue))
    {
      // Read the password from the STDin.
      try
      {
        return readPassword(dn, out);
      }
      catch (Exception ex)
      {
        logger.traceException(ex);
        try
        {
          err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes());
          err.write(LINE_SEPARATOR.getBytes());
        }
        catch (IOException e)
        {
          // Nothing to do.
        }
      }
    }
    return bindPasswordValue;
  }
  private String readPassword(String dn, OutputStream out) throws IOException,
      ClientException
  {
    out.write(INFO_LDAPAUTH_PASSWORD_PROMPT.get(dn).toString().getBytes());
    out.flush();
    char[] pwChars = ConsoleApplication.readPassword();
    return new String(pwChars);
  }
  /**
   * Gets the password which has to be used for the command.
   *
   * @param dn
   *          The user DN for which to password could be asked.
   * @param out
   *          The input stream to used if we have to prompt to the
   *          user.
   * @param err
   *          The error stream to used if we have to prompt to the
   *          user.
   * @return The password stored into the specified file on by the
   *         command line argument, or prompts it if not specified.
   */
  public String getBindPassword(String dn, OutputStream out, OutputStream err)
  {
    return getBindPassword(dn, out, err, secureArgsList.bindPasswordArg,
        secureArgsList.bindPasswordFileArg);
  }
  /**
   * Gets the password which has to be used for the command without prompting
   * the user.  If no password was specified, return null.
   *
@@ -198,8 +107,7 @@
   */
  public String getBindPassword()
  {
    return getBindPassword(secureArgsList.bindPasswordArg,
        secureArgsList.bindPasswordFileArg);
    return getBindPassword(secureArgsList.getBindPasswordArg(), secureArgsList.getBindPasswordFileArg());
  }
  /**
@@ -220,7 +128,8 @@
    secureArgsList = new SecureConnectionCliArgs(alwaysSSL);
    Set<Argument> set = secureArgsList.createGlobalArguments();
    showUsageArg = showUsageArgument();
    /* The 'showUsage' global argument. */
    final BooleanArgument showUsageArg = showUsageArgument();
    setUsageArgument(showUsageArg, outStream);
    set.add(showUsageArg);
@@ -347,27 +256,6 @@
    return verboseArg.isPresent();
  }
  /**
   * Indicate if the SSL mode is required.
   *
   * @return True if SSL mode is required
   */
  public boolean useSSL()
  {
    return secureArgsList.useSSL();
  }
  /**
   * Indicate if the startTLS mode is required.
   *
   * @return True if startTLS mode is required
   */
  public boolean useStartTLS()
  {
    return secureArgsList.useStartTLS();
  }
  /**
   * Handle TrustStore.
   *
@@ -389,7 +277,7 @@
  {
    try
    {
      return secureArgsList.connectTimeoutArg.getIntValue();
      return secureArgsList.getConnectTimeoutArg().getIntValue();
    }
    catch (ArgumentException ae)
    {
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliArgumentParser.java
@@ -287,11 +287,11 @@
    int returnValue;
    super.validateGlobalOptions(buf);
    ArrayList<LocalizableMessage> errors = new ArrayList<>();
    if (secureArgsList.bindPasswordArg.isPresent() &&
        secureArgsList.bindPasswordFileArg.isPresent()) {
    if (secureArgsList.getBindPasswordArg().isPresent() &&
        secureArgsList.getBindPasswordFileArg().isPresent()) {
      LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
          secureArgsList.bindPasswordArg.getLongIdentifier(),
          secureArgsList.bindPasswordFileArg.getLongIdentifier());
          secureArgsList.getBindPasswordArg().getLongIdentifier(),
          secureArgsList.getBindPasswordFileArg().getLongIdentifier());
      errors.add(message);
    }
@@ -338,8 +338,8 @@
          !isPurgeHistoricalSubcommand())
      {
        errors.add(ERR_REPLICATION_NO_ADMINISTRATOR_PASSWORD_PROVIDED.get(
            "--"+secureArgsList.bindPasswordArg.getLongIdentifier(),
            "--"+secureArgsList.bindPasswordFileArg.getLongIdentifier()));
            "--"+ secureArgsList.getBindPasswordArg().getLongIdentifier(),
            "--"+ secureArgsList.getBindPasswordFileArg().getLongIdentifier()));
      }
    }
@@ -392,11 +392,11 @@
    ArrayList<Argument> defaultArgs = new ArrayList<>(createGlobalArguments(outStream, alwaysSSL));
    Argument[] argsToRemove = {
      secureArgsList.hostNameArg,
      secureArgsList.portArg,
      secureArgsList.bindDnArg,
      secureArgsList.bindPasswordFileArg,
      secureArgsList.bindPasswordArg
            secureArgsList.getHostNameArg(),
            secureArgsList.getPortArg(),
            secureArgsList.getBindDnArg(),
            secureArgsList.getBindPasswordFileArg(),
            secureArgsList.getBindPasswordArg()
    };
    for (Argument arg : argsToRemove)
@@ -421,23 +421,23 @@
    secureArgsList.createVisibleAdminUidArgument(
        INFO_DESCRIPTION_REPLICATION_ADMIN_UID.get(ENABLE_REPLICATION_SUBCMD_NAME));
    defaultArgs.add(index++, secureArgsList.adminUidArg);
    defaultArgs.add(index++, secureArgsList.getAdminUidArg());
    secureArgsList.bindPasswordArg =
    secureArgsList.setBindPasswordArgument(
            StringArgument.builder(OPTION_LONG_ADMIN_PWD)
                    .shortIdentifier(OPTION_SHORT_BINDPWD)
                    .description(INFO_DESCRIPTION_REPLICATION_ADMIN_BINDPASSWORD.get())
                    .valuePlaceholder(INFO_BINDPWD_PLACEHOLDER.get())
                    .buildArgument();
    defaultArgs.add(index++, secureArgsList.bindPasswordArg);
                    .buildArgument());
    defaultArgs.add(index++, secureArgsList.getBindPasswordArg());
    secureArgsList.bindPasswordFileArg =
    secureArgsList.setBindPasswordFileArgument(
            FileBasedArgument.builder(OPTION_LONG_ADMIN_PWD_FILE)
                    .shortIdentifier(OPTION_SHORT_BINDPWD_FILE)
                    .description(INFO_DESCRIPTION_REPLICATION_ADMIN_BINDPASSWORDFILE.get())
                    .valuePlaceholder(INFO_BINDPWD_FILE_PLACEHOLDER.get())
                    .buildArgument();
    defaultArgs.add(index++, secureArgsList.bindPasswordFileArg);
                    .buildArgument());
    defaultArgs.add(index++, secureArgsList.getBindPasswordFileArg());
    defaultArgs.remove(verboseArg);
@@ -672,13 +672,7 @@
    disableReplicationSubCmd = new SubCommand(this,
        DISABLE_REPLICATION_SUBCMD_NAME,
        INFO_DESCRIPTION_SUBCMD_DISABLE_REPLICATION.get());
    secureArgsList.bindDnArg =
            StringArgument.builder(OPTION_LONG_BINDDN)
                    .shortIdentifier(OPTION_SHORT_BINDDN)
                    .description(INFO_DESCRIPTION_DISABLE_REPLICATION_BINDDN.get())
                    .defaultValue("cn=Directory Manager")
                    .valuePlaceholder(INFO_BINDDN_PLACEHOLDER.get())
                    .buildArgument();
    secureArgsList.setBindDnArgDescription(INFO_DESCRIPTION_DISABLE_REPLICATION_BINDDN.get());
    disableReplicationServerArg =
            BooleanArgument.builder("disableReplicationServer")
                    .shortIdentifier('a')
@@ -689,8 +683,8 @@
                    .description(INFO_DESCRIPTION_DISABLE_ALL.get())
                    .buildArgument();
    Argument[] argsToAdd = { secureArgsList.hostNameArg,
        secureArgsList.portArg, secureArgsList.bindDnArg,
    Argument[] argsToAdd = { secureArgsList.getHostNameArg(),
            secureArgsList.getPortArg(), secureArgsList.getBindDnArg(),
        disableReplicationServerArg, disableAllArg};
    for (Argument arg : argsToAdd)
    {
@@ -757,8 +751,8 @@
        INITIALIZE_ALL_REPLICATION_SUBCMD_NAME,
        INFO_DESCRIPTION_SUBCMD_INITIALIZE_ALL_REPLICATION.get(
            INITIALIZE_REPLICATION_SUBCMD_NAME));
    Argument[] argsToAdd = { secureArgsList.hostNameArg,
        secureArgsList.portArg };
    Argument[] argsToAdd = { secureArgsList.getHostNameArg(),
            secureArgsList.getPortArg() };
    for (Argument arg : argsToAdd)
    {
      initializeAllReplicationSubCmd.addArgument(arg);
@@ -786,8 +780,8 @@
                    .hidden()
                    .buildArgument();
    Argument[] argsToAdd = { secureArgsList.hostNameArg,
        secureArgsList.portArg,
    Argument[] argsToAdd = { secureArgsList.getHostNameArg(),
            secureArgsList.getPortArg(),
        externalInitializationLocalOnlyArg};
    for (Argument arg : argsToAdd)
@@ -810,8 +804,8 @@
        POST_EXTERNAL_INITIALIZATION_SUBCMD_NAME,
        INFO_DESCRIPTION_SUBCMD_POST_EXTERNAL_INITIALIZATION.get(
            PRE_EXTERNAL_INITIALIZATION_SUBCMD_NAME));
    Argument[] argsToAdd = { secureArgsList.hostNameArg,
        secureArgsList.portArg };
    Argument[] argsToAdd = { secureArgsList.getHostNameArg(),
            secureArgsList.getPortArg() };
    for (Argument arg : argsToAdd)
    {
      postExternalInitializationSubCmd.addArgument(arg);
@@ -852,7 +846,7 @@
                    .description(INFO_DESCRIPTION_SCRIPT_FRIENDLY.get())
                    .buildArgument();
    addArgumentsToSubCommand(
            statusReplicationSubCmd, secureArgsList.hostNameArg, secureArgsList.portArg, scriptFriendlyArg);
            statusReplicationSubCmd, secureArgsList.getHostNameArg(), secureArgsList.getPortArg(), scriptFriendlyArg);
  }
  /**
@@ -878,7 +872,7 @@
        INFO_DESCRIPTION_SUBCMD_PURGE_HISTORICAL.get());
    addArgumentsToSubCommand(purgeHistoricalSubCmd,
            secureArgsList.hostNameArg, secureArgsList.portArg, maximumDurationArg);
            secureArgsList.getHostNameArg(), secureArgsList.getPortArg(), maximumDurationArg);
    addArgumentsToSubCommand(purgeHistoricalSubCmd, taskArgs.getArguments());
  }
@@ -934,7 +928,7 @@
   */
  public String getBindPasswordAdmin()
  {
    return getBindPassword(secureArgsList.bindPasswordArg, secureArgsList.bindPasswordFileArg);
    return getBindPassword(secureArgsList.getBindPasswordArg(), secureArgsList.getBindPasswordFileArg());
  }
  /**
@@ -962,7 +956,7 @@
   */
  StringArgument getAdminUidArg()
  {
    return secureArgsList.adminUidArg;
    return secureArgsList.getAdminUidArg();
  }
  /**
@@ -1028,7 +1022,7 @@
   */
  public String getHostNameToDisable()
  {
    return getValue(secureArgsList.hostNameArg);
    return getValue(secureArgsList.getHostNameArg());
  }
  /**
@@ -1039,7 +1033,7 @@
   */
  public String getHostNameToDisableOrDefault()
  {
    return getValueOrDefault(secureArgsList.hostNameArg);
    return getValueOrDefault(secureArgsList.getHostNameArg());
  }
  /**
@@ -1050,7 +1044,7 @@
   */
  public String getBindDNToDisable()
  {
    return getValue(secureArgsList.bindDnArg);
    return getValue(secureArgsList.getBindDnArg());
  }
  /**
@@ -1059,7 +1053,7 @@
   */
  public String getHostNameToStatusOrDefault()
  {
    return getValueOrDefault(secureArgsList.hostNameArg);
    return getValueOrDefault(secureArgsList.getHostNameArg());
  }
  /**
@@ -1070,7 +1064,7 @@
   */
  public String getHostNameToInitializeAllOrDefault()
  {
    return getValueOrDefault(secureArgsList.hostNameArg);
    return getValueOrDefault(secureArgsList.getHostNameArg());
  }
  /**
@@ -1169,7 +1163,7 @@
   */
  public int getPortToDisable()
  {
    return getValue(secureArgsList.portArg);
    return getValue(secureArgsList.getPortArg());
  }
  /**
@@ -1180,7 +1174,7 @@
   */
  public int getPortToDisableOrDefault()
  {
    return getValueOrDefault(secureArgsList.portArg);
    return getValueOrDefault(secureArgsList.getPortArg());
  }
  /**
@@ -1191,7 +1185,7 @@
   */
  public int getPortToInitializeAllOrDefault()
  {
    return getValueOrDefault(secureArgsList.portArg);
    return getValueOrDefault(secureArgsList.getPortArg());
  }
  /**
@@ -1200,7 +1194,7 @@
   */
  public int getPortToStatusOrDefault()
  {
    return getValueOrDefault(secureArgsList.portArg);
    return getValueOrDefault(secureArgsList.getPortArg());
  }
  /**
@@ -1556,7 +1550,7 @@
  {
    Argument[][] conflictingPairs =
    {
        {getAdminUidArg(), secureArgsList.bindDnArg},
        {getAdminUidArg(), secureArgsList.getBindDnArg() },
        {disableAllArg, disableReplicationServerArg},
        {disableAllArg, baseDNsArg}
    };
@@ -1665,8 +1659,8 @@
      // This have to be explicitly specified because their original definition
      // has been replaced.
      boolean adminArgsPresent = getAdminUidArg().isPresent() ||
      secureArgsList.bindPasswordArg.isPresent() ||
      secureArgsList.bindPasswordFileArg.isPresent();
      secureArgsList.getBindPasswordArg().isPresent() ||
      secureArgsList.getBindPasswordFileArg().isPresent();
      return secureArgsPresent || adminArgsPresent;
    }
    return true;
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java
@@ -448,7 +448,7 @@
      }
    }
    if (argParser.getSecureArgsList().bindPasswordFileArg.isPresent())
    if (argParser.getSecureArgsList().getBindPasswordFileArg().isPresent())
    {
      try
      {
@@ -458,7 +458,7 @@
                .valuePlaceholder(INFO_BINDPWD_FILE_PLACEHOLDER.get())
                .buildArgument();
        userProvidedAdminPwdFile.getNameToValueMap().putAll(
            argParser.getSecureArgsList().bindPasswordFileArg.getNameToValueMap());
            argParser.getSecureArgsList().getBindPasswordFileArg().getNameToValueMap());
      }
      catch (Throwable t)
      {
@@ -2150,9 +2150,9 @@
    else if (bindDn1 == null)
    {
      pwd = adminPwd;
      if (argParser.getSecureArgsList().bindPasswordFileArg.isPresent())
      if (argParser.getSecureArgsList().getBindPasswordFileArg().isPresent())
      {
        pwdFile = argParser.getSecureArgsList().bindPasswordFileArg.
        pwdFile = argParser.getSecureArgsList().getBindPasswordFileArg().
          getNameToValueMap();
      }
    }
@@ -2352,7 +2352,7 @@
    uData.getServer1().setSecureReplication(secureReplication1);
    uData.getServer1().setConfigureReplicationServer(configureReplicationServer1);
    uData.getServer1().setConfigureReplicationDomain(configureReplicationDomain1);
    firstServerCommandBuilder = new CommandBuilder(null, null);
    firstServerCommandBuilder = new CommandBuilder();
    if (mustPrintCommandBuilder())
    {
      firstServerCommandBuilder.append(sourceServerCI.getCommandBuilder());
@@ -2390,9 +2390,9 @@
      {
        doNotDisplayFirstError = true;
        pwd = adminPwd;
        if (argParser.getSecureArgsList().bindPasswordFileArg.isPresent())
        if (argParser.getSecureArgsList().getBindPasswordFileArg().isPresent())
        {
          pwdFile = argParser.getSecureArgsList().bindPasswordFileArg.
          pwdFile = argParser.getSecureArgsList().getBindPasswordFileArg().
            getNameToValueMap();
        }
      }
@@ -3138,9 +3138,9 @@
    int portSource = argParser.getPortSource();
    Map<String, String> pwdFile = null;
    if (argParser.getSecureArgsList().bindPasswordFileArg.isPresent())
    if (argParser.getSecureArgsList().getBindPasswordFileArg().isPresent())
    {
      pwdFile = argParser.getSecureArgsList().bindPasswordFileArg.getNameToValueMap();
      pwdFile = argParser.getSecureArgsList().getBindPasswordFileArg().getNameToValueMap();
    }
    /*
@@ -3193,7 +3193,7 @@
      uData.setAdminPwd(adminPwd);
    }
    firstServerCommandBuilder = new CommandBuilder(null, null);
    firstServerCommandBuilder = new CommandBuilder();
    if (mustPrintCommandBuilder())
    {
      firstServerCommandBuilder.append(sourceServerCI.getCommandBuilder());
opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java
@@ -278,10 +278,10 @@
      {
        logger.error(LocalizableMessage.raw("Error parsing url: " + ldapUrl));
      }
      secureArgsList.hostNameArg.setPresent(true);
      secureArgsList.portArg.setPresent(true);
      secureArgsList.hostNameArg.addValue(secureArgsList.hostNameArg.getDefaultValue());
      secureArgsList.portArg.addValue(Integer.toString(port));
      secureArgsList.getHostNameArg().setPresent(true);
      secureArgsList.getPortArg().setPresent(true);
      secureArgsList.getHostNameArg().addValue(secureArgsList.getHostNameArg().getDefaultValue());
      secureArgsList.getPortArg().addValue(Integer.toString(port));
      // We already know if SSL or StartTLS can be used.  If we cannot
      // use them we will not propose them in the connection parameters
      // and if none of them can be used we will just not ask for the
opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCliArgumentParser.java
@@ -78,8 +78,8 @@
  throws ArgumentException
  {
    ArrayList<Argument> defaultArgs = new ArrayList<>(createGlobalArguments(outStream, alwaysSSL));
    defaultArgs.remove(secureArgsList.portArg);
    defaultArgs.remove(secureArgsList.hostNameArg);
    defaultArgs.remove(secureArgsList.getPortArg());
    defaultArgs.remove(secureArgsList.getHostNameArg());
    defaultArgs.remove(verboseArg);
    defaultArgs.remove(noPropertiesFileArg);
    defaultArgs.remove(propertiesFileArg);
@@ -174,9 +174,9 @@
   */
  public String getExplicitBindDn()
  {
    if (secureArgsList.bindDnArg.isPresent())
    if (secureArgsList.getBindDnArg().isPresent())
    {
      return secureArgsList.bindDnArg.getValue();
      return secureArgsList.getBindDnArg().getValue();
    }
    return null;
  }
@@ -187,6 +187,6 @@
   */
  public String getDefaultBindDn()
  {
    return secureArgsList.bindDnArg.getDefaultValue();
    return secureArgsList.getBindDnArg().getDefaultValue();
  }
}
opendj-server-legacy/src/main/java/org/opends/server/util/args/LDAPConnectionArgumentParser.java
@@ -12,7 +12,7 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2015 ForgeRock AS.
 * Portions Copyright 2011-2016 ForgeRock AS.
 */
package org.opends.server.util.args;
@@ -139,29 +139,11 @@
  private LDAPConnection connect(SecureConnectionCliArgs args, PrintStream out, PrintStream err)
      throws LDAPConnectionException, ArgumentException
  {
    // If both a bind password and bind password file were provided, then return
    // an error.
    if (args.bindPasswordArg.isPresent() && args.bindPasswordFileArg.isPresent())
    {
      printAndThrowException(err, ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
          args.bindPasswordArg.getLongIdentifier(), args.bindPasswordFileArg.getLongIdentifier()));
    }
    // If both a key store password and key store password file were provided,
    // then return an error.
    if (args.keyStorePasswordArg.isPresent() && args.keyStorePasswordFileArg.isPresent())
    {
      printAndThrowException(err, ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
          args.keyStorePasswordArg.getLongIdentifier(), args.keyStorePasswordFileArg.getLongIdentifier()));
    }
    // If both a trust store password and trust store password file were
    // provided, then return an error.
    if (args.trustStorePasswordArg.isPresent() && args.trustStorePasswordFileArg.isPresent())
    {
      printAndThrowException(err, ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
          args.trustStorePasswordArg.getLongIdentifier(), args.trustStorePasswordFileArg.getLongIdentifier()));
    }
    // Checks for conflicting arguments
    throwIfArgumentsConflict(err, args.getBindPasswordArg(), args.getBindPasswordArg());
    throwIfArgumentsConflict(err, args.getKeyStorePasswordArg(), args.getKeyStorePasswordFileArg());
    throwIfArgumentsConflict(err, args.getTrustStorePasswordArg(), args.getTrustStorePasswordFileArg());
    throwIfArgumentsConflict(err, args.getUseSSLArg(), args.getUseStartTLSArg());
    // Create the LDAP connection options object, which will be used to
    // customize the way that we connect to the server and specify a set of
@@ -171,30 +153,25 @@
    // See if we should use SSL or StartTLS when establishing the connection.
    // If so, then make sure only one of them was specified.
    if (args.useSSLArg.isPresent())
    if (args.getUseSSLArg().isPresent())
    {
      if (args.useStartTLSArg.isPresent())
      {
        printAndThrowException(err, ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
            args.useSSLArg.getLongIdentifier(), args.useSSLArg.getLongIdentifier()));
      }
      connectionOptions.setUseSSL(true);
    }
    else if (args.useStartTLSArg.isPresent())
    else if (args.getUseStartTLSArg().isPresent())
    {
      connectionOptions.setStartTLS(true);
    }
    // If we should blindly trust any certificate, then install the appropriate
    // SSL connection factory.
    if (args.useSSLArg.isPresent() || args.useStartTLSArg.isPresent())
    if (args.getUseSSLArg().isPresent() || args.getUseStartTLSArg().isPresent())
    {
      try
      {
        String clientAlias;
        if (args.certNicknameArg.isPresent())
        if (args.getCertNicknameArg().isPresent())
        {
          clientAlias = args.certNicknameArg.getValue();
          clientAlias = args.getCertNicknameArg().getValue();
        }
        else
        {
@@ -202,12 +179,12 @@
        }
        SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
        sslConnectionFactory.init(args.trustAllArg.isPresent(),
                                  args.keyStorePathArg.getValue(),
                                  args.keyStorePasswordArg.getValue(),
        sslConnectionFactory.init(args.getTrustAllArg().isPresent(),
                                  args.getKeyStorePathArg().getValue(),
                                  args.getKeyStorePasswordArg().getValue(),
                                  clientAlias,
                                  args.trustStorePathArg.getValue(),
                                  args.trustStorePasswordArg.getValue());
                                  args.getTrustStorePathArg().getValue(),
                                  args.getTrustStorePasswordArg().getValue());
        connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
      }
      catch (SSLConnectionException sce)
@@ -218,12 +195,12 @@
    // If one or more SASL options were provided, then make sure that one of
    // them was "mech" and specified a valid SASL mechanism.
    if (args.saslOptionArg.isPresent())
    if (args.getSaslOptionArg().isPresent())
    {
      String mechanism = null;
      LinkedList<String> options = new LinkedList<>();
      for (String s : args.saslOptionArg.getValues())
      for (String s : args.getSaslOptionArg().getValues())
      {
        int equalPos = s.indexOf('=');
        if (equalPos <= 0)
@@ -256,14 +233,14 @@
      }
    }
    int timeout = args.connectTimeoutArg.getIntValue();
    int timeout = args.getConnectTimeoutArg().getIntValue();
    final String passwordValue = getPasswordValue(
        args.bindPasswordArg, args.bindPasswordFileArg, args.bindDnArg, out, err);
            args.getBindPasswordArg(), args.getBindPasswordFileArg(), args.getBindDnArg(), out, err);
    return connect(
            args.hostNameArg.getValue(),
            args.portArg.getIntValue(),
            args.bindDnArg.getValue(),
            args.getHostNameArg().getValue(),
            args.getPortArg().getIntValue(),
            args.getBindDnArg().getValue(),
            passwordValue,
            connectionOptions, timeout, out, err);
  }
@@ -486,4 +463,13 @@
      ae.printStackTrace(); // Should never happen
    }
  }
  private void throwIfArgumentsConflict(final PrintStream err, final Argument arg1, final Argument arg2)
      throws ArgumentException
  {
    if (arg1.isPresent() && arg2.isPresent())
    {
      printAndThrowException(err, ERR_TOOL_CONFLICTING_ARGS.get(arg1.getLongIdentifier(), arg2.getLongIdentifier()));
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
@@ -16,25 +16,31 @@
 */
package org.opends.server.util.cli;
import static com.forgerock.opendj.cli.Utils.portValidationCallback;
import static com.forgerock.opendj.cli.Utils.isDN;
import static com.forgerock.opendj.cli.Utils.getAdministratorDN;
import static com.forgerock.opendj.cli.Utils.getThrowableMsg;
import static org.opends.messages.ToolMessages.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.net.ssl.KeyManager;
import com.forgerock.opendj.cli.Argument;
import com.forgerock.opendj.cli.FileBasedArgument;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.opends.admin.ads.util.ApplicationKeyManager;
@@ -65,6 +71,13 @@
public class LDAPConnectionConsoleInteraction
{
  private static final Protocol DEFAULT_PROMPT_PROTOCOL = Protocol.SSL;
  private static final TrustMethod DEFAULT_PROMPT_TRUST_METHOD = TrustMethod.DISPLAY_CERTIFICATE;
  private static final TrustOption DEFAULT_PROMPT_TRUST_OPTION = TrustOption.SESSION;
  private static final boolean ALLOW_EMPTY_PATH = true;
  private static final boolean FILE_MUST_EXISTS = true;
  /**
   * Information from the latest console interaction.
   * TODO: should it extend MonoServerReplicationUserData or a subclass?
@@ -97,71 +110,61 @@
    private String truststorePassword;
    private KeyManager keyManager;
    private String keystorePath;
    private String keyStorePath;
    private String keystorePassword;
    private String certifNickname;
    private State(SecureConnectionCliArgs secureArgs)
    {
      useSSL = secureArgs.useSSL();
      useStartTLS = secureArgs.useStartTLS();
      trustAll = secureArgs.trustAllArg.isPresent();
      setSsl(secureArgs);
      trustAll = secureArgs.getTrustAllArg().isPresent();
    }
    /**
     * @return
     */
    protected LocalizableMessage getPrompt()
    {
      LocalizableMessage prompt;
      if (providedAdminUID != null)
      {
        prompt = INFO_LDAPAUTH_PASSWORD_PROMPT.get(providedAdminUID);
        return INFO_LDAPAUTH_PASSWORD_PROMPT.get(providedAdminUID);
      }
      else if (providedBindDN != null)
      {
        prompt = INFO_LDAPAUTH_PASSWORD_PROMPT.get(providedBindDN);
        return INFO_LDAPAUTH_PASSWORD_PROMPT.get(providedBindDN);
      }
      else if (bindDN != null)
      {
        prompt = INFO_LDAPAUTH_PASSWORD_PROMPT.get(bindDN);
        return INFO_LDAPAUTH_PASSWORD_PROMPT.get(bindDN);
      }
      else
      {
        prompt = INFO_LDAPAUTH_PASSWORD_PROMPT.get(adminUID);
      }
      return prompt;
      return INFO_LDAPAUTH_PASSWORD_PROMPT.get(adminUID);
    }
    /**
     * @return
     */
    protected String getAdminOrBindDN()
    {
      String dn;
      if (providedBindDN != null)
      {
        dn = providedBindDN;
        return providedBindDN;
      }
      else if (providedAdminUID != null)
      {
        dn = getAdministratorDN(providedAdminUID);
        return getAdministratorDN(providedAdminUID);
      }
      else if (bindDN != null)
      {
        dn = bindDN;
        return bindDN;
      }
      else if (adminUID != null)
      {
        dn = getAdministratorDN(adminUID);
        return getAdministratorDN(adminUID);
      }
      else
      {
        dn = null;
      }
      return dn;
      return null;
    }
    private void setSsl(final SecureConnectionCliArgs secureArgs)
    {
      this.useSSL = secureArgs.alwaysSSL() || secureArgs.getUseSSLArg().isPresent();
      this.useStartTLS = secureArgs.getUseStartTLSArg().isPresent();
    }
  }
  /** The console application. */
@@ -170,7 +173,7 @@
  private State state;
  /** The SecureConnectionCliArgsList object. */
  private SecureConnectionCliArgs secureArgsList;
  private final SecureConnectionCliArgs secureArgsList;
  /** The command builder that we can return with the connection information. */
  private CommandBuilder commandBuilder;
@@ -192,147 +195,87 @@
  private boolean useAdminOrBindDn;
  /** Enumeration description protocols for interactive CLI choices. */
  private enum Protocols
  private enum Protocol
  {
    LDAP(1, INFO_LDAP_CONN_PROMPT_SECURITY_LDAP.get()),
    SSL(2,  INFO_LDAP_CONN_PROMPT_SECURITY_USE_SSL.get()),
    START_TLS(3, INFO_LDAP_CONN_PROMPT_SECURITY_USE_START_TLS.get());
    LDAP(INFO_LDAP_CONN_PROMPT_SECURITY_LDAP.get()),
    SSL(INFO_LDAP_CONN_PROMPT_SECURITY_USE_SSL.get()),
    START_TLS(INFO_LDAP_CONN_PROMPT_SECURITY_USE_START_TLS.get());
    private Integer choice;
    private final LocalizableMessage message;
    private LocalizableMessage msg;
    /**
     * Private constructor.
     *
     * @param i
     *          the menu return value.
     * @param msg
     *          the message message.
     */
    private Protocols(int i, LocalizableMessage msg)
    Protocol(final LocalizableMessage message)
    {
      choice = i;
      this.msg = msg;
      this.message = message;
    }
    /**
     * Returns the choice number.
     *
     * @return the attribute name.
     */
    public Integer getChoice()
    private int getChoice()
    {
      return choice;
    }
    /**
     * Return the menu message.
     *
     * @return the menu message.
     */
    public LocalizableMessage getMenuMessage()
    {
      return msg;
      return ordinal() + 1;
    }
  }
  /**
   * Enumeration description protocols for interactive CLI choices.
   */
  /** Enumeration description protocols for interactive CLI choices. */
  private enum TrustMethod
  {
    TRUSTALL(1, INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL.get()),
    TRUSTALL(INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL.get()),
    TRUSTSTORE(INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE.get()),
    DISPLAY_CERTIFICATE(INFO_LDAP_CONN_PROMPT_SECURITY_MANUAL_CHECK.get());
    TRUSTSTORE(2, INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE.get()),
    private LocalizableMessage message;
    DISPLAY_CERTIFICATE(3, INFO_LDAP_CONN_PROMPT_SECURITY_MANUAL_CHECK.get());
    private Integer choice;
    private LocalizableMessage msg;
    /**
     * Private constructor.
     *
     * @param i
     *          the menu return value.
     * @param msg
     *          the message message.
     */
    private TrustMethod(int i, LocalizableMessage msg)
    TrustMethod(final LocalizableMessage message)
    {
      choice = Integer.valueOf(i);
      this.msg = msg;
      this.message = message;
    }
    /**
     * Returns the choice number.
     *
     * @return the attribute name.
     */
    public Integer getChoice()
    private int getChoice()
    {
      return choice;
      return ordinal() + 1;
    }
    /**
     * Return the menu message.
     *
     * @return the menu message.
     */
    public LocalizableMessage getMenuMessage()
    private static TrustMethod getTrustMethodForIndex(final int value)
    {
      return msg;
      for (final TrustMethod trustMethod : TrustMethod.values())
      {
        if (trustMethod.getChoice() == value)
        {
          return trustMethod;
        }
      }
      return null;
    }
  }
  /**
   * Enumeration description server certificate trust option.
   */
  /** Enumeration description server certificate trust option. */
  private enum TrustOption
  {
    UNTRUSTED(1, INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO.get()),
    SESSION(2, INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION.get()),
    PERMAMENT(3, INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS.get()),
    CERTIFICATE_DETAILS(4, INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS.get());
    UNTRUSTED(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO.get()),
    SESSION(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION.get()),
    PERMAMENT(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS.get()),
    CERTIFICATE_DETAILS(INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS.get());
    private Integer choice;
    private LocalizableMessage message;
    private LocalizableMessage msg;
    /**
     * Private constructor.
     *
     * @param i
     *          the menu return value.
     * @param msg
     *          the message message.
     */
    private TrustOption(int i, LocalizableMessage msg)
    TrustOption(final LocalizableMessage message)
    {
      choice = Integer.valueOf(i);
      this.msg = msg;
      this.message = message;
    }
    /**
     * Returns the choice number.
     *
     * @return the attribute name.
     */
    public Integer getChoice()
    private int getChoice()
    {
      return choice;
      return ordinal() + 1;
    }
    /**
     * Return the menu message.
     *
     * @return the menu message.
     */
    public LocalizableMessage getMenuMessage()
    private static TrustOption getTrustOptionForIndex(final int value)
    {
      return msg;
      for (final TrustOption trustOption : TrustOption.values())
      {
        if (trustOption.getChoice() == value)
        {
          return trustOption;
        }
      }
      return null;
    }
  }
@@ -349,7 +292,7 @@
  {
    this.app = app;
    this.secureArgsList = secureArgs;
    this.commandBuilder = new CommandBuilder(null, null);
    this.commandBuilder = new CommandBuilder();
    state = new State(secureArgs);
    copySecureArgsList = new SecureConnectionCliArgs(secureArgs.alwaysSSL());
    try
@@ -387,447 +330,328 @@
   */
  public void run(boolean canUseStartTLS) throws ArgumentException
  {
    // Reset everything
    resetBeforeRun();
    resolveHostName();
    resolveConnectionType(canUseStartTLS);
    resolvePortNumber();
    resolveTrustAndKeyManagers();
    resolveCredentialLogin();
    resolveCredentialPassword();
    resolveConnectTimeout();
  }
  private void resetBeforeRun() throws ArgumentException
  {
    commandBuilder.clearArguments();
    copySecureArgsList.createGlobalArguments();
    state.providedAdminUID = null;
    state.providedBindDN = null;
  }
    boolean secureConnection = true;
  private void resolveHostName() throws ArgumentException
  {
    state.hostName = secureArgsList.getHostNameArg().getValue();
    promptForHostNameIfRequired();
    addArgToCommandBuilder(copySecureArgsList.getHostNameArg(), state.hostName);
  }
    // Get the LDAP host.
    state.hostName = secureArgsList.hostNameArg.getValue();
    final String tmpHostName = state.hostName;
    if (app.isInteractive() && !secureArgsList.hostNameArg.isPresent())
    {
      checkHeadingDisplayed();
  private void resolveConnectionType(boolean canUseStartTLS)
  {
    state.setSsl(secureArgsList);
    promptForConnectionTypeIfRequired(canUseStartTLS);
    addConnectionTypeToCommandBuilder();
  }
      ValidationCallback<String> callback = new ValidationCallback<String>()
      {
  private void resolvePortNumber() throws ArgumentException
  {
    portNumber = (state.useSSL && !secureArgsList.getPortArg().isPresent())
        ? secureArgsList.getPortFromConfig()
        : secureArgsList.getPortArg().getIntValue();
    promptForPortNumberIfRequired();
    addArgToCommandBuilder(copySecureArgsList.getPortArg(), String.valueOf(portNumber));
  }
        @Override
        public String validate(ConsoleApplication app, String input)
            throws ClientException
        {
          String ninput = input.trim();
          if (ninput.length() == 0)
          {
            return tmpHostName;
          }
          else
          {
            try
            {
              InetAddress.getByName(ninput);
              return ninput;
            }
            catch (UnknownHostException e)
            {
              // Try again...
              app.println();
              app.println(ERR_LDAP_CONN_BAD_HOST_NAME.get(ninput));
              app.println();
              return null;
            }
          }
        }
      };
      try
      {
        app.println();
        state.hostName = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_HOST_NAME.get(state.hostName), callback);
      }
      catch (ClientException e)
      {
        throw cannotReadConnectionParameters(e);
      }
    }
    copySecureArgsList.hostNameArg.clearValues();
    copySecureArgsList.hostNameArg.addValue(state.hostName);
    commandBuilder.addArgument(copySecureArgsList.hostNameArg);
    // Connection type
    state.useSSL = secureArgsList.useSSL();
    state.useStartTLS = secureArgsList.useStartTLS();
    boolean connectionTypeIsSet =
        secureArgsList.alwaysSSL()
            || secureArgsList.useSSLArg.isPresent()
            || secureArgsList.useStartTLSArg.isPresent()
            || (secureArgsList.useSSLArg.isValueSetByProperty() && secureArgsList.useStartTLSArg
                .isValueSetByProperty());
    if (app.isInteractive() && !connectionTypeIsSet)
    {
      checkHeadingDisplayed();
      MenuBuilder<Integer> builder = new MenuBuilder<>(app);
      builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_USE_SECURE_CTX.get());
      Protocols defaultProtocol;
      if (secureConnection)
      {
        defaultProtocol = Protocols.SSL;
      }
      else
      {
        defaultProtocol = Protocols.LDAP;
      }
      for (Protocols p : Protocols.values())
      {
        if (secureConnection && p.equals(Protocols.LDAP) && !displayLdapIfSecureParameters)
        {
          continue;
        }
        if (!canUseStartTLS && p.equals(Protocols.START_TLS))
        {
          continue;
        }
        int i =
            builder.addNumberedOption(p.getMenuMessage(), MenuResult.success(p
                .getChoice()));
        if (p.equals(defaultProtocol))
        {
          builder.setDefault(
              INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE.get(i),
              MenuResult.success(p.getChoice()));
        }
      }
      Menu<Integer> menu = builder.toMenu();
      try
      {
        MenuResult<Integer> result = menu.run();
        if (result.isSuccess())
        {
          if (result.getValue().equals(Protocols.SSL.getChoice()))
          {
            state.useSSL = true;
          }
          else if (result.getValue().equals(Protocols.START_TLS.getChoice()))
          {
            state.useStartTLS = true;
          }
        }
        else
        {
          // Should never happen.
          throw new RuntimeException();
        }
      }
      catch (ClientException e)
      {
        throw new RuntimeException(e);
      }
    }
    if (state.useSSL)
    {
      commandBuilder.addArgument(copySecureArgsList.useSSLArg);
    }
    else if (state.useStartTLS)
    {
      commandBuilder.addArgument(copySecureArgsList.useStartTLSArg);
    }
    // Get the LDAP port.
    if (!state.useSSL)
    {
      portNumber = secureArgsList.portArg.getIntValue();
    }
    else
    {
      if (secureArgsList.portArg.isPresent())
      {
        portNumber = secureArgsList.portArg.getIntValue();
      }
      else
      {
        portNumber = secureArgsList.getPortFromConfig();
      }
    }
    final int tmpPortNumber = portNumber;
    if (app.isInteractive() && !secureArgsList.portArg.isPresent())
    {
      checkHeadingDisplayed();
      ValidationCallback<Integer> callback = new ValidationCallback<Integer>()
      {
        @Override
        public Integer validate(ConsoleApplication app, String input)
            throws ClientException
        {
          String ninput = input.trim();
          if (ninput.length() == 0)
          {
            return tmpPortNumber;
          }
          else
          {
            try
            {
              int i = Integer.parseInt(ninput);
              if (i < 1 || i > 65535)
              {
                throw new NumberFormatException();
              }
              return i;
            }
            catch (NumberFormatException e)
            {
              // Try again...
              app.println();
              app.println(ERR_LDAP_CONN_BAD_PORT_NUMBER.get(ninput));
              app.println();
              return null;
            }
          }
        }
      };
      try
      {
        app.println();
        LocalizableMessage askPortNumber = null;
        if (secureArgsList.alwaysSSL())
        {
          askPortNumber = INFO_ADMIN_CONN_PROMPT_PORT_NUMBER.get(portNumber);
        }
        else
        {
          askPortNumber = INFO_LDAP_CONN_PROMPT_PORT_NUMBER.get(portNumber);
        }
        portNumber = app.readValidatedInput(askPortNumber, callback);
      }
      catch (ClientException e)
      {
        throw cannotReadConnectionParameters(e);
      }
    }
    copySecureArgsList.portArg.clearValues();
    copySecureArgsList.portArg.addValue(String.valueOf(portNumber));
    commandBuilder.addArgument(copySecureArgsList.portArg);
    // Handle certificate
  private void resolveTrustAndKeyManagers() throws ArgumentException {
    if ((state.useSSL || state.useStartTLS) && state.trustManager == null)
    {
      initializeTrustManager();
      initializeTrustAndKeyManagers();
    }
  }
  private void resolveCredentialLogin() throws ArgumentException
  {
    setAdminUidAndBindDnFromArgs();
    if (useKeyManager())
    {
      return;
    }
    promptForCredentialLoginIfRequired(secureArgsList.getBindDnArg().getValue(),
                                       secureArgsList.getAdminUidArg().getValue());
    final boolean onlyBindDnProvided = state.providedAdminUID != null || state.providedBindDN == null;
    if ((useAdminOrBindDn && onlyBindDnProvided)
     || (!useAdminOrBindDn && isAdminUidArgVisible()))
    {
      addArgToCommandBuilder(copySecureArgsList.getAdminUidArg(), getAdministratorUID());
    }
    else
    {
      addArgToCommandBuilder(copySecureArgsList.getBindDnArg(), getBindDN());
    }
  }
  private void setAdminUidAndBindDnFromArgs()
  {
    final Argument adminUid = secureArgsList.getAdminUidArg();
    final Argument bindDn = secureArgsList.getBindDnArg();
    state.providedAdminUID = (isAdminUidArgVisible() && adminUid.isPresent()) ? adminUid.getValue() : null;
    state.providedBindDN = ((useAdminOrBindDn || !isAdminUidArgVisible()) && bindDn.isPresent()) ? bindDn.getValue()
                                                                                                 : null;
    state.adminUID = !useKeyManager() ? adminUid.getValue() : null;
    state.bindDN = !useKeyManager() ? bindDn.getValue() : null;
  }
  private void resolveCredentialPassword() throws ArgumentException
  {
    if (secureArgsList.getBindPasswordArg().isPresent())
    {
      state.bindPassword = secureArgsList.getBindPasswordArg().getValue();
    }
    // Get the LDAP bind credentials.
    state.bindDN = secureArgsList.bindDnArg.getValue();
    state.adminUID= secureArgsList.adminUidArg.getValue();
    final boolean useAdmin = secureArgsList.useAdminUID();
    if (useAdmin && secureArgsList.adminUidArg.isPresent())
    if (useKeyManager())
    {
      state.providedAdminUID = state.adminUID;
      return;
    }
    else
    setBindPasswordFileFromArgs();
    final boolean addedPasswordFileArgument = secureArgsList.getBindPasswordFileArg().isPresent();
    if (!addedPasswordFileArgument && (state.bindPassword == null || "-".equals(state.bindPassword)))
    {
      state.providedAdminUID = null;
      promptForBindPasswordIfRequired();
    }
    if ((!useAdmin || useAdminOrBindDn) && secureArgsList.bindDnArg.isPresent())
    final Argument bindPassword = copySecureArgsList.getBindPasswordArg();
    bindPassword.clearValues();
    bindPassword.addValue(state.bindPassword);
    if (!addedPasswordFileArgument)
    {
      state.providedBindDN = state.bindDN;
      commandBuilder.addObfuscatedArgument(bindPassword);
    }
    else
  }
  private void setBindPasswordFileFromArgs() throws ArgumentException
  {
    final FileBasedArgument bindPasswordFile = secureArgsList.getBindPasswordFileArg();
    if (bindPasswordFile.isPresent())
    {
      state.providedBindDN = null;
    }
    boolean argIsPresent = state.providedAdminUID != null || state.providedBindDN != null;
    final String tmpBindDN = state.bindDN;
    final String tmpAdminUID = state.adminUID;
    if (state.keyManager == null)
    {
      if (app.isInteractive() && !argIsPresent)
      // Read from file if it exists.
      state.bindPassword = bindPasswordFile.getValue();
      if (state.bindPassword == null)
      {
        checkHeadingDisplayed();
        throw new ArgumentException(
            ERR_ERROR_NO_ADMIN_PASSWORD.get(isAdminUidArgVisible() ? state.adminUID : state.bindDN));
      }
      addArgToCommandBuilder(copySecureArgsList.getBindPasswordFileArg(), bindPasswordFile.getNameToValueMap());
    }
  }
        ValidationCallback<String> callback = new ValidationCallback<String>()
  private void resolveConnectTimeout() throws ArgumentException
  {
    state.connectTimeout = secureArgsList.getConnectTimeoutArg().getIntValue();
  }
  private void promptForHostNameIfRequired() throws ArgumentException
  {
    if (!app.isInteractive() || secureArgsList.getHostNameArg().isPresent())
    {
      return;
    }
    checkHeadingDisplayed();
    ValidationCallback<String> callback = new ValidationCallback<String>()
    {
      @Override
      public String validate(ConsoleApplication app, String rawInput) throws ClientException
      {
        final String input = rawInput.trim();
        if (input.length() == 0)
        {
          @Override
          public String validate(ConsoleApplication app, String input)
              throws ClientException
          {
            String ninput = input.trim();
            if (ninput.length() == 0)
            {
              if (useAdmin)
              {
                return tmpAdminUID;
              }
              else
              {
                return tmpBindDN;
              }
            }
            else
            {
              return ninput;
            }
          }
        };
          return state.hostName;
        }
        try
        {
          app.println();
          if (useAdminOrBindDn)
          {
            String def = state.adminUID != null ? state.adminUID : state.bindDN;
            String v =
                app.readValidatedInput(
                    INFO_LDAP_CONN_GLOBAL_ADMINISTRATOR_OR_BINDDN_PROMPT.get(def), callback);
            if (isDN(v))
            {
              state.bindDN = v;
              state.providedBindDN = v;
              state.adminUID = null;
              state.providedAdminUID = null;
            }
            else
            {
              state.bindDN = null;
              state.providedBindDN = null;
              state.adminUID = v;
              state.providedAdminUID = v;
            }
          }
          else if (useAdmin)
          {
            state.adminUID =
                app.readValidatedInput(INFO_LDAP_CONN_PROMPT_ADMINISTRATOR_UID.get(state.adminUID), callback);
            state.providedAdminUID = state.adminUID;
          }
          else
          {
            state.bindDN =
                app.readValidatedInput(INFO_LDAP_CONN_PROMPT_BIND_DN.get(state.bindDN), callback);
            state.providedBindDN = state.bindDN;
          }
          // Ensure that the prompted host is known
          InetAddress.getByName(input);
          return input;
        }
        catch (ClientException e)
        catch (UnknownHostException e)
        {
          throw cannotReadConnectionParameters(e);
          // Try again...
          app.println();
          app.println(ERR_LDAP_CONN_BAD_HOST_NAME.get(input));
          app.println();
          return null;
        }
      }
    };
    try
    {
      app.println();
      state.hostName = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_HOST_NAME.get(state.hostName), callback);
    }
    catch (ClientException e)
    {
      throw cannotReadConnectionParameters(e);
    }
  }
  private void promptForConnectionTypeIfRequired(final boolean canUseStartTLS)
  {
    final boolean valuesSetByProperty = secureArgsList.getUseSSLArg().isValueSetByProperty()
                                     && secureArgsList.getUseStartTLSArg().isValueSetByProperty();
    if (!app.isInteractive() || state.useSSL || state.useStartTLS || valuesSetByProperty)
    {
      return;
    }
    checkHeadingDisplayed();
    final MenuBuilder<Integer> builder = new MenuBuilder<>(app);
    builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_USE_SECURE_CTX.get());
    for (Protocol p : Protocol.values())
    {
      if ((!displayLdapIfSecureParameters && Protocol.LDAP.equals(p))
          || (!canUseStartTLS && Protocol.START_TLS.equals(p)))
      {
        continue;
      }
      final MenuResult<Integer> menuResult = MenuResult.success(p.getChoice());
      final int i = builder.addNumberedOption(p.message, menuResult);
      if (DEFAULT_PROMPT_PROTOCOL.equals(p))
      {
        builder.setDefault(INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE.get(i), menuResult);
      }
    }
    Menu<Integer> menu = builder.toMenu();
    try
    {
      final MenuResult<Integer> result = menu.run();
      throwIfMenuResultNotSucceeded(result);
      final int userChoice = result.getValue();
      if (Protocol.SSL.getChoice() == userChoice)
      {
        state.useSSL = true;
      }
      else if (Protocol.START_TLS.getChoice() == userChoice)
      {
        state.useStartTLS = true;
      }
    }
    catch (ClientException e)
    {
      throw new RuntimeException(e);
    }
  }
  private void promptForPortNumberIfRequired() throws ArgumentException
  {
    if (!app.isInteractive() || secureArgsList.getPortArg().isPresent())
    {
      return;
    }
    checkHeadingDisplayed();
    try
    {
      app.println();
      final LocalizableMessage askPortNumberMsg = secureArgsList.alwaysSSL() ?
          INFO_ADMIN_CONN_PROMPT_PORT_NUMBER.get(portNumber) :
          INFO_LDAP_CONN_PROMPT_PORT_NUMBER.get(portNumber);
      portNumber = app.readValidatedInput(askPortNumberMsg, portValidationCallback(portNumber));
    }
    catch (ClientException e)
    {
      throw cannotReadConnectionParameters(e);
    }
  }
  private void promptForCredentialLoginIfRequired(final String defaultBindDN, final String defaultAdminUID)
      throws ArgumentException
  {
    if (!app.isInteractive() || state.providedAdminUID != null || state.providedBindDN != null)
    {
      return;
    }
    checkHeadingDisplayed();
    ValidationCallback<String> callback = new ValidationCallback<String>()
    {
      @Override public String validate(ConsoleApplication app, String rawInput) throws ClientException
      {
        final String input = rawInput.trim();
        if (input.isEmpty())
        {
          return isAdminUidArgVisible() ? defaultAdminUID : defaultBindDN;
        }
        return input;
      }
    };
    try
    {
      app.println();
      if (useAdminOrBindDn)
      {
        boolean addAdmin = state.providedAdminUID != null;
        boolean addBindDN = state.providedBindDN != null;
        if (!addAdmin && !addBindDN)
        String def = state.adminUID != null ? state.adminUID : state.bindDN;
        String v = app.readValidatedInput(INFO_LDAP_CONN_GLOBAL_ADMINISTRATOR_OR_BINDDN_PROMPT.get(def), callback);
        if (isDN(v))
        {
          addAdmin = getAdministratorUID() != null;
          addBindDN = getBindDN() != null;
          state.bindDN = v;
          state.providedBindDN = v;
          state.adminUID = null;
          state.providedAdminUID = null;
        }
        if (addAdmin)
        else
        {
          copySecureArgsList.adminUidArg.clearValues();
          copySecureArgsList.adminUidArg.addValue(getAdministratorUID());
          commandBuilder.addArgument(copySecureArgsList.adminUidArg);
        }
        else if (addBindDN)
        {
          copySecureArgsList.bindDnArg.clearValues();
          copySecureArgsList.bindDnArg.addValue(getBindDN());
          commandBuilder.addArgument(copySecureArgsList.bindDnArg);
          state.bindDN = null;
          state.providedBindDN = null;
          state.adminUID = v;
          state.providedAdminUID = v;
        }
      }
      else if (useAdmin)
      else if (isAdminUidArgVisible())
      {
        copySecureArgsList.adminUidArg.clearValues();
        copySecureArgsList.adminUidArg.addValue(getAdministratorUID());
        commandBuilder.addArgument(copySecureArgsList.adminUidArg);
        state.adminUID = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_ADMINISTRATOR_UID.get(state.adminUID), callback);
        state.providedAdminUID = state.adminUID;
      }
      else
      {
        copySecureArgsList.bindDnArg.clearValues();
        copySecureArgsList.bindDnArg.addValue(getBindDN());
        commandBuilder.addArgument(copySecureArgsList.bindDnArg);
        state.bindDN = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_BIND_DN.get(state.bindDN), callback);
        state.providedBindDN = state.bindDN;
      }
    }
    else
    catch (ClientException e)
    {
      state.bindDN = null;
      state.adminUID = null;
      throw cannotReadConnectionParameters(e);
    }
    boolean addedPasswordFileArgument = false;
    if (secureArgsList.bindPasswordArg.isPresent())
    {
      state.bindPassword = secureArgsList.bindPasswordArg.getValue();
    }
    if (state.keyManager == null)
    {
      if (secureArgsList.bindPasswordFileArg.isPresent())
      {
        // Read from file if it exists.
        state.bindPassword = secureArgsList.bindPasswordFileArg.getValue();
        if (state.bindPassword == null)
        {
          if (useAdmin)
          {
            throw new ArgumentException(ERR_ERROR_NO_ADMIN_PASSWORD.get(state.adminUID));
          }
          else
          {
            throw new ArgumentException(ERR_ERROR_NO_ADMIN_PASSWORD.get(state.bindDN));
          }
        }
        copySecureArgsList.bindPasswordFileArg.clearValues();
        copySecureArgsList.bindPasswordFileArg.getNameToValueMap().putAll(
            secureArgsList.bindPasswordFileArg.getNameToValueMap());
        commandBuilder.addArgument(copySecureArgsList.bindPasswordFileArg);
        addedPasswordFileArgument = true;
      }
      else if (state.bindPassword == null || "-".equals(state.bindPassword))
      {
        // Read the password from the stdin.
        if (!app.isInteractive())
        {
          throw new ArgumentException(ERR_ERROR_BIND_PASSWORD_NONINTERACTIVE.get());
        }
        checkHeadingDisplayed();
        try
        {
          app.println();
          state.bindPassword = readPassword(state.getPrompt());
        }
        catch (Exception e)
        {
          throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
        }
      }
      copySecureArgsList.bindPasswordArg.clearValues();
      copySecureArgsList.bindPasswordArg.addValue(state.bindPassword);
      if (!addedPasswordFileArgument)
      {
        commandBuilder.addObfuscatedArgument(copySecureArgsList.bindPasswordArg);
      }
    }
    state.connectTimeout = secureArgsList.connectTimeoutArg.getIntValue();
  }
  private ArgumentException cannotReadConnectionParameters(ClientException e)
  private void promptForBindPasswordIfRequired() throws ArgumentException
  {
    return new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
  }
  private String readPassword(LocalizableMessage prompt) throws ClientException
  {
    final char[] pwd = app.readPassword(prompt);
    if (pwd != null)
    if (!app.isInteractive())
    {
      return String.valueOf(pwd);
      throw new ArgumentException(ERR_ERROR_BIND_PASSWORD_NONINTERACTIVE.get());
    }
    return null;
    checkHeadingDisplayed();
    try
    {
      state.bindPassword = readPassword(state.getPrompt());
    }
    catch (Exception e)
    {
      throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
    }
  }
  /**
@@ -837,205 +661,90 @@
   * @throws ArgumentException
   *           If an error occurs when getting args values.
   */
  private ApplicationTrustManager getTrustManagerInternal()
      throws ArgumentException
  private ApplicationTrustManager getTrustManagerInternal() throws ArgumentException
  {
    // Remove these arguments since this method might be called several times.
    commandBuilder.removeArgument(copySecureArgsList.trustAllArg);
    commandBuilder.removeArgument(copySecureArgsList.trustStorePathArg);
    commandBuilder.removeArgument(copySecureArgsList.trustStorePasswordArg);
    commandBuilder.removeArgument(copySecureArgsList.trustStorePasswordFileArg);
    commandBuilder.removeArguments(copySecureArgsList.getTrustAllArg(),
                                   copySecureArgsList.getTrustStorePathArg(),
                                   copySecureArgsList.getTrustStorePasswordArg(),
                                   copySecureArgsList.getTrustStorePasswordFileArg());
    // If we have the trustALL flag, don't do anything
    // just return null
    if (secureArgsList.trustAllArg.isPresent())
    final TrustMethod trustMethod = resolveTrustMethod();
    if (TrustMethod.TRUSTALL == trustMethod)
    {
      commandBuilder.addArgument(copySecureArgsList.trustAllArg);
      return null;
    }
    // Check if some trust manager info are set
    boolean weDontKnowTheTrustMethod =
        !secureArgsList.trustAllArg.isPresent()
        && !secureArgsList.trustStorePathArg.isPresent()
        && !secureArgsList.trustStorePasswordArg.isPresent()
        && !secureArgsList.trustStorePasswordFileArg.isPresent();
    boolean askForTrustStore = false;
    state.trustAll = secureArgsList.trustAllArg.isPresent();
    // Try to use the local instance trust store, to avoid certificate
    // validation when both the CLI and the server are in the same instance.
    if (weDontKnowTheTrustMethod && addLocalTrustStore())
    {
      weDontKnowTheTrustMethod = false;
    }
    if (app.isInteractive() && weDontKnowTheTrustMethod)
    {
      checkHeadingDisplayed();
      app.println();
      MenuBuilder<Integer> builder = new MenuBuilder<>(app);
      builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_METHOD.get());
      TrustMethod defaultTrustMethod = TrustMethod.DISPLAY_CERTIFICATE;
      for (TrustMethod t : TrustMethod.values())
      {
        int i =
            builder.addNumberedOption(t.getMenuMessage(), MenuResult.success(t
                .getChoice()));
        if (t.equals(defaultTrustMethod))
        {
          builder.setDefault(
              INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE
                  .get(Integer.valueOf(i)), MenuResult.success(t.getChoice()));
        }
      }
      Menu<Integer> menu = builder.toMenu();
      state.trustStoreInMemory = false;
      try
      {
        MenuResult<Integer> result = menu.run();
        if (result.isSuccess())
        {
          if (result.getValue().equals(TrustMethod.TRUSTALL.getChoice()))
          {
            commandBuilder.addArgument(copySecureArgsList.trustAllArg);
            state.trustAll = true;
            // If we have the trustALL flag, don't do anything
            // just return null
            return null;
          }
          else if (result.getValue().equals(TrustMethod.TRUSTSTORE.getChoice()))
          {
            // We have to ask for trust store info
            askForTrustStore = true;
          }
          else if (result.getValue().equals(
              TrustMethod.DISPLAY_CERTIFICATE.getChoice()))
          {
            // The certificate will be displayed to the user
            askForTrustStore = false;
            state.trustStoreInMemory = true;
            // There is no direct equivalent for this option, so propose the
            // trust all option as command-line argument.
            commandBuilder.addArgument(copySecureArgsList.trustAllArg);
          }
          else
          {
            // Should never happen.
            throw new RuntimeException();
          }
        }
        else
        {
          // Should never happen.
          throw new RuntimeException();
        }
      }
      catch (ClientException e)
      {
        throw new RuntimeException(e);
      }
    }
    // If we do not trust all server certificates, we have to get info
    // about trust store. First get the trust store path.
    state.truststorePath = secureArgsList.trustStorePathArg.getValue();
    if (app.isInteractive() && !secureArgsList.trustStorePathArg.isPresent() && askForTrustStore)
    {
      checkHeadingDisplayed();
      ValidationCallback<String> callback = new ValidationCallback<String>()
      {
        @Override
        public String validate(ConsoleApplication app, String input)
            throws ClientException
        {
          String ninput = input.trim();
          if (ninput.length() == 0)
          {
            app.println();
            app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH.get());
            app.println();
            return null;
          }
          File f = new File(ninput);
          if (f.exists() && f.canRead() && !f.isDirectory())
          {
            return ninput;
          }
          else
          {
            app.println();
            app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH.get());
            app.println();
            return null;
          }
        }
      };
      try
      {
        app.println();
        state.truststorePath = app.readValidatedInput(
                INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH.get(), callback);
      }
      catch (ClientException e)
      {
        throw cannotReadConnectionParameters(e);
      }
    }
    if (state.truststorePath != null)
    {
      copySecureArgsList.trustStorePathArg.clearValues();
      copySecureArgsList.trustStorePathArg.addValue(state.truststorePath);
      commandBuilder.addArgument(copySecureArgsList.trustStorePathArg);
    }
    // Then the truststore password.
    //  As the most common case is to have no password for truststore,
    // we don't ask it in the interactive mode.
    if (secureArgsList.trustStorePasswordArg.isPresent())
    {
      state.truststorePassword = secureArgsList.trustStorePasswordArg.getValue();
    }
    if (secureArgsList.trustStorePasswordFileArg.isPresent())
    {
      // Read from file if it exists.
      state.truststorePassword = secureArgsList.trustStorePasswordFileArg.getValue();
    }
    final boolean promptForTrustStore = TrustMethod.TRUSTSTORE == trustMethod;
    resolveTrustStorePath(promptForTrustStore);
    setTrustStorePassword();
    setTrustStorePasswordFromFile();
    if ("-".equals(state.truststorePassword))
    {
      // Read the password from the stdin.
      if (!app.isInteractive())
      {
        state.truststorePassword = null;
      }
      else
      {
        checkHeadingDisplayed();
        try
        {
          app.println();
          LocalizableMessage prompt = INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PASSWORD.get(state.truststorePath);
          state.truststorePassword = readPassword(prompt);
        }
        catch (Exception e)
        {
          throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
        }
      }
      promptForTrustStorePasswordIfRequired();
    }
    // We've got all the information to get the truststore manager
    return resolveTrustStore();
  }
  /** As the most common case is to have no password for trust store, we do not ask it in the interactive mode.*/
  private void setTrustStorePassword()
  {
    if (secureArgsList.getTrustStorePasswordArg().isPresent())
    {
      state.truststorePassword = secureArgsList.getTrustStorePasswordArg().getValue();
    }
  }
  private void setTrustStorePasswordFromFile()
  {
    if (secureArgsList.getTrustStorePasswordFileArg().isPresent())
    {
      state.truststorePassword = secureArgsList.getTrustStorePasswordFileArg().getValue();
    }
  }
  /** Return the trust method chosen by user or {@code null} if the information is not available. */
  private TrustMethod resolveTrustMethod()
  {
    state.trustAll = secureArgsList.getTrustAllArg().isPresent();
    // Check if some trust manager info are set
    boolean needPromptForTrustMethod = !state.trustAll
        && !secureArgsList.getTrustStorePathArg().isPresent()
        && !secureArgsList.getTrustStorePasswordArg().isPresent()
        && !secureArgsList.getTrustStorePasswordFileArg().isPresent();
    TrustMethod trustMethod = state.trustAll ? TrustMethod.TRUSTALL : null;
    // Try to use the local instance trust store, to avoid certificate
    // validation when both the CLI and the server are in the same instance.
    if (needPromptForTrustMethod && !useLocalTrustStoreIfPossible())
    {
      trustMethod = promptForTrustMethodIfRequired();
    }
    if (trustMethod != TrustMethod.TRUSTSTORE)
    {
      // There is no direct equivalent for the display certificate option,
      // so propose trust all option as command-line argument.
      commandBuilder.addArgument(copySecureArgsList.getTrustAllArg());
    }
    return trustMethod;
  }
  private void resolveTrustStorePath(final boolean promptForTrustStore) throws ArgumentException
  {
    state.truststorePath = secureArgsList.getTrustStorePathArg().getValue();
    if (promptForTrustStore)
    {
      promptForTrustStorePathIfRequired();
    }
    addArgToCommandBuilder(copySecureArgsList.getTrustStorePathArg(), state.truststorePath);
  }
  private ApplicationTrustManager resolveTrustStore() throws ArgumentException
  {
    try
    {
      state.truststore = KeyStore.getInstance(KeyStore.getDefaultType());
@@ -1043,14 +752,7 @@
      {
        try (FileInputStream fos = new FileInputStream(state.truststorePath))
        {
          if (state.truststorePassword != null)
          {
            state.truststore.load(fos, state.truststorePassword.toCharArray());
          }
          else
          {
            state.truststore.load(fos, null);
          }
          state.truststore.load(fos, state.truststorePassword != null ? state.truststorePassword.toCharArray() : null);
        }
      }
      else
@@ -1058,20 +760,14 @@
        state.truststore.load(null, null);
      }
      if (secureArgsList.trustStorePasswordFileArg.isPresent() && state.truststorePath != null)
      if (secureArgsList.getTrustStorePasswordFileArg().isPresent() && state.truststorePath != null)
      {
        copySecureArgsList.trustStorePasswordFileArg.clearValues();
        copySecureArgsList.trustStorePasswordFileArg.getNameToValueMap()
            .putAll(secureArgsList.trustStorePasswordFileArg.getNameToValueMap());
        commandBuilder.addArgument(copySecureArgsList.trustStorePasswordFileArg);
        addArgToCommandBuilder(copySecureArgsList.getTrustStorePasswordFileArg(),
            secureArgsList.getTrustStorePasswordFileArg().getNameToValueMap());
      }
      else if (state.truststorePassword != null && state.truststorePath != null)
      {
        // Only add the trust store password if there is one AND if the user
        // specified a trust store path.
        copySecureArgsList.trustStorePasswordArg.clearValues();
        copySecureArgsList.trustStorePasswordArg.addValue(state.truststorePassword);
        commandBuilder.addObfuscatedArgument(copySecureArgsList.trustStorePasswordArg);
        addObfuscatedArgToCommandBuilder(copySecureArgsList.getTrustStorePasswordArg(), state.truststorePassword);
      }
      return new ApplicationTrustManager(state.truststore);
@@ -1082,6 +778,91 @@
    }
  }
  private TrustMethod promptForTrustMethodIfRequired()
  {
    if (!app.isInteractive())
    {
      return null;
    }
    checkHeadingDisplayed();
    app.println();
    MenuBuilder<Integer> builder = new MenuBuilder<>(app);
    builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_METHOD.get());
    for (TrustMethod t : TrustMethod.values())
    {
      int i = builder.addNumberedOption(t.message, MenuResult.success(t.getChoice()));
      if (DEFAULT_PROMPT_TRUST_METHOD.equals(t))
      {
        builder.setDefault(
            INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE.get(i), MenuResult.success(t.getChoice()));
      }
    }
    Menu<Integer> menu = builder.toMenu();
    state.trustStoreInMemory = false;
    try
    {
      final MenuResult<Integer> result = menu.run();
      throwIfMenuResultNotSucceeded(result);
      final int userChoice = result.getValue();
      if (TrustMethod.TRUSTALL.getChoice() == userChoice)
      {
        state.trustAll = true;
      }
      else if (TrustMethod.DISPLAY_CERTIFICATE.getChoice() == userChoice)
      {
        state.trustStoreInMemory = true;
      }
      return TrustMethod.getTrustMethodForIndex(userChoice);
    }
    catch (ClientException e)
    {
      throw new RuntimeException(e);
    }
  }
  private void promptForTrustStorePathIfRequired() throws ArgumentException
  {
    if (!app.isInteractive() || secureArgsList.getTrustStorePathArg().isPresent())
    {
      return;
    }
    checkHeadingDisplayed();
    try
    {
      app.println();
      state.truststorePath = app.readValidatedInput(
          INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH.get(),
          filePathValidationCallback(!ALLOW_EMPTY_PATH, FILE_MUST_EXISTS));
    }
    catch (ClientException e)
    {
      throw cannotReadConnectionParameters(e);
    }
  }
  private void promptForTrustStorePasswordIfRequired() throws ArgumentException
  {
    if (!app.isInteractive())
    {
      return;
    }
    checkHeadingDisplayed();
    try
    {
      state.truststorePassword = readPassword(
          INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PASSWORD.get(state.truststorePath));
    }
    catch (Exception e)
    {
      throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
    }
  }
  /**
   * Get the key manager.
   *
@@ -1092,218 +873,283 @@
  private KeyManager getKeyManagerInternal() throws ArgumentException
  {
    //  Remove these arguments since this method might be called several times.
    commandBuilder.removeArgument(copySecureArgsList.certNicknameArg);
    commandBuilder.removeArgument(copySecureArgsList.keyStorePathArg);
    commandBuilder.removeArgument(copySecureArgsList.keyStorePasswordArg);
    commandBuilder.removeArgument(copySecureArgsList.keyStorePasswordFileArg);
    commandBuilder.removeArguments(copySecureArgsList.getCertNicknameArg(),
                                   copySecureArgsList.getKeyStorePathArg(),
                                   copySecureArgsList.getKeyStorePasswordArg(),
                                   copySecureArgsList.getKeyStorePasswordFileArg());
    // Do we need client side authentication ?
    // If one of the client side authentication args is set, we assume
    // that we
    // need client side authentication.
    boolean weDontKnowIfWeNeedKeystore =
        !secureArgsList.keyStorePathArg.isPresent()
        && !secureArgsList.keyStorePasswordArg.isPresent()
        && !secureArgsList.keyStorePasswordFileArg.isPresent()
        && !secureArgsList.certNicknameArg.isPresent();
    // We don't have specific key manager parameter.
    // We assume that no client side authentication is required
    // Client side authentication is not the common use case. As a
    // consequence, interactive mode doesn't add an extra question
    // which will be in most cases useless.
    if (weDontKnowIfWeNeedKeystore)
    if (!secureArgsList.getKeyStorePathArg().isPresent()
     && !secureArgsList.getKeyStorePasswordArg().isPresent()
     && !secureArgsList.getKeyStorePasswordFileArg().isPresent()
     && !secureArgsList.getCertNicknameArg().isPresent())
    {
      // If no one of these parameters above are set, we assume that we do not need client side authentication.
      // Client side authentication is not the common use case so interactive mode doesn't add an extra question.
      return null;
    }
    // Get info about keystore. First get the keystore path.
    state.keystorePath = secureArgsList.keyStorePathArg.getValue();
    if (app.isInteractive() && !secureArgsList.keyStorePathArg.isPresent())
    resolveKeyStorePath();
    resolveKeyStorePassword();
    final KeyStore keystore = createKeyStore();
    resolveCertificateNickname(keystore);
    final ApplicationKeyManager keyManager = new ApplicationKeyManager(keystore, state.keystorePassword.toCharArray());
    addKeyStorePasswordArgToCommandBuilder();
    if (state.certifNickname != null)
    {
      checkHeadingDisplayed();
      ValidationCallback<String> callback = new ValidationCallback<String>()
      {
        @Override
        public String validate(ConsoleApplication app, String input)
            throws ClientException
        {
          String ninput = input.trim();
          if (ninput.length() == 0)
          {
            return ninput;
          }
          File f = new File(ninput);
          if (f.exists() && f.canRead() && !f.isDirectory())
          {
            return ninput;
          }
          else
          {
            app.println();
            app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH.get());
            app.println();
            return null;
          }
        }
      };
      try
      {
        app.println();
        state.keystorePath = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PATH.get(), callback);
      }
      catch (ClientException e)
      {
        throw cannotReadConnectionParameters(e);
      }
      addArgToCommandBuilder(copySecureArgsList.getCertNicknameArg(), state.certifNickname);
      return SelectableCertificateKeyManager.wrap(
          new KeyManager[] { keyManager }, CollectionUtils.newTreeSet(state.certifNickname))[0];
    }
    if (state.keystorePath != null)
    return keyManager;
  }
  private void resolveKeyStorePath() throws ArgumentException
  {
    state.keyStorePath = secureArgsList.getKeyStorePathArg().getValue();
    promptForKeyStorePathIfRequired();
    if (state.keyStorePath == null)
    {
      copySecureArgsList.keyStorePathArg.clearValues();
      copySecureArgsList.keyStorePathArg.addValue(state.keystorePath);
      commandBuilder.addArgument(copySecureArgsList.keyStorePathArg);
    }
    else
    {
      // KeystorePath is null. Either it's unspecified or there's a pb
      // We should throw an exception here, anyway since code below will
      // anyway
      throw new ArgumentException(ERR_ERROR_INCOMPATIBLE_PROPERTY_MOD.get("null keystorePath"));
    }
    addArgToCommandBuilder(copySecureArgsList.getKeyStorePathArg(), state.keyStorePath);
  }
    // Then the keystore password.
    state.keystorePassword = secureArgsList.keyStorePasswordArg.getValue();
  private void resolveKeyStorePassword() throws ArgumentException
  {
    state.keystorePassword = secureArgsList.getKeyStorePasswordArg().getValue();
    if (secureArgsList.keyStorePasswordFileArg.isPresent())
    if (secureArgsList.getKeyStorePasswordFileArg().isPresent())
    {
      // Read from file if it exists.
      state.keystorePassword = secureArgsList.keyStorePasswordFileArg.getValue();
      state.keystorePassword = secureArgsList.getKeyStorePasswordFileArg().getValue();
      if (state.keystorePassword == null)
      {
        throw new ArgumentException(ERR_ERROR_NO_ADMIN_PASSWORD.get(state.keystorePassword));
        throw new ArgumentException(ERR_INSTALLDS_NO_KEYSTORE_PASSWORD.get(
            secureArgsList.getKeyStorePathArg().getLongIdentifier(),
            secureArgsList.getKeyStorePasswordFileArg().getLongIdentifier()));
      }
    }
    else if (state.keystorePassword == null || "-".equals(state.keystorePassword))
    {
      // Read the password from the stdin.
      if (!app.isInteractive())
      {
        throw new ArgumentException(ERR_ERROR_BIND_PASSWORD_NONINTERACTIVE.get());
      }
      checkHeadingDisplayed();
      try
      {
        app.println();
        LocalizableMessage prompt = INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD.get(state.keystorePath);
        state.keystorePassword = readPassword(prompt);
      }
      catch (Exception e)
      {
        throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
      }
      promptForKeyStorePasswordIfRequired();
    }
  }
    // finally the certificate name, if needed.
    KeyStore keystore = null;
    Enumeration<String> aliasesEnum = null;
    try (FileInputStream fos = new FileInputStream(state.keystorePath))
  private KeyStore createKeyStore() throws ArgumentException
  {
    try (FileInputStream fos = new FileInputStream(state.keyStorePath))
    {
      keystore = KeyStore.getInstance(KeyStore.getDefaultType());
      final KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
      keystore.load(fos, state.keystorePassword.toCharArray());
      aliasesEnum = keystore.aliases();
      return keystore;
    }
    catch (Exception e)
    {
      throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
    }
  }
    state.certifNickname = secureArgsList.certNicknameArg.getValue();
    if (app.isInteractive() && !secureArgsList.certNicknameArg.isPresent() && aliasesEnum.hasMoreElements())
  private void resolveCertificateNickname(final KeyStore keystore) throws ArgumentException
  {
    state.certifNickname = secureArgsList.getCertNicknameArg().getValue();
    try
    {
      checkHeadingDisplayed();
      promptForCertificateNicknameIfRequired(keystore, keystore.aliases());
    }
    catch (final KeyStoreException e)
    {
      throw new ArgumentException(ERR_RESOLVE_KEYSTORE_ALIASES.get(e.getMessage()), e);
    }
  }
      try
  private void promptForKeyStorePathIfRequired() throws ArgumentException
  {
    if (!app.isInteractive() || secureArgsList.getKeyStorePathArg().isPresent())
    {
      return;
    }
    checkHeadingDisplayed();
    try
    {
      app.println();
      state.keyStorePath = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PATH.get(),
                                                  filePathValidationCallback(ALLOW_EMPTY_PATH, FILE_MUST_EXISTS));
    }
    catch (ClientException e)
    {
      throw cannotReadConnectionParameters(e);
    }
  }
  private void promptForKeyStorePasswordIfRequired() throws ArgumentException
  {
    if (!app.isInteractive())
    {
      throw new ArgumentException(ERR_ERROR_BIND_PASSWORD_NONINTERACTIVE.get());
    }
    checkHeadingDisplayed();
    try
    {
      state.keystorePassword = readPassword(INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD.get(state.keyStorePath));
    }
    catch (Exception e)
    {
      throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
    }
  }
  private void promptForCertificateNicknameIfRequired(KeyStore keystore, Enumeration<String> aliasesEnum)
      throws ArgumentException
  {
    if (!app.isInteractive() || secureArgsList.getCertNicknameArg().isPresent() || !aliasesEnum.hasMoreElements())
    {
      return;
    }
    state.certifNickname = null;
    checkHeadingDisplayed();
    try
    {
      MenuBuilder<String> builder = new MenuBuilder<>(app);
      builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIASES.get());
      int certificateNumber = 0;
      while (aliasesEnum.hasMoreElements())
      {
        MenuBuilder<String> builder = new MenuBuilder<>(app);
        builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIASES.get());
        int certificateNumber = 0;
        for (; aliasesEnum.hasMoreElements();)
        final String alias = aliasesEnum.nextElement();
        if (keystore.isKeyEntry(alias))
        {
          String alias = aliasesEnum.nextElement();
          if (keystore.isKeyEntry(alias))
          {
            X509Certificate certif =
                (X509Certificate) keystore.getCertificate(alias);
            certificateNumber++;
            builder.addNumberedOption(
                    INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIAS.get(alias,
                        certif.getSubjectDN().getName()), MenuResult.success(alias));
          }
        }
        if (certificateNumber > 1)
        {
          app.println();
          Menu<String> menu = builder.toMenu();
          MenuResult<String> result = menu.run();
          if (result.isSuccess())
          {
            state.certifNickname = result.getValue();
          }
          else
          {
            // Should never happen.
            throw new RuntimeException();
          }
        }
        else
        {
          state.certifNickname = null;
          certificateNumber++;
          X509Certificate certif = (X509Certificate) keystore.getCertificate(alias);
          builder.addNumberedOption(INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIAS.get(
                                                                                alias, certif.getSubjectDN().getName()),
                                    MenuResult.success(alias));
        }
      }
      catch (KeyStoreException e)
      if (certificateNumber > 1)
      {
        throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
      }
      catch (ClientException e)
      {
        throw cannotReadConnectionParameters(e);
        app.println();
        Menu<String> menu = builder.toMenu();
        final MenuResult<String> result = menu.run();
        throwIfMenuResultNotSucceeded(result);
        state.certifNickname = result.getValue();
      }
    }
    // We'we got all the information to get the keys manager
    ApplicationKeyManager akm =
        new ApplicationKeyManager(keystore, state.keystorePassword.toCharArray());
    if (secureArgsList.keyStorePasswordFileArg.isPresent())
    catch (KeyStoreException e)
    {
      copySecureArgsList.keyStorePasswordFileArg.clearValues();
      copySecureArgsList.keyStorePasswordFileArg.getNameToValueMap().putAll(
          secureArgsList.keyStorePasswordFileArg.getNameToValueMap());
      commandBuilder.addArgument(copySecureArgsList.keyStorePasswordFileArg);
      throw new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
    }
    catch (ClientException e)
    {
      throw cannotReadConnectionParameters(e);
    }
  }
  private void addKeyStorePasswordArgToCommandBuilder()
  {
    if (secureArgsList.getKeyStorePasswordFileArg().isPresent())
    {
      addArgToCommandBuilder(copySecureArgsList.getKeyStorePasswordFileArg(),
          secureArgsList.getKeyStorePasswordFileArg().getNameToValueMap());
    }
    else if (state.keystorePassword != null)
    {
      copySecureArgsList.keyStorePasswordArg.clearValues();
      copySecureArgsList.keyStorePasswordArg.addValue(state.keystorePassword);
      commandBuilder.addObfuscatedArgument(copySecureArgsList.keyStorePasswordArg);
      addObfuscatedArgToCommandBuilder(copySecureArgsList.getKeyStorePasswordArg(), state.keystorePassword);
    }
  }
    if (state.certifNickname != null)
  private void addConnectionTypeToCommandBuilder()
  {
    if (state.useSSL)
    {
      copySecureArgsList.certNicknameArg.clearValues();
      copySecureArgsList.certNicknameArg.addValue(state.certifNickname);
      return SelectableCertificateKeyManager.wrap(
          new KeyManager[] { akm },
          CollectionUtils.newTreeSet(state.certifNickname))[0];
      commandBuilder.addArgument(copySecureArgsList.getUseSSLArg());
    }
    return akm;
    else if (state.useStartTLS)
    {
      commandBuilder.addArgument(copySecureArgsList.getUseStartTLSArg());
    }
  }
  private void addArgToCommandBuilder(final Argument arg, final String value)
  {
    addArgToCommandBuilder(arg, value, false);
  }
  private void addObfuscatedArgToCommandBuilder(final Argument arg, final String value)
  {
    addArgToCommandBuilder(arg, value, true);
  }
  private void addArgToCommandBuilder(final Argument arg, final String value, final boolean obfuscated)
  {
    if (value != null)
    {
      arg.clearValues();
      arg.addValue(value);
      commandBuilder.addArgument(arg);
    }
  }
  private void addArgToCommandBuilder(final FileBasedArgument arg, final Map<String, String> nameToValueMap)
  {
    arg.clearValues();
    arg.getNameToValueMap().putAll(nameToValueMap);
    commandBuilder.addArgument(arg);
  }
  private ArgumentException cannotReadConnectionParameters(ClientException e)
  {
    return new ArgumentException(ERR_ERROR_CANNOT_READ_CONNECTION_PARAMETERS.get(e.getMessage()), e.getCause());
  }
  private String readPassword(LocalizableMessage prompt) throws ClientException
  {
    app.println();
    final char[] pwd = app.readPassword(prompt);
    if (pwd != null)
    {
      return String.valueOf(pwd);
    }
    return null;
  }
  private ValidationCallback<String> filePathValidationCallback(
      final boolean allowEmptyPath, final boolean checkExistenceAndReadability)
  {
    return new ValidationCallback<String>()
    {
      @Override
      public String validate(final ConsoleApplication app, final String filePathUserInput) throws ClientException
      {
        final String filePath = filePathUserInput.trim();
        final File f = new File(filePath);
        if ((!allowEmptyPath && filePath.isEmpty())
            || f.isDirectory()
            || (checkExistenceAndReadability && !(f.exists() && f.canRead())))
        {
          app.println();
          app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH.get());
          app.println();
          return null;
        }
        return filePath;
      }
    };
  }
  /** Returns {@code true} if client script uses the adminUID argument. */
  private boolean isAdminUidArgVisible()
  {
    return !secureArgsList.getAdminUidArg().isHidden();
  }
  private boolean useKeyManager()
  {
    return state.keyManager != null;
  }
  /**
@@ -1374,10 +1220,6 @@
    {
      return state.getAdminOrBindDN();
    }
    else if (secureArgsList.useAdminUID())
    {
      return getAdministratorDN(state.adminUID);
    }
    else
    {
      return state.bindDN;
@@ -1480,219 +1322,196 @@
   *          the host we tried to connect and that presented the certificate.
   * @return true if the server certificate is trusted.
   */
  public boolean checkServerCertificate(X509Certificate[] chain,
      String authType, String host)
  public boolean checkServerCertificate(final X509Certificate[] chain, final String authType, final String host)
  {
    if (state.trustManager == null)
    {
      try
      {
        initializeTrustManager();
        initializeTrustAndKeyManagers();
      }
      catch (ArgumentException ae)
      {
        // Should not occur
        // Should not append because this.run() should has been called at this stage.
        throw new RuntimeException(ae);
      }
    }
    app.println();
    app.println(INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE.get());
    app.println();
    for (int i = 0; i < chain.length; i++)
    {
      // Certificate DN
      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN.get(chain[i].getSubjectDN()));
      // certificate validity
      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY.get(
          chain[i].getNotBefore(), chain[i].getNotAfter()));
      // certificate Issuer
      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER.get(chain[i].getIssuerDN()));
      if (i + 1 < chain.length)
      {
        app.println();
        app.println();
      }
    }
    printCertificateChain(chain);
    MenuBuilder<Integer> builder = new MenuBuilder<>(app);
    builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION.get());
    TrustOption defaultTrustMethod = TrustOption.SESSION;
    for (TrustOption t : TrustOption.values())
    {
      int i = builder.addNumberedOption(t.getMenuMessage(), MenuResult.success(t.getChoice()));
      if (t.equals(defaultTrustMethod))
      final MenuResult<Integer> result = MenuResult.success(t.getChoice());
      int i = builder.addNumberedOption(t.message, result);
      if (DEFAULT_PROMPT_TRUST_OPTION.equals(t))
      {
        builder.setDefault(INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE.get(
            Integer.valueOf(i)), MenuResult.success(t.getChoice()));
        builder.setDefault(INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE.get(i), result);
      }
    }
    app.println();
    app.println();
    Menu<Integer> menu = builder.toMenu();
    while (true)
    final Menu<Integer> menu = builder.toMenu();
    try
    {
      try
      boolean promptAgain;
      int userChoice;
      do
      {
        MenuResult<Integer> result = menu.run();
        if (result.isSuccess())
        promptAgain = false;
        final MenuResult<Integer> result = menu.run();
        throwIfMenuResultNotSucceeded(result);
        userChoice = result.getValue();
        if (TrustOption.CERTIFICATE_DETAILS.getChoice() == userChoice)
        {
          if (result.getValue().equals(TrustOption.UNTRUSTED.getChoice()))
          {
            return false;
          }
          if (result.getValue().equals(
              TrustOption.CERTIFICATE_DETAILS.getChoice()))
          {
            for (X509Certificate cert : chain)
            {
              app.println();
              app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE.get(cert));
            }
            continue;
          }
          // We should add it in the memory truststore
          for (X509Certificate cert : chain)
          {
            String alias = cert.getSubjectDN().getName();
            try
            {
              state.truststore.setCertificateEntry(alias, cert);
            }
            catch (KeyStoreException e1)
            {
              // What else should we do?
              return false;
            }
          }
          // Update the trust manager
          if (state.trustManager == null)
          {
            state.trustManager = new ApplicationTrustManager(state.truststore);
          }
          if (authType != null && host != null)
          {
            // Update the trust manager with the new certificate
            state.trustManager.acceptCertificate(chain, authType, host);
          }
          else
          {
            // Do a full reset of the contents of the keystore.
            state.trustManager = new ApplicationTrustManager(state.truststore);
          }
          if (result.getValue().equals(TrustOption.PERMAMENT.getChoice()))
          {
            ValidationCallback<String> callback =
                new ValidationCallback<String>()
                {
                  @Override
                  public String validate(ConsoleApplication app, String input)
                      throws ClientException
                  {
                    String ninput = input.trim();
                    if (ninput.length() == 0)
                    {
                      app.println();
                      app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH.get());
                      app.println();
                      return null;
                    }
                    File f = new File(ninput);
                    if (!f.isDirectory())
                    {
                      return ninput;
                    }
                    else
                    {
                      app.println();
                      app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH.get());
                      app.println();
                      return null;
                    }
                  }
                };
            String truststorePath;
            try
            {
              app.println();
              truststorePath =
                  app.readValidatedInput(INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH.get(), callback);
            }
            catch (ClientException e)
            {
              return true;
            }
            // Read the password from the stdin.
            String truststorePassword;
            try
            {
              app.println();
              LocalizableMessage prompt = INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD.get(truststorePath);
              truststorePassword = readPassword(prompt);
            }
            catch (Exception e)
            {
              return true;
            }
            try
            {
              KeyStore ts = KeyStore.getInstance("JKS");
              FileInputStream fis;
              try
              {
                fis = new FileInputStream(truststorePath);
              }
              catch (FileNotFoundException e)
              {
                fis = null;
              }
              ts.load(fis, truststorePassword.toCharArray());
              if (fis != null)
              {
                fis.close();
              }
              for (X509Certificate cert : chain)
              {
                String alias = cert.getSubjectDN().getName();
                ts.setCertificateEntry(alias, cert);
              }
              FileOutputStream fos = new FileOutputStream(truststorePath);
              try
              {
                ts.store(fos, truststorePassword.toCharArray());
              }
              finally
              {
                fos.close();
              }
            }
            catch (Exception e)
            {
              return true;
            }
          }
          return true;
        }
        else
        {
          // Should never happen.
          throw new RuntimeException();
          promptAgain = true;
          printCertificateDetails(chain);
        }
      }
      catch (ClientException cliE)
      while (promptAgain);
      return trustCertificate(TrustOption.getTrustOptionForIndex(userChoice), chain, authType, host);
    }
    catch (ClientException e)
    {
      throw new RuntimeException(e);
    }
  }
  private void printCertificateChain(X509Certificate[] chain)
  {
    app.println();
    app.println(INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE.get());
    app.println();
    boolean printSeparatorLines = false;
    for (final X509Certificate cert : chain)
    {
      if (!printSeparatorLines)
      {
        throw new RuntimeException(cliE);
        app.println();
        app.println();
        printSeparatorLines = true;
      }
      // Certificate DN
      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN.get(cert.getSubjectDN()));
      // certificate validity
      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY.get(
          cert.getNotBefore(), cert.getNotAfter()));
      // certificate Issuer
      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER.get(cert.getIssuerDN()));
    }
  }
  private void printCertificateDetails(X509Certificate[] chain)
  {
    for (X509Certificate cert : chain)
    {
      app.println();
      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE.get(cert));
    }
  }
  private boolean trustCertificate(final TrustOption trustOption, final X509Certificate[] chain,
      final String authType, final String host) throws ClientException
  {
    try
    {
      switch (trustOption)
      {
      case SESSION:
        updateTrustManager(chain, authType, host);
        return true;
      case PERMAMENT:
        updateTrustManager(chain, authType, host);
        try
        {
          trustCertificatePermanently(chain);
        }
        catch (Exception e)
        {
          app.println(ERR_TRUSTING_CERTIFICATE_PERMANENTLY.get(e.getMessage()));
        }
        return true;
      case UNTRUSTED:
      default:
        return false;
      }
    }
    catch (KeyStoreException e)
    {
      app.println(ERR_TRUSTING_CERTIFICATE.get(e.getMessage()));
      return false;
    }
  }
  private void updateTrustManager(X509Certificate[] chain, String authType, String host) throws KeyStoreException
  {
    // User choice if to add the certificate to the trust store for the current session or permanently.
    for (final X509Certificate cert : chain)
    {
      state.truststore.setCertificateEntry(cert.getSubjectDN().getName(), cert);
    }
    // Update the trust manager
    if (state.trustManager == null)
    {
      state.trustManager = new ApplicationTrustManager(state.truststore);
    }
    if (authType != null && host != null)
    {
      // Update the trust manager with the new certificate
      state.trustManager.acceptCertificate(chain, authType, host);
    }
    else
    {
      // Do a full reset of the contents of the keystore.
      state.trustManager = new ApplicationTrustManager(state.truststore);
    }
  }
  private void trustCertificatePermanently(final X509Certificate[] chain) throws Exception
  {
    app.println();
    final String trustStorePath = app.readValidatedInput(
        INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH.get(),
        filePathValidationCallback(!ALLOW_EMPTY_PATH, !FILE_MUST_EXISTS));
    // Read the password from the stdin.
    final String trustStorePasswordStr = readPassword(
        INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD.get(trustStorePath));
    final KeyStore keyStore = KeyStore.getInstance("JKS");
    final char[] trustStorePassword = trustStorePasswordStr.toCharArray();
    loadKeyStoreFromFile(keyStore, trustStorePath, trustStorePassword);
    for (final X509Certificate cert : chain)
    {
      keyStore.setCertificateEntry(cert.getSubjectDN().getName(), cert);
    }
    try (final FileOutputStream trustStoreOutputFile = new FileOutputStream(trustStorePath))
    {
      keyStore.store(trustStoreOutputFile, trustStorePassword);
    }
  }
  private void loadKeyStoreFromFile(
      final KeyStore keyStore, final String trustStorePath, final char[] trustStorePassword) throws Exception
  {
      try (FileInputStream inputStream = new FileInputStream(trustStorePath))
      {
        keyStore.load(inputStream, trustStorePassword);
      }
      catch (FileNotFoundException ignored)
      {
        // create empty keystore
        keyStore.load(null, trustStorePassword);
      }
  }
  /**
@@ -1718,7 +1537,7 @@
    if (state.useSSL)
    {
      SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
      sslConnectionFactory.init(getTrustManager() == null, state.keystorePath,
      sslConnectionFactory.init(getTrustManager() == null, state.keyStorePath,
          state.keystorePassword, state.certifNickname, state.truststorePath, state.truststorePassword);
      options.setSSLConnectionFactory(sslConnectionFactory);
    }
@@ -1729,9 +1548,8 @@
  /**
   * Prompts the user to accept the certificate.
   *
   * @param t
   *          the throwable that was generated because the certificate was not
   *          trusted.
   * @param errorRaised
   *          the error raised because the certificate was not trusted.
   * @param usedTrustManager
   *          the trustManager used when trying to establish the connection.
   * @param usedUrl
@@ -1741,85 +1559,58 @@
   * @return {@code true} if the user accepted the certificate and
   *         {@code false} otherwise.
   */
  public boolean promptForCertificateConfirmation(Throwable t,
  public boolean promptForCertificateConfirmation(Throwable errorRaised,
      ApplicationTrustManager usedTrustManager, String usedUrl, LocalizedLogger logger)
  {
    ApplicationTrustManager.Cause cause;
    if (usedTrustManager != null)
    final ApplicationTrustManager.Cause cause = usedTrustManager != null ? usedTrustManager.getLastRefusedCause()
                                                                         : null;
    logger.debug(INFO_CERTIFICATE_EXCEPTION_CAUSE.get(cause));
    if (cause == null)
    {
      cause = usedTrustManager.getLastRefusedCause();
      app.println(getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), errorRaised));
      return false;
    }
    String host;
    int port;
    try
    {
      URI uri = new URI(usedUrl);
      host = uri.getHost();
      port = uri.getPort();
    }
    catch (URISyntaxException e)
    {
      logger.warn(ERROR_CERTIFICATE_PARSING_URL.get(usedUrl, e));
      host = INFO_NOT_AVAILABLE_LABEL.get().toString();
      port = -1;
    }
    final String authType = usedTrustManager.getLastRefusedAuthType();
    if (authType == null)
    {
      logger.warn(ERROR_CERTIFICATE_NULL_AUTH_TYPE.get());
    }
    else
    {
      cause = null;
    }
    if (logger != null)
    {
      logger.debug(LocalizableMessage.raw("Certificate exception cause: " + cause));
      app.println(ApplicationTrustManager.Cause.NOT_TRUSTED.equals(authType)
          ? INFO_CERTIFICATE_NOT_TRUSTED_TEXT_CLI.get(host, port)
          : INFO_CERTIFICATE_NAME_MISMATCH_TEXT_CLI.get(host, port, host, host, port));
    }
    if (cause != null)
    final X509Certificate[] chain = usedTrustManager.getLastRefusedChain();
    if (chain == null)
    {
      String h;
      int p;
      try
      {
        URI uri = new URI(usedUrl);
        h = uri.getHost();
        p = uri.getPort();
      }
      catch (Throwable t1)
      {
        printLogger(logger, "Error parsing ldap url of ldap url. " + t1);
        h = INFO_NOT_AVAILABLE_LABEL.get().toString();
        p = -1;
      }
      String authType = usedTrustManager.getLastRefusedAuthType();
      if (authType == null)
      {
        printLogger(logger, "Null auth type for this certificate exception.");
      }
      else
      {
        LocalizableMessage msg;
        if (authType.equals(ApplicationTrustManager.Cause.NOT_TRUSTED))
        {
          msg = INFO_CERTIFICATE_NOT_TRUSTED_TEXT_CLI.get(h, p);
        }
        else
        {
          msg = INFO_CERTIFICATE_NAME_MISMATCH_TEXT_CLI.get(h, p, h, h, p);
        }
        app.println(msg);
      }
      X509Certificate[] chain = usedTrustManager.getLastRefusedChain();
      if (chain == null)
      {
        printLogger(logger, "Null chain for this certificate exception.");
        return false;
      }
      if (h == null)
      {
        printLogger(logger, "Null host name for this certificate exception.");
      }
      return checkServerCertificate(chain, authType, h);
      logger.warn(ERROR_CERTIFICATE_NULL_CHAIN.get());
      return false;
    }
    else
    if (host == null)
    {
      app.println(getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), t));
      logger.warn(ERROR_CERTIFICATE_NULL_HOST_NAME.get());
    }
    return false;
  }
  private void printLogger(final LocalizedLogger logger,
      final String msg)
  {
    if (logger != null)
    {
      logger.warn(LocalizableMessage.raw(msg));
    }
    return checkServerCertificate(chain, authType, host);
  }
  /**
@@ -1860,20 +1651,9 @@
  }
  /**
   * Tells whether during interaction we can ask for both the DN or the admin
   * UID.
   *
   * @return {@code true} if during interaction we can ask for both the DN
   *         and the admin UID and {@code false} otherwise.
   */
  public boolean isUseAdminOrBindDn()
  {
    return useAdminOrBindDn;
  }
  /**
   * Tells whether we can ask during interaction for both the DN and the admin
   * UID or not.
   * Default value is {@code false}.
   *
   * @param useAdminOrBindDn
   *          whether we can ask for both the DN and the admin UID during
@@ -1893,8 +1673,7 @@
   *          whether propose LDAP as protocol even if the user provided
   *          security parameters or not.
   */
  public void setDisplayLdapIfSecureParameters(
      boolean displayLdapIfSecureParameters)
  public void setDisplayLdapIfSecureParameters(boolean displayLdapIfSecureParameters)
  {
    this.displayLdapIfSecureParameters = displayLdapIfSecureParameters;
  }
@@ -1919,7 +1698,7 @@
  {
    if (!state.trustManagerInitialized)
    {
      initializeTrustManager();
      initializeTrustAndKeyManagers();
    }
  }
@@ -1948,46 +1727,46 @@
    resetConnectionArguments();
    if (hostName != null)
    {
      secureArgsList.hostNameArg.addValue(hostName);
      secureArgsList.hostNameArg.setPresent(true);
      secureArgsList.getHostNameArg().addValue(hostName);
      secureArgsList.getHostNameArg().setPresent(true);
    }
    // resetConnectionArguments does not clear the values for the port
    secureArgsList.portArg.clearValues();
    secureArgsList.getPortArg().clearValues();
    if (port != -1)
    {
      secureArgsList.portArg.addValue(String.valueOf(port));
      secureArgsList.portArg.setPresent(true);
      secureArgsList.getPortArg().addValue(String.valueOf(port));
      secureArgsList.getPortArg().setPresent(true);
    }
    else
    {
      // This is done to be able to call IntegerArgument.getIntValue()
      secureArgsList.portArg.addValue(secureArgsList.portArg.getDefaultValue());
      secureArgsList.getPortArg().addValue(secureArgsList.getPortArg().getDefaultValue());
    }
    secureArgsList.useSSLArg.setPresent(state.useSSL);
    secureArgsList.useStartTLSArg.setPresent(state.useStartTLS);
    secureArgsList.getUseSSLArg().setPresent(state.useSSL);
    secureArgsList.getUseStartTLSArg().setPresent(state.useStartTLS);
    if (adminUid != null)
    {
      secureArgsList.adminUidArg.addValue(adminUid);
      secureArgsList.adminUidArg.setPresent(true);
      secureArgsList.getAdminUidArg().addValue(adminUid);
      secureArgsList.getAdminUidArg().setPresent(true);
    }
    if (bindDn != null)
    {
      secureArgsList.bindDnArg.addValue(bindDn);
      secureArgsList.bindDnArg.setPresent(true);
      secureArgsList.getBindDnArg().addValue(bindDn);
      secureArgsList.getBindDnArg().setPresent(true);
    }
    if (pwdFile != null)
    {
      secureArgsList.bindPasswordFileArg.getNameToValueMap().putAll(pwdFile);
      secureArgsList.getBindPasswordFileArg().getNameToValueMap().putAll(pwdFile);
      for (String value : pwdFile.keySet())
      {
        secureArgsList.bindPasswordFileArg.addValue(value);
        secureArgsList.getBindPasswordFileArg().addValue(value);
      }
      secureArgsList.bindPasswordFileArg.setPresent(true);
      secureArgsList.getBindPasswordFileArg().setPresent(true);
    }
    else if (bindPwd != null)
    {
      secureArgsList.bindPasswordArg.addValue(bindPwd);
      secureArgsList.bindPasswordArg.setPresent(true);
      secureArgsList.getBindPasswordArg().addValue(bindPwd);
      secureArgsList.getBindPasswordArg().setPresent(true);
    }
    state = new State(secureArgsList);
  }
@@ -2000,32 +1779,30 @@
   */
  public void resetConnectionArguments()
  {
    secureArgsList.hostNameArg.clearValues();
    secureArgsList.hostNameArg.setPresent(false);
    secureArgsList.portArg.clearValues();
    secureArgsList.portArg.setPresent(false);
    secureArgsList.getHostNameArg().clearValues();
    secureArgsList.getHostNameArg().setPresent(false);
    secureArgsList.getPortArg().clearValues();
    secureArgsList.getPortArg().setPresent(false);
    //  This is done to be able to call IntegerArgument.getIntValue()
    secureArgsList.portArg.addValue(secureArgsList.portArg.getDefaultValue());
    secureArgsList.bindDnArg.clearValues();
    secureArgsList.bindDnArg.setPresent(false);
    secureArgsList.bindPasswordArg.clearValues();
    secureArgsList.bindPasswordArg.setPresent(false);
    secureArgsList.bindPasswordFileArg.clearValues();
    secureArgsList.bindPasswordFileArg.getNameToValueMap().clear();
    secureArgsList.bindPasswordFileArg.setPresent(false);
    secureArgsList.getPortArg().addValue(secureArgsList.getPortArg().getDefaultValue());
    secureArgsList.getBindDnArg().clearValues();
    secureArgsList.getBindDnArg().setPresent(false);
    secureArgsList.getBindPasswordArg().clearValues();
    secureArgsList.getBindPasswordArg().setPresent(false);
    secureArgsList.getBindPasswordFileArg().clearValues();
    secureArgsList.getBindPasswordFileArg().getNameToValueMap().clear();
    secureArgsList.getBindPasswordFileArg().setPresent(false);
    state.bindPassword = null;
    secureArgsList.adminUidArg.clearValues();
    secureArgsList.adminUidArg.setPresent(false);
    secureArgsList.getAdminUidArg().clearValues();
    secureArgsList.getAdminUidArg().setPresent(false);
  }
  private void initializeTrustManager() throws ArgumentException
  private void initializeTrustAndKeyManagers() throws ArgumentException
  {
    // Get trust store info
    state.trustManager = getTrustManagerInternal();
    // Check if we need client side authentication
    state.keyManager = getKeyManagerInternal();
    state.trustManagerInitialized = true;
  }
@@ -2058,35 +1835,33 @@
   *
   * @return true if the local trust store has been added.
   */
  private boolean addLocalTrustStore()
  private boolean useLocalTrustStoreIfPossible()
  {
    try
    {
      // If remote host, return
      if (!InetAddress.getLocalHost().getHostName().equals(state.hostName)
          || secureArgsList.getAdminPortFromConfig() != portNumber)
      if (InetAddress.getLocalHost().getHostName().equals(state.hostName)
          && secureArgsList.getAdminPortFromConfig() == portNumber)
      {
        return false;
        final String trustStoreFileAbsolute = secureArgsList.getTruststoreFileFromConfig();
        if (trustStoreFileAbsolute != null)
        {
          secureArgsList.getTrustStorePathArg().addValue(trustStoreFileAbsolute);
          return true;
        }
      }
      // check if we are in a local instance. Already checked the host,
      // now check the port
      if (secureArgsList.getAdminPortFromConfig() != portNumber)
      {
        return false;
      }
      String truststoreFileAbsolute = secureArgsList.getTruststoreFileFromConfig();
      if (truststoreFileAbsolute != null)
      {
        secureArgsList.trustStorePathArg.addValue(truststoreFileAbsolute);
        return true;
      }
      return false;
    }
    catch (Exception ex)
    {
      // do nothing
      return false;
    }
    return false;
  }
  private void throwIfMenuResultNotSucceeded(final MenuResult<?> result)
  {
    if (!result.isSuccess())
    {
      throw new RuntimeException("Expected successful menu result, but got " + result);
    }
  }
}
opendj-server-legacy/src/messages/org/opends/messages/tool.properties
@@ -2706,3 +2706,13 @@
ERR_CONFIRMATION_TRIES_LIMIT_REACHED=Confirmation tries limit reached (%d)
REF_SHORT_DESC_UNINSTALL=remove OpenDJ directory server software
INFO_CERTIFICATE_EXCEPTION_CAUSE=Certificate exception cause: %s
ERROR_CERTIFICATE_PARSING_URL=Error parsing ldap url %s: %s
ERROR_CERTIFICATE_NULL_AUTH_TYPE=Null auth type for this certificate exception
ERROR_CERTIFICATE_NULL_CHAIN=Null chain for this certificate exception
ERROR_CERTIFICATE_NULL_HOST_NAME=Null host name for this certificate exception
ERR_RESOLVE_KEYSTORE_ALIASES=Unable to resolve keystore aliases: %s
ERR_TRUSTING_CERTIFICATE=Unable to trust the certificate because: %s
ERR_TRUSTING_CERTIFICATE_PERMANENTLY=Unable to trust the certificate permanently, \
 certificate will be trusted only for this session. Error details: %s