001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2011-2016 ForgeRock AS.
016 */
017package org.opends.server.tools;
018
019import static com.forgerock.opendj.cli.ArgumentConstants.*;
020import static com.forgerock.opendj.cli.CliMessages.INFO_JMXPORT_PLACEHOLDER;
021import static com.forgerock.opendj.cli.CliMessages.INFO_KEYSTORE_PWD_FILE_PLACEHOLDER;
022import static com.forgerock.opendj.cli.CliMessages.INFO_NUM_ENTRIES_PLACEHOLDER;
023import static com.forgerock.opendj.cli.CliMessages.INFO_PORT_PLACEHOLDER;
024import static com.forgerock.opendj.cli.CliMessages.INFO_ROOT_USER_PWD_FILE_PLACEHOLDER;
025import static com.forgerock.opendj.cli.CommonArguments.*;
026import static com.forgerock.opendj.cli.Utils.addErrorMessageIfArgumentsConflict;
027import static com.forgerock.opendj.util.OperatingSystem.*;
028
029import static org.opends.messages.ToolMessages.*;
030
031import java.util.Collection;
032import java.util.HashSet;
033import java.util.LinkedHashSet;
034import java.util.Set;
035
036import org.forgerock.i18n.LocalizableMessage;
037import org.forgerock.i18n.LocalizableMessageDescriptor.Arg1;
038import org.forgerock.i18n.slf4j.LocalizedLogger;
039import org.opends.quicksetup.Constants;
040import org.opends.quicksetup.Installation;
041import org.opends.quicksetup.UserData;
042import org.opends.quicksetup.util.Utils;
043import org.opends.server.config.AdministrationConnector;
044import org.opends.server.core.DirectoryServer.DirectoryServerVersionHandler;
045
046import com.forgerock.opendj.cli.Argument;
047import com.forgerock.opendj.cli.ArgumentException;
048import com.forgerock.opendj.cli.ArgumentParser;
049import com.forgerock.opendj.cli.BooleanArgument;
050import com.forgerock.opendj.cli.CliConstants;
051import com.forgerock.opendj.cli.FileBasedArgument;
052import com.forgerock.opendj.cli.IntegerArgument;
053import com.forgerock.opendj.cli.StringArgument;
054
055/**
056 * Class used to parse the arguments of the setup command-line and to check
057 * that there are not conflicting arguments (nor missing arguments in no prompt
058 * mode).
059 * Note that this class does not perform checks involving network (like if
060 * a given port is free) nor the validity of the certificate information
061 * provided.
062 */
063public class InstallDSArgumentParser extends ArgumentParser
064{
065  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
066
067  private BooleanArgument cliArg;
068  BooleanArgument   addBaseEntryArg;
069  private BooleanArgument showUsageArg;
070  BooleanArgument   quietArg;
071  BooleanArgument   noPromptArg;
072  BooleanArgument   verboseArg;
073  private StringArgument propertiesFileArgument;
074  private BooleanArgument noPropertiesFileArgument;
075  BooleanArgument   skipPortCheckArg;
076  BooleanArgument   enableWindowsServiceArg;
077  BooleanArgument   doNotStartArg;
078  BooleanArgument   enableStartTLSArg;
079  BooleanArgument   generateSelfSignedCertificateArg;
080  StringArgument    hostNameArg;
081  BooleanArgument   usePkcs11Arg;
082  private FileBasedArgument directoryManagerPwdFileArg;
083  private FileBasedArgument keyStorePasswordFileArg;
084  IntegerArgument   ldapPortArg;
085  IntegerArgument   adminConnectorPortArg;
086  IntegerArgument   ldapsPortArg;
087  IntegerArgument   jmxPortArg;
088  IntegerArgument   sampleDataArg;
089  StringArgument    baseDNArg;
090  StringArgument    importLDIFArg;
091  StringArgument    rejectedImportFileArg;
092  StringArgument    skippedImportFileArg;
093  StringArgument    directoryManagerDNArg;
094  private StringArgument directoryManagerPwdStringArg;
095  StringArgument    useJavaKeyStoreArg;
096  StringArgument    useJCEKSArg;
097  StringArgument    usePkcs12Arg;
098  private StringArgument keyStorePasswordArg;
099  StringArgument    certNicknameArg;
100  private StringArgument progNameArg;
101  private IntegerArgument connectTimeoutArg;
102  BooleanArgument   acceptLicense;
103  StringArgument    backendTypeArg;
104
105  /**
106   * The default constructor for this class.
107   * @param mainClassName the class name of the main class for the command-line
108   * that is being used.
109   */
110  public InstallDSArgumentParser(String mainClassName)
111  {
112    super(mainClassName, INFO_INSTALLDS_TOOL_DESCRIPTION.get(), false);
113    setShortToolDescription(REF_SHORT_DESC_SETUP.get());
114    setVersionHandler(new DirectoryServerVersionHandler());
115  }
116
117  /**
118   * Initializes the arguments without parsing them.
119   * @throws ArgumentException if there was an error creating or adding the
120   * arguments.  If this occurs is likely to be a bug.
121   */
122  public void initializeArguments() throws ArgumentException
123  {
124    cliArg = cliArgument();
125    addArgument(cliArg);
126
127    progNameArg = StringArgument.builder("programName")
128            .shortIdentifier('P')
129            .description(INFO_INSTALLDS_DESCRIPTION_PROGNAME.get())
130            .hidden()
131            .defaultValue(Installation.getSetupFileName())
132            .valuePlaceholder(INFO_PROGRAM_NAME_PLACEHOLDER.get())
133            .buildArgument();
134    addArgument(progNameArg);
135
136    noPromptArg = noPromptArgument();
137    addArgument(noPromptArg);
138
139    quietArg = quietArgument();
140    addArgument(quietArg);
141
142    verboseArg = verboseArgument();
143    addArgument(verboseArg);
144
145    propertiesFileArgument =
146            StringArgument.builder(OPTION_LONG_PROP_FILE_PATH)
147                    .description(INFO_DESCRIPTION_PROP_FILE_PATH.get())
148                    .valuePlaceholder(INFO_PROP_FILE_PATH_PLACEHOLDER.get())
149                    .buildArgument();
150    addArgument(propertiesFileArgument);
151    setFilePropertiesArgument(propertiesFileArgument);
152
153    noPropertiesFileArgument =
154            BooleanArgument.builder(OPTION_LONG_NO_PROP_FILE)
155                    .description(INFO_DESCRIPTION_NO_PROP_FILE.get())
156                    .buildArgument();
157    addArgument(noPropertiesFileArgument);
158    setNoPropertiesFileArgument(noPropertiesFileArgument);
159
160    baseDNArg =
161            StringArgument.builder(OPTION_LONG_BASEDN)
162                    .shortIdentifier(OPTION_SHORT_BASEDN)
163                    .description(INFO_INSTALLDS_DESCRIPTION_BASEDN.get())
164                    .multiValued()
165                    .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get())
166                    .buildArgument();
167    addArgument(baseDNArg);
168
169    addBaseEntryArg =
170            BooleanArgument.builder("addBaseEntry")
171                    .shortIdentifier('a')
172                    .description(INFO_INSTALLDS_DESCRIPTION_ADDBASE.get())
173                    .buildArgument();
174    addArgument(addBaseEntryArg);
175
176    importLDIFArg =
177            StringArgument.builder(OPTION_LONG_LDIF_FILE)
178                    .shortIdentifier(OPTION_SHORT_LDIF_FILE)
179                    .description(INFO_INSTALLDS_DESCRIPTION_IMPORTLDIF.get())
180                    .multiValued()
181                    .valuePlaceholder(INFO_LDIFFILE_PLACEHOLDER.get())
182                    .buildArgument();
183    addArgument(importLDIFArg);
184
185    rejectedImportFileArg =
186            StringArgument.builder("rejectFile")
187                    .shortIdentifier('R')
188                    .description(INFO_INSTALLDS_DESCRIPTION_REJECTED_FILE.get())
189                    .valuePlaceholder(INFO_REJECT_FILE_PLACEHOLDER.get())
190                    .buildArgument();
191    addArgument(rejectedImportFileArg);
192
193    skippedImportFileArg =
194            StringArgument.builder("skipFile")
195                    .description(INFO_INSTALLDS_DESCRIPTION_SKIPPED_FILE.get())
196                    .valuePlaceholder(INFO_SKIP_FILE_PLACEHOLDER.get())
197                    .buildArgument();
198    addArgument(skippedImportFileArg);
199
200    sampleDataArg =
201            IntegerArgument.builder("sampleData")
202                    .shortIdentifier('d')
203                    .description(INFO_INSTALLDS_DESCRIPTION_SAMPLE_DATA.get())
204                    .lowerBound(0)
205                    .defaultValue(0)
206                    .valuePlaceholder(INFO_NUM_ENTRIES_PLACEHOLDER.get())
207                    .buildArgument();
208    addArgument(sampleDataArg);
209
210    int defaultLdapPort = UserData.getDefaultPort();
211    if (defaultLdapPort == -1)
212    {
213      defaultLdapPort = 389;
214    }
215
216    ldapPortArg =
217            IntegerArgument.builder("ldapPort")
218                    .shortIdentifier(OPTION_SHORT_PORT)
219                    .description(INFO_INSTALLDS_DESCRIPTION_LDAPPORT.get())
220                    .range(1, 65535)
221                    .defaultValue(defaultLdapPort)
222                    .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
223                    .buildArgument();
224    addArgument(ldapPortArg);
225
226    int defaultAdminPort = UserData.getDefaultAdminConnectorPort();
227    if (defaultAdminPort == -1)
228    {
229      defaultAdminPort =
230        AdministrationConnector.DEFAULT_ADMINISTRATION_CONNECTOR_PORT;
231    }
232
233    adminConnectorPortArg =
234            IntegerArgument.builder("adminConnectorPort")
235                    .description(INFO_INSTALLDS_DESCRIPTION_ADMINCONNECTORPORT.get())
236                    .range(1, 65535)
237                    .defaultValue(defaultAdminPort)
238                    .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
239                    .buildArgument();
240    addArgument(adminConnectorPortArg);
241
242    jmxPortArg =
243            IntegerArgument.builder("jmxPort")
244                    .shortIdentifier('x')
245                    .description(INFO_INSTALLDS_DESCRIPTION_JMXPORT.get())
246                    .range(1, 65535)
247                    .defaultValue(CliConstants.DEFAULT_JMX_PORT)
248                    .valuePlaceholder(INFO_JMXPORT_PLACEHOLDER.get())
249                    .buildArgument();
250    addArgument(jmxPortArg);
251
252    skipPortCheckArg =
253            BooleanArgument.builder("skipPortCheck")
254                    .shortIdentifier('S')
255                    .description(INFO_INSTALLDS_DESCRIPTION_SKIPPORT.get())
256                    .buildArgument();
257    addArgument(skipPortCheckArg);
258
259    directoryManagerDNArg =
260            StringArgument.builder(OPTION_LONG_ROOT_USER_DN)
261                    .shortIdentifier(OPTION_SHORT_ROOT_USER_DN)
262                    .description(INFO_INSTALLDS_DESCRIPTION_ROOTDN.get())
263                    .defaultValue("cn=Directory Manager")
264                    .valuePlaceholder(INFO_ROOT_USER_DN_PLACEHOLDER.get())
265                    .buildArgument();
266    addArgument(directoryManagerDNArg);
267
268    directoryManagerPwdStringArg =
269            StringArgument.builder("rootUserPassword")
270                    .shortIdentifier(OPTION_SHORT_BINDPWD)
271                    .description(INFO_INSTALLDS_DESCRIPTION_ROOTPW.get())
272                    .valuePlaceholder(INFO_ROOT_USER_PWD_PLACEHOLDER.get())
273                    .buildArgument();
274    addArgument(directoryManagerPwdStringArg);
275
276    directoryManagerPwdFileArg =
277            FileBasedArgument.builder("rootUserPasswordFile")
278                    .shortIdentifier(OPTION_SHORT_BINDPWD_FILE)
279                    .description(INFO_INSTALLDS_DESCRIPTION_ROOTPWFILE.get())
280                    .valuePlaceholder(INFO_ROOT_USER_PWD_FILE_PLACEHOLDER.get())
281                    .buildArgument();
282    addArgument(directoryManagerPwdFileArg);
283
284    enableWindowsServiceArg =
285            BooleanArgument.builder("enableWindowsService")
286                    .shortIdentifier('e')
287                    .description(INFO_INSTALLDS_DESCRIPTION_ENABLE_WINDOWS_SERVICE.get())
288                    .buildArgument();
289    if (isWindows())
290    {
291      addArgument(enableWindowsServiceArg);
292    }
293
294    doNotStartArg =
295            BooleanArgument.builder("doNotStart")
296                    .shortIdentifier('O')
297                    .description(INFO_INSTALLDS_DESCRIPTION_DO_NOT_START.get())
298                    .buildArgument();
299    addArgument(doNotStartArg);
300
301    enableStartTLSArg =
302            BooleanArgument.builder("enableStartTLS")
303                    .shortIdentifier(OPTION_SHORT_START_TLS)
304                    .description(INFO_INSTALLDS_DESCRIPTION_ENABLE_STARTTLS.get())
305                    .buildArgument();
306    addArgument(enableStartTLSArg);
307
308    int defaultSecurePort = UserData.getDefaultSslPort(defaultLdapPort);
309    if (defaultSecurePort == -1)
310    {
311      defaultSecurePort = 636;
312    }
313
314    ldapsPortArg =
315            IntegerArgument.builder("ldapsPort")
316                    .shortIdentifier(OPTION_SHORT_USE_SSL)
317                    .description(INFO_INSTALLDS_DESCRIPTION_LDAPSPORT.get())
318                    .range(1, 65535)
319                    .defaultValue(defaultSecurePort)
320                    .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
321                    .buildArgument();
322    addArgument(ldapsPortArg);
323
324    generateSelfSignedCertificateArg =
325            BooleanArgument.builder("generateSelfSignedCertificate")
326                    .description(INFO_INSTALLDS_DESCRIPTION_USE_SELF_SIGNED.get())
327                    .buildArgument();
328    addArgument(generateSelfSignedCertificateArg);
329
330    hostNameArg =
331            StringArgument.builder(OPTION_LONG_HOST)
332                    .shortIdentifier(OPTION_SHORT_HOST)
333                    .description(INFO_INSTALLDS_DESCRIPTION_HOST_NAME.get())
334                    .defaultValue(UserData.getDefaultHostName())
335                    .valuePlaceholder(INFO_HOST_PLACEHOLDER.get())
336                    .buildArgument();
337    addDefaultArgument(hostNameArg);
338
339    usePkcs11Arg =
340            BooleanArgument.builder("usePkcs11Keystore")
341                    .description(INFO_INSTALLDS_DESCRIPTION_USE_PKCS11.get())
342                    .buildArgument();
343    addArgument(usePkcs11Arg);
344
345    useJavaKeyStoreArg =
346            StringArgument.builder("useJavaKeystore")
347                    .description(INFO_INSTALLDS_DESCRIPTION_USE_JAVAKEYSTORE.get())
348                    .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
349                    .buildArgument();
350    addArgument(useJavaKeyStoreArg);
351
352    useJCEKSArg =
353            StringArgument.builder("useJCEKS")
354                    .description(INFO_INSTALLDS_DESCRIPTION_USE_JCEKS.get())
355                    .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
356                    .buildArgument();
357    addArgument(useJCEKSArg);
358
359    usePkcs12Arg =
360            StringArgument.builder("usePkcs12keyStore")
361                    .description(INFO_INSTALLDS_DESCRIPTION_USE_PKCS12.get())
362                    .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
363                    .buildArgument();
364    addArgument(usePkcs12Arg);
365
366    keyStorePasswordArg =
367            StringArgument.builder(OPTION_LONG_KEYSTORE_PWD)
368                    .shortIdentifier(OPTION_SHORT_KEYSTORE_PWD)
369                    .description(INFO_INSTALLDS_DESCRIPTION_KEYSTOREPASSWORD.get())
370                    .valuePlaceholder(INFO_KEYSTORE_PWD_PLACEHOLDER.get())
371                    .buildArgument();
372    addDefaultArgument(keyStorePasswordArg);
373
374    keyStorePasswordFileArg =
375            FileBasedArgument.builder(OPTION_LONG_KEYSTORE_PWD_FILE)
376                    .shortIdentifier(OPTION_SHORT_KEYSTORE_PWD_FILE)
377                    .description(INFO_INSTALLDS_DESCRIPTION_KEYSTOREPASSWORD_FILE.get())
378                    .valuePlaceholder(INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get())
379                    .buildArgument();
380    addDefaultArgument(keyStorePasswordFileArg);
381
382    certNicknameArg =
383            StringArgument.builder(OPTION_LONG_CERT_NICKNAME)
384                    .shortIdentifier(OPTION_SHORT_CERT_NICKNAME)
385                    .description(INFO_INSTALLDS_DESCRIPTION_CERT_NICKNAME.get())
386                    .multiValued()
387                    .valuePlaceholder(INFO_NICKNAME_PLACEHOLDER.get())
388                    .buildArgument();
389    addDefaultArgument(certNicknameArg);
390
391    connectTimeoutArg = connectTimeOutHiddenArgument();
392    addArgument(connectTimeoutArg);
393
394    acceptLicense = acceptLicenseArgument();
395    addArgument(acceptLicense);
396
397    showUsageArg = showUsageArgument();
398    addArgument(showUsageArg);
399    setUsageArgument(showUsageArg);
400
401    backendTypeArg =
402            StringArgument.builder(OPTION_LONG_BACKEND_TYPE)
403                    .shortIdentifier(OPTION_SHORT_BACKEND_TYPE)
404                    .description(INFO_INSTALLDS_DESCRIPTION_BACKEND_TYPE.get())
405                    .defaultValue(BackendTypeHelper.filterSchemaBackendName(
406                            new BackendTypeHelper().getBackendTypes().get(0).getName()))
407                    .valuePlaceholder(INFO_INSTALLDS_BACKEND_TYPE_PLACEHOLDER.get())
408                    .buildArgument();
409    addArgument(backendTypeArg);
410  }
411
412  /**
413   * Returns whether the command was launched in CLI mode or not.
414   * @return <CODE>true</CODE> if the command was launched to use CLI mode and
415   * <CODE>false</CODE> otherwise.
416   */
417  public boolean isCli()
418  {
419    return cliArg.isPresent();
420  }
421
422  @Override
423  public void parseArguments(String[] args) throws ArgumentException
424  {
425    LinkedHashSet<LocalizableMessage> errorMessages = new LinkedHashSet<>();
426    try
427    {
428      super.parseArguments(args);
429    }
430    catch (ArgumentException ae)
431    {
432      logger.error(LocalizableMessage.raw("Error parsing arguments: "+ae, ae));
433      errorMessages.add(ae.getMessageObject());
434    }
435
436    if (!isUsageArgumentPresent() && !isVersionArgumentPresent())
437    {
438      checkServerPassword(errorMessages);
439      checkProvidedPorts(errorMessages);
440      checkImportDataArguments(errorMessages);
441      checkSecurityArguments(errorMessages);
442
443      if (!errorMessages.isEmpty())
444      {
445        throw new ArgumentException(ERR_CANNOT_INITIALIZE_ARGS.get(
446            Utils.getMessageFromCollection(errorMessages, Constants.LINE_SEPARATOR)));
447      }
448    }
449  }
450
451  /**
452   * Returns the directory manager password provided by the user.  This method
453   * should be called after a call to parseArguments.
454   * @return the directory manager password provided by the user.
455   */
456  public String getDirectoryManagerPassword()
457  {
458    if (directoryManagerPwdStringArg.isPresent())
459    {
460      return directoryManagerPwdStringArg.getValue();
461    }
462    else if (directoryManagerPwdFileArg.isPresent())
463    {
464      return directoryManagerPwdFileArg.getValue();
465    }
466    return null;
467  }
468
469  /**
470   * Returns the key store password provided by the user.  This method should be
471   * called after a call to parseArguments.
472   * @return the key store password provided by the user.
473   */
474  public String getKeyStorePassword()
475  {
476    if (keyStorePasswordArg.isPresent())
477    {
478      return keyStorePasswordArg.getValue();
479    }
480    else if (keyStorePasswordFileArg.isPresent())
481    {
482      return keyStorePasswordFileArg.getValue();
483    }
484    return null;
485  }
486
487  /**
488   * Checks that there are no conflicts with the directory manager passwords.
489   * If we are in no prompt mode, check that the password was provided.
490   * @param errorMessages the list of messages to which we add the error
491   * messages describing the problems encountered during the execution of the
492   * checking.
493   */
494  private void checkServerPassword(Collection<LocalizableMessage> errorMessages)
495  {
496    addErrorMessageIfArgumentsConflict(errorMessages, directoryManagerPwdStringArg, directoryManagerPwdFileArg);
497
498    if (noPromptArg.isPresent() && !directoryManagerPwdStringArg.isPresent() &&
499        !directoryManagerPwdFileArg.isPresent())
500    {
501      errorMessages.add(ERR_INSTALLDS_NO_ROOT_PASSWORD.get(
502          directoryManagerPwdStringArg.getLongIdentifier(),
503          directoryManagerPwdFileArg.getLongIdentifier()));
504    }
505  }
506
507  /**
508   * Checks that there are no conflicts with the provided ports (like if the
509   * user provided the same port for different protocols).
510   * @param errorMessages the list of messages to which we add the error
511   * messages describing the problems encountered during the execution of the
512   * checking.
513   */
514  private void checkProvidedPorts(Collection<LocalizableMessage> errorMessages)
515  {
516    try
517    {
518      Set<Integer> ports = new HashSet<>();
519      ports.add(ldapPortArg.getIntValue());
520
521      checkPortAlreadyUsed(ports, adminConnectorPortArg.getIntValue(), errorMessages,
522          ERR_CONFIGDS_PORT_ALREADY_SPECIFIED);
523      if (jmxPortArg.isPresent())
524      {
525        checkPortAlreadyUsed(ports, jmxPortArg.getIntValue(), errorMessages, ERR_CONFIGDS_PORT_ALREADY_SPECIFIED);
526      }
527      if (ldapsPortArg.isPresent())
528      {
529        checkPortAlreadyUsed(ports, ldapsPortArg.getIntValue(), errorMessages, ERR_CONFIGDS_PORT_ALREADY_SPECIFIED);
530      }
531    }
532    catch (ArgumentException ae)
533    {
534      logger.error(LocalizableMessage.raw("Unexpected error.  "+
535          "Assuming that it is caused by a previous parsing issue: "+ae, ae));
536    }
537  }
538
539  private void checkPortAlreadyUsed(Set<Integer> ports, int port, Collection<LocalizableMessage> errorMessages,
540      Arg1<Object> errorMsg)
541  {
542    if (!ports.add(port))
543    {
544      errorMessages.add(errorMsg.get(port));
545    }
546  }
547
548  /**
549   * Checks that there are no conflicts with the import data arguments.
550   *
551   * @param errorMessages
552   *          the list of messages to which we add the error messages describing
553   *          the problems encountered during the execution of the checking.
554   */
555  private void checkImportDataArguments(Collection<LocalizableMessage> errorMessages)
556  {
557    //  Make sure that the user didn't provide conflicting arguments.
558    addErrorMessageIfArgumentsConflict(errorMessages, addBaseEntryArg, importLDIFArg);
559    addErrorMessageIfArgumentsConflict(errorMessages, addBaseEntryArg, sampleDataArg);
560    addErrorMessageIfArgumentsConflict(errorMessages, importLDIFArg, sampleDataArg);
561    addErrorMessageIfArgumentsConflict(errorMessages, addBaseEntryArg, rejectedImportFileArg);
562    addErrorMessageIfArgumentsConflict(errorMessages, rejectedImportFileArg, sampleDataArg);
563    addErrorMessageIfArgumentsConflict(errorMessages, addBaseEntryArg, skippedImportFileArg);
564    addErrorMessageIfArgumentsConflict(errorMessages, skippedImportFileArg, sampleDataArg);
565
566    final boolean noBaseDNProvided = !baseDNArg.isPresent() && baseDNArg.getDefaultValue() == null;
567    if (noPromptArg.isPresent() && noBaseDNProvided)
568    {
569      final Argument[] args = {importLDIFArg, addBaseEntryArg, sampleDataArg, backendTypeArg};
570      for (Argument arg : args)
571      {
572        if (arg.isPresent())
573        {
574          errorMessages.add(ERR_INSTALLDS_NO_BASE_DN_AND_CONFLICTING_ARG.get("--" + arg.getLongIdentifier()));
575        }
576      }
577    }
578  }
579
580  /**
581   * Checks that there are no conflicts with the security arguments.
582   * If we are in no prompt mode, check that all the information required has
583   * been provided (but not if this information is valid: we do not try to
584   * open the keystores or to check that the LDAPS port is in use).
585   * @param errorMessages the list of messages to which we add the error
586   * messages describing the problems encountered during the execution of the
587   * checking.
588   */
589  private void checkSecurityArguments(Collection<LocalizableMessage> errorMessages)
590  {
591    boolean certificateRequired = ldapsPortArg.isPresent() || enableStartTLSArg.isPresent();
592
593    int certificateType = 0;
594    if (generateSelfSignedCertificateArg.isPresent())
595    {
596      certificateType++;
597    }
598    if (useJavaKeyStoreArg.isPresent())
599    {
600      certificateType++;
601    }
602    if (useJCEKSArg.isPresent())
603    {
604      certificateType++;
605    }
606    if (usePkcs11Arg.isPresent())
607    {
608      certificateType++;
609    }
610    if (usePkcs12Arg.isPresent())
611    {
612      certificateType++;
613    }
614
615    if (certificateType > 1)
616    {
617      errorMessages.add(ERR_INSTALLDS_SEVERAL_CERTIFICATE_TYPE_SPECIFIED.get());
618    }
619
620    if (certificateRequired && noPromptArg.isPresent() && certificateType == 0)
621    {
622      errorMessages.add(
623          ERR_INSTALLDS_CERTIFICATE_REQUIRED_FOR_SSL_OR_STARTTLS.get());
624    }
625
626    if (certificateType == 1)
627    {
628      if (!generateSelfSignedCertificateArg.isPresent())
629      {
630        addErrorMessageIfArgumentsConflict(errorMessages, keyStorePasswordArg, keyStorePasswordFileArg);
631
632        // Check that we have one password in no prompt mode.
633        if (noPromptArg.isPresent() && !keyStorePasswordArg.isPresent() &&
634            !keyStorePasswordFileArg.isPresent())
635        {
636          errorMessages.add(ERR_INSTALLDS_NO_KEYSTORE_PASSWORD.get(
637              keyStorePasswordArg.getLongIdentifier(),
638              keyStorePasswordFileArg.getLongIdentifier()));
639        }
640      }
641      if (noPromptArg.isPresent() && !ldapsPortArg.isPresent() &&
642          !enableStartTLSArg.isPresent())
643      {
644        errorMessages.add(ERR_INSTALLDS_SSL_OR_STARTTLS_REQUIRED.get(
645            ldapsPortArg.getLongIdentifier(),
646            enableStartTLSArg.getLongIdentifier()));
647      }
648    }
649  }
650
651  /**
652   * Returns the timeout to be used to connect in milliseconds.  The method
653   * must be called after parsing the arguments.
654   * @return the timeout to be used to connect in milliseconds.  Returns
655   * {@code 0} if there is no timeout.
656   * @throws IllegalStateException if the method is called before
657   * parsing the arguments.
658   */
659  public int getConnectTimeout() throws IllegalStateException
660  {
661    try
662    {
663      return connectTimeoutArg.getIntValue();
664    }
665    catch (ArgumentException ae)
666    {
667      throw new IllegalStateException("Argument parser is not parsed: "+ae, ae);
668    }
669  }
670}