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