001/* 002 * Copyright 2011-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2011-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2011-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.listener; 037 038 039 040import java.io.File; 041import java.io.OutputStream; 042import java.io.Serializable; 043import java.net.Socket; 044import java.security.MessageDigest; 045import java.util.ArrayList; 046import java.util.EnumSet; 047import java.util.Iterator; 048import java.util.LinkedHashMap; 049import java.util.List; 050import java.util.Map; 051import java.util.Set; 052import java.util.TreeMap; 053import java.util.logging.FileHandler; 054import java.util.logging.Level; 055import java.util.logging.StreamHandler; 056import javax.net.ssl.KeyManager; 057import javax.net.ssl.TrustManager; 058 059import com.unboundid.ldap.sdk.DN; 060import com.unboundid.ldap.sdk.LDAPException; 061import com.unboundid.ldap.sdk.OperationType; 062import com.unboundid.ldap.sdk.ResultCode; 063import com.unboundid.ldap.sdk.Version; 064import com.unboundid.ldap.sdk.schema.Schema; 065import com.unboundid.ldap.sdk.schema.SchemaValidator; 066import com.unboundid.util.CommandLineTool; 067import com.unboundid.util.Debug; 068import com.unboundid.util.MinimalLogFormatter; 069import com.unboundid.util.NotMutable; 070import com.unboundid.util.NotNull; 071import com.unboundid.util.Nullable; 072import com.unboundid.util.ObjectPair; 073import com.unboundid.util.StaticUtils; 074import com.unboundid.util.ThreadSafety; 075import com.unboundid.util.ThreadSafetyLevel; 076import com.unboundid.util.args.ArgumentException; 077import com.unboundid.util.args.ArgumentParser; 078import com.unboundid.util.args.BooleanArgument; 079import com.unboundid.util.args.DNArgument; 080import com.unboundid.util.args.IntegerArgument; 081import com.unboundid.util.args.FileArgument; 082import com.unboundid.util.args.StringArgument; 083import com.unboundid.util.ssl.KeyStoreKeyManager; 084import com.unboundid.util.ssl.SSLUtil; 085import com.unboundid.util.ssl.TrustAllTrustManager; 086import com.unboundid.util.ssl.TrustStoreTrustManager; 087import com.unboundid.util.ssl.cert.CertException; 088 089import static com.unboundid.ldap.listener.ListenerMessages.*; 090 091 092 093/** 094 * This class provides a command-line tool that can be used to run an instance 095 * of the in-memory directory server. Instances of the server may also be 096 * created and controlled programmatically using the 097 * {@link InMemoryDirectoryServer} class. 098 * <BR><BR> 099 * The following command-line arguments may be used with this class: 100 * <UL> 101 * <LI>"-b {baseDN}" or "--baseDN {baseDN}" -- specifies a base DN to use for 102 * the server. At least one base DN must be specified, and multiple 103 * base DNs may be provided as separate arguments.</LI> 104 * <LI>"-p {port}" or "--port {port}" -- specifies the port on which the 105 * server should listen for client connections. If this is not provided, 106 * then a free port will be automatically chosen for use by the 107 * server.</LI> 108 * <LI>"-l {path}" or "--ldifFile {path}" -- specifies the path to an LDIF 109 * file to use to initially populate the server. If this is not provided, 110 * then the server will initially be empty. The LDIF file will not be 111 * updated as operations are processed in the server.</LI> 112 * <LI>"-D {bindDN}" or "--additionalBindDN {bindDN}" -- specifies an 113 * additional DN that can be used to authenticate to the server, even if 114 * there is no account for that user. If this is provided, then the 115 * --additionalBindPassword argument must also be given.</LI> 116 * <LI>"-w {password}" or "--additionalBindPassword {password}" -- specifies 117 * the password that should be used when attempting to bind as the user 118 * specified with the "-additionalBindDN" argument. If this is provided, 119 * then the --additionalBindDN argument must also be given.</LI> 120 * <LI>"-c {count}" or "--maxChangeLogEntries {count}" -- Indicates whether an 121 * LDAP changelog should be enabled, and if so how many changelog records 122 * should be maintained. If this argument is not provided, or if it is 123 * provided with a value of zero, then no changelog will be 124 * maintained.</LI> 125 * <LI>"-A" or "--accessLogToStandardOut" -- indicates that access log 126 * information should be written to standard output. This cannot be 127 * provided in conjunction with the "--accessLogFile" argument. If 128 * neither argument is provided, then no access logging will be 129 * performed</LI> 130 * <LI>"-a {path}" or "--accessLogFile {path}" -- specifies the path to a file 131 * that should be used as a server access log. This cannot be provided in 132 * conjunction with the "--accessLogToStandardOut" argument. If neither 133 * argument is provided, then no access logging will be performed</LI> 134 * <LI>"---jsonAccessLogToStandardOut" -- indicates that JSON-formatted access 135 * log information should be written to standard output. This cannot be 136 * provided in conjunction with the "--jsonAccessLogFile" argument. If 137 * neither argument is provided, then no JSON-formatted access logging 138 * will be performed</LI> 139 * <LI>"--jsonAccessLogFile {path}" -- specifies the path to a file that 140 * should be used as a server access log with JSON-formatted messages. 141 * This cannot be provided in conjunction with the 142 * "--jsonAccessLogToStandardOut" argument. If neither argument is 143 * provided, then no JSON-formatted access logging will be performed</LI> 144 * <LI>"--ldapDebugLogToStandardOut" -- Indicates that LDAP debug log 145 * information should be written to standard output. This cannot be 146 * provided in conjunction with the "--ldapDebugLogFile" argument. If 147 * neither argument is provided, then no debug logging will be 148 * performed.</LI> 149 * <LI>"-d {path}" or "--ldapDebugLogFile {path}" -- specifies the path to a 150 * file that should be used as a server LDAP debug log. This cannot be 151 * provided in conjunction with the "--ldapDebugLogToStandardOut" 152 * argument. If neither argument is provided, then no debug logging will 153 * be performed.</LI> 154 * <LI>"-s" or "--useDefaultSchema" -- Indicates that the server should use 155 * the default standard schema provided as part of the LDAP SDK. If 156 * neither this argument nor the "--useSchemaFile" argument is provided, 157 * then the server will not enforce schema compliance.</LI> 158 * <LI>"-S {path}" or "--useSchemaFile {path}" -- specifies the path to a file 159 * or directory containing schema definitions to use for the server. If 160 * neither this argument nor the "--useDefaultSchema" argument is 161 * provided, then the server will not enforce schema compliance. If 162 * the specified path represents a file, then it must be an LDIF file 163 * containing a valid LDAP subschema subentry. If the path is a 164 * directory, then its files will be processed in lexicographic order by 165 * name.</LI> 166 * <LI>"--doNotValidateSchemaDefinitions" -- indicates that the server should 167 * not perform any validation for the custom schema provided using the 168 * --useSchemaFile argument. If this argument is not used and a custom 169 * schema is configured, then the server will validate that schema and 170 * report errors or warnings for any issues that it identifies with that 171 * schema.</LI> 172 * <LI>"-I {attr}" or "--equalityIndex {attr}" -- specifies that an equality 173 * index should be maintained for the specified attribute. The equality 174 * index may be used to speed up certain kinds of searches, although it 175 * will cause the server to consume more memory.</LI> 176 * <LI>"-Z" or "--useSSL" -- indicates that the server should encrypt all 177 * communication using SSL. If this is provided, then the 178 * "--keyStorePath" and "--keyStorePassword" arguments must also be 179 * provided, and the "--useStartTLS" argument must not be provided.</LI> 180 * <LI>"-q" or "--useStartTLS" -- indicates that the server should support the 181 * use of the StartTLS extended request. If this is provided, then the 182 * "--keyStorePath" and "--keyStorePassword" arguments must also be 183 * provided, and the "--useSSL" argument must not be provided.</LI> 184 * <LI>"-K {path}" or "--keyStorePath {path}" -- specifies the path to the JKS 185 * key store file that should be used to obtain the server certificate to 186 * use for SSL communication. If this argument is provided, then the 187 * "--keyStorePassword" argument must also be provided, along with exactly 188 * one of the "--useSSL" or "--useStartTLS" arguments.</LI> 189 * <LI>"-W {password}" or "--keyStorePassword {password}" -- specifies the 190 * password that should be used to access the contents of the SSL key 191 * store. If this argument is provided, then the "--keyStorePath" 192 * argument must also be provided, along with exactly one of the 193 * "--useSSL" or "--useStartTLS" arguments.</LI> 194 * <LI>"--keyStoreType {type}" -- specifies the type of keystore represented 195 * by the file specified by the keystore path. If this argument is 196 * provided, then the "--keyStorePath" argument must also be provided, 197 * along with exactly one of the "--useSSL" or "--useStartTLS" arguments. 198 * If this argument is not provided, then a default key store type of 199 * "JKS" will be assumed.</LI> 200 * <LI>"--generateSelfSignedCertificate" -- indicates that the server should 201 * generate a self-signed certificate to use for SSL or StartTLS 202 * communication. If this argument is provided, then exactly one of the 203 * "--useSSL" or "--useStartTLS" arguments must also be specified.</LI> 204 * <LI>"-P {path}" or "--trustStorePath {path}" -- specifies the path to the 205 * JKS trust store file that should be used to determine whether to trust 206 * any SSL certificates that may be presented by the client. If this 207 * argument is provided, then exactly one of the "--useSSL" or 208 * "--useStartTLS" arguments must also be provided. If this argument is 209 * not provided but SSL or StartTLS is to be used, then all client 210 * certificates will be automatically trusted.</LI> 211 * <LI>"-T {password}" or "--trustStorePassword {password}" -- specifies the 212 * password that should be used to access the contents of the SSL trust 213 * store. If this argument is provided, then the "--trustStorePath" 214 * argument must also be provided, along with exactly one of the 215 * "--useSSL" or "--useStartTLS" arguments. If an SSL trust store path 216 * was provided without a trust store password, then the server will 217 * attempt to use the trust store without a password.</LI> 218 * <LI>"--trustStoreType {type}" -- specifies the type of trust store 219 * represented by the file specified by the trust store path. If this 220 * argument is provided, then the "--trustStorePath" argument must also 221 * be provided, along with exactly one of the "--useSSL" or 222 * "--useStartTLS" arguments. If this argument is not provided, then a 223 * default trust store type of "JKS" will be assumed.</LI> 224 * <LI>"--maxConcurrentConnections {num}" -- specifies the maximum number of 225 * concurrent connections that the server will allow.</LI> 226 * <LI>"--sizeLimit {num}" -- specifies the maximum number of entries that 227 * the server will return for a single search operation.</LI> 228 * <LI>"--passwordAttribute {attr}" -- specifies an attribute that will hold 229 * user passwords.</LI> 230 * <LI>"--defaultPasswordEncoding {scheme}" -- specifies the name of the 231 * default scheme that the server will use to encode clear-text 232 * passwords. Allowed values include MD5, SMD5, SHA, SSHA, SHA256, 233 * SSHA256, SHA384, SSHA384, SHA512, SSHA512, CLEAR, BASE64, and HEX.</LI> 234 * <LI>"--allowedOperationType {type}" -- specifies a type of operation that 235 * the server will allow. Allowed values include add, bind, compare, 236 * delete, extended, modify, modify-dn, and search.</LI> 237 * <LI>"--authenticationRequiredOperationType {type}" -- specifies a type of 238 * operation that the server will only allow for authenticated clients. 239 * Allowed values include add, compare, delete, extended, modify, 240 * modify-dn, and search.</LI> 241 * <LI>"--vendorName {name}" -- specifies the vendor name value to appear in 242 * the server root DSE.</LI> 243 * <LI>"--vendorVersion {version}" -- specifies the vendor version value to 244 * appear in the server root DSE.</LI> 245 * </UL> 246 */ 247@NotMutable() 248@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 249public final class InMemoryDirectoryServerTool 250 extends CommandLineTool 251 implements Serializable, LDAPListenerExceptionHandler 252{ 253 /** 254 * The column at which long lines should be wrapped. 255 */ 256 private static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1; 257 258 259 260 /** 261 * The serial version UID for this serializable class. 262 */ 263 private static final long serialVersionUID = 6484637038039050412L; 264 265 266 267 // The argument used to indicate that access log information should be written 268 // to standard output. 269 @Nullable private BooleanArgument accessLogToStandardOutArgument; 270 271 // Indicates that the should not attempt to validate custom schema definitions 272 // provided by the useSchemaFile argument. 273 @Nullable private BooleanArgument doNotValidateSchemaDefinitions; 274 275 // The argument used to prevent the in-memory server from starting. This is 276 // only intended to be used for internal testing purposes. 277 @Nullable private BooleanArgument dontStartArgument; 278 279 // The argument used to indicate that the server should generate a self-signed 280 // certificate for use in SSL or StartTLS negotiation. 281 @Nullable private BooleanArgument generateSelfSignedCertificateArgument; 282 283 // The argument used to indicate that JSON-formatted access log information 284 // should be written to standard output. 285 @Nullable private BooleanArgument jsonAccessLogToStandardOutArgument; 286 287 // The argument used to indicate that LDAP debug log information should be 288 // written to standard output. 289 @Nullable private BooleanArgument ldapDebugLogToStandardOutArgument; 290 291 // The argument used to indicate that the default standard schema should be 292 // used. 293 @Nullable private BooleanArgument useDefaultSchemaArgument; 294 295 // The argument used to indicate that the server should use SSL 296 @Nullable private BooleanArgument useSSLArgument; 297 298 // The argument used to indicate that the server should support the StartTLS 299 // extended operation 300 @Nullable private BooleanArgument useStartTLSArgument; 301 302 // The argument used to specify an additional bind DN to use for the server. 303 @Nullable private DNArgument additionalBindDNArgument; 304 305 // The argument used to specify the base DNs to use for the server. 306 @Nullable private DNArgument baseDNArgument; 307 308 // The argument used to specify the path to an access log file to which 309 // information should be written about operations processed by the server. 310 @Nullable private FileArgument accessLogFileArgument; 311 312 // The argument used to specify the code log file to use, if any. 313 @Nullable private FileArgument codeLogFile; 314 315 // The argument used to specify the path to an access log file to which 316 // JSON-formatted operation should be written about operations processed by 317 // the server. 318 @Nullable private FileArgument jsonAccessLogFileArgument; 319 320 // The argument used to specify the path to the SSL key store file. 321 @Nullable private FileArgument keyStorePathArgument; 322 323 // The argument used to specify the path to an LDAP debug log file to which 324 // information should be written about detailed LDAP communication performed 325 // by the server. 326 @Nullable private FileArgument ldapDebugLogFileArgument; 327 328 // The argument used to specify the path to an LDIF file with data to use to 329 // initially populate the server. 330 @Nullable private FileArgument ldifFileArgument; 331 332 // The argument used to specify the path to the SSL trust store file. 333 @Nullable private FileArgument trustStorePathArgument; 334 335 // The argument used to specify the path to a directory containing schema 336 // definitions. 337 @Nullable private FileArgument useSchemaFileArgument; 338 339 // The in-memory directory server instance that has been created by this tool. 340 @Nullable private InMemoryDirectoryServer directoryServer; 341 342 // The argument used to specify the maximum number of changelog entries that 343 // the server should maintain. 344 @Nullable private IntegerArgument maxChangeLogEntriesArgument; 345 346 // The argument used to specify the maximum number of concurrent connections. 347 @Nullable private IntegerArgument maxConcurrentConnectionsArgument; 348 349 // The argument used to specify the port on which the server should listen. 350 @Nullable private IntegerArgument portArgument; 351 352 // The argument used to specify the maximum search size limit. 353 @Nullable private IntegerArgument sizeLimitArgument; 354 355 // The argument used to specify the password for the additional bind DN. 356 @Nullable private StringArgument additionalBindPasswordArgument; 357 358 // The argument used to specify the types of allowed operations. 359 @Nullable private StringArgument allowedOperationTypeArgument; 360 361 // The argument used to specify the types of operations for which 362 // authentication is required. 363 @Nullable private StringArgument authenticationRequiredOperationTypeArgument; 364 365 // The argument used to specify the name of the default encoding scheme to use 366 // use for clear-text passwords. 367 @Nullable private StringArgument defaultPasswordEncodingArgument; 368 369 // The argument used to specify the attributes for which to maintain equality 370 // indexes. 371 @Nullable private StringArgument equalityIndexArgument; 372 373 // The argument used to specify the password to use to access the contents of 374 // the SSL key store 375 @Nullable private StringArgument keyStorePasswordArgument; 376 377 // The argument used to specify the key store type. 378 @Nullable private StringArgument keyStoreTypeArgument; 379 380 // The argument used to specify the password attribute types. 381 @Nullable private StringArgument passwordAttributeArgument; 382 383 // The argument used to specify the password to use to access the contents of 384 // the SSL trust store 385 @Nullable private StringArgument trustStorePasswordArgument; 386 387 // The argument used to specify the trust store type. 388 @Nullable private StringArgument trustStoreTypeArgument; 389 390 // The argument used to specify the server vendor name. 391 @Nullable private StringArgument vendorNameArgument; 392 393 // The argument used to specify the server vendor version. 394 @Nullable private StringArgument vendorVersionArgument; 395 396 397 398 /** 399 * Parse the provided command line arguments and uses them to start the 400 * directory server. 401 * 402 * @param args The command line arguments provided to this program. 403 */ 404 public static void main(@NotNull final String... args) 405 { 406 final ResultCode resultCode = main(args, System.out, System.err); 407 if (resultCode != ResultCode.SUCCESS) 408 { 409 System.exit(resultCode.intValue()); 410 } 411 } 412 413 414 415 /** 416 * Parse the provided command line arguments and uses them to start the 417 * directory server. 418 * 419 * @param outStream The output stream to which standard out should be 420 * written. It may be {@code null} if output should be 421 * suppressed. 422 * @param errStream The output stream to which standard error should be 423 * written. It may be {@code null} if error messages 424 * should be suppressed. 425 * @param args The command line arguments provided to this program. 426 * 427 * @return A result code indicating whether the processing was successful. 428 */ 429 @NotNull() 430 public static ResultCode main(@NotNull final String[] args, 431 @Nullable final OutputStream outStream, 432 @Nullable final OutputStream errStream) 433 { 434 final InMemoryDirectoryServerTool tool = 435 new InMemoryDirectoryServerTool(outStream, errStream); 436 return tool.runTool(args); 437 } 438 439 440 441 /** 442 * Creates a new instance of this tool that use the provided output streams 443 * for standard output and standard error. 444 * 445 * @param outStream The output stream to use for standard output. It may be 446 * {@code System.out} for the JVM's default standard output 447 * stream, {@code null} if no output should be generated, 448 * or a custom output stream if the output should be sent 449 * to an alternate location. 450 * @param errStream The output stream to use for standard error. It may be 451 * {@code System.err} for the JVM's default standard error 452 * stream, {@code null} if no output should be generated, 453 * or a custom output stream if the output should be sent 454 * to an alternate location. 455 */ 456 public InMemoryDirectoryServerTool(@Nullable final OutputStream outStream, 457 @Nullable final OutputStream errStream) 458 { 459 super(outStream, errStream); 460 461 directoryServer = null; 462 doNotValidateSchemaDefinitions = null; 463 dontStartArgument = null; 464 generateSelfSignedCertificateArgument = null; 465 useDefaultSchemaArgument = null; 466 useSSLArgument = null; 467 useStartTLSArgument = null; 468 additionalBindDNArgument = null; 469 baseDNArgument = null; 470 accessLogToStandardOutArgument = null; 471 accessLogFileArgument = null; 472 jsonAccessLogToStandardOutArgument = null; 473 jsonAccessLogFileArgument = null; 474 keyStorePathArgument = null; 475 ldapDebugLogToStandardOutArgument = null; 476 ldapDebugLogFileArgument = null; 477 ldifFileArgument = null; 478 trustStorePathArgument = null; 479 useSchemaFileArgument = null; 480 maxChangeLogEntriesArgument = null; 481 maxConcurrentConnectionsArgument = null; 482 portArgument = null; 483 sizeLimitArgument = null; 484 additionalBindPasswordArgument = null; 485 allowedOperationTypeArgument = null; 486 authenticationRequiredOperationTypeArgument = null; 487 defaultPasswordEncodingArgument = null; 488 equalityIndexArgument = null; 489 keyStorePasswordArgument = null; 490 keyStoreTypeArgument = null; 491 passwordAttributeArgument = null; 492 trustStorePasswordArgument = null; 493 trustStoreTypeArgument = null; 494 vendorNameArgument = null; 495 vendorVersionArgument = null; 496 } 497 498 499 500 /** 501 * {@inheritDoc} 502 */ 503 @Override() 504 @NotNull() 505 public String getToolName() 506 { 507 return "in-memory-directory-server"; 508 } 509 510 511 512 /** 513 * {@inheritDoc} 514 */ 515 @Override() 516 @NotNull() 517 public String getToolDescription() 518 { 519 return INFO_MEM_DS_TOOL_DESC.get(InMemoryDirectoryServer.class.getName()); 520 } 521 522 523 524 /** 525 * Retrieves the version string for this tool. 526 * 527 * @return The version string for this tool. 528 */ 529 @Override() 530 @NotNull() 531 public String getToolVersion() 532 { 533 return Version.NUMERIC_VERSION_STRING; 534 } 535 536 537 538 /** 539 * {@inheritDoc} 540 */ 541 @Override() 542 public void addToolArguments(@NotNull final ArgumentParser parser) 543 throws ArgumentException 544 { 545 portArgument = new IntegerArgument('p', "port", false, 1, 546 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PORT.get(), 547 INFO_MEM_DS_TOOL_ARG_DESC_PORT.get(), 0, 65_535); 548 portArgument.setArgumentGroupName( 549 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 550 parser.addArgument(portArgument); 551 552 useSSLArgument = new BooleanArgument('Z', "useSSL", 553 INFO_MEM_DS_TOOL_ARG_DESC_USE_SSL.get()); 554 useSSLArgument.setArgumentGroupName( 555 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 556 useSSLArgument.addLongIdentifier("use-ssl", true); 557 parser.addArgument(useSSLArgument); 558 559 useStartTLSArgument = new BooleanArgument('q', "useStartTLS", 560 INFO_MEM_DS_TOOL_ARG_DESC_USE_START_TLS.get()); 561 useStartTLSArgument.setArgumentGroupName( 562 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 563 useStartTLSArgument.addLongIdentifier("use-starttls", true); 564 useStartTLSArgument.addLongIdentifier("use-start-tls", true); 565 parser.addArgument(useStartTLSArgument); 566 567 keyStorePathArgument = new FileArgument('K', "keyStorePath", false, 1, 568 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 569 INFO_MEM_DS_TOOL_ARG_DESC_KEY_STORE_PATH.get(), true, true, true, 570 false); 571 keyStorePathArgument.setArgumentGroupName( 572 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 573 keyStorePathArgument.addLongIdentifier("key-store-path", true); 574 parser.addArgument(keyStorePathArgument); 575 576 keyStorePasswordArgument = new StringArgument('W', "keyStorePassword", 577 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PASSWORD.get(), 578 INFO_MEM_DS_TOOL_ARG_DESC_KEY_STORE_PW.get()); 579 keyStorePasswordArgument.setSensitive(true); 580 keyStorePasswordArgument.setArgumentGroupName( 581 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 582 keyStorePasswordArgument.addLongIdentifier("keyStorePIN", true); 583 keyStorePasswordArgument.addLongIdentifier("key-store-password", true); 584 keyStorePasswordArgument.addLongIdentifier("key-store-pin", true); 585 parser.addArgument(keyStorePasswordArgument); 586 587 keyStoreTypeArgument = new StringArgument(null, "keyStoreType", 588 false, 1, "{type}", INFO_MEM_DS_TOOL_ARG_DESC_KEY_STORE_TYPE.get(), 589 "JKS"); 590 keyStoreTypeArgument.setArgumentGroupName( 591 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 592 keyStoreTypeArgument.addLongIdentifier("keyStoreFormat", true); 593 keyStoreTypeArgument.addLongIdentifier("key-store-type", true); 594 keyStoreTypeArgument.addLongIdentifier("key-store-format", true); 595 parser.addArgument(keyStoreTypeArgument); 596 597 generateSelfSignedCertificateArgument = new BooleanArgument(null, 598 "generateSelfSignedCertificate", 1, 599 INFO_MEM_DS_TOOL_ARG_DESC_SELF_SIGNED_CERT.get()); 600 generateSelfSignedCertificateArgument.setArgumentGroupName( 601 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 602 generateSelfSignedCertificateArgument.addLongIdentifier( 603 "useSelfSignedCertificate", true); 604 generateSelfSignedCertificateArgument.addLongIdentifier( 605 "selfSignedCertificate", true); 606 generateSelfSignedCertificateArgument.addLongIdentifier( 607 "generate-self-signed-certificate", true); 608 generateSelfSignedCertificateArgument.addLongIdentifier( 609 "use-self-signed-certificate", true); 610 generateSelfSignedCertificateArgument.addLongIdentifier( 611 "self-signed-certificate", true); 612 parser.addArgument(generateSelfSignedCertificateArgument); 613 614 trustStorePathArgument = new FileArgument('P', "trustStorePath", false, 1, 615 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 616 INFO_MEM_DS_TOOL_ARG_DESC_TRUST_STORE_PATH.get(), true, true, true, 617 false); 618 trustStorePathArgument.setArgumentGroupName( 619 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 620 trustStorePathArgument.addLongIdentifier("trust-store-path", true); 621 parser.addArgument(trustStorePathArgument); 622 623 trustStorePasswordArgument = new StringArgument('T', "trustStorePassword", 624 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PASSWORD.get(), 625 INFO_MEM_DS_TOOL_ARG_DESC_TRUST_STORE_PW.get()); 626 trustStorePasswordArgument.setSensitive(true); 627 trustStorePasswordArgument.setArgumentGroupName( 628 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 629 trustStorePasswordArgument.addLongIdentifier("trustStorePIN", true); 630 trustStorePasswordArgument.addLongIdentifier("trust-store-password", true); 631 trustStorePasswordArgument.addLongIdentifier("trust-store-pin", true); 632 parser.addArgument(trustStorePasswordArgument); 633 634 trustStoreTypeArgument = new StringArgument(null, "trustStoreType", 635 false, 1, "{type}", INFO_MEM_DS_TOOL_ARG_DESC_TRUST_STORE_TYPE.get(), 636 "JKS"); 637 trustStoreTypeArgument.setArgumentGroupName( 638 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 639 trustStoreTypeArgument.addLongIdentifier("trustStoreFormat", true); 640 trustStoreTypeArgument.addLongIdentifier("trust-store-type", true); 641 trustStoreTypeArgument.addLongIdentifier("trust-store-format", true); 642 parser.addArgument(trustStoreTypeArgument); 643 644 maxConcurrentConnectionsArgument = new IntegerArgument(null, 645 "maxConcurrentConnections", false, 1, null, 646 INFO_MEM_DS_TOOL_ARG_DESC_MAX_CONNECTIONS.get(), 1, 647 Integer.MAX_VALUE, Integer.MAX_VALUE); 648 maxConcurrentConnectionsArgument.setArgumentGroupName( 649 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 650 maxConcurrentConnectionsArgument.addLongIdentifier( 651 "maximumConcurrentConnections", true); 652 maxConcurrentConnectionsArgument.addLongIdentifier( 653 "maxConnections", true); 654 maxConcurrentConnectionsArgument.addLongIdentifier( 655 "maximumConnections", true); 656 maxConcurrentConnectionsArgument.addLongIdentifier( 657 "max-concurrent-connections", true); 658 maxConcurrentConnectionsArgument.addLongIdentifier( 659 "maximum-concurrent-connections", true); 660 maxConcurrentConnectionsArgument.addLongIdentifier( 661 "max-connections", true); 662 maxConcurrentConnectionsArgument.addLongIdentifier( 663 "maximum-connections", true); 664 parser.addArgument(maxConcurrentConnectionsArgument); 665 666 dontStartArgument = new BooleanArgument(null, "dontStart", 667 INFO_MEM_DS_TOOL_ARG_DESC_DONT_START.get()); 668 dontStartArgument.setArgumentGroupName( 669 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 670 dontStartArgument.setHidden(true); 671 dontStartArgument.addLongIdentifier("doNotStart", true); 672 dontStartArgument.addLongIdentifier("dont-start", true); 673 dontStartArgument.addLongIdentifier("do-not-start", true); 674 parser.addArgument(dontStartArgument); 675 676 baseDNArgument = new DNArgument('b', "baseDN", true, 0, 677 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_BASE_DN.get(), 678 INFO_MEM_DS_TOOL_ARG_DESC_BASE_DN.get()); 679 baseDNArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 680 baseDNArgument.addLongIdentifier("base-dn", true); 681 parser.addArgument(baseDNArgument); 682 683 ldifFileArgument = new FileArgument('l', "ldifFile", false, 1, 684 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 685 INFO_MEM_DS_TOOL_ARG_DESC_LDIF_FILE.get(), true, true, true, false); 686 ldifFileArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 687 ldifFileArgument.addLongIdentifier("ldif-file", true); 688 parser.addArgument(ldifFileArgument); 689 690 additionalBindDNArgument = new DNArgument('D', "additionalBindDN", false, 1, 691 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_BIND_DN.get(), 692 INFO_MEM_DS_TOOL_ARG_DESC_ADDITIONAL_BIND_DN.get()); 693 additionalBindDNArgument.setArgumentGroupName( 694 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 695 additionalBindDNArgument.addLongIdentifier("additional-bind-dn", true); 696 parser.addArgument(additionalBindDNArgument); 697 698 additionalBindPasswordArgument = new StringArgument('w', 699 "additionalBindPassword", false, 1, 700 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PASSWORD.get(), 701 INFO_MEM_DS_TOOL_ARG_DESC_ADDITIONAL_BIND_PW.get()); 702 additionalBindPasswordArgument.setSensitive(true); 703 additionalBindPasswordArgument.setArgumentGroupName( 704 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 705 additionalBindPasswordArgument.addLongIdentifier( 706 "additional-bind-password", true); 707 parser.addArgument(additionalBindPasswordArgument); 708 709 useDefaultSchemaArgument = new BooleanArgument('s', "useDefaultSchema", 710 INFO_MEM_DS_TOOL_ARG_DESC_USE_DEFAULT_SCHEMA.get()); 711 useDefaultSchemaArgument.setArgumentGroupName( 712 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 713 useDefaultSchemaArgument.addLongIdentifier("use-default-schema", true); 714 parser.addArgument(useDefaultSchemaArgument); 715 716 useSchemaFileArgument = new FileArgument('S', "useSchemaFile", false, 0, 717 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 718 INFO_MEM_DS_TOOL_ARG_DESC_USE_SCHEMA_FILE.get(), true, true, false, 719 false); 720 useSchemaFileArgument.setArgumentGroupName( 721 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 722 useSchemaFileArgument.addLongIdentifier("use-schema-file", true); 723 parser.addArgument(useSchemaFileArgument); 724 725 doNotValidateSchemaDefinitions = new BooleanArgument(null, 726 "doNotValidateSchemaDefinitions", 1, 727 INFO_MEM_DS_TOOL_ARG_DESC_DO_NOT_VALIDATE_SCHEMA.get( 728 useSchemaFileArgument.getIdentifierString())); 729 doNotValidateSchemaDefinitions.setArgumentGroupName( 730 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 731 doNotValidateSchemaDefinitions.addLongIdentifier( 732 "do-not-validate-schema-definitions", true); 733 parser.addArgument(doNotValidateSchemaDefinitions); 734 735 equalityIndexArgument = new StringArgument('I', "equalityIndex", false, 0, 736 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_ATTR.get(), 737 INFO_MEM_DS_TOOL_ARG_DESC_EQ_INDEX.get()); 738 equalityIndexArgument.setArgumentGroupName( 739 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 740 equalityIndexArgument.addLongIdentifier("equality-index", true); 741 parser.addArgument(equalityIndexArgument); 742 743 maxChangeLogEntriesArgument = new IntegerArgument('c', 744 "maxChangeLogEntries", false, 1, 745 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_COUNT.get(), 746 INFO_MEM_DS_TOOL_ARG_DESC_MAX_CHANGELOG_ENTRIES.get(), 0, 747 Integer.MAX_VALUE, 0); 748 maxChangeLogEntriesArgument.setArgumentGroupName( 749 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 750 maxChangeLogEntriesArgument.addLongIdentifier("max-changelog-entries", 751 true); 752 maxChangeLogEntriesArgument.addLongIdentifier("max-change-log-entries", 753 true); 754 parser.addArgument(maxChangeLogEntriesArgument); 755 756 sizeLimitArgument = new IntegerArgument(null, "sizeLimit", false, 1, null, 757 INFO_MEM_DS_TOOL_ARG_DESC_SIZE_LIMIT.get(), 1, Integer.MAX_VALUE, 758 Integer.MAX_VALUE); 759 sizeLimitArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 760 sizeLimitArgument.addLongIdentifier("searchSizeLimit", true); 761 sizeLimitArgument.addLongIdentifier("size-limit", true); 762 sizeLimitArgument.addLongIdentifier("search-size-limit", true); 763 parser.addArgument(sizeLimitArgument); 764 765 passwordAttributeArgument = new StringArgument(null, "passwordAttribute", 766 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_ATTR.get(), 767 INFO_MEM_DS_TOOL_ARG_DESC_PASSWORD_ATTRIBUTE.get(), "userPassword"); 768 passwordAttributeArgument.setArgumentGroupName( 769 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 770 passwordAttributeArgument.addLongIdentifier("passwordAttributeType", true); 771 passwordAttributeArgument.addLongIdentifier("password-attribute", true); 772 passwordAttributeArgument.addLongIdentifier("password-attribute-type", 773 true); 774 parser.addArgument(passwordAttributeArgument); 775 776 final Set<String> allowedSchemes = StaticUtils.setOf("md5", "smd5", "sha", 777 "ssha", "sha256", "ssha256", "sha384", "ssha384", "sha512", "ssha512", 778 "clear", "base64", "hex"); 779 defaultPasswordEncodingArgument = new StringArgument(null, 780 "defaultPasswordEncoding", false, 1, 781 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_SCHEME.get(), 782 INFO_MEM_DS_TOOL_ARG_DESC_DEFAULT_PASSWORD_ENCODING.get(), 783 allowedSchemes); 784 defaultPasswordEncodingArgument.setArgumentGroupName( 785 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 786 defaultPasswordEncodingArgument.addLongIdentifier( 787 "defaultPasswordEncodingScheme", true); 788 defaultPasswordEncodingArgument.addLongIdentifier( 789 "defaultPasswordStorageScheme", true); 790 defaultPasswordEncodingArgument.addLongIdentifier( 791 "defaultPasswordScheme", true); 792 defaultPasswordEncodingArgument.addLongIdentifier( 793 "default-password-encoding", true); 794 defaultPasswordEncodingArgument.addLongIdentifier( 795 "default-password-encoding-scheme", true); 796 defaultPasswordEncodingArgument.addLongIdentifier( 797 "default-password-storage-scheme", true); 798 defaultPasswordEncodingArgument.addLongIdentifier( 799 "default-password-scheme", true); 800 parser.addArgument(defaultPasswordEncodingArgument); 801 802 final Set<String> allowedOperationTypeAllowedValues = StaticUtils.setOf( 803 "add", "bind", "compare", "delete", "extended", "modify", "modify-dn", 804 "search"); 805 allowedOperationTypeArgument = new StringArgument(null, 806 "allowedOperationType", false, 0, 807 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_TYPE.get(), 808 INFO_MEM_DS_TOOL_ARG_DESC_ALLOWED_OP_TYPE.get(), 809 allowedOperationTypeAllowedValues); 810 allowedOperationTypeArgument.setArgumentGroupName( 811 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 812 allowedOperationTypeArgument.addLongIdentifier("allowed-operation-type", 813 true); 814 parser.addArgument(allowedOperationTypeArgument); 815 816 final Set<String> authRequiredTypeAllowedValues = StaticUtils.setOf("add", 817 "compare", "delete", "extended", "modify", "modify-dn", "search"); 818 authenticationRequiredOperationTypeArgument = new StringArgument(null, 819 "authenticationRequiredOperationType", false, 0, 820 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_TYPE.get(), 821 INFO_MEM_DS_TOOL_ARG_DESC_AUTH_REQUIRED_OP_TYPE.get(), 822 authRequiredTypeAllowedValues); 823 authenticationRequiredOperationTypeArgument.setArgumentGroupName( 824 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 825 authenticationRequiredOperationTypeArgument.addLongIdentifier( 826 "requiredAuthenticationOperationType", true); 827 authenticationRequiredOperationTypeArgument.addLongIdentifier( 828 "requireAuthenticationOperationType", true); 829 authenticationRequiredOperationTypeArgument.addLongIdentifier( 830 "authentication-required-operation-type", true); 831 authenticationRequiredOperationTypeArgument.addLongIdentifier( 832 "required-authentication-operation-type", true); 833 authenticationRequiredOperationTypeArgument.addLongIdentifier( 834 "require-authentication-operation-type", true); 835 parser.addArgument(authenticationRequiredOperationTypeArgument); 836 837 vendorNameArgument = new StringArgument(null, "vendorName", false, 1, 838 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_VALUE.get(), 839 INFO_MEM_DS_TOOL_ARG_DESC_VENDOR_NAME.get()); 840 vendorNameArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 841 vendorNameArgument.addLongIdentifier("vendor-name", true); 842 parser.addArgument(vendorNameArgument); 843 844 vendorVersionArgument = new StringArgument(null, "vendorVersion", false, 1, 845 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_VALUE.get(), 846 INFO_MEM_DS_TOOL_ARG_DESC_VENDOR_VERSION.get()); 847 vendorVersionArgument.setArgumentGroupName( 848 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 849 vendorVersionArgument.addLongIdentifier("vendor-version", true); 850 parser.addArgument(vendorVersionArgument); 851 852 accessLogToStandardOutArgument = new BooleanArgument('A', 853 "accessLogToStandardOut", 854 INFO_MEM_DS_TOOL_ARG_DESC_ACCESS_LOG_TO_STDOUT.get()); 855 accessLogToStandardOutArgument.setArgumentGroupName( 856 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 857 accessLogToStandardOutArgument.addLongIdentifier( 858 "access-log-to-standard-out", true); 859 parser.addArgument(accessLogToStandardOutArgument); 860 861 accessLogFileArgument = new FileArgument('a', "accessLogFile", false, 1, 862 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 863 INFO_MEM_DS_TOOL_ARG_DESC_ACCESS_LOG_FILE.get(), false, true, true, 864 false); 865 accessLogFileArgument.setArgumentGroupName( 866 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 867 accessLogFileArgument.addLongIdentifier("access-log-format", true); 868 parser.addArgument(accessLogFileArgument); 869 870 jsonAccessLogToStandardOutArgument = new BooleanArgument(null, 871 "jsonAccessLogToStandardOut", 872 INFO_MEM_DS_TOOL_ARG_DESC_JSON_ACCESS_LOG_TO_STDOUT.get()); 873 jsonAccessLogToStandardOutArgument.setArgumentGroupName( 874 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 875 jsonAccessLogToStandardOutArgument.addLongIdentifier( 876 "json-access-log-to-standard-out", true); 877 parser.addArgument(jsonAccessLogToStandardOutArgument); 878 879 jsonAccessLogFileArgument = new FileArgument(null, "jsonAccessLogFile", 880 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 881 INFO_MEM_DS_TOOL_ARG_DESC_JSON_ACCESS_LOG_FILE.get(), false, true, 882 true, false); 883 jsonAccessLogFileArgument.setArgumentGroupName( 884 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 885 jsonAccessLogFileArgument.addLongIdentifier("json-access-log-format", true); 886 parser.addArgument(jsonAccessLogFileArgument); 887 888 ldapDebugLogToStandardOutArgument = new BooleanArgument(null, 889 "ldapDebugLogToStandardOut", 890 INFO_MEM_DS_TOOL_ARG_DESC_LDAP_DEBUG_LOG_TO_STDOUT.get()); 891 ldapDebugLogToStandardOutArgument.setArgumentGroupName( 892 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 893 ldapDebugLogToStandardOutArgument.addLongIdentifier( 894 "ldap-debug-log-to-standard-out", true); 895 parser.addArgument(ldapDebugLogToStandardOutArgument); 896 897 ldapDebugLogFileArgument = new FileArgument('d', "ldapDebugLogFile", false, 898 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 899 INFO_MEM_DS_TOOL_ARG_DESC_LDAP_DEBUG_LOG_FILE.get(), false, true, true, 900 false); 901 ldapDebugLogFileArgument.setArgumentGroupName( 902 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 903 ldapDebugLogFileArgument.addLongIdentifier("ldap-debug-log-file", true); 904 parser.addArgument(ldapDebugLogFileArgument); 905 906 codeLogFile = new FileArgument('C', "codeLogFile", false, 1, "{path}", 907 INFO_MEM_DS_TOOL_ARG_DESC_CODE_LOG_FILE.get(), false, true, true, 908 false); 909 codeLogFile.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 910 codeLogFile.addLongIdentifier("code-log-file", true); 911 parser.addArgument(codeLogFile); 912 913 parser.addExclusiveArgumentSet(useDefaultSchemaArgument, 914 useSchemaFileArgument); 915 916 parser.addDependentArgumentSet(doNotValidateSchemaDefinitions, 917 useSchemaFileArgument); 918 919 parser.addExclusiveArgumentSet(useSSLArgument, useStartTLSArgument); 920 921 parser.addExclusiveArgumentSet(keyStorePathArgument, 922 generateSelfSignedCertificateArgument); 923 924 parser.addExclusiveArgumentSet(accessLogToStandardOutArgument, 925 accessLogFileArgument); 926 927 parser.addExclusiveArgumentSet(jsonAccessLogToStandardOutArgument, 928 jsonAccessLogFileArgument); 929 930 parser.addExclusiveArgumentSet(ldapDebugLogToStandardOutArgument, 931 ldapDebugLogFileArgument); 932 933 parser.addDependentArgumentSet(additionalBindDNArgument, 934 additionalBindPasswordArgument); 935 936 parser.addDependentArgumentSet(additionalBindPasswordArgument, 937 additionalBindDNArgument); 938 939 parser.addDependentArgumentSet(useSSLArgument, keyStorePathArgument, 940 generateSelfSignedCertificateArgument); 941 942 parser.addDependentArgumentSet(keyStorePathArgument, 943 keyStorePasswordArgument); 944 945 parser.addDependentArgumentSet(keyStorePasswordArgument, 946 keyStorePathArgument); 947 948 parser.addDependentArgumentSet(keyStoreTypeArgument, 949 keyStorePathArgument); 950 951 parser.addDependentArgumentSet(useStartTLSArgument, keyStorePathArgument, 952 generateSelfSignedCertificateArgument); 953 954 parser.addDependentArgumentSet(keyStorePathArgument, useSSLArgument, 955 useStartTLSArgument); 956 957 parser.addDependentArgumentSet(generateSelfSignedCertificateArgument, 958 useSSLArgument, useStartTLSArgument); 959 960 parser.addDependentArgumentSet(trustStorePathArgument, useSSLArgument, 961 useStartTLSArgument); 962 963 parser.addDependentArgumentSet(trustStorePasswordArgument, 964 trustStorePathArgument); 965 966 parser.addDependentArgumentSet(trustStoreTypeArgument, 967 trustStorePathArgument); 968 } 969 970 971 972 /** 973 * {@inheritDoc} 974 */ 975 @Override() 976 public boolean supportsInteractiveMode() 977 { 978 return true; 979 } 980 981 982 983 /** 984 * {@inheritDoc} 985 */ 986 @Override() 987 public boolean defaultsToInteractiveMode() 988 { 989 return true; 990 } 991 992 993 994 /** 995 * Indicates whether this tool supports the use of a properties file for 996 * specifying default values for arguments that aren't specified on the 997 * command line. 998 * 999 * @return {@code true} if this tool supports the use of a properties file 1000 * for specifying default values for arguments that aren't specified 1001 * on the command line, or {@code false} if not. 1002 */ 1003 @Override() 1004 public boolean supportsPropertiesFile() 1005 { 1006 return true; 1007 } 1008 1009 1010 1011 /** 1012 * {@inheritDoc} 1013 */ 1014 @Override() 1015 @NotNull() 1016 public ResultCode doToolProcessing() 1017 { 1018 // Create a base configuration. 1019 final InMemoryDirectoryServerConfig serverConfig; 1020 try 1021 { 1022 serverConfig = getConfig(); 1023 } 1024 catch (final LDAPException le) 1025 { 1026 Debug.debugException(le); 1027 wrapErr(0, WRAP_COLUMN, 1028 ERR_MEM_DS_TOOL_ERROR_INITIALIZING_CONFIG.get(le.getMessage())); 1029 return le.getResultCode(); 1030 } 1031 1032 1033 // Create the server instance using the provided configuration, but don't 1034 // start it yet. 1035 try 1036 { 1037 directoryServer = new InMemoryDirectoryServer(serverConfig); 1038 } 1039 catch (final LDAPException le) 1040 { 1041 Debug.debugException(le); 1042 wrapErr(0, WRAP_COLUMN, 1043 ERR_MEM_DS_TOOL_ERROR_CREATING_SERVER_INSTANCE.get(le.getMessage())); 1044 return le.getResultCode(); 1045 } 1046 1047 1048 // If an LDIF file was provided, then use it to populate the server. 1049 if (ldifFileArgument.isPresent()) 1050 { 1051 final File ldifFile = ldifFileArgument.getValue(); 1052 try 1053 { 1054 final int numEntries = directoryServer.importFromLDIF(true, 1055 ldifFile.getAbsolutePath()); 1056 wrapOut(0, WRAP_COLUMN, 1057 INFO_MEM_DS_TOOL_ADDED_ENTRIES_FROM_LDIF.get(numEntries, 1058 ldifFile.getAbsolutePath())); 1059 } 1060 catch (final LDAPException le) 1061 { 1062 Debug.debugException(le); 1063 wrapErr(0, WRAP_COLUMN, 1064 ERR_MEM_DS_TOOL_ERROR_POPULATING_SERVER_INSTANCE.get( 1065 ldifFile.getAbsolutePath(), le.getMessage())); 1066 return le.getResultCode(); 1067 } 1068 } 1069 1070 1071 // Start the server. 1072 try 1073 { 1074 if (! dontStartArgument.isPresent()) 1075 { 1076 directoryServer.startListening(); 1077 wrapOut(0, WRAP_COLUMN, 1078 INFO_MEM_DS_TOOL_LISTENING.get(directoryServer.getListenPort())); 1079 } 1080 } 1081 catch (final Exception e) 1082 { 1083 Debug.debugException(e); 1084 wrapErr(0, WRAP_COLUMN, 1085 ERR_MEM_DS_TOOL_ERROR_STARTING_SERVER.get( 1086 StaticUtils.getExceptionMessage(e))); 1087 return ResultCode.LOCAL_ERROR; 1088 } 1089 1090 return ResultCode.SUCCESS; 1091 } 1092 1093 1094 1095 /** 1096 * Creates a server configuration based on information provided with 1097 * command line arguments. 1098 * 1099 * @return The configuration that was created. 1100 * 1101 * @throws LDAPException If a problem is encountered while creating the 1102 * configuration. 1103 */ 1104 @NotNull() 1105 private InMemoryDirectoryServerConfig getConfig() 1106 throws LDAPException 1107 { 1108 final List<DN> dnList = baseDNArgument.getValues(); 1109 final DN[] baseDNs = new DN[dnList.size()]; 1110 dnList.toArray(baseDNs); 1111 1112 final InMemoryDirectoryServerConfig serverConfig = 1113 new InMemoryDirectoryServerConfig(baseDNs); 1114 1115 1116 // If a listen port was specified, then update the configuration to use it. 1117 int listenPort = 0; 1118 if (portArgument.isPresent()) 1119 { 1120 listenPort = portArgument.getValue(); 1121 } 1122 1123 1124 // If schema should be used, then get it. 1125 if (useDefaultSchemaArgument.isPresent()) 1126 { 1127 serverConfig.setSchema(Schema.getDefaultStandardSchema()); 1128 } 1129 else if (useSchemaFileArgument.isPresent()) 1130 { 1131 final Map<String,File> schemaFiles = new TreeMap<>(); 1132 for (final File f : useSchemaFileArgument.getValues()) 1133 { 1134 if (f.exists()) 1135 { 1136 if (f.isFile()) 1137 { 1138 schemaFiles.put(f.getName(), f); 1139 } 1140 else 1141 { 1142 for (final File subFile : f.listFiles()) 1143 { 1144 if (subFile.isFile()) 1145 { 1146 schemaFiles.put(subFile.getName(), subFile); 1147 } 1148 } 1149 } 1150 } 1151 else 1152 { 1153 throw new LDAPException(ResultCode.PARAM_ERROR, 1154 ERR_MEM_DS_TOOL_NO_SUCH_SCHEMA_FILE.get(f.getAbsolutePath())); 1155 } 1156 } 1157 1158 if (! doNotValidateSchemaDefinitions.isPresent()) 1159 { 1160 Schema schema = null; 1161 final List<String> errorMessages = new ArrayList<>(); 1162 final SchemaValidator schemaValidator = new SchemaValidator(); 1163 for (final File schemaFile : schemaFiles.values()) 1164 { 1165 schema = schemaValidator.validateSchema(schemaFile, schema, 1166 errorMessages); 1167 } 1168 1169 if (! errorMessages.isEmpty()) 1170 { 1171 wrapErr(0, WRAP_COLUMN, 1172 WARN_MEM_DS_TOOL_SCHEMA_ISSUES_IDENTIFIED.get()); 1173 for (final String message : errorMessages) 1174 { 1175 err(); 1176 final List<String> wrappedLines = StaticUtils.wrapLine(message, 1177 (WRAP_COLUMN - 2)); 1178 final Iterator<String> iterator = wrappedLines.iterator(); 1179 err("* " + iterator.next()); 1180 while (iterator.hasNext()) 1181 { 1182 err(" " + iterator.next()); 1183 } 1184 } 1185 err(); 1186 wrapErr(0, WRAP_COLUMN, 1187 WARN_MEM_DS_TOOL_WILL_CONTINUE_WITH_SCHEMA.get( 1188 doNotValidateSchemaDefinitions.getIdentifierString())); 1189 err(); 1190 } 1191 } 1192 1193 try 1194 { 1195 serverConfig.setSchema(Schema.getSchema( 1196 new ArrayList<File>(schemaFiles.values()))); 1197 } 1198 catch (final Exception e) 1199 { 1200 Debug.debugException(e); 1201 1202 final StringBuilder fileList = new StringBuilder(); 1203 final Iterator<File> fileIterator = schemaFiles.values().iterator(); 1204 while (fileIterator.hasNext()) 1205 { 1206 fileList.append(fileIterator.next().getAbsolutePath()); 1207 if (fileIterator.hasNext()) 1208 { 1209 fileList.append(", "); 1210 } 1211 } 1212 1213 throw new LDAPException(ResultCode.LOCAL_ERROR, 1214 ERR_MEM_DS_TOOL_ERROR_READING_SCHEMA.get( 1215 fileList, StaticUtils.getExceptionMessage(e)), 1216 e); 1217 } 1218 } 1219 else 1220 { 1221 serverConfig.setSchema(null); 1222 } 1223 1224 1225 // If an additional bind DN and password are provided, then include them in 1226 // the configuration. 1227 if (additionalBindDNArgument.isPresent()) 1228 { 1229 serverConfig.addAdditionalBindCredentials( 1230 additionalBindDNArgument.getValue().toString(), 1231 additionalBindPasswordArgument.getValue()); 1232 } 1233 1234 1235 // If a maximum number of changelog entries was specified, then update the 1236 // configuration with that. 1237 if (maxChangeLogEntriesArgument.isPresent()) 1238 { 1239 serverConfig.setMaxChangeLogEntries( 1240 maxChangeLogEntriesArgument.getValue()); 1241 } 1242 1243 1244 // If a maximum number of concurrent connections was specified, then update 1245 // the configuration with that. 1246 if (maxConcurrentConnectionsArgument.isPresent()) 1247 { 1248 serverConfig.setMaxConnections( 1249 maxConcurrentConnectionsArgument.getValue()); 1250 } 1251 1252 1253 // If a size limit was specified, then update the configuration with that. 1254 if (sizeLimitArgument.isPresent()) 1255 { 1256 serverConfig.setMaxSizeLimit(sizeLimitArgument.getValue()); 1257 } 1258 1259 1260 // If the password argument was specified, then set the password arguments. 1261 if (passwordAttributeArgument.isPresent()) 1262 { 1263 serverConfig.setPasswordAttributes(passwordAttributeArgument.getValues()); 1264 } 1265 1266 1267 // Configure password encodings for the server. 1268 final LinkedHashMap<String,InMemoryPasswordEncoder> passwordEncoders = 1269 new LinkedHashMap<>(10); 1270 addUnsaltedEncoder("MD5", "MD5", passwordEncoders); 1271 addUnsaltedEncoder("SHA", "SHA-1", passwordEncoders); 1272 addUnsaltedEncoder("SHA1", "SHA-1", passwordEncoders); 1273 addUnsaltedEncoder("SHA-1", "SHA-1", passwordEncoders); 1274 addUnsaltedEncoder("SHA256", "SHA-256", passwordEncoders); 1275 addUnsaltedEncoder("SHA-256", "SHA-256", passwordEncoders); 1276 addUnsaltedEncoder("SHA384", "SHA-384", passwordEncoders); 1277 addUnsaltedEncoder("SHA-384", "SHA-384", passwordEncoders); 1278 addUnsaltedEncoder("SHA512", "SHA-512", passwordEncoders); 1279 addUnsaltedEncoder("SHA-512", "SHA-512", passwordEncoders); 1280 addSaltedEncoder("SMD5", "MD5", passwordEncoders); 1281 addSaltedEncoder("SSHA", "SHA-1", passwordEncoders); 1282 addSaltedEncoder("SSHA1", "SHA-1", passwordEncoders); 1283 addSaltedEncoder("SSHA-1", "SHA-1", passwordEncoders); 1284 addSaltedEncoder("SSHA256", "SHA-256", passwordEncoders); 1285 addSaltedEncoder("SSHA-256", "SHA-256", passwordEncoders); 1286 addSaltedEncoder("SSHA384", "SHA-384", passwordEncoders); 1287 addSaltedEncoder("SSHA-384", "SHA-384", passwordEncoders); 1288 addSaltedEncoder("SSHA512", "SHA-512", passwordEncoders); 1289 addSaltedEncoder("SSHA-512", "SHA-512", passwordEncoders); 1290 addClearEncoder("CLEAR", null, passwordEncoders); 1291 addClearEncoder("BASE64", 1292 Base64PasswordEncoderOutputFormatter.getInstance(), passwordEncoders); 1293 addClearEncoder("HEX", 1294 HexPasswordEncoderOutputFormatter.getLowercaseInstance(), 1295 passwordEncoders); 1296 1297 final InMemoryPasswordEncoder primaryEncoder; 1298 if (defaultPasswordEncodingArgument.isPresent()) 1299 { 1300 primaryEncoder = passwordEncoders.remove( 1301 StaticUtils.toLowerCase(defaultPasswordEncodingArgument.getValue())); 1302 if (primaryEncoder == null) 1303 { 1304 throw new LDAPException(ResultCode.PARAM_ERROR, 1305 ERR_MEM_DS_TOOL_UNAVAILABLE_PW_ENCODING.get( 1306 defaultPasswordEncodingArgument.getValue(), 1307 String.valueOf(passwordEncoders.keySet()))); 1308 } 1309 } 1310 else 1311 { 1312 primaryEncoder = null; 1313 } 1314 1315 serverConfig.setPasswordEncoders(primaryEncoder, 1316 passwordEncoders.values()); 1317 1318 1319 // Configure the allowed operation types. 1320 if (allowedOperationTypeArgument.isPresent()) 1321 { 1322 final EnumSet<OperationType> operationTypes = 1323 EnumSet.noneOf(OperationType.class); 1324 for (final String operationTypeName : 1325 allowedOperationTypeArgument.getValues()) 1326 { 1327 final OperationType name = OperationType.forName(operationTypeName); 1328 if (name == null) 1329 { 1330 throw new LDAPException(ResultCode.PARAM_ERROR, 1331 ERR_MEM_DS_TOOL_UNSUPPORTED_ALLOWED_OP_TYPE.get(name)); 1332 } 1333 else 1334 { 1335 switch (name) 1336 { 1337 case ADD: 1338 case BIND: 1339 case COMPARE: 1340 case DELETE: 1341 case EXTENDED: 1342 case MODIFY: 1343 case MODIFY_DN: 1344 case SEARCH: 1345 operationTypes.add(name); 1346 break; 1347 case ABANDON: 1348 case UNBIND: 1349 default: 1350 throw new LDAPException(ResultCode.PARAM_ERROR, 1351 ERR_MEM_DS_TOOL_UNSUPPORTED_ALLOWED_OP_TYPE.get(name)); 1352 } 1353 } 1354 } 1355 1356 serverConfig.setAllowedOperationTypes(operationTypes); 1357 } 1358 1359 1360 // Configure the authentication required operation types. 1361 if (authenticationRequiredOperationTypeArgument.isPresent()) 1362 { 1363 final EnumSet<OperationType> operationTypes = 1364 EnumSet.noneOf(OperationType.class); 1365 for (final String operationTypeName : 1366 authenticationRequiredOperationTypeArgument.getValues()) 1367 { 1368 final OperationType name = OperationType.forName(operationTypeName); 1369 if (name == null) 1370 { 1371 throw new LDAPException(ResultCode.PARAM_ERROR, 1372 ERR_MEM_DS_TOOL_UNSUPPORTED_AUTH_REQUIRED_OP_TYPE.get(name)); 1373 } 1374 else 1375 { 1376 switch (name) 1377 { 1378 case ADD: 1379 case COMPARE: 1380 case DELETE: 1381 case EXTENDED: 1382 case MODIFY: 1383 case MODIFY_DN: 1384 case SEARCH: 1385 operationTypes.add(name); 1386 break; 1387 case ABANDON: 1388 case UNBIND: 1389 default: 1390 throw new LDAPException(ResultCode.PARAM_ERROR, 1391 ERR_MEM_DS_TOOL_UNSUPPORTED_AUTH_REQUIRED_OP_TYPE.get(name)); 1392 } 1393 } 1394 } 1395 1396 serverConfig.setAuthenticationRequiredOperationTypes(operationTypes); 1397 } 1398 1399 1400 // If an access log file was specified, then create the appropriate log 1401 // handler. 1402 if (accessLogToStandardOutArgument.isPresent()) 1403 { 1404 final StreamHandler handler = new StreamHandler(System.out, 1405 new MinimalLogFormatter(null, false, false, true)); 1406 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1407 serverConfig.setAccessLogHandler(handler); 1408 } 1409 else if (accessLogFileArgument.isPresent()) 1410 { 1411 final File logFile = accessLogFileArgument.getValue(); 1412 try 1413 { 1414 final FileHandler handler = 1415 new FileHandler(logFile.getAbsolutePath(), true); 1416 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1417 handler.setFormatter(new MinimalLogFormatter(null, false, false, 1418 true)); 1419 serverConfig.setAccessLogHandler(handler); 1420 } 1421 catch (final Exception e) 1422 { 1423 Debug.debugException(e); 1424 throw new LDAPException(ResultCode.LOCAL_ERROR, 1425 ERR_MEM_DS_TOOL_ERROR_CREATING_LOG_HANDLER.get( 1426 logFile.getAbsolutePath(), 1427 StaticUtils.getExceptionMessage(e)), 1428 e); 1429 } 1430 } 1431 1432 1433 // If a JSON-formatted access log file was specified, then create the 1434 // appropriate log handler. 1435 if (jsonAccessLogToStandardOutArgument.isPresent()) 1436 { 1437 final StreamHandler handler = new StreamHandler(System.out, 1438 new MinimalLogFormatter(null, false, false, true)); 1439 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1440 serverConfig.setJSONAccessLogHandler(handler); 1441 } 1442 else if (jsonAccessLogFileArgument.isPresent()) 1443 { 1444 final File logFile = jsonAccessLogFileArgument.getValue(); 1445 try 1446 { 1447 final FileHandler handler = 1448 new FileHandler(logFile.getAbsolutePath(), true); 1449 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1450 handler.setFormatter(new MinimalLogFormatter(null, false, false, 1451 true)); 1452 serverConfig.setJSONAccessLogHandler(handler); 1453 } 1454 catch (final Exception e) 1455 { 1456 Debug.debugException(e); 1457 throw new LDAPException(ResultCode.LOCAL_ERROR, 1458 ERR_MEM_DS_TOOL_ERROR_CREATING_LOG_HANDLER.get( 1459 logFile.getAbsolutePath(), 1460 StaticUtils.getExceptionMessage(e)), 1461 e); 1462 } 1463 } 1464 1465 1466 // If an LDAP debug log file was specified, then create the appropriate log 1467 // handler. 1468 if (ldapDebugLogToStandardOutArgument.isPresent()) 1469 { 1470 final StreamHandler handler = new StreamHandler(System.out, 1471 new MinimalLogFormatter(null, false, false, true)); 1472 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1473 serverConfig.setLDAPDebugLogHandler(handler); 1474 } 1475 else if (ldapDebugLogFileArgument.isPresent()) 1476 { 1477 final File logFile = ldapDebugLogFileArgument.getValue(); 1478 try 1479 { 1480 final FileHandler handler = 1481 new FileHandler(logFile.getAbsolutePath(), true); 1482 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1483 handler.setFormatter(new MinimalLogFormatter(null, false, false, 1484 true)); 1485 serverConfig.setLDAPDebugLogHandler(handler); 1486 } 1487 catch (final Exception e) 1488 { 1489 Debug.debugException(e); 1490 throw new LDAPException(ResultCode.LOCAL_ERROR, 1491 ERR_MEM_DS_TOOL_ERROR_CREATING_LOG_HANDLER.get( 1492 logFile.getAbsolutePath(), 1493 StaticUtils.getExceptionMessage(e)), 1494 e); 1495 } 1496 } 1497 1498 1499 // If a code log file was specified, then update the configuration 1500 // accordingly. 1501 if (codeLogFile.isPresent()) 1502 { 1503 serverConfig.setCodeLogDetails(codeLogFile.getValue().getAbsolutePath(), 1504 true); 1505 } 1506 1507 1508 // If SSL is to be used, then create the corresponding socket factories. 1509 if (useSSLArgument.isPresent() || useStartTLSArgument.isPresent()) 1510 { 1511 final File keyStorePath; 1512 final char[] keyStorePIN; 1513 final String keyStoreType; 1514 if (keyStorePathArgument.isPresent()) 1515 { 1516 keyStorePath = keyStorePathArgument.getValue(); 1517 keyStorePIN = keyStorePasswordArgument.getValue().toCharArray(); 1518 keyStoreType = keyStoreTypeArgument.getValue(); 1519 } 1520 else 1521 { 1522 try 1523 { 1524 keyStoreType = "JKS"; 1525 final ObjectPair<File,char[]> keyStoreInfo = 1526 SelfSignedCertificateGenerator. 1527 generateTemporarySelfSignedCertificate( 1528 getToolName(), keyStoreType); 1529 keyStorePath = keyStoreInfo.getFirst(); 1530 keyStorePIN = keyStoreInfo.getSecond(); 1531 } 1532 catch (final CertException e) 1533 { 1534 Debug.debugException(e); 1535 throw new LDAPException(ResultCode.LOCAL_ERROR, e.getMessage(), e); 1536 } 1537 } 1538 1539 1540 try 1541 { 1542 final KeyManager keyManager = new KeyStoreKeyManager(keyStorePath, 1543 keyStorePIN, keyStoreType, null, true); 1544 1545 final TrustManager trustManager; 1546 if (trustStorePathArgument.isPresent()) 1547 { 1548 final char[] password; 1549 if (trustStorePasswordArgument.isPresent()) 1550 { 1551 password = trustStorePasswordArgument.getValue().toCharArray(); 1552 } 1553 else 1554 { 1555 password = null; 1556 } 1557 1558 trustManager = new TrustStoreTrustManager( 1559 trustStorePathArgument.getValue(), password, 1560 trustStoreTypeArgument.getValue(), true); 1561 } 1562 else 1563 { 1564 trustManager = new TrustAllTrustManager(); 1565 } 1566 1567 final SSLUtil serverSSLUtil = new SSLUtil(keyManager, trustManager); 1568 1569 if (useSSLArgument.isPresent()) 1570 { 1571 final SSLUtil clientSSLUtil = new SSLUtil(new TrustAllTrustManager()); 1572 serverConfig.setListenerConfigs( 1573 InMemoryListenerConfig.createLDAPSConfig("LDAPS", null, 1574 listenPort, serverSSLUtil.createSSLServerSocketFactory(), 1575 clientSSLUtil.createSSLSocketFactory())); 1576 } 1577 else 1578 { 1579 serverConfig.setListenerConfigs( 1580 InMemoryListenerConfig.createLDAPConfig("LDAP+StartTLS", null, 1581 listenPort, serverSSLUtil.createSSLSocketFactory())); 1582 } 1583 } 1584 catch (final Exception e) 1585 { 1586 Debug.debugException(e); 1587 throw new LDAPException(ResultCode.LOCAL_ERROR, 1588 ERR_MEM_DS_TOOL_ERROR_INITIALIZING_SSL.get( 1589 StaticUtils.getExceptionMessage(e)), 1590 e); 1591 } 1592 } 1593 else 1594 { 1595 serverConfig.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig( 1596 "LDAP", listenPort)); 1597 } 1598 1599 1600 // If vendor name and/or vendor version values were provided, then configure 1601 // them for use. 1602 if (vendorNameArgument.isPresent()) 1603 { 1604 serverConfig.setVendorName(vendorNameArgument.getValue()); 1605 } 1606 1607 if (vendorVersionArgument.isPresent()) 1608 { 1609 serverConfig.setVendorVersion(vendorVersionArgument.getValue()); 1610 } 1611 1612 1613 // If equality indexing is to be performed, then configure it. 1614 if (equalityIndexArgument.isPresent()) 1615 { 1616 serverConfig.setEqualityIndexAttributes( 1617 equalityIndexArgument.getValues()); 1618 } 1619 1620 return serverConfig; 1621 } 1622 1623 1624 1625 /** 1626 * Updates the map with an unsalted password encoder with the provided 1627 * information. 1628 * 1629 * @param schemeName The name to use to identify the scheme, without 1630 * the curly braces. 1631 * @param digestAlgorithm The name of the message digest algorithm to use 1632 * for the password encoder. 1633 * @param encoderMap The map to which the encoder will bea added. 1634 */ 1635 private static void addUnsaltedEncoder(@NotNull final String schemeName, 1636 @NotNull final String digestAlgorithm, 1637 @NotNull final Map<String,InMemoryPasswordEncoder> encoderMap) 1638 { 1639 try 1640 { 1641 final UnsaltedMessageDigestInMemoryPasswordEncoder encoder = 1642 new UnsaltedMessageDigestInMemoryPasswordEncoder( 1643 '{' + schemeName + '}', 1644 Base64PasswordEncoderOutputFormatter.getInstance(), 1645 MessageDigest.getInstance(digestAlgorithm)); 1646 encoderMap.put(StaticUtils.toLowerCase(schemeName), encoder); 1647 } 1648 catch (final Exception e) 1649 { 1650 Debug.debugException(e); 1651 } 1652 } 1653 1654 1655 1656 /** 1657 * Updates the map with a salted password encoder with the provided 1658 * information. 1659 * 1660 * @param schemeName The name to use to identify the scheme, without 1661 * the curly braces. 1662 * @param digestAlgorithm The name of the message digest algorithm to use 1663 * for the password encoder. 1664 * @param encoderMap The map to which the encoder will bea added. 1665 */ 1666 private static void addSaltedEncoder(@NotNull final String schemeName, 1667 @NotNull final String digestAlgorithm, 1668 @NotNull final Map<String,InMemoryPasswordEncoder> encoderMap) 1669 { 1670 try 1671 { 1672 final SaltedMessageDigestInMemoryPasswordEncoder encoder = 1673 new SaltedMessageDigestInMemoryPasswordEncoder( 1674 '{' + schemeName + '}', 1675 Base64PasswordEncoderOutputFormatter.getInstance(), 1676 MessageDigest.getInstance(digestAlgorithm), 8, true, true); 1677 encoderMap.put(StaticUtils.toLowerCase(schemeName), encoder); 1678 } 1679 catch (final Exception e) 1680 { 1681 Debug.debugException(e); 1682 } 1683 } 1684 1685 1686 1687 /** 1688 * Updates the map with a clear-text password encoder with the provided 1689 * information. 1690 * 1691 * @param schemeName The name to use to identify the scheme, without 1692 * the curly braces. 1693 * @param outputFormatter The output formatter to use. It may be 1694 * {@code null} if the output should remain in the 1695 * clear. 1696 * @param encoderMap The map to which the encoder will bea added. 1697 */ 1698 private static void addClearEncoder(@NotNull final String schemeName, 1699 @Nullable final PasswordEncoderOutputFormatter outputFormatter, 1700 @NotNull final Map<String,InMemoryPasswordEncoder> encoderMap) 1701 { 1702 final ClearInMemoryPasswordEncoder encoder = 1703 new ClearInMemoryPasswordEncoder('{' + schemeName + '}', 1704 outputFormatter); 1705 encoderMap.put(StaticUtils.toLowerCase(schemeName), encoder); 1706 } 1707 1708 1709 1710 /** 1711 * {@inheritDoc} 1712 */ 1713 @Override() 1714 @NotNull() 1715 public LinkedHashMap<String[],String> getExampleUsages() 1716 { 1717 final LinkedHashMap<String[],String> exampleUsages = 1718 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 1719 1720 final String[] example1Args = 1721 { 1722 "--baseDN", "dc=example,dc=com" 1723 }; 1724 exampleUsages.put(example1Args, INFO_MEM_DS_TOOL_EXAMPLE_1.get()); 1725 1726 final String[] example2Args = 1727 { 1728 "--baseDN", "dc=example,dc=com", 1729 "--port", "1389", 1730 "--ldifFile", "test.ldif", 1731 "--accessLogFile", "access.log", 1732 "--useDefaultSchema" 1733 }; 1734 exampleUsages.put(example2Args, INFO_MEM_DS_TOOL_EXAMPLE_2.get()); 1735 1736 return exampleUsages; 1737 } 1738 1739 1740 1741 /** 1742 * Retrieves the in-memory directory server instance that has been created by 1743 * this tool. It will only be valid after the {@link #doToolProcessing()} 1744 * method has been called. 1745 * 1746 * @return The in-memory directory server instance that has been created by 1747 * this tool, or {@code null} if the directory server instance has 1748 * not been successfully created. 1749 */ 1750 @Nullable() 1751 public InMemoryDirectoryServer getDirectoryServer() 1752 { 1753 return directoryServer; 1754 } 1755 1756 1757 1758 /** 1759 * {@inheritDoc} 1760 */ 1761 @Override() 1762 public void connectionCreationFailure(@Nullable final Socket socket, 1763 @NotNull final Throwable cause) 1764 { 1765 wrapErr(0, WRAP_COLUMN, 1766 ERR_MEM_DS_TOOL_ERROR_ACCEPTING_CONNECTION.get( 1767 StaticUtils.getExceptionMessage(cause))); 1768 } 1769 1770 1771 1772 /** 1773 * {@inheritDoc} 1774 */ 1775 @Override() 1776 public void connectionTerminated( 1777 @NotNull final LDAPListenerClientConnection connection, 1778 @NotNull final LDAPException cause) 1779 { 1780 wrapErr(0, WRAP_COLUMN, 1781 ERR_MEM_DS_TOOL_CONNECTION_TERMINATED_BY_EXCEPTION.get( 1782 StaticUtils.getExceptionMessage(cause))); 1783 } 1784}