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 2006-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2012-2016 ForgeRock AS.
016 */
017package org.opends.server.tools;
018
019import static com.forgerock.opendj.cli.CliMessages.INFO_FILE_PLACEHOLDER;
020import static com.forgerock.opendj.cli.CliMessages.INFO_JMXPORT_PLACEHOLDER;
021import static com.forgerock.opendj.cli.CliMessages.INFO_PORT_PLACEHOLDER;
022import static org.opends.messages.ConfigMessages.*;
023import static org.opends.messages.ExtensionMessages.*;
024import static org.opends.messages.ProtocolMessages.*;
025import static org.opends.messages.ToolMessages.*;
026import static org.opends.server.config.ConfigConstants.*;
027import static org.opends.server.util.ServerConstants.*;
028import static org.opends.server.util.StaticUtils.*;
029
030import static com.forgerock.opendj.cli.ArgumentConstants.*;
031import static com.forgerock.opendj.cli.Utils.*;
032import static com.forgerock.opendj.cli.CommonArguments.*;
033
034import java.io.File;
035import java.io.OutputStream;
036import java.io.PrintStream;
037import java.io.StringReader;
038import java.net.InetAddress;
039import java.security.GeneralSecurityException;
040import java.util.Collection;
041import java.util.HashSet;
042import java.util.LinkedList;
043import java.util.List;
044import java.util.Set;
045
046import javax.crypto.Cipher;
047
048import org.forgerock.i18n.LocalizableMessage;
049import org.forgerock.i18n.LocalizedIllegalArgumentException;
050import org.forgerock.opendj.config.ManagedObjectDefinition;
051import org.forgerock.opendj.ldap.DN;
052import org.forgerock.opendj.server.config.client.BackendCfgClient;
053import org.forgerock.opendj.server.config.server.BackendCfg;
054import org.opends.quicksetup.installer.Installer;
055import org.opends.server.admin.DefaultBehaviorProvider;
056import org.opends.server.admin.DefinedDefaultBehaviorProvider;
057import org.opends.server.admin.StringPropertyDefinition;
058import org.opends.server.admin.std.meta.CryptoManagerCfgDefn;
059import org.opends.server.api.ConfigHandler;
060import org.opends.server.config.BooleanConfigAttribute;
061import org.opends.server.config.ConfigEntry;
062import org.opends.server.config.DNConfigAttribute;
063import org.opends.server.config.IntegerConfigAttribute;
064import org.opends.server.config.StringConfigAttribute;
065import org.opends.server.core.DirectoryServer;
066import org.opends.server.core.LockFileManager;
067import org.opends.server.extensions.ConfigFileHandler;
068import org.opends.server.extensions.SaltedSHA512PasswordStorageScheme;
069import org.opends.server.protocols.ldap.LDAPResultCode;
070import org.opends.server.types.DirectoryEnvironmentConfig;
071import org.opends.server.types.DirectoryException;
072import org.opends.server.types.Entry;
073import org.opends.server.types.InitializationException;
074import org.opends.server.types.LDIFImportConfig;
075import org.opends.server.types.NullOutputStream;
076import org.opends.server.util.LDIFReader;
077
078import com.forgerock.opendj.cli.Argument;
079import com.forgerock.opendj.cli.ArgumentException;
080import com.forgerock.opendj.cli.ArgumentParser;
081import com.forgerock.opendj.cli.BooleanArgument;
082import com.forgerock.opendj.cli.CliConstants;
083import com.forgerock.opendj.cli.FileBasedArgument;
084import com.forgerock.opendj.cli.IntegerArgument;
085import com.forgerock.opendj.cli.StringArgument;
086
087/**
088 * This class provides a very basic tool that can be used to configure some of
089 * the most important settings in the Directory Server.  This configuration is
090 * performed by editing the server's configuration files and therefore the
091 * Directory Server must be offline.  This utility will be used during the
092 * Directory Server installation process.
093 * <BR><BR>
094 * The options that this tool can currently set include:
095 * <BR>
096 * <UL>
097 *   <LI>The port on which the server will listen for LDAP communication</LI>
098 *   <LI>The DN and password for the initial root user.
099 *   <LI>The set of base DNs for user data</LI>
100 * </UL>
101 */
102public class ConfigureDS
103{
104  private static final boolean WRONG_USAGE = true;
105
106  /** Private exception class to handle error message printing. */
107  @SuppressWarnings("serial")
108  private class ConfigureDSException extends Exception
109  {
110    private final int returnedErrorCode;
111    private final LocalizableMessage errorMessage;
112    private final boolean wrongUsage;
113
114    ConfigureDSException(final LocalizableMessage errorMessage)
115    {
116      this(new Exception("An error occured in ConfigureDS: " + errorMessage), errorMessage, false);
117    }
118
119    ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage)
120    {
121      this(parentException, errorMessage, false);
122    }
123
124    ConfigureDSException(final LocalizableMessage errorMessage, final boolean showUsage)
125    {
126      this(new Exception("An error occured in ConfigureDS: " + errorMessage), errorMessage, showUsage);
127    }
128
129    ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage,
130        final boolean showUsage)
131    {
132      this(parentException, errorMessage, showUsage, ERROR);
133    }
134
135    ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage,
136        final boolean wrongUsage, final int retCode)
137    {
138      super(parentException);
139      this.errorMessage = errorMessage;
140      this.wrongUsage = wrongUsage;
141      returnedErrorCode = retCode;
142    }
143
144    private LocalizableMessage getErrorMessage()
145    {
146      return errorMessage;
147    }
148
149    private boolean isWrongUsage()
150    {
151      return wrongUsage;
152    }
153
154    private int getErrorCode()
155    {
156      return returnedErrorCode;
157    }
158  }
159
160  //FIXME: Find a better way to do to prevent hardcoded ldif entries.
161  private static final String NEW_LINE = System.getProperty("line.separator");
162
163  private static final String JCKES_KEY_MANAGER_DN = "cn=JCEKS,cn=Key Manager Providers,cn=config";
164  private static final String JCKES_KEY_MANAGER_LDIF_ENTRY =
165        "dn: " + JCKES_KEY_MANAGER_DN + NEW_LINE
166      + "objectClass: top" + NEW_LINE
167      + "objectClass: ds-cfg-key-manager-provider" + NEW_LINE
168      + "objectClass: ds-cfg-file-based-key-manager-provider" + NEW_LINE
169      + "cn: JCEKS" + NEW_LINE
170      + "ds-cfg-java-class: org.opends.server.extensions.FileBasedKeyManagerProvider" + NEW_LINE
171      + "ds-cfg-enabled: true" + NEW_LINE
172      + "ds-cfg-key-store-type: JCEKS" + NEW_LINE
173      + "ds-cfg-key-store-file: config/keystore.jceks" + NEW_LINE
174      + "ds-cfg-key-store-pin-file: config/keystore.pin" + NEW_LINE;
175
176  private static final String JCKES_TRUST_MANAGER_DN = "cn=JCEKS,cn=Trust Manager Providers,cn=config";
177  private static final String JCKES_TRUST_MANAGER_LDIF_ENTRY =
178        "dn: " + JCKES_TRUST_MANAGER_DN + NEW_LINE
179      + "objectClass: top" + NEW_LINE
180      + "objectClass: ds-cfg-trust-manager-provider" + NEW_LINE
181      + "objectClass: ds-cfg-file-based-trust-manager-provider" + NEW_LINE
182      + "cn: JCEKS" + NEW_LINE
183      + "ds-cfg-java-class: org.opends.server.extensions.FileBasedTrustManagerProvider" + NEW_LINE
184      + "ds-cfg-enabled: false" + NEW_LINE
185      + "ds-cfg-trust-store-type: JCEKS" + NEW_LINE
186      + "ds-cfg-trust-store-file: config/truststore" + NEW_LINE;
187
188  /** The fully-qualified name of this class. */
189  private static final String CLASS_NAME = "org.opends.server.tools.ConfigureDS";
190
191  /** The DN of the configuration entry defining the LDAP connection handler. */
192  public static final String DN_LDAP_CONNECTION_HANDLER = "cn=LDAP Connection Handler," + DN_CONNHANDLER_BASE;
193
194  /** The DN of the configuration entry defining the Administration connector. */
195  public static final String DN_ADMIN_CONNECTOR = "cn=Administration Connector," + DN_CONFIG_ROOT;
196
197  /** The DN of the configuration entry defining the LDAPS connection handler. */
198  private static final String DN_LDAPS_CONNECTION_HANDLER = "cn=LDAPS Connection Handler," + DN_CONNHANDLER_BASE;
199
200  /** The DN of the configuration entry defining the HTTP connection handler. */
201  private static final String DN_HTTP_CONNECTION_HANDLER =
202      "cn=HTTP Connection Handler,cn=Connection Handlers,cn=config";
203
204  /** The DN of the configuration entry defining the JMX connection handler. */
205  private static final String DN_JMX_CONNECTION_HANDLER = "cn=JMX Connection Handler," + DN_CONNHANDLER_BASE;
206
207  /** The DN of the configuration entry defining the initial root user. */
208  public static final String DN_ROOT_USER = "cn=Directory Manager," + DN_ROOT_DN_CONFIG_BASE;
209
210  /** The DN of the Crypto Manager. */
211  public static final String DN_CRYPTO_MANAGER = "cn=Crypto Manager,cn=config";
212
213  /** The DN of the DIGEST-MD5 SASL mechanism handler. */
214  public static final String DN_DIGEST_MD5_SASL_MECHANISM = "cn=DIGEST-MD5,cn=SASL Mechanisms,cn=config";
215
216  private static int SUCCESS = 0;
217  private static int ERROR = 1;
218
219  /**
220   * Provides the command-line arguments to the <CODE>configMain</CODE> method
221   * for processing.
222   *
223   * @param  args  The set of command-line arguments provided to this program.
224   */
225  public static void main(String[] args)
226  {
227    final int exitCode = configMain(args, System.out, System.err);
228    if (exitCode != SUCCESS)
229    {
230      System.exit(filterExitCode(exitCode));
231    }
232  }
233
234  /**
235   * Parses the provided command-line arguments and makes the appropriate
236   * changes to the Directory Server configuration.
237   *
238   * @param  args  The command-line arguments provided to this program.
239   *
240   * @param outStream Output stream.
241   * @param errStream Error stream.
242   * @return  The exit code from the configuration processing.  A nonzero value
243   *          indicates that there was some kind of problem during the
244   *          configuration processing.
245   */
246  public static int configMain(final String[] args, final OutputStream outStream, final OutputStream errStream)
247  {
248    final ConfigureDS tool = new ConfigureDS(args, outStream, errStream);
249    return tool.run();
250  }
251
252  private final String[] arguments;
253  private final PrintStream out;
254  private final PrintStream err;
255
256  private final ArgumentParser argParser;
257
258  private BooleanArgument showUsage;
259  private BooleanArgument enableStartTLS;
260  private FileBasedArgument rootPasswordFile;
261  private StringArgument hostName;
262  private IntegerArgument ldapPort;
263  private IntegerArgument adminConnectorPort;
264  private IntegerArgument ldapsPort;
265  private IntegerArgument jmxPort;
266  private StringArgument baseDNString;
267  private StringArgument configClass;
268  private StringArgument configFile;
269  private StringArgument rootDNString;
270  private StringArgument rootPassword;
271  private StringArgument keyManagerProviderDN;
272  private StringArgument trustManagerProviderDN;
273  private StringArgument certNickNames;
274  private StringArgument keyManagerPath;
275  private StringArgument serverRoot;
276  private StringArgument backendType;
277
278  private final String serverLockFileName = LockFileManager.getServerLockFileName();
279  private final StringBuilder failureReason = new StringBuilder();
280  private ConfigHandler<?> configHandler;
281
282  private ConfigureDS(final String[] args, final OutputStream outStream, final OutputStream errStream)
283  {
284    arguments = args;
285    out = NullOutputStream.wrapOrNullStream(outStream);
286    err = NullOutputStream.wrapOrNullStream(errStream);
287    argParser = new ArgumentParser(CLASS_NAME, INFO_CONFIGDS_TOOL_DESCRIPTION.get(), false);
288  }
289
290  private int run()
291  {
292    try
293    {
294      initializeArguments();
295      parseArguments();
296      if (argParser.usageOrVersionDisplayed())
297      {
298        return SUCCESS;
299      }
300
301      checkArgumentsConsistency();
302      checkPortArguments();
303
304      tryAcquireExclusiveLocks();
305      updateBaseDNs(parseProvidedBaseDNs());
306
307      initializeDirectoryServer();
308
309      final DN rootDN = parseRootDN();
310      final String rootPW = parseRootDNPassword();
311
312      // Get the Directory Server configuration handler and use it to make the
313      // appropriate configuration changes.
314      configHandler = DirectoryServer.getConfigHandler();
315
316      checkManagerProvider(keyManagerProviderDN, JCKES_KEY_MANAGER_DN, JCKES_KEY_MANAGER_LDIF_ENTRY, true);
317      checkManagerProvider(trustManagerProviderDN, JCKES_TRUST_MANAGER_DN, JCKES_TRUST_MANAGER_LDIF_ENTRY, false);
318      // Check that the keystore path values are valid.
319      if (keyManagerPath.isPresent() && !keyManagerProviderDN.isPresent())
320      {
321        final LocalizableMessage message = ERR_CONFIGDS_KEYMANAGER_PROVIDER_DN_REQUIRED.get(
322            keyManagerProviderDN.getLongIdentifier(), keyManagerPath.getLongIdentifier());
323        throw new ConfigureDSException(message);
324      }
325
326      updateLdapPort();
327      updateAdminConnectorPort();
328      updateLdapSecurePort();
329      updateJMXport();
330      updateStartTLS();
331      updateKeyManager();
332      updateTrustManager();
333      updateRootUser(rootDN, rootPW);
334      addFQDNDigestMD5();
335      updateCryptoCipher();
336      writeUpdatedConfiguration();
337
338      return SUCCESS;
339    }
340    catch (final ConfigureDSException e)
341    {
342     if (e.isWrongUsage())
343     {
344       argParser.displayMessageAndUsageReference(err, e.getErrorMessage());
345     }
346     else
347     {
348       printWrappedText(err, e.getErrorMessage());
349     }
350     return e.getErrorCode();
351    }
352    finally
353    {
354      LockFileManager.releaseLock(serverLockFileName, failureReason);
355    }
356  }
357
358  private void initializeArguments() throws ConfigureDSException
359  {
360    try
361    {
362      configFile =
363              StringArgument.builder("configFile")
364                      .shortIdentifier('c')
365                      .description(INFO_DESCRIPTION_CONFIG_FILE.get())
366                      .hidden()
367                      .required()
368                      .valuePlaceholder(INFO_CONFIGFILE_PLACEHOLDER.get())
369                      .buildAndAddToParser(argParser);
370      configClass =
371              StringArgument.builder(OPTION_LONG_CONFIG_CLASS)
372                      .shortIdentifier(OPTION_SHORT_CONFIG_CLASS)
373                      .description(INFO_DESCRIPTION_CONFIG_CLASS.get())
374                      .hidden()
375                      .defaultValue(ConfigFileHandler.class.getName())
376                      .valuePlaceholder(INFO_CONFIGCLASS_PLACEHOLDER.get())
377                      .buildAndAddToParser(argParser);
378
379      String defaultHostName;
380      try
381      {
382        defaultHostName = InetAddress.getLocalHost().getHostName();
383      }
384      catch (final Exception e)
385      {
386        // Not much we can do here.
387        defaultHostName = "localhost";
388      }
389
390      hostName =
391              StringArgument.builder(OPTION_LONG_HOST)
392                      .shortIdentifier(OPTION_SHORT_HOST)
393                      .description(INFO_INSTALLDS_DESCRIPTION_HOST_NAME.get())
394                      .defaultValue(defaultHostName)
395                      .valuePlaceholder(INFO_HOST_PLACEHOLDER.get())
396                      .buildAndAddToParser(argParser);
397      ldapPort =
398              IntegerArgument.builder("ldapPort")
399                      .shortIdentifier(OPTION_SHORT_PORT)
400                      .description(INFO_CONFIGDS_DESCRIPTION_LDAP_PORT.get())
401                      .range(1, 65535)
402                      .defaultValue(389)
403                      .valuePlaceholder(INFO_LDAPPORT_PLACEHOLDER.get())
404                      .buildAndAddToParser(argParser);
405      adminConnectorPort =
406              IntegerArgument.builder("adminConnectorPort")
407                      .description(INFO_INSTALLDS_DESCRIPTION_ADMINCONNECTORPORT.get())
408                      .range(1, 65535)
409                      .defaultValue(4444)
410                      .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
411                      .buildAndAddToParser(argParser);
412      ldapsPort =
413              IntegerArgument.builder("ldapsPort")
414                      .shortIdentifier('P')
415                      .description(INFO_CONFIGDS_DESCRIPTION_LDAPS_PORT.get())
416                      .range(1, 65535)
417                      .defaultValue(636)
418                      .valuePlaceholder(INFO_LDAPPORT_PLACEHOLDER.get())
419                      .buildAndAddToParser(argParser);
420      enableStartTLS =
421              BooleanArgument.builder("enableStartTLS")
422                      .shortIdentifier(OPTION_SHORT_START_TLS)
423                      .description(INFO_CONFIGDS_DESCRIPTION_ENABLE_START_TLS.get())
424                      .buildAndAddToParser(argParser);
425      jmxPort =
426              IntegerArgument.builder("jmxPort")
427                      .shortIdentifier('x')
428                      .description(INFO_CONFIGDS_DESCRIPTION_JMX_PORT.get())
429                      .range(1, 65535)
430                      .defaultValue(CliConstants.DEFAULT_JMX_PORT)
431                      .valuePlaceholder(INFO_JMXPORT_PLACEHOLDER.get())
432                      .buildAndAddToParser(argParser);
433      keyManagerProviderDN =
434              StringArgument.builder("keyManagerProviderDN")
435                      .shortIdentifier('k')
436                      .description(INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PROVIDER_DN.get())
437                      .valuePlaceholder(INFO_KEY_MANAGER_PROVIDER_DN_PLACEHOLDER.get())
438                      .buildAndAddToParser(argParser);
439      trustManagerProviderDN =
440              StringArgument.builder("trustManagerProviderDN")
441                      .shortIdentifier('t')
442                      .description(INFO_CONFIGDS_DESCRIPTION_TRUSTMANAGER_PROVIDER_DN.get())
443                      .valuePlaceholder(INFO_TRUST_MANAGER_PROVIDER_DN_PLACEHOLDER.get())
444                      .buildAndAddToParser(argParser);
445      keyManagerPath =
446              StringArgument.builder("keyManagerPath")
447                      .shortIdentifier('m')
448                      .description(INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PATH.get())
449                      .valuePlaceholder(INFO_KEY_MANAGER_PATH_PLACEHOLDER.get())
450                      .buildAndAddToParser(argParser);
451      certNickNames =
452              StringArgument.builder("certNickName")
453                      .shortIdentifier('a')
454                      .description(INFO_CONFIGDS_DESCRIPTION_CERTNICKNAME.get())
455                      .multiValued()
456                      .valuePlaceholder(INFO_NICKNAME_PLACEHOLDER.get())
457                      .buildAndAddToParser(argParser);
458      baseDNString =
459              StringArgument.builder(OPTION_LONG_BASEDN)
460                      .shortIdentifier(OPTION_SHORT_BASEDN)
461                      .description(INFO_CONFIGDS_DESCRIPTION_BASE_DN.get())
462                      .multiValued()
463                      .defaultValue("dc=example,dc=com")
464                      .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get())
465                      .buildAndAddToParser(argParser);
466      rootDNString =
467              StringArgument.builder(OPTION_LONG_ROOT_USER_DN)
468                      .shortIdentifier(OPTION_SHORT_ROOT_USER_DN)
469                      .description(INFO_CONFIGDS_DESCRIPTION_ROOT_DN.get())
470                      .defaultValue("cn=Directory Manager")
471                      .valuePlaceholder(INFO_ROOT_USER_DN_PLACEHOLDER.get())
472                      .buildAndAddToParser(argParser);
473      rootPassword =
474              StringArgument.builder("rootPassword")
475                      .shortIdentifier(OPTION_SHORT_BINDPWD)
476                      .description(INFO_CONFIGDS_DESCRIPTION_ROOT_PW.get())
477                      .valuePlaceholder(INFO_ROOT_USER_PWD_PLACEHOLDER.get())
478                      .buildAndAddToParser(argParser);
479      rootPasswordFile =
480              FileBasedArgument.builder("rootPasswordFile")
481                      .shortIdentifier(OPTION_SHORT_BINDPWD_FILE)
482                      .description(INFO_CONFIGDS_DESCRIPTION_ROOT_PW_FILE.get())
483                      .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
484                      .buildAndAddToParser(argParser);
485
486      showUsage = showUsageArgument();
487      argParser.addArgument(showUsage);
488      argParser.setUsageArgument(showUsage);
489
490      serverRoot =
491              StringArgument.builder(OPTION_LONG_SERVER_ROOT)
492                      .shortIdentifier(OPTION_SHORT_SERVER_ROOT)
493                      .hidden()
494                      .valuePlaceholder(INFO_SERVER_ROOT_DIR_PLACEHOLDER.get())
495                      .buildAndAddToParser(argParser);
496      backendType =
497              StringArgument.builder(OPTION_LONG_BACKEND_TYPE)
498                      .description(INFO_INSTALLDS_DESCRIPTION_BACKEND_TYPE.get())
499                      .valuePlaceholder(INFO_INSTALLDS_BACKEND_TYPE_PLACEHOLDER.get())
500                      .buildAndAddToParser(argParser);
501    }
502    catch (final ArgumentException ae)
503    {
504      throw new ConfigureDSException(ae, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
505    }
506  }
507
508  private int parseArguments() throws ConfigureDSException
509  {
510    try
511    {
512      argParser.parseArguments(arguments);
513      return SUCCESS;
514    }
515    catch (final ArgumentException ae)
516    {
517      throw new ConfigureDSException(ae, ERR_ERROR_PARSING_ARGS.get(ae.getMessage()),
518          WRONG_USAGE, LDAPResultCode.CLIENT_SIDE_PARAM_ERROR);
519    }
520  }
521
522  /** Make sure that the user actually tried to configure something. */
523  private void checkArgumentsConsistency() throws ConfigureDSException
524  {
525    if (!baseDNString.isPresent()
526        && !ldapPort.isPresent()
527        && !jmxPort.isPresent()
528        && !rootDNString.isPresent())
529    {
530      throw new ConfigureDSException(ERR_CONFIGDS_NO_CONFIG_CHANGES.get(), WRONG_USAGE);
531    }
532  }
533
534  private void checkPortArguments() throws ConfigureDSException
535  {
536    try
537    {
538      final IntegerArgument[] portArgs = {ldapPort, adminConnectorPort, ldapsPort, jmxPort};
539      final Set<Integer> portsAdded = new HashSet<>();
540
541      for (final IntegerArgument portArg : portArgs)
542      {
543        if (portArg.isPresent())
544        {
545          final int portNumber = portArg.getIntValue();
546          if (portsAdded.contains(portNumber))
547          {
548            throw new ConfigureDSException(ERR_CONFIGDS_PORT_ALREADY_SPECIFIED.get(portArg.getIntValue()), WRONG_USAGE);
549          }
550          portsAdded.add(portNumber);
551        }
552      }
553    }
554    catch (final ArgumentException ae)
555    {
556      throw new ConfigureDSException(ae, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
557    }
558  }
559
560  private void initializeDirectoryServer() throws ConfigureDSException
561  {
562    if (serverRoot.isPresent()) {
563      final DirectoryEnvironmentConfig env = DirectoryServer.getEnvironmentConfig();
564      final String root = serverRoot.getValue();
565      try {
566        env.setServerRoot(new File(serverRoot.getValue()));
567      } catch (final InitializationException e) {
568        ERR_INITIALIZE_SERVER_ROOT.get(root, e.getMessageObject());
569      }
570    }
571
572    // Initialize the Directory Server configuration handler using the
573    // information that was provided.
574    final DirectoryServer directoryServer = DirectoryServer.getInstance();
575    DirectoryServer.bootstrapClient();
576
577    try
578    {
579      DirectoryServer.initializeJMX();
580    }
581    catch (final Exception e)
582    {
583      final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_JMX.get(configFile.getValue(), e.getMessage());
584      throw new ConfigureDSException(e, msg);
585    }
586
587    try
588    {
589      directoryServer.initializeConfiguration(configClass.getValue(), configFile.getValue());
590    }
591    catch (final Exception e)
592    {
593      final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_CONFIG.get(configFile.getValue(), e.getMessage());
594      throw new ConfigureDSException(e, msg);
595    }
596
597    try
598    {
599      directoryServer.initializeSchema();
600    }
601    catch (final Exception e)
602    {
603      final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_SCHEMA.get(configFile.getValue(), e.getMessage());
604      throw new ConfigureDSException(e, msg);
605    }
606  }
607
608  /**
609   * Make sure that we can get an exclusive lock for the Directory Server, so
610   * that no other operation will be allowed while this is in progress.
611   *
612   * @throws ConfigureDSException
613   */
614  private void tryAcquireExclusiveLocks() throws ConfigureDSException
615  {
616    if (! LockFileManager.acquireExclusiveLock(serverLockFileName, failureReason))
617    {
618      throw new ConfigureDSException(ERR_CONFIGDS_CANNOT_ACQUIRE_SERVER_LOCK.get(serverLockFileName, failureReason));
619    }
620  }
621
622  private LinkedList<DN> parseProvidedBaseDNs() throws ConfigureDSException
623  {
624    LinkedList<DN> baseDNs = new LinkedList<>();
625    if (baseDNString.isPresent())
626    {
627      for (final String dnString : baseDNString.getValues())
628      {
629        try
630        {
631          baseDNs.add(DN.valueOf(dnString));
632        }
633        catch (final Exception e)
634        {
635          throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_PARSE_BASE_DN.get(dnString, e.getMessage()));
636        }
637      }
638    }
639
640    return baseDNs;
641  }
642
643  private DN parseRootDN() throws ConfigureDSException
644  {
645    DN rootDN = null;
646    if (rootDNString.isPresent())
647    {
648      try
649      {
650        rootDN = DN.valueOf(rootDNString.getValue());
651      }
652      catch (final LocalizedIllegalArgumentException e)
653      {
654        final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_PARSE_ROOT_DN.get(
655            rootDNString.getValue(), e.getMessageObject());
656        throw new ConfigureDSException(e, msg);
657      }
658    }
659    return rootDN;
660  }
661
662  private String parseRootDNPassword() throws ConfigureDSException
663  {
664    String rootPW = null;
665    if (rootDNString.isPresent())
666    {
667      if (rootPassword.isPresent())
668      {
669        rootPW = rootPassword.getValue();
670      }
671      else if (rootPasswordFile.isPresent())
672      {
673        rootPW = rootPasswordFile.getValue();
674      }
675      else
676      {
677        throw new ConfigureDSException(ERR_CONFIGDS_NO_ROOT_PW.get());
678      }
679    }
680    return rootPW;
681  }
682
683  private void checkManagerProvider(final Argument arg, final String jckesDN, final String ldifEntry,
684      final boolean isKeyManager) throws ConfigureDSException
685  {
686    if (arg.isPresent())
687    {
688      DN dn = null;
689      DN JCEKSManagerDN = null;
690      try
691      {
692        dn = DN.valueOf(trustManagerProviderDN.getValue());
693        JCEKSManagerDN = DN.valueOf(jckesDN);
694      }
695      catch (final LocalizedIllegalArgumentException e)
696      {
697        final String value = trustManagerProviderDN.getValue();
698        final LocalizableMessage errorMessage = e.getMessageObject();
699        final LocalizableMessage message =
700            isKeyManager ? ERR_CONFIGDS_CANNOT_PARSE_KEYMANAGER_PROVIDER_DN.get(value, errorMessage)
701                         : ERR_CONFIGDS_CANNOT_PARSE_TRUSTMANAGER_PROVIDER_DN.get(value, errorMessage);
702        throw new ConfigureDSException(e, message);
703      }
704
705      if (dn.equals(JCEKSManagerDN))
706      {
707        LDIFReader reader = null;
708        try
709        {
710
711          final String ldif = ldifEntry;
712          final LDIFImportConfig ldifImportConfig = new LDIFImportConfig(new StringReader(ldif));
713          reader = new LDIFReader(ldifImportConfig);
714          Entry mangerConfigEntry;
715          while ((mangerConfigEntry = reader.readEntry()) != null)
716          {
717            configHandler.addEntry(mangerConfigEntry, null);
718          }
719        }
720        catch (final Exception e)
721        {
722          final LocalizableMessage message = isKeyManager ? ERR_CONFIG_KEYMANAGER_CANNOT_CREATE_JCEKS_PROVIDER.get(e)
723                                                          : ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e);
724          throw new ConfigureDSException(e, message);
725        }
726        finally
727        {
728          close(reader);
729        }
730      }
731      else
732      {
733        try
734        {
735          configHandler.getConfigEntry(dn);
736        }
737        catch (final Exception e)
738        {
739          final LocalizableMessage message = isKeyManager ? ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e)
740                                                          : ERR_CONFIG_TRUSTMANAGER_CANNOT_GET_BASE.get(e);
741          throw new ConfigureDSException(e, message);
742        }
743      }
744    }
745  }
746
747  @SuppressWarnings("unchecked")
748  private void updateBaseDNs(final List<DN> baseDNs) throws ConfigureDSException
749  {
750    if (!baseDNs.isEmpty())
751    {
752      final String backendTypeName = backendType.getValue();
753      final BackendTypeHelper backendTypeHelper = new BackendTypeHelper();
754      final ManagedObjectDefinition<?, ?> backend = backendTypeHelper.retrieveBackendTypeFromName(backendTypeName);
755      if (backend == null)
756      {
757        throw new ConfigureDSException(
758            ERR_CONFIGDS_BACKEND_TYPE_UNKNOWN.get(backendTypeName, backendTypeHelper.getPrintableBackendTypeNames()));
759      }
760
761      try
762      {
763        BackendCreationHelper.createBackendOffline(Installer.ROOT_BACKEND_NAME, baseDNs,
764            (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>) backend);
765      }
766      catch (Exception e)
767      {
768        throw new ConfigureDSException(ERR_CONFIGDS_SET_BACKEND_TYPE.get(backendTypeName, e.getMessage()));
769      }
770    }
771  }
772
773  private void updateLdapPort() throws ConfigureDSException
774  {
775    if (ldapPort.isPresent())
776    {
777      try
778      {
779        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
780            ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
781            true, false, true, true, 1, true, 65535, ldapPort.getIntValue());
782        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAP_CONNECTION_HANDLER));
783        configEntry.putConfigAttribute(portAttr);
784      }
785      catch (final Exception e)
786      {
787        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_LDAP_PORT.get(e));
788      }
789    }
790  }
791
792  private void updateAdminConnectorPort() throws ConfigureDSException
793  {
794    if (adminConnectorPort.isPresent())
795    {
796      try
797      {
798        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
799            ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
800            true, false, true, true, 1, true, 65535, adminConnectorPort.getIntValue());
801        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_ADMIN_CONNECTOR));
802        configEntry.putConfigAttribute(portAttr);
803      }
804      catch (final Exception e)
805      {
806        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_ADMIN_CONNECTOR_PORT.get(e));
807      }
808    }
809  }
810
811  private void updateLdapSecurePort() throws ConfigureDSException
812  {
813    if (ldapsPort.isPresent())
814    {
815      try
816      {
817        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
818            ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
819            true, false, true, true, 1, true, 65535, ldapsPort.getIntValue());
820        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAPS_CONNECTION_HANDLER));
821        configEntry.putConfigAttribute(portAttr);
822
823        final BooleanConfigAttribute enablePortAttr = new BooleanConfigAttribute(
824            ATTR_CONNECTION_HANDLER_ENABLED, INFO_LDAPS_CONNHANDLER_DESCRIPTION_ENABLE.get(), true, true);
825        configEntry.putConfigAttribute(enablePortAttr);
826      }
827      catch (final Exception e)
828      {
829        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_LDAPS_PORT.get(e));
830      }
831    }
832  }
833
834  private void updateJMXport() throws ConfigureDSException
835  {
836    if (jmxPort.isPresent())
837    {
838      try
839      {
840
841        final IntegerConfigAttribute portAttr = new IntegerConfigAttribute(
842            ATTR_LISTEN_PORT, INFO_JMX_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(),
843            true, false, true, true, 1, true, 65535, jmxPort.getIntValue());
844        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_JMX_CONNECTION_HANDLER));
845        configEntry.putConfigAttribute(portAttr);
846
847        final BooleanConfigAttribute enablePortAttr = new BooleanConfigAttribute(
848            ATTR_CONNECTION_HANDLER_ENABLED, INFO_JMX_CONNHANDLER_DESCRIPTION_ENABLE.get(), true, true);
849        configEntry.putConfigAttribute(enablePortAttr);
850      }
851      catch (final Exception e)
852      {
853        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_JMX_PORT.get(e));
854      }
855    }
856  }
857
858  private void updateStartTLS() throws ConfigureDSException
859  {
860    if (enableStartTLS.isPresent())
861    {
862      try
863      {
864        final BooleanConfigAttribute startTLS = new BooleanConfigAttribute(
865            ATTR_ALLOW_STARTTLS, INFO_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS.get(), true, true);
866        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAP_CONNECTION_HANDLER));
867        configEntry.putConfigAttribute(startTLS);
868      }
869      catch (final Exception e)
870      {
871        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_STARTTLS.get(e));
872      }
873    }
874  }
875
876  private void updateKeyManager() throws ConfigureDSException
877  {
878    if (keyManagerProviderDN.isPresent())
879    {
880      if (enableStartTLS.isPresent() || ldapsPort.isPresent())
881      {
882        try
883        {
884          // Enable the key manager
885          final BooleanConfigAttribute enableAttr = new BooleanConfigAttribute(
886              ATTR_KEYMANAGER_ENABLED, INFO_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED.get(), true, true);
887          final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(keyManagerProviderDN.getValue()));
888          configEntry.putConfigAttribute(enableAttr);
889        }
890        catch (final Exception e)
891        {
892          throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_KEYMANAGER.get(e));
893        }
894      }
895
896      putKeyManagerConfigAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER);
897      putKeyManagerConfigAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER);
898      putKeyManagerConfigAttribute(ldapsPort, DN_HTTP_CONNECTION_HANDLER);
899
900      if (keyManagerPath.isPresent())
901      {
902        try
903        {
904          final StringConfigAttribute pathAttr = new StringConfigAttribute(
905              ATTR_KEYSTORE_FILE, INFO_FILE_KEYMANAGER_DESCRIPTION_FILE.get(),
906              true, true, true, keyManagerPath.getValue());
907          final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(keyManagerProviderDN.getValue()));
908          configEntry.putConfigAttribute(pathAttr);
909        }
910        catch (final Exception e)
911        {
912          throw new ConfigureDSException(e, LocalizableMessage.raw(e.toString()));
913        }
914      }
915    }
916  }
917
918  private void putKeyManagerConfigAttribute(final Argument arg, final String attributeDN)
919      throws ConfigureDSException
920  {
921    if (arg.isPresent())
922    {
923      try
924      {
925        final StringConfigAttribute keyManagerProviderAttr = new StringConfigAttribute(
926            ATTR_KEYMANAGER_DN, INFO_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN.get(),
927            false, false, true, keyManagerProviderDN.getValue());
928        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
929        configEntry.putConfigAttribute(keyManagerProviderAttr);
930      }
931      catch (final Exception e)
932      {
933        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_KEYMANAGER_REFERENCE.get(e));
934      }
935    }
936  }
937
938  private void updateTrustManager() throws ConfigureDSException
939  {
940    if (trustManagerProviderDN.isPresent())
941    {
942      if (enableStartTLS.isPresent() || ldapsPort.isPresent())
943      {
944        try
945        {
946          final BooleanConfigAttribute enableAttr = new BooleanConfigAttribute(
947              ATTR_TRUSTMANAGER_ENABLED, ERR_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED.get(), true, true);
948          final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(trustManagerProviderDN.getValue()));
949          configEntry.putConfigAttribute(enableAttr);
950        }
951        catch (final Exception e)
952        {
953          throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_TRUSTMANAGER.get(e));
954        }
955      }
956      putTrustManagerAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER);
957      putTrustManagerAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER);
958      putTrustManagerAttribute(ldapsPort, DN_HTTP_CONNECTION_HANDLER);
959    }
960
961    if (certNickNames.isPresent())
962    {
963      final StringConfigAttribute certNickNamesAttr = new StringConfigAttribute(
964          ATTR_SSL_CERT_NICKNAME, INFO_LDAP_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(),
965          false, true, true, certNickNames.getValues());
966      updateCertNicknameEntry(ldapPort, DN_LDAP_CONNECTION_HANDLER, certNickNamesAttr);
967      updateCertNicknameEntry(ldapsPort, DN_LDAPS_CONNECTION_HANDLER, certNickNamesAttr);
968      updateCertNicknameEntry(certNickNames, DN_HTTP_CONNECTION_HANDLER, certNickNamesAttr);
969
970      final StringConfigAttribute certNickNamesJmxAttr = new StringConfigAttribute(
971          ATTR_SSL_CERT_NICKNAME, INFO_JMX_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(),
972          false, false, true, certNickNames.getValues());
973      updateCertNicknameEntry(jmxPort, DN_JMX_CONNECTION_HANDLER, certNickNamesJmxAttr);
974    }
975    else
976    {
977      // Use the key manager specified for connection handlers
978      removeSSLCertNicknameAttribute(DN_LDAP_CONNECTION_HANDLER);
979      removeSSLCertNicknameAttribute(DN_LDAPS_CONNECTION_HANDLER);
980      removeSSLCertNicknameAttribute(DN_HTTP_CONNECTION_HANDLER);
981      removeSSLCertNicknameAttribute(DN_JMX_CONNECTION_HANDLER);
982    }
983  }
984
985  private void putTrustManagerAttribute(final Argument arg, final String attributeDN) throws ConfigureDSException
986  {
987    if (arg.isPresent())
988    {
989      try
990      {
991        final StringConfigAttribute trustManagerProviderAttr = new StringConfigAttribute(
992            ATTR_TRUSTMANAGER_DN, INFO_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN.get(),
993            false, false, true, trustManagerProviderDN.getValue());
994        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
995        configEntry.putConfigAttribute(trustManagerProviderAttr);
996      }
997      catch (final Exception e)
998      {
999        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_TRUSTMANAGER_REFERENCE.get(e));
1000      }
1001    }
1002  }
1003
1004  private void updateCertNicknameEntry(final Argument arg, final String attributeDN,
1005      final StringConfigAttribute configAttr) throws ConfigureDSException
1006  {
1007    try
1008    {
1009      ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
1010      if (arg.isPresent())
1011      {
1012        configEntry.putConfigAttribute(configAttr);
1013      }
1014      else
1015      {
1016        configEntry.removeConfigAttribute(ATTR_SSL_CERT_NICKNAME);
1017      }
1018    }
1019    catch (final Exception e)
1020    {
1021      throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e));
1022    }
1023  }
1024
1025  private void removeSSLCertNicknameAttribute(final String attributeDN) throws ConfigureDSException
1026  {
1027    try
1028    {
1029      final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN));
1030      configEntry.removeConfigAttribute(ATTR_SSL_CERT_NICKNAME.toLowerCase());
1031    }
1032    catch (final Exception e)
1033    {
1034      throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e));
1035    }
1036  }
1037
1038  private void updateRootUser(final DN rootDN, final String rootPW) throws ConfigureDSException
1039  {
1040    if (rootDN != null)
1041    {
1042      try
1043      {
1044        final DNConfigAttribute bindDNAttr = new DNConfigAttribute(
1045            ATTR_ROOTDN_ALTERNATE_BIND_DN, INFO_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN.get(),
1046            false, true, false, rootDN);
1047        final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_ROOT_USER));
1048        configEntry.putConfigAttribute(bindDNAttr);
1049
1050        final String encodedPassword = SaltedSHA512PasswordStorageScheme.encodeOffline(getBytes(rootPW));
1051        final StringConfigAttribute bindPWAttr = new StringConfigAttribute(
1052            ATTR_USER_PASSWORD, LocalizableMessage.EMPTY, false, false, false, encodedPassword);
1053        configEntry.putConfigAttribute(bindPWAttr);
1054      }
1055      catch (final Exception e)
1056      {
1057        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_ROOT_USER.get(e));
1058      }
1059    }
1060  }
1061
1062  /** Set the FQDN for the DIGEST-MD5 SASL mechanism. */
1063  private void addFQDNDigestMD5() throws ConfigureDSException
1064  {
1065    try
1066    {
1067      final StringConfigAttribute fqdnAttr = new StringConfigAttribute(
1068            "ds-cfg-server-fqdn", LocalizableMessage.EMPTY, false, false, false, hostName.getValue());
1069      final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_DIGEST_MD5_SASL_MECHANISM));
1070      configEntry.putConfigAttribute(fqdnAttr);
1071    }
1072    catch (final Exception e)
1073    {
1074      throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_DIGEST_MD5_FQDN.get(e));
1075    }
1076  }
1077
1078  /**
1079   * Check that the cipher specified is supported. This is intended to fix
1080   * issues with JVM that do not support the default cipher (see issue 3075 for
1081   * instance).
1082   *
1083   * @throws ConfigureDSException
1084   */
1085  private void updateCryptoCipher() throws ConfigureDSException
1086  {
1087    final CryptoManagerCfgDefn cryptoManager = CryptoManagerCfgDefn.getInstance();
1088    final StringPropertyDefinition prop = cryptoManager.getKeyWrappingTransformationPropertyDefinition();
1089    String defaultCipher = null;
1090
1091    final DefaultBehaviorProvider<?> p = prop.getDefaultBehaviorProvider();
1092    if (p instanceof DefinedDefaultBehaviorProvider)
1093    {
1094      final Collection<?> defaultValues = ((DefinedDefaultBehaviorProvider<?>) p).getDefaultValues();
1095      if (!defaultValues.isEmpty())
1096      {
1097        defaultCipher = defaultValues.iterator().next().toString();
1098      }
1099    }
1100
1101    if (defaultCipher != null)
1102    {
1103      // Check that the default cipher is supported by the JVM.
1104      try
1105      {
1106        Cipher.getInstance(defaultCipher);
1107      }
1108      catch (final GeneralSecurityException ex)
1109      {
1110        // The cipher is not supported: try to find an alternative one.
1111        final String alternativeCipher = getAlternativeCipher();
1112        if (alternativeCipher != null)
1113        {
1114          try
1115          {
1116            final StringConfigAttribute keyWrappingTransformation = new StringConfigAttribute(
1117                ATTR_CRYPTO_CIPHER_KEY_WRAPPING_TRANSFORMATION, LocalizableMessage.EMPTY,
1118                false, false, true, alternativeCipher);
1119            final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_CRYPTO_MANAGER));
1120            configEntry.putConfigAttribute(keyWrappingTransformation);
1121          }
1122          catch (final Exception e)
1123          {
1124            throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CRYPTO_MANAGER.get(e));
1125          }
1126        }
1127      }
1128    }
1129  }
1130
1131  private void writeUpdatedConfiguration() throws ConfigureDSException
1132  {
1133    try
1134    {
1135      configHandler.writeUpdatedConfig();
1136      printWrappedText(out, INFO_CONFIGDS_WROTE_UPDATED_CONFIG.get());
1137    }
1138    catch (final DirectoryException de)
1139    {
1140      throw new ConfigureDSException(de, ERR_CONFIGDS_CANNOT_WRITE_UPDATED_CONFIG.get(de.getMessageObject()));
1141    }
1142  }
1143
1144  /**
1145   * Returns a cipher that is supported by the JVM we are running at.
1146   * Returns <CODE>null</CODE> if no alternative cipher could be found.
1147   * @return a cipher that is supported by the JVM we are running at.
1148   */
1149  public static String getAlternativeCipher()
1150  {
1151    final String[] preferredAlternativeCiphers =
1152    {
1153        "RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING",
1154        "RSA/ECB/PKCS1Padding"
1155    };
1156    String alternativeCipher = null;
1157    for (final String cipher : preferredAlternativeCiphers)
1158    {
1159      try
1160      {
1161        Cipher.getInstance(cipher);
1162        alternativeCipher = cipher;
1163        break;
1164      }
1165      catch (final Throwable t)
1166      {
1167      }
1168    }
1169    return alternativeCipher;
1170  }
1171}
1172