001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2010-2015 ForgeRock AS. 026 */ 027package org.opends.server.core; 028 029import static org.forgerock.util.Reject.*; 030import static org.opends.messages.CoreMessages.*; 031import static org.opends.messages.ToolMessages.*; 032import static org.opends.server.config.ConfigConstants.*; 033import static org.opends.server.schema.SchemaConstants.*; 034import static org.opends.server.tools.ConfigureWindowsService.*; 035import static org.opends.server.util.CollectionUtils.*; 036import static org.opends.server.util.DynamicConstants.*; 037import static org.opends.server.util.ServerConstants.*; 038import static org.opends.server.util.StaticUtils.*; 039 040import java.io.File; 041import java.io.FileOutputStream; 042import java.io.IOException; 043import java.io.OutputStream; 044import java.io.PrintStream; 045import java.lang.management.ManagementFactory; 046import java.net.InetAddress; 047import java.text.DecimalFormat; 048import java.util.Collection; 049import java.util.Collections; 050import java.util.LinkedHashMap; 051import java.util.LinkedHashSet; 052import java.util.LinkedList; 053import java.util.List; 054import java.util.Map; 055import java.util.Properties; 056import java.util.Set; 057import java.util.TreeMap; 058import java.util.TreeSet; 059import java.util.concurrent.ConcurrentHashMap; 060import java.util.concurrent.ConcurrentMap; 061import java.util.concurrent.CopyOnWriteArrayList; 062import java.util.concurrent.CopyOnWriteArraySet; 063import java.util.concurrent.atomic.AtomicInteger; 064 065import javax.management.MBeanServer; 066import javax.management.MBeanServerFactory; 067 068import org.forgerock.i18n.LocalizableMessage; 069import org.forgerock.i18n.slf4j.LocalizedLogger; 070import org.forgerock.opendj.config.server.ConfigException; 071import org.forgerock.opendj.ldap.ResultCode; 072import org.forgerock.opendj.ldap.schema.AttributeUsage; 073import org.forgerock.opendj.ldap.schema.CoreSchema; 074import org.forgerock.opendj.ldap.schema.MatchingRule; 075import org.forgerock.opendj.ldap.schema.ObjectClassType; 076import org.forgerock.opendj.ldap.schema.SchemaBuilder; 077import org.forgerock.opendj.ldap.schema.Syntax; 078import org.forgerock.util.Reject; 079import org.forgerock.util.Utils; 080import org.opends.server.admin.AdministrationConnector; 081import org.opends.server.admin.AdministrationDataSync; 082import org.opends.server.admin.ClassLoaderProvider; 083import org.opends.server.admin.server.ServerManagementContext; 084import org.opends.server.admin.std.server.AlertHandlerCfg; 085import org.opends.server.admin.std.server.ConnectionHandlerCfg; 086import org.opends.server.admin.std.server.CryptoManagerCfg; 087import org.opends.server.admin.std.server.MonitorProviderCfg; 088import org.opends.server.admin.std.server.PasswordValidatorCfg; 089import org.opends.server.admin.std.server.RootCfg; 090import org.opends.server.admin.std.server.RootDSEBackendCfg; 091import org.opends.server.admin.std.server.SynchronizationProviderCfg; 092import org.opends.server.api.AccessControlHandler; 093import org.opends.server.api.AccountStatusNotificationHandler; 094import org.opends.server.api.AlertGenerator; 095import org.opends.server.api.AlertHandler; 096import org.opends.server.api.AuthenticationPolicy; 097import org.opends.server.api.Backend; 098import org.opends.server.api.BackendInitializationListener; 099import org.opends.server.api.BackupTaskListener; 100import org.opends.server.api.CertificateMapper; 101import org.opends.server.api.ClientConnection; 102import org.opends.server.api.CompressedSchema; 103import org.opends.server.api.ConfigAddListener; 104import org.opends.server.api.ConfigChangeListener; 105import org.opends.server.api.ConfigDeleteListener; 106import org.opends.server.api.ConfigHandler; 107import org.opends.server.api.ConnectionHandler; 108import org.opends.server.api.DirectoryServerMBean; 109import org.opends.server.api.EntryCache; 110import org.opends.server.api.ExportTaskListener; 111import org.opends.server.api.ExtendedOperationHandler; 112import org.opends.server.api.IdentityMapper; 113import org.opends.server.api.ImportTaskListener; 114import org.opends.server.api.InitializationCompletedListener; 115import org.opends.server.api.InvokableComponent; 116import org.opends.server.api.KeyManagerProvider; 117import org.opends.server.api.MatchingRuleFactory; 118import org.opends.server.api.MonitorProvider; 119import org.opends.server.api.PasswordGenerator; 120import org.opends.server.api.PasswordStorageScheme; 121import org.opends.server.api.PasswordValidator; 122import org.opends.server.api.RestoreTaskListener; 123import org.opends.server.api.SASLMechanismHandler; 124import org.opends.server.api.ServerShutdownListener; 125import org.opends.server.api.SynchronizationProvider; 126import org.opends.server.api.TrustManagerProvider; 127import org.opends.server.api.WorkQueue; 128import org.opends.server.api.plugin.InternalDirectoryServerPlugin; 129import org.opends.server.api.plugin.PluginResult; 130import org.opends.server.api.plugin.PluginType; 131import org.opends.server.backends.RootDSEBackend; 132import org.opends.server.config.ConfigEntry; 133import org.opends.server.config.JMXMBean; 134import org.opends.server.controls.PasswordPolicyErrorType; 135import org.opends.server.controls.PasswordPolicyResponseControl; 136import org.opends.server.crypto.CryptoManagerImpl; 137import org.opends.server.crypto.CryptoManagerSync; 138import org.opends.server.extensions.ConfigFileHandler; 139import org.opends.server.extensions.DiskSpaceMonitor; 140import org.opends.server.extensions.JMXAlertHandler; 141import org.opends.server.loggers.AccessLogger; 142import org.opends.server.loggers.DebugLogPublisher; 143import org.opends.server.loggers.DebugLogger; 144import org.opends.server.loggers.ErrorLogPublisher; 145import org.opends.server.loggers.ErrorLogger; 146import org.opends.server.loggers.RetentionPolicy; 147import org.opends.server.loggers.RotationPolicy; 148import org.opends.server.loggers.TextErrorLogPublisher; 149import org.opends.server.loggers.TextWriter; 150import org.opends.server.monitors.BackendMonitor; 151import org.opends.server.monitors.ConnectionHandlerMonitor; 152import org.opends.server.protocols.internal.InternalClientConnection; 153import org.opends.server.protocols.internal.InternalConnectionHandler; 154import org.opends.server.schema.BooleanEqualityMatchingRuleFactory; 155import org.opends.server.schema.CaseExactEqualityMatchingRuleFactory; 156import org.opends.server.schema.CaseExactIA5EqualityMatchingRuleFactory; 157import org.opends.server.schema.CaseExactIA5SubstringMatchingRuleFactory; 158import org.opends.server.schema.CaseExactOrderingMatchingRuleFactory; 159import org.opends.server.schema.CaseExactSubstringMatchingRuleFactory; 160import org.opends.server.schema.CaseIgnoreEqualityMatchingRuleFactory; 161import org.opends.server.schema.CaseIgnoreIA5EqualityMatchingRuleFactory; 162import org.opends.server.schema.CaseIgnoreIA5SubstringMatchingRuleFactory; 163import org.opends.server.schema.CaseIgnoreOrderingMatchingRuleFactory; 164import org.opends.server.schema.CaseIgnoreSubstringMatchingRuleFactory; 165import org.opends.server.schema.DistinguishedNameEqualityMatchingRuleFactory; 166import org.opends.server.schema.DoubleMetaphoneApproximateMatchingRuleFactory; 167import org.opends.server.schema.GeneralizedTimeEqualityMatchingRuleFactory; 168import org.opends.server.schema.GeneralizedTimeOrderingMatchingRuleFactory; 169import org.opends.server.schema.IntegerEqualityMatchingRuleFactory; 170import org.opends.server.schema.IntegerOrderingMatchingRuleFactory; 171import org.opends.server.schema.ObjectIdentifierEqualityMatchingRuleFactory; 172import org.opends.server.schema.OctetStringEqualityMatchingRuleFactory; 173import org.opends.server.schema.OctetStringOrderingMatchingRuleFactory; 174import org.opends.server.schema.OctetStringSubstringMatchingRuleFactory; 175import org.opends.server.schema.SchemaUpdater; 176import org.opends.server.schema.TelephoneNumberEqualityMatchingRuleFactory; 177import org.opends.server.schema.TelephoneNumberSubstringMatchingRuleFactory; 178import org.opends.server.types.AcceptRejectWarn; 179import org.opends.server.types.AttributeType; 180import org.opends.server.types.BackupConfig; 181import org.opends.server.types.Control; 182import org.opends.server.types.DITContentRule; 183import org.opends.server.types.DITStructureRule; 184import org.opends.server.types.DN; 185import org.opends.server.types.DirectoryEnvironmentConfig; 186import org.opends.server.types.DirectoryException; 187import org.opends.server.types.Entry; 188import org.opends.server.types.HostPort; 189import org.opends.server.types.InitializationException; 190import org.opends.server.types.LDIFExportConfig; 191import org.opends.server.types.LDIFImportConfig; 192import org.opends.server.types.LockManager; 193import org.opends.server.types.MatchingRuleUse; 194import org.opends.server.types.Modification; 195import org.opends.server.types.NameForm; 196import org.opends.server.types.ObjectClass; 197import org.opends.server.types.Operation; 198import org.opends.server.types.Privilege; 199import org.opends.server.types.RestoreConfig; 200import org.opends.server.types.Schema; 201import org.opends.server.types.VirtualAttributeRule; 202import org.opends.server.types.WritabilityMode; 203import org.opends.server.util.ActivateOnceNewConfigFrameworkIsUsed; 204import org.opends.server.util.ActivateOnceSDKSchemaIsUsed; 205import org.opends.server.util.BuildVersion; 206import org.opends.server.util.MultiOutputStream; 207import org.opends.server.util.RemoveOnceSDKSchemaIsUsed; 208import org.opends.server.util.RuntimeInformation; 209import org.opends.server.util.SetupUtils; 210import org.opends.server.util.TimeThread; 211import org.opends.server.util.VersionCompatibilityIssue; 212import org.opends.server.workflowelement.localbackend.LocalBackendWorkflowElement; 213 214import com.forgerock.opendj.cli.ArgumentConstants; 215import com.forgerock.opendj.cli.ArgumentException; 216import com.forgerock.opendj.cli.ArgumentParser; 217import com.forgerock.opendj.cli.BooleanArgument; 218import com.forgerock.opendj.cli.CommonArguments; 219import com.forgerock.opendj.cli.IntegerArgument; 220import com.forgerock.opendj.cli.StringArgument; 221import com.forgerock.opendj.cli.VersionHandler; 222import com.forgerock.opendj.util.OperatingSystem; 223 224/** 225 * This class defines the core of the Directory Server. It manages the startup 226 * and shutdown processes and coordinates activities between all other 227 * components. 228 */ 229public final class DirectoryServer 230 implements AlertGenerator 231{ 232 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 233 234 /** The singleton Directory Server instance. */ 235 private static DirectoryServer directoryServer = new DirectoryServer(); 236 237 /** Indicates whether the server currently holds an exclusive lock on the server lock file. */ 238 private static boolean serverLocked; 239 240 /** The message to be displayed on the command-line when the user asks for the usage. */ 241 private static LocalizableMessage toolDescription = INFO_DSCORE_TOOL_DESCRIPTION.get(); 242 243 /** 244 * Return codes used when the hidden option --checkStartability is used. 245 * NOTE: when checkstartability is specified is recommended not to allocate 246 * a lot of memory for the JVM (Using -Xms and -Xmx options) as there might 247 * be calls to Runtime.exec. 248 */ 249 /** 250 * Returned when the user specified the --checkStartability option with other 251 * options like printing the usage, dumping messages, displaying version, etc. 252 */ 253 private static final int NOTHING_TO_DO = 0; 254 /** 255 * Returned when the user specified the --checkStartability option with 256 * some incompatible arguments. 257 */ 258 private static final int CHECK_ERROR = 1; 259 /** The server is already started. */ 260 private static final int SERVER_ALREADY_STARTED = 98; 261 /** The server must be started as detached process. */ 262 private static final int START_AS_DETACH = 99; 263 /** The server must be started as a non-detached process. */ 264 private static final int START_AS_NON_DETACH = 100; 265 /** The server must be started as a window service. */ 266 private static final int START_AS_WINDOWS_SERVICE = 101; 267 /** The server must be started as detached and it is being called from the Windows Service. */ 268 private static final int START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE = 102; 269 /** The server must be started as detached process and should not produce any output. */ 270 private static final int START_AS_DETACH_QUIET = 103; 271 /** The server must be started as non-detached process and should not produce any output. */ 272 private static final int START_AS_NON_DETACH_QUIET = 104; 273 274 /** Temporary context object, to provide instance methods instead of static methods. */ 275 private final DirectoryServerContext serverContext; 276 277 /** The policy to use regarding single structural objectclass enforcement. */ 278 private AcceptRejectWarn singleStructuralClassPolicy; 279 /** The policy to use regarding syntax enforcement. */ 280 private AcceptRejectWarn syntaxEnforcementPolicy; 281 282 /** The account status notification handler config manager for the server. */ 283 private AccountStatusNotificationHandlerConfigManager accountStatusNotificationHandlerConfigManager; 284 285 /** The attribute type used to reference the "objectclass" attribute. */ 286 private AttributeType objectClassAttributeType; 287 /** The authenticated users manager for the server. */ 288 private AuthenticatedUsers authenticatedUsers; 289 /** The configuration manager that will handle the server backends. */ 290 private BackendConfigManager backendConfigManager; 291 292 /** 293 * Indicates whether to automatically add missing RDN attributes to entries 294 * during an add request. 295 */ 296 private boolean addMissingRDNAttributes; 297 298 /** 299 * Indicates whether to allow attribute name exceptions (i.e., attribute names 300 * can contain underscores and may start with a digit). 301 */ 302 private boolean allowAttributeNameExceptions; 303 304 /** Indicates whether a simple bind request containing a DN must also provide a password. */ 305 private boolean bindWithDNRequiresPassword; 306 307 /** Indicates whether the Directory Server should perform schema checking for update operations. */ 308 private boolean checkSchema; 309 310 /** Indicates whether the server has been bootstrapped. */ 311 private boolean isBootstrapped; 312 /** Indicates whether the server is currently online. */ 313 private boolean isRunning; 314 /** Indicates whether the server is currently in "lockdown mode". */ 315 private boolean lockdownMode; 316 317 /** Indicates whether the server should send a response to operations that have been abandoned. */ 318 private boolean notifyAbandonedOperations; 319 320 /** Indicates whether to save a copy of the configuration on successful startup. */ 321 private boolean saveConfigOnSuccessfulStartup; 322 323 /** Indicates whether the server is currently in the process of shutting down. */ 324 private boolean shuttingDown; 325 326 /** Indicates whether the server should reject unauthenticated requests. */ 327 private boolean rejectUnauthenticatedRequests; 328 329 /** Indicates whether bind responses should include failure reason messages. */ 330 private boolean returnBindErrorMessages; 331 332 /** The configuration manager that will handle the certificate mapper. */ 333 private CertificateMapperConfigManager certificateMapperConfigManager; 334 335 /** The class used to provide the config handler implementation. */ 336 private Class<ConfigHandler> configClass; 337 338 /** The configuration handler for the Directory Server. */ 339 private ConfigHandler configHandler; 340 341 /** The set of account status notification handlers defined in the server. */ 342 private ConcurrentMap<DN, AccountStatusNotificationHandler> 343 accountStatusNotificationHandlers; 344 345 /** The set of certificate mappers registered with the server. */ 346 private ConcurrentMap<DN, CertificateMapper> certificateMappers; 347 348 /** The set of alternate bind DNs for the root users. */ 349 private ConcurrentMap<DN, DN> alternateRootBindDNs; 350 351 /** 352 * The set of identity mappers registered with the server (mapped between the 353 * configuration entry Dn and the mapper). 354 */ 355 private ConcurrentMap<DN, IdentityMapper> identityMappers; 356 357 /** 358 * The set of JMX MBeans that have been registered with the server (mapped 359 * between the associated configuration entry DN and the MBean). 360 */ 361 private ConcurrentHashMap<DN,JMXMBean> mBeans; 362 363 /** The set of key manager providers registered with the server. */ 364 private ConcurrentMap<DN, KeyManagerProvider> keyManagerProviders; 365 366 /** 367 * The set of password generators registered with the Directory Server, as a 368 * mapping between the DN of the associated configuration entry and the 369 * generator implementation. 370 */ 371 private ConcurrentMap<DN, PasswordGenerator> passwordGenerators; 372 373 /** 374 * The set of authentication policies registered with the Directory Server, as 375 * a mapping between the DN of the associated configuration entry and the 376 * policy implementation. 377 */ 378 private ConcurrentMap<DN, AuthenticationPolicy> authenticationPolicies; 379 380 /** 381 * The set of password validators registered with the Directory Server, as a 382 * mapping between the DN of the associated configuration entry and the 383 * validator implementation. 384 */ 385 private ConcurrentMap<DN, PasswordValidator<? extends PasswordValidatorCfg>> 386 passwordValidators; 387 388 /** The set of trust manager providers registered with the server. */ 389 private ConcurrentMap<DN, TrustManagerProvider> trustManagerProviders; 390 391 /** 392 * The set of log rotation policies registered with the Directory Server, as a 393 * mapping between the DN of the associated configuration entry and the policy 394 * implementation. 395 */ 396 private ConcurrentMap<DN, RotationPolicy> rotationPolicies; 397 398 /** 399 * The set of log retention policies registered with the Directory Server, as 400 * a mapping between the DN of the associated configuration entry and the 401 * policy implementation. 402 */ 403 private ConcurrentMap<DN, RetentionPolicy> retentionPolicies; 404 405 /** The set supported LDAP protocol versions. */ 406 private ConcurrentMap<Integer, List<ConnectionHandler>> 407 supportedLDAPVersions; 408 409 /** 410 * The set of extended operation handlers registered with the server (mapped 411 * between the OID of the extended operation and the handler). 412 */ 413 private ConcurrentMap<String, ExtendedOperationHandler> 414 extendedOperationHandlers; 415 416 /** 417 * The set of monitor providers registered with the Directory Server, as a 418 * mapping between the monitor name and the corresponding implementation. 419 */ 420 private ConcurrentMap<String, MonitorProvider<? extends MonitorProviderCfg>> 421 monitorProviders; 422 423 /** 424 * The set of password storage schemes defined in the server (mapped between 425 * the lowercase scheme name and the storage scheme) that support the 426 * authentication password syntax. 427 */ 428 private ConcurrentHashMap<String,PasswordStorageScheme> 429 authPasswordStorageSchemes; 430 431 /** 432 * The set of password storage schemes defined in the server (mapped between 433 * the lowercase scheme name and the storage scheme). 434 */ 435 private ConcurrentHashMap<String,PasswordStorageScheme> 436 passwordStorageSchemes; 437 438 /** 439 * The set of password storage schemes defined in the server (mapped between 440 * the DN of the configuration entry and the storage scheme). 441 */ 442 private ConcurrentMap<DN, PasswordStorageScheme> 443 passwordStorageSchemesByDN; 444 445 /** 446 * The set of SASL mechanism handlers registered with the server (mapped 447 * between the mechanism name and the handler). 448 */ 449 private ConcurrentMap<String, SASLMechanismHandler> saslMechanismHandlers; 450 451 /** The connection handler configuration manager for the Directory Server. */ 452 private ConnectionHandlerConfigManager connectionHandlerConfigManager; 453 454 /** The set of alert handlers registered with the Directory Server. */ 455 private List<AlertHandler> alertHandlers; 456 457 /** The set of backup task listeners registered with the Directory Server. */ 458 private CopyOnWriteArrayList<BackupTaskListener> backupTaskListeners; 459 460 /** The set of connection handlers registered with the Directory Server. */ 461 private List<ConnectionHandler> connectionHandlers; 462 463 /** The set of export task listeners registered with the Directory Server. */ 464 private CopyOnWriteArrayList<ExportTaskListener> exportTaskListeners; 465 466 /** The set of import task listeners registered with the Directory Server. */ 467 private CopyOnWriteArrayList<ImportTaskListener> importTaskListeners; 468 469 /** The set of restore task listeners registered with the Directory Server. */ 470 private CopyOnWriteArrayList<RestoreTaskListener> restoreTaskListeners; 471 472 /** 473 * The set of initialization completed listeners that have been registered 474 * with the Directory Server. 475 */ 476 private List<InitializationCompletedListener> 477 initializationCompletedListeners; 478 479 /** The set of shutdown listeners that have been registered with the Directory Server. */ 480 private List<ServerShutdownListener> shutdownListeners; 481 /** The set of synchronization providers that have been registered with the Directory Server. */ 482 private List<SynchronizationProvider<SynchronizationProviderCfg>> synchronizationProviders; 483 /** The set of backend initialization listeners registered with the Directory Server. */ 484 private Set<BackendInitializationListener> backendInitializationListeners; 485 486 /** The set of root DNs registered with the Directory Server. */ 487 private Set<DN> rootDNs; 488 489 /** The core configuration manager for the Directory Server. */ 490 private CoreConfigManager coreConfigManager; 491 492 /** The crypto manager for the Directory Server. */ 493 private CryptoManagerImpl cryptoManager; 494 495 /** The default compressed schema manager. */ 496 private DefaultCompressedSchema compressedSchema; 497 498 /** The environment configuration for the Directory Server. */ 499 private DirectoryEnvironmentConfig environmentConfig; 500 501 /** The shutdown hook that has been registered with the server. */ 502 private DirectoryServerShutdownHook shutdownHook; 503 504 /** The DN of the default password policy configuration entry. */ 505 private DN defaultPasswordPolicyDN; 506 507 /** 508 * The DN of the identity mapper that will be used to resolve authorization 509 * IDs contained in the proxied authorization V2 control. 510 */ 511 private DN proxiedAuthorizationIdentityMapperDN; 512 513 /** The DN of the entry containing the server schema definitions. */ 514 private DN schemaDN; 515 516 /** The Directory Server entry cache. */ 517 private EntryCache entryCache; 518 519 /** The configuration manager for the entry cache. */ 520 private EntryCacheConfigManager entryCacheConfigManager; 521 522 /** The configuration manager for extended operation handlers. */ 523 private ExtendedOperationConfigManager extendedOperationConfigManager; 524 525 /** 526 * The path to the file containing the Directory Server configuration, or the 527 * information needed to bootstrap the configuration handler. 528 */ 529 private File configFile; 530 531 /** The group manager for the Directory Server. */ 532 private GroupManager groupManager; 533 534 /** The subentry manager for the Directory Server. */ 535 private SubentryManager subentryManager; 536 537 /** The configuration manager for identity mappers. */ 538 private IdentityMapperConfigManager identityMapperConfigManager; 539 540 /** 541 * The maximum number of entries that should be returned for a search unless 542 * overridden on a per-user basis. 543 */ 544 private int sizeLimit; 545 546 /** 547 * The maximum length of time in seconds that should be allowed for a search 548 * unless overridden on a per-user basis. 549 */ 550 private int timeLimit; 551 /** The maximum number of candidates that should be check for matches during a search. */ 552 private int lookthroughLimit; 553 554 /** The current active persistent searches. */ 555 private final AtomicInteger activePSearches = new AtomicInteger(0); 556 557 /** The maximum number of concurrent persistent searches. */ 558 private int maxPSearches; 559 560 /** Whether to use collect operation processing times in nanosecond resolution. */ 561 private boolean useNanoTime; 562 563 /** The key manager provider configuration manager for the Directory Server. */ 564 private KeyManagerProviderConfigManager keyManagerProviderConfigManager; 565 566 /** The set of connections that are currently established. */ 567 private Set<ClientConnection> establishedConnections; 568 569 /** The sets of mail server properties. */ 570 private List<Properties> mailServerPropertySets; 571 572 /** 573 * The set of schema changes made by editing the schema configuration files 574 * with the server offline. 575 */ 576 private List<Modification> offlineSchemaChanges; 577 578 /** The log rotation policy config manager for the Directory Server. */ 579 private LogRotationPolicyConfigManager rotationPolicyConfigManager; 580 581 /** The log retention policy config manager for the Directory Server. */ 582 private LogRetentionPolicyConfigManager retentionPolicyConfigManager; 583 584 /** The logger configuration manager for the Directory Server. */ 585 private LoggerConfigManager loggerConfigManager; 586 587 /** The number of connections currently established to the server. */ 588 private long currentConnections; 589 /** The idle time limit for the server. */ 590 private long idleTimeLimit; 591 592 /** The maximum number of connections that will be allowed at any given time. */ 593 private long maxAllowedConnections; 594 /** The maximum number of connections established at one time. */ 595 private long maxConnections; 596 597 /** The time that this Directory Server instance was started. */ 598 private long startUpTime; 599 600 /** The total number of connections established since startup. */ 601 private long totalConnections; 602 603 /** The MBean server used to handle JMX interaction. */ 604 private MBeanServer mBeanServer; 605 606 /** The monitor config manager for the Directory Server. */ 607 private MonitorConfigManager monitorConfigManager; 608 609 /** The operating system on which the server is running. */ 610 private final OperatingSystem operatingSystem; 611 612 /** The configuration handler used to manage the password generators. */ 613 private PasswordGeneratorConfigManager passwordGeneratorConfigManager; 614 /** The default password policy for the Directory Server. */ 615 private PasswordPolicy defaultPasswordPolicy; 616 /** The configuration handler used to manage the authentication policies. */ 617 private PasswordPolicyConfigManager authenticationPolicyConfigManager; 618 /** The configuration handler used to manage the password storage schemes. */ 619 private PasswordStorageSchemeConfigManager storageSchemeConfigManager; 620 /** The configuration handler used to manage the password validators. */ 621 private PasswordValidatorConfigManager passwordValidatorConfigManager; 622 623 /** The plugin config manager for the Directory Server. */ 624 private PluginConfigManager pluginConfigManager; 625 626 /** The result code that should be used for internal "server" errors. */ 627 private ResultCode serverErrorResultCode; 628 629 /** The special backend used for the Directory Server root DSE. */ 630 private RootDSEBackend rootDSEBackend; 631 /** The root DN config manager for the server. */ 632 private RootDNConfigManager rootDNConfigManager; 633 634 /** The SASL mechanism config manager for the Directory Server. */ 635 private SASLConfigManager saslConfigManager; 636 637 /** The schema for the Directory Server. */ 638 private Schema schema; 639 640 /** 641 * The schema for the Directory Server. 642 * <p> 643 * This schema is synchronized indirectly to the existing schema, because 644 * syntaxes are defined in schemaNG (i.e, migrated to SDK classes) and there 645 * is currently no way to handle the SchemaOptions in the configuration (e.g. 646 * SchemaOptions.ALLOW_ZERO_LENGTH_DIRECTORY_STRINGS). 647 * Thus, configuration of the legacy syntaxes are kept, and any change related 648 * to them is synchronized with this schema. 649 */ 650 @RemoveOnceSDKSchemaIsUsed("'schema' field will then be a reference to a SDK schema") 651 private org.forgerock.opendj.ldap.schema.Schema schemaNG; 652 653 /** The schema configuration manager for the Directory Server. */ 654 private SchemaConfigManager schemaConfigManager; 655 656 /** The set of disabled privileges. */ 657 private Set<Privilege> disabledPrivileges; 658 659 /** The set of allowed task classes. */ 660 private Set<String> allowedTasks; 661 662 /** The time that the server was started, formatted in UTC time. */ 663 private String startTimeUTC; 664 665 /** The synchronization provider configuration manager for the Directory Server. */ 666 private SynchronizationProviderConfigManager synchronizationProviderConfigManager; 667 668 /** Registry for base DN and naming context information. */ 669 private BaseDnRegistry baseDnRegistry; 670 671 /** The set of backends registered with the server. */ 672 private TreeMap<String, Backend<?>> backends; 673 674 /** The set of supported controls registered with the Directory Server. */ 675 private final TreeSet<String> supportedControls = newTreeSet( 676 OID_LDAP_ASSERTION, 677 OID_LDAP_READENTRY_PREREAD, 678 OID_LDAP_READENTRY_POSTREAD, 679 OID_LDAP_NOOP_OPENLDAP_ASSIGNED, 680 OID_PERSISTENT_SEARCH, 681 OID_PROXIED_AUTH_V1, 682 OID_PROXIED_AUTH_V2, 683 OID_AUTHZID_REQUEST, 684 OID_MATCHED_VALUES, 685 OID_LDAP_SUBENTRIES, 686 OID_LDUP_SUBENTRIES, 687 OID_PASSWORD_POLICY_CONTROL, 688 OID_PERMISSIVE_MODIFY_CONTROL, 689 OID_REAL_ATTRS_ONLY, 690 OID_VIRTUAL_ATTRS_ONLY, 691 OID_ACCOUNT_USABLE_CONTROL, 692 OID_NS_PASSWORD_EXPIRED, 693 OID_NS_PASSWORD_EXPIRING); 694 695 /** The set of supported feature OIDs registered with the Directory Server. */ 696 private final TreeSet<String> supportedFeatures = newTreeSet( 697 OID_ALL_OPERATIONAL_ATTRS_FEATURE, 698 OID_MODIFY_INCREMENT_FEATURE, 699 OID_TRUE_FALSE_FILTERS_FEATURE); 700 701 /** The trust manager provider configuration manager for the Directory Server. */ 702 private TrustManagerProviderConfigManager trustManagerProviderConfigManager; 703 704 /** The virtual attribute provider configuration manager for the Directory Server. */ 705 private final VirtualAttributeConfigManager virtualAttributeConfigManager; 706 707 /** The work queue that will be used to service client requests. */ 708 private WorkQueue workQueue; 709 710 /** The writability mode for the Directory Server. */ 711 private WritabilityMode writabilityMode; 712 713 /** The memory reservation system. */ 714 private MemoryQuota memoryQuota; 715 716 /** The Disk Space Monitor. */ 717 private DiskSpaceMonitor diskSpaceMonitor; 718 719 /** The lock manager which will be used for coordinating access to LDAP entries. */ 720 private final LockManager lockManager = new LockManager(); 721 722 /** The maximum size that internal buffers will be allowed to grow to until they are trimmed. */ 723 private int maxInternalBufferSize = DEFAULT_MAX_INTERNAL_BUFFER_SIZE; 724 725 /** The default timeout used to start the server in detach mode. */ 726 public static final int DEFAULT_TIMEOUT = 200; 727 728 /** Entry point for server configuration. */ 729 private org.forgerock.opendj.config.server.ServerManagementContext serverManagementContext; 730 731 /** Class that prints the version of OpenDJ server to System.out. */ 732 public static final class DirectoryServerVersionHandler implements VersionHandler 733 { 734 /** {@inheritDoc} */ 735 @Override 736 public void printVersion() 737 { 738 try 739 { 740 DirectoryServer.printVersion(System.out); 741 } 742 catch (Exception e){} 743 } 744 } 745 746 /** 747 * Temporary class to provide instance methods instead of static methods for 748 * server. Once all static methods related to context are removed from the 749 * server then DirectoryServer class can be used directly as implementation of 750 * ServerContext. 751 */ 752 private class DirectoryServerContext implements ServerContext 753 { 754 755 /** {@inheritDoc} */ 756 @Override 757 public String getInstanceRoot() 758 { 759 return DirectoryServer.getInstanceRoot(); 760 } 761 762 /** {@inheritDoc} */ 763 @Override 764 public String getServerRoot() 765 { 766 return DirectoryServer.getServerRoot(); 767 } 768 769 /** {@inheritDoc} */ 770 @Override 771 public Schema getSchema() 772 { 773 return directoryServer.schema; 774 } 775 776 /** {@inheritDoc} */ 777 @Override 778 public org.forgerock.opendj.ldap.schema.Schema getSchemaNG() 779 { 780 return directoryServer.schemaNG; 781 } 782 783 /** {@inheritDoc} */ 784 @Override 785 public DirectoryEnvironmentConfig getEnvironment() 786 { 787 return directoryServer.environmentConfig; 788 } 789 790 /** {@inheritDoc} */ 791 @Override 792 public SchemaUpdater getSchemaUpdater() 793 { 794 return new SchemaUpdater() 795 { 796 @Override 797 public boolean updateSchema(org.forgerock.opendj.ldap.schema.Schema schema) 798 { 799 schemaNG = schema; 800 return true; 801 } 802 803 @Override 804 public SchemaBuilder getSchemaBuilder() 805 { 806 return new SchemaBuilder(schemaNG); 807 } 808 }; 809 } 810 811 /** {@inheritDoc} */ 812 @Override 813 public org.forgerock.opendj.config.server.ServerManagementContext getServerManagementContext() 814 { 815 return serverManagementContext; 816 } 817 818 @Override 819 public MemoryQuota getMemoryQuota() 820 { 821 return directoryServer.memoryQuota; 822 } 823 824 @Override 825 public DiskSpaceMonitor getDiskSpaceMonitor() 826 { 827 return directoryServer.diskSpaceMonitor; 828 } 829 } 830 831 /** 832 * Creates a new instance of the Directory Server. This will allow only a 833 * single instance of the server per JVM. 834 */ 835 private DirectoryServer() 836 { 837 this(new DirectoryEnvironmentConfig()); 838 } 839 840 /** 841 * Creates a new instance of the Directory Server. This will allow only a 842 * single instance of the server per JVM. 843 * 844 * @param config The environment configuration to use for the Directory 845 * Server instance. 846 */ 847 private DirectoryServer(DirectoryEnvironmentConfig config) 848 { 849 environmentConfig = config; 850 isBootstrapped = false; 851 isRunning = false; 852 shuttingDown = false; 853 lockdownMode = false; 854 serverErrorResultCode = ResultCode.OTHER; 855 856 operatingSystem = OperatingSystem.forName(System.getProperty("os.name")); 857 serverContext = new DirectoryServerContext(); 858 virtualAttributeConfigManager = new VirtualAttributeConfigManager(serverContext); 859 memoryQuota = new MemoryQuota(); 860 diskSpaceMonitor = new DiskSpaceMonitor(); 861 } 862 863 /** 864 * Retrieves the instance of the Directory Server that is associated with this 865 * JVM. 866 * 867 * @return The instance of the Directory Server that is associated with this 868 * JVM. 869 */ 870 public static DirectoryServer getInstance() 871 { 872 return directoryServer; 873 } 874 875 /** 876 * Creates a new instance of the Directory Server and replaces the static 877 * reference to it. This should only be used in the context of an in-core 878 * restart after the existing server has been shut down. 879 * 880 * @param config The environment configuration for the Directory Server. 881 * 882 * @return The new instance of the Directory Server that is associated with 883 * this JVM. 884 */ 885 private static DirectoryServer 886 getNewInstance(DirectoryEnvironmentConfig config) 887 { 888 synchronized (directoryServer) 889 { 890 return directoryServer = new DirectoryServer(config); 891 } 892 } 893 894 /** 895 * Retrieves the environment configuration for the Directory Server. 896 * 897 * @return The environment configuration for the Directory Server. 898 */ 899 public static DirectoryEnvironmentConfig getEnvironmentConfig() 900 { 901 return directoryServer.environmentConfig; 902 } 903 904 /** 905 * Sets the environment configuration for the Directory Server. This method 906 * may only be invoked when the server is not running. 907 * 908 * @param config The environment configuration for the Directory Server. 909 * 910 * @throws InitializationException If the Directory Server is currently 911 * running. 912 */ 913 public void setEnvironmentConfig(DirectoryEnvironmentConfig config) 914 throws InitializationException 915 { 916 if (isRunning) 917 { 918 throw new InitializationException( 919 ERR_CANNOT_SET_ENVIRONMENT_CONFIG_WHILE_RUNNING.get()); 920 } 921 922 environmentConfig = config; 923 } 924 925 /** 926 * Returns the server context. 927 * 928 * @return the server context 929 */ 930 public ServerContext getServerContext() { 931 return serverContext; 932 } 933 934 /** 935 * Indicates whether the Directory Server is currently running. 936 * 937 * @return {@code true} if the server is currently running, or {@code false} 938 * if not. 939 */ 940 public static boolean isRunning() 941 { 942 return directoryServer.isRunning; 943 } 944 945 /** 946 * Bootstraps the appropriate Directory Server structures that may be needed 947 * by both server and client-side tools. 948 */ 949 public static void bootstrapClient() 950 { 951 synchronized (directoryServer) 952 { 953 // Set default values for variables that may be needed during schema 954 // processing. 955 directoryServer.syntaxEnforcementPolicy = AcceptRejectWarn.REJECT; 956 957 // Create the server schema and initialize and register a minimal set of 958 // matching rules and attribute syntaxes. 959 directoryServer.schema = new Schema(); 960 directoryServer.schemaNG = new SchemaBuilder("mainSchema").addSchema(CoreSchema.getInstance(), true).toSchema(); 961 directoryServer.bootstrapMatchingRules(); 962 directoryServer.bootstrapAttributeSyntaxes(); 963 964 // Perform any additional initialization that might be necessary before 965 // loading the configuration. 966 directoryServer.alertHandlers = new CopyOnWriteArrayList<>(); 967 directoryServer.passwordStorageSchemes = new ConcurrentHashMap<>(); 968 directoryServer.passwordStorageSchemesByDN = new ConcurrentHashMap<>(); 969 directoryServer.passwordGenerators = new ConcurrentHashMap<>(); 970 directoryServer.authPasswordStorageSchemes = new ConcurrentHashMap<>(); 971 directoryServer.passwordValidators = new ConcurrentHashMap<>(); 972 directoryServer.accountStatusNotificationHandlers = new ConcurrentHashMap<>(); 973 directoryServer.rootDNs = new CopyOnWriteArraySet<>(); 974 directoryServer.alternateRootBindDNs = new ConcurrentHashMap<>(); 975 directoryServer.keyManagerProviders = new ConcurrentHashMap<>(); 976 directoryServer.trustManagerProviders = new ConcurrentHashMap<>(); 977 directoryServer.rotationPolicies = new ConcurrentHashMap<>(); 978 directoryServer.retentionPolicies = new ConcurrentHashMap<>(); 979 directoryServer.certificateMappers = new ConcurrentHashMap<>(); 980 directoryServer.authenticationPolicies = new ConcurrentHashMap<>(); 981 directoryServer.defaultPasswordPolicyDN = null; 982 directoryServer.defaultPasswordPolicy = null; 983 directoryServer.monitorProviders = new ConcurrentHashMap<>(); 984 directoryServer.backends = new TreeMap<>(); 985 directoryServer.backendInitializationListeners = new CopyOnWriteArraySet<>(); 986 directoryServer.baseDnRegistry = new BaseDnRegistry(); 987 directoryServer.initializationCompletedListeners = new CopyOnWriteArrayList<>(); 988 directoryServer.shutdownListeners = new CopyOnWriteArrayList<>(); 989 directoryServer.synchronizationProviders = new CopyOnWriteArrayList<>(); 990 directoryServer.supportedLDAPVersions = new ConcurrentHashMap<>(); 991 directoryServer.connectionHandlers = new CopyOnWriteArrayList<>(); 992 directoryServer.identityMappers = new ConcurrentHashMap<>(); 993 directoryServer.extendedOperationHandlers = new ConcurrentHashMap<>(); 994 directoryServer.saslMechanismHandlers = new ConcurrentHashMap<>(); 995 directoryServer.offlineSchemaChanges = new LinkedList<>(); 996 directoryServer.backupTaskListeners = new CopyOnWriteArrayList<>(); 997 directoryServer.restoreTaskListeners = new CopyOnWriteArrayList<>(); 998 directoryServer.exportTaskListeners = new CopyOnWriteArrayList<>(); 999 directoryServer.importTaskListeners = new CopyOnWriteArrayList<>(); 1000 directoryServer.allowedTasks = new LinkedHashSet<>(0); 1001 directoryServer.disabledPrivileges = new LinkedHashSet<>(0); 1002 directoryServer.returnBindErrorMessages = false; 1003 directoryServer.idleTimeLimit = 0L; 1004 } 1005 } 1006 1007 /** 1008 * Bootstraps the Directory Server by initializing all the necessary 1009 * structures that should be in place before the configuration may be read. 1010 * This step must be completed before the server may be started or the 1011 * configuration is loaded, but it will not be allowed while the server is 1012 * running. 1013 * 1014 * @throws InitializationException If a problem occurs while attempting to 1015 * bootstrap the server. 1016 */ 1017 private void bootstrapServer() throws InitializationException 1018 { 1019 // First, make sure that the server isn't currently running. If it isn't, 1020 // then make sure that no other thread will try to start or bootstrap the 1021 // server before this thread is done. 1022 synchronized (directoryServer) 1023 { 1024 if (isRunning) 1025 { 1026 LocalizableMessage message = ERR_CANNOT_BOOTSTRAP_WHILE_RUNNING.get(); 1027 throw new InitializationException(message); 1028 } 1029 1030 isBootstrapped = false; 1031 shuttingDown = false; 1032 } 1033 1034 // Add a shutdown hook so that the server can be notified when the JVM 1035 // starts shutting down. 1036 shutdownHook = new DirectoryServerShutdownHook(); 1037 Runtime.getRuntime().addShutdownHook(shutdownHook); 1038 1039 // Create the MBean server that we will use for JMX interaction. 1040 initializeJMX(); 1041 1042 logger.debug(INFO_DIRECTORY_BOOTSTRAPPING); 1043 1044 // Perform all the bootstrapping that is shared with the client-side processing. 1045 bootstrapClient(); 1046 1047 // Initialize the variables that will be used for connection tracking. 1048 establishedConnections = new LinkedHashSet<>(1000); 1049 currentConnections = 0; 1050 maxConnections = 0; 1051 totalConnections = 0; 1052 1053 // Create the plugin config manager, but don't initialize it yet. This will 1054 // make it possible to process internal operations before the plugins have 1055 // been loaded. 1056 pluginConfigManager = new PluginConfigManager(serverContext); 1057 1058 // If we have gotten here, then the configuration should be properly bootstrapped. 1059 synchronized (directoryServer) 1060 { 1061 isBootstrapped = true; 1062 } 1063 } 1064 1065 /** 1066 * Performs a minimal set of JMX initialization. This may be used by the core 1067 * Directory Server or by command-line tools. 1068 * 1069 * @throws InitializationException If a problem occurs while attempting to 1070 * initialize the JMX subsystem. 1071 */ 1072 public static void initializeJMX() 1073 throws InitializationException 1074 { 1075 try 1076 { 1077 // It is recommended by ManagementFactory javadoc that the platform 1078 // MBeanServer also be used to register other application managed 1079 // beans besides the platform MXBeans. Try platform MBeanServer 1080 // first. If it fails create a new, private, MBeanServer instance. 1081 try 1082 { 1083 directoryServer.mBeanServer = 1084 ManagementFactory.getPlatformMBeanServer(); 1085 } 1086 catch (Exception e) 1087 { 1088 logger.traceException(e); 1089 1090 directoryServer.mBeanServer = MBeanServerFactory.newMBeanServer(); 1091 } 1092 directoryServer.mBeans = new ConcurrentHashMap<>(); 1093 registerAlertGenerator(directoryServer); 1094 } 1095 catch (Exception e) 1096 { 1097 logger.traceException(e); 1098 1099 throw new InitializationException(ERR_CANNOT_CREATE_MBEAN_SERVER.get(e), e); 1100 } 1101 } 1102 1103 /** 1104 * Instantiates the configuration handler and loads the Directory Server 1105 * configuration. 1106 * 1107 * @param configClass The fully-qualified name of the Java class that will 1108 * serve as the configuration handler for the Directory 1109 * Server. 1110 * @param configFile The path to the file that will hold either the entire 1111 * server configuration or enough information to allow 1112 * the server to access the configuration in some other 1113 * repository. 1114 * 1115 * @throws InitializationException If a problem occurs while trying to 1116 * initialize the config handler. 1117 */ 1118 public void initializeConfiguration(String configClass, String configFile) 1119 throws InitializationException 1120 { 1121 Class<?> cfgClass; 1122 try 1123 { 1124 cfgClass = Class.forName(configClass); 1125 } 1126 catch (Exception e) 1127 { 1128 logger.traceException(e); 1129 1130 LocalizableMessage message = 1131 ERR_CANNOT_LOAD_CONFIG_HANDLER_CLASS.get( 1132 configClass, stackTraceToSingleLineString(e)); 1133 throw new InitializationException(message, e); 1134 } 1135 1136 File cfgFile = new File(configFile); 1137 1138 environmentConfig.setConfigClass(cfgClass); 1139 environmentConfig.setConfigFile(cfgFile); 1140 initializeConfiguration(); 1141 } 1142 1143 /** 1144 * Initializes this server. 1145 * <p> 1146 * Initialization involves the following steps: 1147 * <ul> 1148 * <li>Configuration</li> 1149 * <li>Schema</li> 1150 * </ul> 1151 * @throws InitializationException 1152 */ 1153 @ActivateOnceNewConfigFrameworkIsUsed("it will need adaptation to be activated before sdk schema is ready") 1154 @ActivateOnceSDKSchemaIsUsed 1155 private void initializeNG() throws InitializationException 1156 { 1157 serverManagementContext = ConfigurationBootstrapper.bootstrap(serverContext); 1158 initializeSchemaNG(); 1159 1160 // TODO : config backend should be initialized later, with the other backends 1161 //ConfigBackend configBackend = new ConfigBackend(); 1162 //configBackend.initializeConfigBackend(serverContext, configurationHandler); 1163 } 1164 1165 /** Initialize the schema of this server. */ 1166 @ActivateOnceSDKSchemaIsUsed 1167 private void initializeSchemaNG() throws InitializationException 1168 { 1169 SchemaHandler schemaHandler = new SchemaHandler(); 1170 try 1171 { 1172 schemaHandler.initialize(serverContext); 1173 } 1174 catch (org.forgerock.opendj.config.server.ConfigException e) 1175 { 1176 // TODO : fix message 1177 throw new InitializationException(LocalizableMessage.raw("Cannot initialize schema handler"), e); 1178 } 1179 } 1180 1181 /** 1182 * Instantiates the configuration handler and loads the Directory Server 1183 * configuration. 1184 * 1185 * @throws InitializationException If a problem occurs while trying to 1186 * initialize the config handler. 1187 */ 1188 public void initializeConfiguration() 1189 throws InitializationException 1190 { 1191 this.configClass = environmentConfig.getConfigClass(); 1192 this.configFile = environmentConfig.getConfigFile(); 1193 1194 // Make sure that administration framework definition classes are loaded. 1195 ClassLoaderProvider provider = ClassLoaderProvider.getInstance(); 1196 if (! provider.isEnabled()) 1197 { 1198 provider.enable(); 1199 } 1200 1201 // Load and instantiate the configuration handler class. 1202 Class<ConfigHandler> handlerClass = configClass; 1203 try 1204 { 1205 configHandler = handlerClass.newInstance(); 1206 } 1207 catch (Exception e) 1208 { 1209 logger.traceException(e); 1210 1211 LocalizableMessage message = 1212 ERR_CANNOT_INSTANTIATE_CONFIG_HANDLER.get(configClass, e.getLocalizedMessage()); 1213 throw new InitializationException(message, e); 1214 } 1215 1216 // Perform the handler-specific initialization. 1217 try 1218 { 1219 String path; 1220 try 1221 { 1222 path = configFile.getCanonicalPath(); 1223 } 1224 catch (Exception ex) 1225 { 1226 path = configFile.getAbsolutePath(); 1227 } 1228 configHandler.initializeConfigHandler(path, false); 1229 } 1230 catch (InitializationException ie) 1231 { 1232 logger.traceException(ie); 1233 1234 throw ie; 1235 } 1236 catch (Exception e) 1237 { 1238 logger.traceException(e); 1239 1240 LocalizableMessage message = 1241 ERR_CANNOT_INITIALIZE_CONFIG_HANDLER.get( 1242 configClass, configFile, e.getLocalizedMessage()); 1243 throw new InitializationException(message, e); 1244 } 1245 } 1246 1247 /** 1248 * Retrieves the path to the configuration file used to initialize the 1249 * Directory Server. 1250 * 1251 * @return The path to the configuration file used to initialize the 1252 * Directory Server. 1253 */ 1254 public static String getConfigFile() 1255 { 1256 return directoryServer.configFile.getAbsolutePath(); 1257 } 1258 1259 /** 1260 * Starts up the Directory Server. It must have already been bootstrapped 1261 * and cannot be running. 1262 * 1263 * @throws ConfigException If there is a problem with the Directory Server 1264 * configuration that prevents a critical component 1265 * from being instantiated. 1266 * 1267 * @throws InitializationException If some other problem occurs while 1268 * attempting to initialize and start the 1269 * Directory Server. 1270 */ 1271 public void startServer() 1272 throws ConfigException, InitializationException 1273 { 1274 // Checks the version - if upgrade required, cannot launch the server. 1275 try 1276 { 1277 BuildVersion.checkVersionMismatch(); 1278 } 1279 catch (InitializationException e) 1280 { 1281 logger.traceException(e); 1282 throw new InitializationException(e.getMessageObject()); 1283 } 1284 1285 synchronized (directoryServer) 1286 { 1287 if (! isBootstrapped) 1288 { 1289 LocalizableMessage message = ERR_CANNOT_START_BEFORE_BOOTSTRAP.get(); 1290 throw new InitializationException(message); 1291 } 1292 1293 if (isRunning) 1294 { 1295 LocalizableMessage message = ERR_CANNOT_START_WHILE_RUNNING.get(); 1296 throw new InitializationException(message); 1297 } 1298 1299 logger.info(NOTE_DIRECTORY_SERVER_STARTING, getVersionString(), BUILD_ID, REVISION_NUMBER); 1300 1301 // Acquire an exclusive lock for the Directory Server process. 1302 if (! serverLocked) 1303 { 1304 String lockFile = LockFileManager.getServerLockFileName(); 1305 try 1306 { 1307 StringBuilder failureReason = new StringBuilder(); 1308 if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason)) 1309 { 1310 LocalizableMessage message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get( 1311 lockFile, failureReason); 1312 throw new InitializationException(message); 1313 } 1314 1315 serverLocked = true; 1316 } 1317 catch (InitializationException ie) 1318 { 1319 throw ie; 1320 } 1321 catch (Exception e) 1322 { 1323 logger.traceException(e); 1324 1325 LocalizableMessage message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get( 1326 lockFile, stackTraceToSingleLineString(e)); 1327 throw new InitializationException(message, e); 1328 } 1329 } 1330 1331 // Mark the current time as the start time. 1332 startUpTime = System.currentTimeMillis(); 1333 startTimeUTC = TimeThread.getGMTTime(); 1334 1335 // Determine whether or not we should start the connection handlers. 1336 boolean startConnectionHandlers = !environmentConfig.disableConnectionHandlers(); 1337 1338 diskSpaceMonitor.startDiskSpaceMonitor(); 1339 1340 initializeSchema(); 1341 1342 // Allow internal plugins to be registered. 1343 pluginConfigManager.initializePluginConfigManager(); 1344 1345 virtualAttributeConfigManager.initializeVirtualAttributes(); 1346 1347 // The core Directory Server configuration. 1348 coreConfigManager = new CoreConfigManager(serverContext); 1349 coreConfigManager.initializeCoreConfig(); 1350 1351 initializeCryptoManager(); 1352 1353 rotationPolicyConfigManager = new LogRotationPolicyConfigManager(serverContext); 1354 rotationPolicyConfigManager.initializeLogRotationPolicyConfig(); 1355 1356 retentionPolicyConfigManager = new LogRetentionPolicyConfigManager(serverContext); 1357 retentionPolicyConfigManager.initializeLogRetentionPolicyConfig(); 1358 1359 loggerConfigManager = new LoggerConfigManager(serverContext); 1360 loggerConfigManager.initializeLoggerConfig(); 1361 1362 RuntimeInformation.logInfo(); 1363 1364 new AlertHandlerConfigManager(serverContext).initializeAlertHandlers(); 1365 1366 // Initialize the default entry cache. We have to have one before 1367 // <CODE>initializeBackends()</CODE> method kicks in further down. 1368 entryCacheConfigManager = new EntryCacheConfigManager(serverContext); 1369 entryCacheConfigManager.initializeDefaultEntryCache(); 1370 1371 // Initialize the administration connector self signed certificate if 1372 // needed and do this before initializing the key managers so that it is 1373 // picked up. 1374 if (startConnectionHandlers) 1375 { 1376 AdministrationConnector.createSelfSignedCertificateIfNeeded(serverContext); 1377 } 1378 1379 keyManagerProviderConfigManager = new KeyManagerProviderConfigManager(serverContext); 1380 keyManagerProviderConfigManager.initializeKeyManagerProviders(); 1381 1382 trustManagerProviderConfigManager = new TrustManagerProviderConfigManager(serverContext); 1383 trustManagerProviderConfigManager.initializeTrustManagerProviders(); 1384 1385 certificateMapperConfigManager = new CertificateMapperConfigManager(serverContext); 1386 certificateMapperConfigManager.initializeCertificateMappers(); 1387 1388 identityMapperConfigManager = new IdentityMapperConfigManager(serverContext); 1389 identityMapperConfigManager.initializeIdentityMappers(); 1390 1391 initializeRootDNConfigManager(); 1392 1393 initializeAuthenticatedUsers(); 1394 // initialize both subentry manager and group manager for this backend. 1395 initializeSubentryManager(); 1396 initializeGroupManager(); 1397 1398 // Initialize both subentry manager and group manager 1399 // for the configuration backend. 1400 // TODO : why do we initialize these now ? Can't we do them after backend initialization ? 1401 subentryManager.performBackendInitializationProcessing(configHandler); 1402 groupManager.performBackendInitializationProcessing(configHandler); 1403 1404 AccessControlConfigManager.getInstance().initializeAccessControl(serverContext); 1405 1406 // Initialize all the backends and their associated suffixes 1407 // and initialize the workflows when workflow configuration mode is auto. 1408 initializeBackends(); 1409 1410 // configure the remaining workflows (rootDSE and config backend). 1411 createAndRegisterRemainingWorkflows(); 1412 1413 // Check for and initialize user configured entry cache if any. 1414 // If not then stick with default entry cache initialized earlier. 1415 entryCacheConfigManager.initializeEntryCache(); 1416 1417 initializeExtendedOperations(); 1418 initializeSASLMechanisms(); 1419 1420 if (startConnectionHandlers) 1421 { 1422 // Includes the administration connector. 1423 initializeConnectionHandlers(); 1424 } 1425 1426 monitorConfigManager = new MonitorConfigManager(serverContext); 1427 monitorConfigManager.initializeMonitorProviders(); 1428 1429 initializeAuthenticationPolicyComponents(); 1430 1431 pluginConfigManager.initializeUserPlugins(null); 1432 1433 if (!environmentConfig.disableSynchronization()) 1434 { 1435 synchronizationProviderConfigManager = new SynchronizationProviderConfigManager(serverContext); 1436 synchronizationProviderConfigManager.initializeSynchronizationProviders(); 1437 } 1438 1439 workQueue = new WorkQueueConfigManager(serverContext).initializeWorkQueue(); 1440 1441 PluginResult.Startup startupPluginResult = pluginConfigManager.invokeStartupPlugins(); 1442 if (! startupPluginResult.continueProcessing()) 1443 { 1444 throw new InitializationException(ERR_STARTUP_PLUGIN_ERROR.get(startupPluginResult.getErrorMessage(), 1445 startupPluginResult.getErrorMessage().ordinal())); 1446 } 1447 1448 for (InitializationCompletedListener listener : initializationCompletedListeners) 1449 { 1450 try 1451 { 1452 listener.initializationCompleted(); 1453 } 1454 catch (Exception e) 1455 { 1456 logger.traceException(e); 1457 } 1458 } 1459 1460 if (startConnectionHandlers) 1461 { 1462 startConnectionHandlers(); 1463 new IdleTimeLimitThread().start(); 1464 } 1465 1466 // Synchronization of ADS with the crypto manager. 1467 new CryptoManagerSync(); 1468 1469 // Write a copy of the config if needed. 1470 if (saveConfigOnSuccessfulStartup) 1471 { 1472 configHandler.writeSuccessfulStartupConfig(); 1473 } 1474 1475 isRunning = true; 1476 1477 LocalizableMessage message = NOTE_DIRECTORY_SERVER_STARTED.get(); 1478 logger.info(message); 1479 sendAlertNotification(this, ALERT_TYPE_SERVER_STARTED, message); 1480 1481 // Force the root connection to be initialized. 1482 InternalClientConnection rootConnection = InternalClientConnection.getRootConnection(); 1483 1484 if (! environmentConfig.disableAdminDataSynchronization()) 1485 { 1486 AdministrationDataSync admDataSync = new AdministrationDataSync(rootConnection); 1487 admDataSync.synchronize(); 1488 } 1489 1490 deleteUnnecessaryFiles(); 1491 } 1492 } 1493 1494 /** Delete "server.starting" and "hostname" files if they are present. */ 1495 private void deleteUnnecessaryFiles() 1496 { 1497 File serverStartingFile = new File(configHandler.getInstanceRoot() + File.separator + "logs" 1498 + File.separator + "server.starting"); 1499 if (serverStartingFile.exists()) 1500 { 1501 serverStartingFile.delete(); 1502 } 1503 1504 File hostNameFile = new File(configHandler.getInstanceRoot() + File.separator + SetupUtils.HOST_NAME_FILE); 1505 if (hostNameFile.exists()) 1506 { 1507 hostNameFile.delete(); 1508 } 1509 } 1510 1511 /** Initializes authenticated users. */ 1512 public void initializeAuthenticatedUsers() 1513 { 1514 directoryServer.authenticatedUsers = new AuthenticatedUsers(); 1515 } 1516 1517 /** 1518 * Registers a basic set of matching rules with the server that should always 1519 * be available regardless of the server configuration and may be needed for 1520 * configuration processing. 1521 */ 1522 private void bootstrapMatchingRules() 1523 { 1524 MatchingRuleFactory<?>[] factories = 1525 new MatchingRuleFactory<?>[] { 1526 new DoubleMetaphoneApproximateMatchingRuleFactory(), 1527 new BooleanEqualityMatchingRuleFactory(), 1528 new CaseExactEqualityMatchingRuleFactory(), 1529 new CaseExactIA5EqualityMatchingRuleFactory(), 1530 new CaseIgnoreEqualityMatchingRuleFactory(), 1531 new CaseIgnoreIA5EqualityMatchingRuleFactory(), 1532 new DistinguishedNameEqualityMatchingRuleFactory(), 1533 new GeneralizedTimeEqualityMatchingRuleFactory(), 1534 new IntegerEqualityMatchingRuleFactory(), 1535 new OctetStringEqualityMatchingRuleFactory(), 1536 new ObjectIdentifierEqualityMatchingRuleFactory(), 1537 new TelephoneNumberEqualityMatchingRuleFactory(), 1538 new CaseExactOrderingMatchingRuleFactory(), 1539 new CaseIgnoreOrderingMatchingRuleFactory(), 1540 new GeneralizedTimeOrderingMatchingRuleFactory(), 1541 new IntegerOrderingMatchingRuleFactory(), 1542 new OctetStringOrderingMatchingRuleFactory(), 1543 new CaseExactSubstringMatchingRuleFactory(), 1544 new CaseExactIA5SubstringMatchingRuleFactory(), 1545 new CaseIgnoreSubstringMatchingRuleFactory(), 1546 new CaseIgnoreIA5SubstringMatchingRuleFactory(), 1547 new OctetStringSubstringMatchingRuleFactory(), 1548 new TelephoneNumberSubstringMatchingRuleFactory()}; 1549 1550 MatchingRuleFactory<?> currentFactory = null; 1551 try 1552 { 1553 for(MatchingRuleFactory<?> factory: factories) 1554 { 1555 currentFactory = factory; 1556 currentFactory.initializeMatchingRule(null); 1557 for(MatchingRule matchingRule: currentFactory.getMatchingRules()) 1558 { 1559 registerMatchingRule(matchingRule, true); 1560 } 1561 } 1562 } 1563 catch (Exception e) 1564 { 1565 logger.traceException(e); 1566 1567 logger.error(ERR_CANNOT_BOOTSTRAP_MATCHING_RULE, currentFactory.getClass().getName(), 1568 stackTraceToSingleLineString(e)); 1569 } 1570 } 1571 1572 /** 1573 * Registers a basic set of attribute syntaxes with the server that should 1574 * always be available regardless of the server configuration and may be 1575 * needed for configuration processing. 1576 */ 1577 private void bootstrapAttributeSyntaxes() 1578 { 1579 schema.registerDefaultSyntax(getDefaultSyntax()); 1580 1581 Syntax[] syntaxes = { 1582 getDefaultBinarySyntax(), 1583 getDefaultBooleanSyntax(), 1584 getDefaultStringSyntax(), 1585 getDefaultDNSyntax(), 1586 getDefaultIntegerSyntax(), 1587 CoreSchema.getAttributeTypeDescriptionSyntax(), 1588 CoreSchema.getIA5StringSyntax(), 1589 CoreSchema.getGeneralizedTimeSyntax(), 1590 CoreSchema.getObjectClassDescriptionSyntax(), 1591 CoreSchema.getOIDSyntax(), 1592 CoreSchema.getTelephoneNumberSyntax() 1593 }; 1594 for (Syntax syntax : syntaxes) 1595 { 1596 registerSyntax(syntax); 1597 } 1598 } 1599 1600 private Syntax registerSyntax(Syntax syntax) 1601 { 1602 try 1603 { 1604 schema.registerSyntax(syntax, true); 1605 } 1606 catch (Exception e) 1607 { 1608 logger.error(ERR_CANNOT_BOOTSTRAP_SYNTAX, syntax.getClass().getName(), stackTraceToSingleLineString(e)); 1609 } 1610 return syntax; 1611 } 1612 1613 /** 1614 * Retrieves the authenticated users manager for the Directory Server. 1615 * 1616 * @return The authenticated users manager for the Directory Server. 1617 */ 1618 public static AuthenticatedUsers getAuthenticatedUsers() 1619 { 1620 return directoryServer.authenticatedUsers; 1621 } 1622 1623 /** 1624 * Initializes the crypto manager for the Directory Server. 1625 * 1626 * @throws ConfigException 1627 * If a configuration problem is identified while initializing the 1628 * crypto manager. 1629 * @throws InitializationException 1630 * If a problem occurs while initializing the crypto manager that is 1631 * not related to the server configuration. 1632 */ 1633 public void initializeCryptoManager() 1634 throws ConfigException, InitializationException 1635 { 1636 RootCfg root = 1637 ServerManagementContext.getInstance().getRootConfiguration(); 1638 CryptoManagerCfg cryptoManagerCfg = root.getCryptoManager(); 1639 cryptoManager = new CryptoManagerImpl(serverContext, cryptoManagerCfg); 1640 } 1641 1642 /** 1643 * Retrieves a reference to the Directory Server crypto manager. 1644 * 1645 * @return A reference to the Directory Server crypto manager. 1646 */ 1647 public static CryptoManagerImpl getCryptoManager() 1648 { 1649 return directoryServer.cryptoManager; 1650 } 1651 1652 /** 1653 * Indicates whether the Directory Server is configured with information about 1654 * one or more mail servers and may therefore be used to send e-mail messages. 1655 * 1656 * @return {@code true} if the Directory Server is configured to be able to 1657 * send e-mail messages, or {@code false} if not. 1658 */ 1659 public static boolean mailServerConfigured() 1660 { 1661 return directoryServer.mailServerPropertySets != null 1662 && !directoryServer.mailServerPropertySets.isEmpty(); 1663 } 1664 1665 /** 1666 * Specifies the set of mail server properties that should be used for SMTP 1667 * communication. 1668 * 1669 * @param mailServerPropertySets A list of {@code Properties} objects that 1670 * provide information that can be used to 1671 * communicate with SMTP servers. 1672 */ 1673 public static void setMailServerPropertySets(List<Properties> 1674 mailServerPropertySets) 1675 { 1676 directoryServer.mailServerPropertySets = mailServerPropertySets; 1677 } 1678 1679 /** 1680 * Retrieves the sets of information about the mail servers configured for use 1681 * by the Directory Server. 1682 * 1683 * @return The sets of information about the mail servers configured for use 1684 * by the Directory Server. 1685 */ 1686 public static List<Properties> getMailServerPropertySets() 1687 { 1688 return directoryServer.mailServerPropertySets; 1689 } 1690 1691 /** 1692 * Initializes the schema elements for the Directory Server, including the 1693 * matching rules, attribute syntaxes, attribute types, and object classes. 1694 * 1695 * @throws ConfigException If there is a configuration problem with any of 1696 * the schema elements. 1697 * 1698 * @throws InitializationException If a problem occurs while initializing 1699 * the schema elements that is not related 1700 * to the server configuration. 1701 */ 1702 public void initializeSchema() 1703 throws ConfigException, InitializationException 1704 { 1705 // Create the schema configuration manager, and initialize the schema from 1706 // the configuration. 1707 schemaConfigManager = new SchemaConfigManager(serverContext); 1708 schema = schemaConfigManager.getSchema(); 1709 1710 schemaConfigManager.initializeMatchingRules(); 1711 schemaConfigManager.initializeAttributeSyntaxes(); 1712 schemaConfigManager.initializeSchemaFromFiles(); 1713 1714 // With server schema in place set compressed schema. 1715 compressedSchema = new DefaultCompressedSchema(); 1716 1717 // At this point we have a problem, because none of the configuration is 1718 // usable because it was all read before we had a schema (and therefore all 1719 // of the attribute types and objectclasses are bogus and won't let us find 1720 // anything). So we have to re-read the configuration so that we can 1721 // continue the necessary startup process. In the process, we want to 1722 // preserve any configuration add/delete/change listeners that might have 1723 // been registered with the old configuration (which will primarily be 1724 // schema elements) so they can be re-registered with the new configuration. 1725 Map<String, List<ConfigAddListener>> addListeners = new LinkedHashMap<>(); 1726 Map<String, List<ConfigDeleteListener>> deleteListeners = new LinkedHashMap<>(); 1727 Map<String, List<ConfigChangeListener>> changeListeners = new LinkedHashMap<>(); 1728 getChangeListeners(configHandler.getConfigRootEntry(), addListeners, 1729 deleteListeners, changeListeners); 1730 1731 try 1732 { 1733 configHandler.finalizeConfigHandler(); 1734 } 1735 catch (Exception e) 1736 { 1737 logger.traceException(e); 1738 } 1739 1740 try 1741 { 1742 configHandler.initializeConfigHandler(configFile.getAbsolutePath(), true); 1743 } 1744 catch (InitializationException ie) 1745 { 1746 logger.traceException(ie); 1747 1748 throw ie; 1749 } 1750 catch (Exception e) 1751 { 1752 logger.traceException(e); 1753 1754 throw new InitializationException(ERR_CANNOT_INITIALIZE_CONFIG_HANDLER.get( 1755 configClass, configFile, e.getLocalizedMessage())); 1756 } 1757 1758 // Re-register all of the change listeners with the configuration. 1759 for (String dnStr : addListeners.keySet()) 1760 { 1761 try 1762 { 1763 DN dn = DN.valueOf(dnStr); 1764 for (ConfigAddListener listener : addListeners.get(dnStr)) 1765 { 1766 configHandler.getConfigEntry(dn).registerAddListener(listener); 1767 } 1768 } 1769 catch (DirectoryException de) 1770 { 1771 // This should never happen, so we'll just re-throw it. 1772 throw new InitializationException(de.getMessageObject()); 1773 } 1774 } 1775 1776 for (String dnStr : deleteListeners.keySet()) 1777 { 1778 try 1779 { 1780 DN dn = DN.valueOf(dnStr); 1781 for (ConfigDeleteListener listener : deleteListeners.get(dnStr)) 1782 { 1783 configHandler.getConfigEntry(dn).registerDeleteListener(listener); 1784 } 1785 } 1786 catch (DirectoryException de) 1787 { 1788 // This should never happen, so we'll just re-throw it. 1789 throw new InitializationException(de.getMessageObject()); 1790 } 1791 } 1792 1793 for (String dnStr : changeListeners.keySet()) 1794 { 1795 try 1796 { 1797 DN dn = DN.valueOf(dnStr); 1798 for (ConfigChangeListener listener : changeListeners.get(dnStr)) 1799 { 1800 configHandler.getConfigEntry(dn).registerChangeListener(listener); 1801 } 1802 } 1803 catch (DirectoryException de) 1804 { 1805 // This should never happen, so we'll just re-throw it. 1806 throw new InitializationException(de.getMessageObject()); 1807 } 1808 } 1809 } 1810 1811 /** 1812 * Retrieves the default compressed schema manager for the Directory Server. 1813 * 1814 * @return The default compressed schema manager for the Directory Server. 1815 */ 1816 public static CompressedSchema getDefaultCompressedSchema() 1817 { 1818 return directoryServer.compressedSchema; 1819 } 1820 1821 /** 1822 * Gets all of the add, delete, and change listeners from the provided 1823 * configuration entry and all of its descendants and puts them in the 1824 * appropriate lists. 1825 * 1826 * @param configEntry The configuration entry to be processed, along 1827 * with all of its descendants. 1828 * @param addListeners The set of add listeners mapped to the DN of the 1829 * corresponding configuration entry. 1830 * @param deleteListeners The set of delete listeners mapped to the DN of 1831 * the corresponding configuration entry. 1832 * @param changeListeners The set of change listeners mapped to the DN of 1833 * the corresponding configuration entry. 1834 */ 1835 private void getChangeListeners(ConfigEntry configEntry, 1836 Map<String, List<ConfigAddListener>> addListeners, 1837 Map<String, List<ConfigDeleteListener>> deleteListeners, 1838 Map<String, List<ConfigChangeListener>> changeListeners) 1839 { 1840 put(addListeners, configEntry, configEntry.getAddListeners()); 1841 put(deleteListeners, configEntry, configEntry.getDeleteListeners()); 1842 put(changeListeners, configEntry, configEntry.getChangeListeners()); 1843 1844 for (ConfigEntry child : configEntry.getChildren().values()) 1845 { 1846 getChangeListeners(child, addListeners, deleteListeners, changeListeners); 1847 } 1848 } 1849 1850 private <T> void put(Map<String, List<T>> listeners, ConfigEntry configEntry, List<T> cfgListeners) 1851 { 1852 if (cfgListeners != null && !cfgListeners.isEmpty()) 1853 { 1854 listeners.put(configEntry.getDN().toString(), cfgListeners); 1855 } 1856 } 1857 1858 /** 1859 * Retrieves the set of backend initialization listeners that have been 1860 * registered with the Directory Server. The contents of the returned set 1861 * must not be altered. 1862 * 1863 * @return The set of backend initialization listeners that have been 1864 * registered with the Directory Server. 1865 */ 1866 public static Set<BackendInitializationListener> 1867 getBackendInitializationListeners() 1868 { 1869 return directoryServer.backendInitializationListeners; 1870 } 1871 1872 /** 1873 * Registers the provided backend initialization listener with the Directory 1874 * Server. 1875 * 1876 * @param listener The backend initialization listener to register with the 1877 * Directory Server. 1878 */ 1879 public static void registerBackendInitializationListener( 1880 BackendInitializationListener listener) 1881 { 1882 directoryServer.backendInitializationListeners.add(listener); 1883 } 1884 1885 /** 1886 * Deregisters the provided backend initialization listener with the Directory 1887 * Server. 1888 * 1889 * @param listener The backend initialization listener to deregister with 1890 * the Directory Server. 1891 */ 1892 public static void deregisterBackendInitializationListener( 1893 BackendInitializationListener listener) 1894 { 1895 directoryServer.backendInitializationListeners.remove(listener); 1896 } 1897 1898 /** 1899 * Initializes the set of backends defined in the Directory Server. 1900 * 1901 * @throws ConfigException If there is a configuration problem with any of 1902 * the backends. 1903 * 1904 * @throws InitializationException If a problem occurs while initializing 1905 * the backends that is not related to the 1906 * server configuration. 1907 */ 1908 private void initializeBackends() throws ConfigException, InitializationException 1909 { 1910 backendConfigManager = new BackendConfigManager(serverContext); 1911 backendConfigManager.initializeBackendConfig(); 1912 1913 // Make sure to initialize the root DSE backend separately after all other 1914 // backends. 1915 RootDSEBackendCfg rootDSECfg; 1916 try 1917 { 1918 RootCfg root = ServerManagementContext.getInstance().getRootConfiguration(); 1919 rootDSECfg = root.getRootDSEBackend(); 1920 } 1921 catch (Exception e) 1922 { 1923 logger.traceException(e); 1924 throw new InitializationException(ERR_CANNOT_GET_ROOT_DSE_CONFIG_ENTRY.get( 1925 stackTraceToSingleLineString(e)), e); 1926 } 1927 1928 rootDSEBackend = new RootDSEBackend(); 1929 rootDSEBackend.configureBackend(rootDSECfg, serverContext); 1930 rootDSEBackend.openBackend(); 1931 } 1932 1933 /** 1934 * Creates a set of workflows for a given backend and registers the 1935 * workflows with the default network group, the internal network group 1936 * and he admin network group. There are as many workflows 1937 * as base DNs defined in the backend. 1938 * 1939 * @param backend the backend handled by the workflow 1940 * 1941 * @throws DirectoryException If the workflow ID for the provided 1942 * workflow conflicts with the workflow 1943 * ID of an existing workflow. 1944 */ 1945 private static void createAndRegisterWorkflows(Backend<?> backend) throws DirectoryException 1946 { 1947 // Create a workflow for each backend base DN and register the workflow 1948 // with the default/internal/admin network group. 1949 for (DN curBaseDN: backend.getBaseDNs()) 1950 { 1951 createWorkflow(curBaseDN, backend); 1952 } 1953 } 1954 1955 /** 1956 * Creates one workflow for a given base DN in a backend. 1957 * 1958 * @param baseDN the base DN of the workflow to create 1959 * @param backend the backend handled by the workflow 1960 * @throws DirectoryException If the workflow ID for the provided 1961 * workflow conflicts with the workflow 1962 * ID of an existing workflow. 1963 */ 1964 private static void createWorkflow(DN baseDN, Backend<?> backend) throws DirectoryException 1965 { 1966 LocalBackendWorkflowElement.createAndRegister(baseDN, backend); 1967 } 1968 1969 /** 1970 * Creates the missing workflows, one for the config backend and one for 1971 * the rootDSE backend. 1972 * 1973 * This method should be invoked whatever may be the workflow 1974 * configuration mode because config backend and rootDSE backend 1975 * will not have any configuration section, ever. 1976 * 1977 * @throws ConfigException If there is a configuration problem with any of 1978 * the workflows. 1979 */ 1980 private void createAndRegisterRemainingWorkflows() 1981 throws ConfigException 1982 { 1983 try 1984 { 1985 createAndRegisterWorkflows(configHandler); 1986 createAndRegisterWorkflows(rootDSEBackend); 1987 } 1988 catch (DirectoryException de) 1989 { 1990 throw new ConfigException(de.getMessageObject()); 1991 } 1992 } 1993 1994 /** 1995 * Initializes the Directory Server group manager. 1996 * 1997 * @throws ConfigException If there is a configuration problem with any of 1998 * the group implementations. 1999 * 2000 * @throws InitializationException If a problem occurs while initializing 2001 * the group manager that is not related to 2002 * the server configuration. 2003 */ 2004 private void initializeGroupManager() 2005 throws ConfigException, InitializationException 2006 { 2007 try 2008 { 2009 groupManager = new GroupManager(serverContext); 2010 } 2011 catch (DirectoryException de) 2012 { 2013 logger.traceException(de); 2014 2015 throw new InitializationException(de.getMessageObject()); 2016 } 2017 2018 groupManager.initializeGroupImplementations(); 2019 2020 // The configuration backend has already been registered by this point 2021 // so we need to handle it explicitly. 2022 // Because subentryManager may depend on the groupManager, let's 2023 // delay this. 2024 // groupManager.performBackendInitializationProcessing(configHandler); 2025 } 2026 2027 /** 2028 * Retrieves the Directory Server group manager. 2029 * 2030 * @return The Directory Server group manager. 2031 */ 2032 public static GroupManager getGroupManager() 2033 { 2034 return directoryServer.groupManager; 2035 } 2036 2037 /** 2038 * Retrieves the Directory Server subentry manager. 2039 * 2040 * @return The Directory Server subentry manager. 2041 */ 2042 public static SubentryManager getSubentryManager() 2043 { 2044 return directoryServer.subentryManager; 2045 } 2046 2047 /** 2048 * Initializes the set of extended operation handlers for the Directory 2049 * Server. 2050 * 2051 * @throws ConfigException If there is a configuration problem with any of 2052 * the extended operation handlers. 2053 * 2054 * @throws InitializationException If a problem occurs while initializing 2055 * the extended operation handlers that is 2056 * not related to the server configuration. 2057 */ 2058 private void initializeExtendedOperations() 2059 throws ConfigException, InitializationException 2060 { 2061 extendedOperationConfigManager = new ExtendedOperationConfigManager(serverContext); 2062 extendedOperationConfigManager.initializeExtendedOperationHandlers(); 2063 } 2064 2065 /** 2066 * Initializes the set of SASL mechanism handlers for the Directory Server. 2067 * 2068 * @throws ConfigException If there is a configuration problem with any of 2069 * the SASL mechanism handlers. 2070 * 2071 * @throws InitializationException If a problem occurs while initializing 2072 * the SASL mechanism handlers that is not 2073 * related to the server configuration. 2074 */ 2075 private void initializeSASLMechanisms() 2076 throws ConfigException, InitializationException 2077 { 2078 saslConfigManager = new SASLConfigManager(serverContext); 2079 saslConfigManager.initializeSASLMechanismHandlers(); 2080 } 2081 2082 /** 2083 * Initializes the set of connection handlers that should be defined in the 2084 * Directory Server. 2085 * 2086 * @throws ConfigException If there is a configuration problem with any of 2087 * the connection handlers. 2088 * 2089 * @throws InitializationException If a problem occurs while initializing 2090 * the connection handlers that is not 2091 * related to the server configuration. 2092 */ 2093 private void initializeConnectionHandlers() 2094 throws ConfigException, InitializationException 2095 { 2096 if (connectionHandlerConfigManager == null) { 2097 connectionHandlerConfigManager = new ConnectionHandlerConfigManager(serverContext); 2098 } 2099 connectionHandlerConfigManager.initializeConnectionHandlerConfig(); 2100 } 2101 2102 /** 2103 * Initializes the subentry manager for the Directory Server. 2104 * Note that the subentry manager initialization should be 2105 * done before any dependent components initialization and 2106 * before bringing any backends online. Configuration backend 2107 * is a special case and therefore is exception to this rule. 2108 * 2109 * @throws InitializationException If a problem occurs while 2110 * initializing the subentry 2111 * manager. 2112 */ 2113 public void initializeSubentryManager() 2114 throws InitializationException 2115 { 2116 try 2117 { 2118 subentryManager = new SubentryManager(); 2119 2120 // The configuration backend should already be registered 2121 // at this point so we need to handle it explicitly here. 2122 // However, subentryManager may have dependencies on the 2123 // groupManager. So lets delay the backend initialization until then. 2124 // subentryManager.performBackendInitializationProcessing( 2125 // configHandler); 2126 } 2127 catch (DirectoryException de) 2128 { 2129 throw new InitializationException(de.getMessageObject()); 2130 } 2131 } 2132 2133 /** 2134 * Initializes the set of authentication policy components for use by the 2135 * Directory Server. 2136 * 2137 * @throws ConfigException 2138 * If there is a configuration problem with any of the 2139 * authentication policy components. 2140 * @throws InitializationException 2141 * If a problem occurs while initializing the authentication policy 2142 * components that is not related to the server configuration. 2143 */ 2144 public void initializeAuthenticationPolicyComponents() throws ConfigException, InitializationException 2145 { 2146 storageSchemeConfigManager = new PasswordStorageSchemeConfigManager(serverContext); 2147 storageSchemeConfigManager.initializePasswordStorageSchemes(); 2148 2149 passwordValidatorConfigManager = new PasswordValidatorConfigManager(serverContext); 2150 passwordValidatorConfigManager.initializePasswordValidators(); 2151 2152 passwordGeneratorConfigManager = new PasswordGeneratorConfigManager(serverContext); 2153 passwordGeneratorConfigManager.initializePasswordGenerators(); 2154 2155 accountStatusNotificationHandlerConfigManager = new AccountStatusNotificationHandlerConfigManager(serverContext); 2156 accountStatusNotificationHandlerConfigManager.initializeNotificationHandlers(); 2157 2158 authenticationPolicyConfigManager = new PasswordPolicyConfigManager(serverContext); 2159 authenticationPolicyConfigManager.initializeAuthenticationPolicies(); 2160 } 2161 2162 /** 2163 * Retrieves the operating system on which the Directory Server is running. 2164 * 2165 * @return The operating system on which the Directory Server is running. 2166 */ 2167 public static OperatingSystem getOperatingSystem() 2168 { 2169 return directoryServer.operatingSystem; 2170 } 2171 2172 /** 2173 * Retrieves a reference to the Directory Server configuration handler. 2174 * 2175 * @return A reference to the Directory Server configuration handler. 2176 */ 2177 public static ConfigHandler getConfigHandler() 2178 { 2179 return directoryServer.configHandler; 2180 } 2181 2182 /** 2183 * Initializes the set of plugins defined in the Directory Server. Only the 2184 * specified types of plugins will be initialized. 2185 * 2186 * @param pluginTypes The set of plugin types for the plugins to 2187 * initialize. 2188 * 2189 * @throws ConfigException If there is a configuration problem with any of 2190 * the Directory Server plugins. 2191 * 2192 * @throws InitializationException If a problem occurs while initializing 2193 * the plugins that is not related to the 2194 * server configuration. 2195 */ 2196 public void initializePlugins(Set<PluginType> pluginTypes) 2197 throws ConfigException, InitializationException 2198 { 2199 pluginConfigManager = new PluginConfigManager(serverContext); 2200 pluginConfigManager.initializePluginConfigManager(); 2201 pluginConfigManager.initializeUserPlugins(pluginTypes); 2202 } 2203 2204 /** 2205 * Initializes the root DN Config Manager in the Directory Server. 2206 * 2207 * @throws ConfigException If a problem occurs registering a DN. 2208 * @throws InitializationException If a problem occurs initializing the root 2209 * DN manager. 2210 */ 2211 public void initializeRootDNConfigManager() 2212 throws ConfigException, InitializationException{ 2213 rootDNConfigManager = new RootDNConfigManager(serverContext); 2214 rootDNConfigManager.initializeRootDNs(); 2215 } 2216 2217 /** 2218 * Initialize the root DSE in the Directory Server. 2219 * 2220 * @throws ConfigException If a problem occurs retrieving the root DSE backend 2221 * configuration. 2222 * @throws InitializationException If a problem occurs initializing the root 2223 * root DSE backend. 2224 */ 2225 public void initializeRootDSE() 2226 throws ConfigException, InitializationException { 2227 RootDSEBackendCfg rootDSECfg; 2228 try { 2229 RootCfg root = 2230 ServerManagementContext.getInstance().getRootConfiguration(); 2231 rootDSECfg = root.getRootDSEBackend(); 2232 } catch (Exception e) { 2233 logger.traceException(e); 2234 LocalizableMessage message = ERR_CANNOT_GET_ROOT_DSE_CONFIG_ENTRY.get( 2235 stackTraceToSingleLineString(e)); 2236 throw new InitializationException(message, e); 2237 } 2238 rootDSEBackend = new RootDSEBackend(); 2239 rootDSEBackend.configureBackend(rootDSECfg, serverContext); 2240 rootDSEBackend.openBackend(); 2241} 2242 2243 /** 2244 * Retrieves a reference to the Directory Server plugin configuration manager. 2245 * 2246 * @return A reference to the Directory Server plugin configuration manager. 2247 */ 2248 public static PluginConfigManager getPluginConfigManager() 2249 { 2250 return directoryServer.pluginConfigManager; 2251 } 2252 2253 /** 2254 * Registers the provided internal plugin with the Directory Server 2255 * and ensures that it will be invoked in the specified ways. 2256 * 2257 * @param plugin 2258 * The internal plugin to register with the Directory Server. 2259 * The plugin must specify a configuration entry which is 2260 * guaranteed to be unique. 2261 */ 2262 public static void registerInternalPlugin( 2263 InternalDirectoryServerPlugin plugin) 2264 { 2265 directoryServer.pluginConfigManager.registerInternalPlugin(plugin); 2266 } 2267 2268 /** 2269 * Deregisters the provided internal plugin with the Directory Server. 2270 * 2271 * @param plugin 2272 * The internal plugin to deregister from the Directory Server. 2273 */ 2274 public static void deregisterInternalPlugin( 2275 InternalDirectoryServerPlugin plugin) 2276 { 2277 directoryServer.pluginConfigManager.deregisterInternalPlugin(plugin); 2278 } 2279 2280 /** 2281 * Retrieves the requested entry from the Directory Server configuration. 2282 * 2283 * @param entryDN The DN of the configuration entry to retrieve. 2284 * 2285 * @return The requested entry from the Directory Server configuration. 2286 * 2287 * @throws ConfigException If a problem occurs while trying to retrieve the 2288 * requested entry. 2289 */ 2290 public static ConfigEntry getConfigEntry(DN entryDN) 2291 throws ConfigException 2292 { 2293 return directoryServer.configHandler.getConfigEntry(entryDN); 2294 } 2295 2296 /** 2297 * Retrieves the path to the root directory for this instance of the Directory 2298 * Server. 2299 * 2300 * @return The path to the root directory for this instance of the Directory 2301 * Server. 2302 */ 2303 public static String getServerRoot() 2304 { 2305 return directoryServer.environmentConfig.getServerRootAsString(); 2306 } 2307 2308 /** 2309 * Retrieves the path to the instance directory for this instance of the 2310 * Directory Server. 2311 * 2312 * @return The path to the instance directory for this instance of 2313 * the Directory Server. 2314 */ 2315 public static String getInstanceRoot() 2316 { 2317 return directoryServer.environmentConfig.getInstanceRootAsString(); 2318 } 2319 2320 /** 2321 * Retrieves the time that the Directory Server was started, in milliseconds 2322 * since the epoch. 2323 * 2324 * @return The time that the Directory Server was started, in milliseconds 2325 * since the epoch. 2326 */ 2327 public static long getStartTime() 2328 { 2329 return directoryServer.startUpTime; 2330 } 2331 2332 /** 2333 * Retrieves the time that the Directory Server was started, formatted in UTC. 2334 * 2335 * @return The time that the Directory Server was started, formatted in UTC. 2336 */ 2337 public static String getStartTimeUTC() 2338 { 2339 return directoryServer.startTimeUTC; 2340 } 2341 2342 /** 2343 * Retrieves a reference to the Directory Server schema. 2344 * 2345 * @return A reference to the Directory Server schema. 2346 */ 2347 public static Schema getSchema() 2348 { 2349 return directoryServer.schema; 2350 } 2351 2352 /** 2353 * Replaces the Directory Server schema with the provided schema. 2354 * 2355 * @param schema The new schema to use for the Directory Server. 2356 */ 2357 public static void setSchema(Schema schema) 2358 { 2359 directoryServer.schema = schema; 2360 } 2361 2362 /** 2363 * Retrieves a list of modifications detailing any schema changes that may 2364 * have been made with the server offline (e.g., by directly editing the 2365 * schema configuration files). Note that this information will not be 2366 * available until the server backends (and in particular, the schema backend) 2367 * have been initialized. 2368 * 2369 * @return A list of modifications detailing any schema changes that may have 2370 * been made with the server offline, or an empty list if no offline 2371 * schema changes have been detected. 2372 */ 2373 public static List<Modification> getOfflineSchemaChanges() 2374 { 2375 return directoryServer.offlineSchemaChanges; 2376 } 2377 2378 /** 2379 * Specifies a list of modifications detailing any schema changes that may 2380 * have been made with the server offline. 2381 * 2382 * @param offlineSchemaChanges A list of modifications detailing any schema 2383 * changes that may have been made with the 2384 * server offline. It must not be {@code null}. 2385 */ 2386 public static void setOfflineSchemaChanges(List<Modification> 2387 offlineSchemaChanges) 2388 { 2389 ifNull(offlineSchemaChanges); 2390 2391 directoryServer.offlineSchemaChanges = offlineSchemaChanges; 2392 } 2393 2394 /** 2395 * Retrieves the set of matching rules registered with the Directory Server. 2396 * The mapping will be between the lowercase name or OID for each matching 2397 * rule and the matching rule implementation. The same matching rule instance 2398 * may be included multiple times with different keys. 2399 * 2400 * @return The set of matching rules registered with the Directory Server. 2401 */ 2402 public static ConcurrentMap<String, MatchingRule> getMatchingRules() 2403 { 2404 return directoryServer.schema.getMatchingRules(); 2405 } 2406 2407 /** 2408 * Retrieves the matching rule with the specified name or OID. 2409 * 2410 * @param lowerName The lowercase name or OID for the matching rule to 2411 * retrieve. 2412 * 2413 * @return The requested matching rule, or <CODE>null</CODE> if no such 2414 * matching rule has been defined in the server. 2415 */ 2416 public static MatchingRule getMatchingRule(String lowerName) 2417 { 2418 return directoryServer.schema.getMatchingRule(lowerName); 2419 } 2420 2421 /** 2422 * Registers the provided matching rule with the Directory Server. 2423 * 2424 * @param matchingRule The matching rule to register with the server. 2425 * @param overwriteExisting Indicates whether to overwrite an existing 2426 * mapping if there are any conflicts (i.e., 2427 * another matching rule with the same OID or 2428 * name). 2429 * 2430 * @throws DirectoryException If a conflict is encountered and the 2431 * <CODE>overwriteExisting</CODE> flag is set to 2432 * <CODE>false</CODE> 2433 */ 2434 public static void registerMatchingRule(MatchingRule matchingRule, 2435 boolean overwriteExisting) 2436 throws DirectoryException 2437 { 2438 directoryServer.schema.registerMatchingRule(matchingRule, 2439 overwriteExisting); 2440 } 2441 2442 /** 2443 * Deregisters the provided matching rule with the Directory Server. 2444 * 2445 * @param matchingRule The matching rule to deregister with the server. 2446 */ 2447 public static void deregisterMatchingRule(MatchingRule matchingRule) 2448 { 2449 directoryServer.schema.deregisterMatchingRule(matchingRule); 2450 } 2451 2452 /** 2453 * Retrieves the set of objectclasses defined in the Directory Server. 2454 * 2455 * @return The set of objectclasses defined in the Directory Server. 2456 */ 2457 public static ConcurrentMap<String, ObjectClass> getObjectClasses() 2458 { 2459 return directoryServer.schema.getObjectClasses(); 2460 } 2461 2462 /** 2463 * Retrieves the objectclass for the provided lowercase name or OID. 2464 * 2465 * @param lowerName The lowercase name or OID for the objectclass to 2466 * retrieve. 2467 * 2468 * @return The requested objectclass, or <CODE>null</CODE> if there is no 2469 * such objectclass defined in the server schema. 2470 */ 2471 public static ObjectClass getObjectClass(String lowerName) 2472 { 2473 return directoryServer.schema.getObjectClass(lowerName); 2474 } 2475 2476 /** 2477 * Retrieves the objectclass for the provided lowercase name or OID. It can 2478 * optionally return a generated "default" version if the requested 2479 * objectclass is not defined in the schema. 2480 * 2481 * @param lowerName The lowercase name or OID for the objectclass to 2482 * retrieve. 2483 * @param returnDefault Indicates whether to generate a default version if 2484 * the requested objectclass is not defined in the 2485 * server schema. 2486 * 2487 * @return The objectclass type, or <CODE>null</CODE> if there is no 2488 * objectclass with the specified name or OID defined in the server 2489 * schema and a default class should not be returned. 2490 */ 2491 public static ObjectClass getObjectClass(String lowerName, 2492 boolean returnDefault) 2493 { 2494 ObjectClass oc = directoryServer.schema.getObjectClass(lowerName); 2495 if (returnDefault && oc == null) 2496 { 2497 oc = getDefaultObjectClass(lowerName); 2498 } 2499 2500 return oc; 2501 } 2502 2503 /** 2504 * Registers the provided objectclass with the Directory Server. 2505 * 2506 * @param objectClass The objectclass instance to register with the 2507 * server. 2508 * @param overwriteExisting Indicates whether to overwrite an existing 2509 * mapping if there are any conflicts (i.e., 2510 * another objectclass with the same OID or 2511 * name). 2512 * 2513 * @throws DirectoryException If a conflict is encountered and the 2514 * <CODE>overwriteExisting</CODE> flag is set to 2515 * <CODE>false</CODE> 2516 */ 2517 public static void registerObjectClass(ObjectClass objectClass, 2518 boolean overwriteExisting) 2519 throws DirectoryException 2520 { 2521 directoryServer.schema.registerObjectClass(objectClass, overwriteExisting); 2522 } 2523 2524 /** 2525 * Deregisters the provided objectclass with the Directory Server. 2526 * 2527 * @param objectClass The objectclass instance to deregister with the 2528 * server. 2529 */ 2530 public static void deregisterObjectClass(ObjectClass objectClass) 2531 { 2532 directoryServer.schema.deregisterObjectClass(objectClass); 2533 } 2534 2535 /** 2536 * Retrieves the "top" objectClass, which should be the topmost objectclass in 2537 * the inheritance chain for most other objectclasses. If no such objectclass 2538 * could be found, then one will be constructed. 2539 * 2540 * @return The "top" objectClass. 2541 */ 2542 public static ObjectClass getTopObjectClass() 2543 { 2544 ObjectClass objectClass = 2545 directoryServer.schema.getObjectClass(TOP_OBJECTCLASS_NAME); 2546 if (objectClass == null) 2547 { 2548 String definition = 2549 "( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass " + 2550 "X-ORIGIN 'RFC 2256' )"; 2551 2552 objectClass = new ObjectClass(definition, TOP_OBJECTCLASS_NAME, 2553 Collections.singleton(TOP_OBJECTCLASS_NAME), 2554 TOP_OBJECTCLASS_OID, 2555 TOP_OBJECTCLASS_DESCRIPTION, null, null, 2556 null, ObjectClassType.ABSTRACT, false, 2557 null); 2558 } 2559 2560 return objectClass; 2561 } 2562 2563 /** 2564 * Causes the Directory Server to construct a new objectclass 2565 * definition with the provided name and with no required or allowed 2566 * attributes. This should only be used if there is no objectclass 2567 * for the specified name. It will not register the created 2568 * objectclass with the Directory Server. 2569 * 2570 * @param name 2571 * The name to use for the objectclass, as provided by the 2572 * user. 2573 * @return The constructed objectclass definition. 2574 */ 2575 public static ObjectClass getDefaultObjectClass(String name) 2576 { 2577 String lowerName = toLowerCase(name); 2578 ObjectClass objectClass = directoryServer.schema.getObjectClass(lowerName); 2579 if (objectClass == null) 2580 { 2581 String oid = lowerName + "-oid"; 2582 String definition = "( " + oid + " NAME '" + name + "' ABSTRACT )"; 2583 2584 // Temporary object classes are immediately dirty. 2585 objectClass = new ObjectClass(definition, name, 2586 Collections.singleton(name), oid, null, 2587 Collections.singleton(getTopObjectClass()), null, null, 2588 ObjectClassType.ABSTRACT, false, null).setDirty(); 2589 } 2590 2591 return objectClass; 2592 } 2593 2594 /** 2595 * Causes the Directory Server to construct a new auxiliary objectclass 2596 * definition with the provided name and with no required or allowed 2597 * attributes. This should only be used if there is no objectclass for the 2598 * specified name. It will not register the created objectclass with the 2599 * Directory Server. 2600 * 2601 * @param name The name to use for the objectclass, as provided by the user. 2602 * 2603 * @return The constructed objectclass definition. 2604 */ 2605 public static ObjectClass getDefaultAuxiliaryObjectClass(String name) 2606 { 2607 String lowerName = toLowerCase(name); 2608 ObjectClass objectClass = directoryServer.schema.getObjectClass(lowerName); 2609 if (objectClass == null) 2610 { 2611 String oid = lowerName + "-oid"; 2612 String definition = "( " + oid + " NAME '" + name + "' ABSTRACT )"; 2613 2614 objectClass = new ObjectClass(definition, name, 2615 Collections.singleton(name), oid, null, 2616 Collections.singleton(getTopObjectClass()), 2617 null, null, 2618 ObjectClassType.AUXILIARY, false, null); 2619 } 2620 2621 return objectClass; 2622 } 2623 2624 /** 2625 * Retrieves the set of attribute type definitions that have been 2626 * defined in the Directory Server. 2627 * 2628 * @return The set of attribute type definitions that have been 2629 * defined in the Directory Server. 2630 */ 2631 public static ConcurrentMap<String, AttributeType> getAttributeTypes() 2632 { 2633 return directoryServer.schema.getAttributeTypes(); 2634 } 2635 2636 /** 2637 * Retrieves the attribute type for the provided lowercase name or OID. 2638 * 2639 * @param lowerName The lowercase attribute name or OID for the attribute 2640 * type to retrieve. 2641 * 2642 * @return The requested attribute type, or <CODE>null</CODE> if there is no 2643 * attribute with the specified type defined in the server schema. 2644 */ 2645 public static AttributeType getAttributeType(String lowerName) 2646 { 2647 return directoryServer.schema.getAttributeType(lowerName); 2648 } 2649 2650 /** 2651 * Retrieves the attribute type for the provided lowercase name or OID. It 2652 * can optionally return a generated "default" version if the requested 2653 * attribute type is not defined in the schema. 2654 * 2655 * @param lowerName The lowercase name or OID for the attribute type to 2656 * retrieve. 2657 * @return The requested attribute type, or <CODE>null</CODE> if there is no 2658 * attribute with the specified type defined in the server schema and 2659 * a default type should not be returned. 2660 */ 2661 public static AttributeType getAttributeTypeOrDefault(String lowerName) 2662 { 2663 AttributeType type = directoryServer.schema.getAttributeType(lowerName); 2664 if (type == null) 2665 { 2666 type = getDefaultAttributeType(lowerName); 2667 } 2668 return type; 2669 } 2670 2671 /** 2672 * Retrieves the attribute type for the provided lowercase name or OID. It will return a generated 2673 * "default" version with the uppercase name or OID if the requested attribute type is not defined 2674 * in the schema. 2675 * 2676 * @param lowerName 2677 * The lowercase name or OID for the attribute type to retrieve. 2678 * @param upperName 2679 * The uppercase name or OID for the attribute type to generate. 2680 * @return The requested attribute type, or a generated "default" version if there is no attribute 2681 * with the specified type defined in the server schema 2682 */ 2683 public static AttributeType getAttributeTypeOrDefault(String lowerName, String upperName) 2684 { 2685 AttributeType type = directoryServer.schema.getAttributeType(lowerName); 2686 if (type == null) 2687 { 2688 type = getDefaultAttributeType(upperName); 2689 } 2690 return type; 2691 } 2692 2693 /** 2694 * Registers the provided attribute type with the Directory Server. 2695 * 2696 * @param attributeType The attribute type to register with the 2697 * Directory Server. 2698 * @param overwriteExisting Indicates whether to overwrite an existing 2699 * mapping if there are any conflicts (i.e., 2700 * another attribute type with the same OID or 2701 * name). 2702 * 2703 * @throws DirectoryException If a conflict is encountered and the 2704 * <CODE>overwriteExisting</CODE> flag is set to 2705 * <CODE>false</CODE> 2706 */ 2707 public static void registerAttributeType(AttributeType attributeType, 2708 boolean overwriteExisting) 2709 throws DirectoryException 2710 { 2711 directoryServer.schema.registerAttributeType(attributeType, 2712 overwriteExisting); 2713 } 2714 2715 /** 2716 * Deregisters the provided attribute type with the Directory Server. 2717 * 2718 * @param attributeType The attribute type to deregister with the Directory 2719 * Server. 2720 */ 2721 public static void deregisterAttributeType(AttributeType attributeType) 2722 { 2723 directoryServer.schema.deregisterAttributeType(attributeType); 2724 } 2725 2726 /** 2727 * Retrieves the attribute type for the "objectClass" attribute. 2728 * 2729 * @return The attribute type for the "objectClass" attribute. 2730 */ 2731 public static AttributeType getObjectClassAttributeType() 2732 { 2733 if (directoryServer.objectClassAttributeType == null) 2734 { 2735 directoryServer.objectClassAttributeType = 2736 directoryServer.schema.getAttributeType( 2737 OBJECTCLASS_ATTRIBUTE_TYPE_NAME); 2738 2739 if (directoryServer.objectClassAttributeType == null) 2740 { 2741 Syntax oidSyntax = directoryServer.schema.getSyntax(SYNTAX_OID_NAME); 2742 if (oidSyntax == null) 2743 { 2744 try 2745 { 2746 oidSyntax = CoreSchema.getOIDSyntax(); 2747 directoryServer.schema.registerSyntax(oidSyntax, true); 2748 } 2749 catch (Exception e) 2750 { 2751 logger.traceException(e); 2752 } 2753 } 2754 2755 String definition = 2756 "( 2.5.4.0 NAME 'objectClass' EQUALITY objectIdentifierMatch " + 2757 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 X-ORIGIN 'RFC 2256' )"; 2758 2759 directoryServer.objectClassAttributeType = 2760 new AttributeType(definition, "objectClass", 2761 Collections.singleton("objectClass"), 2762 OBJECTCLASS_ATTRIBUTE_TYPE_OID, null, null, 2763 oidSyntax, AttributeUsage.USER_APPLICATIONS, 2764 false, false, false, false); 2765 try 2766 { 2767 directoryServer.schema.registerAttributeType( 2768 directoryServer.objectClassAttributeType, true); 2769 } 2770 catch (Exception e) 2771 { 2772 // This should never happen. 2773 logger.traceException(e); 2774 } 2775 } 2776 } 2777 2778 return directoryServer.objectClassAttributeType; 2779 } 2780 2781 /** 2782 * Causes the Directory Server to construct a new attribute type definition 2783 * with the provided name and using the default attribute syntax. This should 2784 * only be used if there is no real attribute type for the specified name. 2785 * 2786 * @param name The name to use for the attribute type, as provided by the 2787 * user. 2788 * 2789 * @return The constructed attribute type definition. 2790 */ 2791 public static AttributeType getDefaultAttributeType(String name) 2792 { 2793 return getDefaultAttributeType(name, getDefaultAttributeSyntax()); 2794 } 2795 2796 /** 2797 * Causes the Directory Server to construct a new attribute type definition 2798 * with the provided name and syntax. This should only be used if there is no 2799 * real attribute type for the specified name. 2800 * 2801 * @param name The name to use for the attribute type, as provided by the 2802 * user. 2803 * @param syntax The syntax to use for the attribute type. 2804 * 2805 * @return The constructed attribute type definition. 2806 */ 2807 public static AttributeType getDefaultAttributeType(String name, Syntax syntax) 2808 { 2809 String oid = toLowerCase(name) + "-oid"; 2810 String definition = "( " + oid + " NAME '" + name + "' SYNTAX " + 2811 syntax.getOID() + " )"; 2812 2813 // Temporary attribute types are immediately dirty. 2814 return new AttributeType(definition, name, Collections.singleton(name), 2815 oid, null, null, syntax, 2816 AttributeUsage.USER_APPLICATIONS, false, false, 2817 false, false).setDirty(); 2818 } 2819 2820 /** 2821 * Retrieves the set of attribute syntaxes defined in the Directory Server. 2822 * 2823 * @return The set of attribute syntaxes defined in the Directory Server. 2824 */ 2825 public static ConcurrentMap<String, Syntax> getAttributeSyntaxes() 2826 { 2827 return directoryServer.schema.getSyntaxes(); 2828 } 2829 2830 /** 2831 * Retrieves the default attribute syntax that should be used for attributes 2832 * that are not defined in the server schema. 2833 * 2834 * @return The default attribute syntax that should be used for attributes 2835 * that are not defined in the server schema. 2836 */ 2837 public static Syntax getDefaultAttributeSyntax() 2838 { 2839 return directoryServer.getDefaultSyntax(); 2840 } 2841 2842 /** 2843 * Retrieves the default attribute syntax that should be used for attributes 2844 * that are not defined in the server schema and are meant to store binary 2845 * values. 2846 * 2847 * @return The default attribute syntax that should be used for attributes 2848 * that are not defined in the server schema and are meant to store 2849 * binary values. 2850 */ 2851 public static Syntax getDefaultBinarySyntax() 2852 { 2853 return CoreSchema.getBinarySyntax(); 2854 } 2855 2856 /** 2857 * Retrieves the default attribute syntax that should be used for attributes 2858 * that are not defined in the server schema and are meant to store Boolean 2859 * values. 2860 * 2861 * @return The default attribute syntax that should be used for attributes 2862 * that are not defined in the server schema and are meant to store 2863 * Boolean values. 2864 */ 2865 public static Syntax getDefaultBooleanSyntax() 2866 { 2867 return CoreSchema.getBooleanSyntax(); 2868 } 2869 2870 /** 2871 * Retrieves the default attribute syntax that should be used for attributes 2872 * that are not defined in the server schema and are meant to store DN values. 2873 * 2874 * @return The default attribute syntax that should be used for attributes 2875 * that are not defined in the server schema and are meant to store 2876 * DN values. 2877 */ 2878 public static Syntax getDefaultDNSyntax() 2879 { 2880 return CoreSchema.getDNSyntax(); 2881 } 2882 2883 /** 2884 * Retrieves the default attribute syntax that should be used for attributes 2885 * that are not defined in the server schema and are meant to store integer 2886 * values. 2887 * 2888 * @return The default attribute syntax that should be used for attributes 2889 * that are not defined in the server schema and are meant to store 2890 * integer values. 2891 */ 2892 public static Syntax getDefaultIntegerSyntax() 2893 { 2894 return CoreSchema.getIntegerSyntax(); 2895 } 2896 2897 /** 2898 * Retrieves the default attribute syntax that should be used for attributes 2899 * that are not defined in the server schema and are meant to store string 2900 * values. 2901 * 2902 * @return The default attribute syntax that should be used for attributes 2903 * that are not defined in the server schema and are meant to store 2904 * string values. 2905 */ 2906 public static Syntax getDefaultStringSyntax() 2907 { 2908 return CoreSchema.getDirectoryStringSyntax(); 2909 } 2910 2911 private Syntax getDefaultSyntax() 2912 { 2913 return CoreSchema.getDirectoryStringSyntax(); 2914 } 2915 2916 /** 2917 * Retrieves the set of matching rule uses defined in the Directory Server. 2918 * 2919 * @return The set of matching rule uses defined in the Directory Server. 2920 */ 2921 public static ConcurrentMap<MatchingRule, MatchingRuleUse> 2922 getMatchingRuleUses() 2923 { 2924 return directoryServer.schema.getMatchingRuleUses(); 2925 } 2926 2927 /** 2928 * Retrieves the matching rule use associated with the provided matching rule. 2929 * 2930 * @param matchingRule The matching rule for which to retrieve the matching 2931 * rule use. 2932 * 2933 * @return The matching rule use for the provided matching rule, or 2934 * <CODE>null</CODE> if none is defined. 2935 */ 2936 public static MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule) 2937 { 2938 return directoryServer.schema.getMatchingRuleUse(matchingRule); 2939 } 2940 2941 /** 2942 * Registers the provided matching rule use with the Directory Server. 2943 * 2944 * @param matchingRuleUse The matching rule use to register with the 2945 * server. 2946 * @param overwriteExisting Indicates whether to overwrite an existing 2947 * mapping if there are any conflicts (i.e., 2948 * another matching rule use with the same matching 2949 * rule). 2950 * 2951 * @throws DirectoryException If a conflict is encountered and the 2952 * <CODE>overwriteExisting</CODE> flag is set to 2953 * <CODE>false</CODE> 2954 */ 2955 public static void registerMatchingRuleUse(MatchingRuleUse matchingRuleUse, 2956 boolean overwriteExisting) 2957 throws DirectoryException 2958 { 2959 directoryServer.schema.registerMatchingRuleUse(matchingRuleUse, 2960 overwriteExisting); 2961 } 2962 2963 /** 2964 * Deregisters the provided matching rule use with the Directory Server. 2965 * 2966 * @param matchingRuleUse The matching rule use to deregister with the 2967 * server. 2968 */ 2969 public static void deregisterMatchingRuleUse(MatchingRuleUse matchingRuleUse) 2970 { 2971 directoryServer.schema.deregisterMatchingRuleUse(matchingRuleUse); 2972 } 2973 2974 /** 2975 * Retrieves the set of DIT content rules defined in the Directory Server. 2976 * 2977 * @return The set of DIT content rules defined in the Directory Server. 2978 */ 2979 public static ConcurrentMap<ObjectClass, DITContentRule> 2980 getDITContentRules() 2981 { 2982 return directoryServer.schema.getDITContentRules(); 2983 } 2984 2985 /** 2986 * Retrieves the DIT content rule associated with the specified objectclass. 2987 * 2988 * @param objectClass The objectclass for which to retrieve the associated 2989 * DIT content rule. 2990 * 2991 * @return The requested DIT content rule, or <CODE>null</CODE> if no such 2992 * rule is defined in the schema. 2993 */ 2994 public static DITContentRule getDITContentRule(ObjectClass objectClass) 2995 { 2996 return directoryServer.schema.getDITContentRule(objectClass); 2997 } 2998 2999 /** 3000 * Registers the provided DIT content rule with the Directory Server. 3001 * 3002 * @param ditContentRule The DIT content rule to register with the 3003 * server. 3004 * @param overwriteExisting Indicates whether to overwrite an existing 3005 * mapping if there are any conflicts (i.e., 3006 * another DIT content rule with the same 3007 * structural objectclass). 3008 * 3009 * @throws DirectoryException If a conflict is encountered and the 3010 * <CODE>overwriteExisting</CODE> flag is set to 3011 * <CODE>false</CODE> 3012 */ 3013 public static void registerDITContentRule(DITContentRule ditContentRule, 3014 boolean overwriteExisting) 3015 throws DirectoryException 3016 { 3017 directoryServer.schema.registerDITContentRule(ditContentRule, 3018 overwriteExisting); 3019 } 3020 3021 /** 3022 * Deregisters the provided DIT content rule with the Directory Server. 3023 * 3024 * @param ditContentRule The DIT content rule to deregister with the server. 3025 */ 3026 public static void deregisterDITContentRule(DITContentRule ditContentRule) 3027 { 3028 directoryServer.schema.deregisterDITContentRule(ditContentRule); 3029 } 3030 3031 /** 3032 * Retrieves the set of DIT structure rules defined in the Directory Server. 3033 * 3034 * @return The set of DIT structure rules defined in the Directory Server. 3035 */ 3036 public static ConcurrentMap<NameForm, DITStructureRule> 3037 getDITStructureRules() 3038 { 3039 return directoryServer.schema.getDITStructureRulesByNameForm(); 3040 } 3041 3042 /** 3043 * Retrieves the DIT structure rule associated with the provided rule ID. 3044 * 3045 * @param ruleID The rule ID for which to retrieve the associated DIT 3046 * structure rule. 3047 * 3048 * @return The requested DIT structure rule, or <CODE>null</CODE> if no such 3049 * rule is defined. 3050 */ 3051 public static DITStructureRule getDITStructureRule(int ruleID) 3052 { 3053 return directoryServer.schema.getDITStructureRule(ruleID); 3054 } 3055 3056 /** 3057 * Retrieves the DIT structure rule associated with the provided name form. 3058 * 3059 * @param nameForm The name form for which to retrieve the associated DIT 3060 * structure rule. 3061 * 3062 * @return The requested DIT structure rule, or <CODE>null</CODE> if no such 3063 * rule is defined. 3064 */ 3065 public static DITStructureRule getDITStructureRule(NameForm nameForm) 3066 { 3067 return directoryServer.schema.getDITStructureRule(nameForm); 3068 } 3069 3070 /** 3071 * Registers the provided DIT structure rule with the Directory Server. 3072 * 3073 * @param ditStructureRule The DIT structure rule to register with the 3074 * server. 3075 * @param overwriteExisting Indicates whether to overwrite an existing 3076 * mapping if there are any conflicts (i.e., 3077 * another DIT structure rule with the same name 3078 * form). 3079 * 3080 * @throws DirectoryException If a conflict is encountered and the 3081 * <CODE>overwriteExisting</CODE> flag is set to 3082 * <CODE>false</CODE> 3083 */ 3084 public static void registerDITStructureRule(DITStructureRule ditStructureRule, 3085 boolean overwriteExisting) 3086 throws DirectoryException 3087 { 3088 directoryServer.schema.registerDITStructureRule(ditStructureRule, 3089 overwriteExisting); 3090 } 3091 3092 /** 3093 * Deregisters the provided DIT structure rule with the Directory Server. 3094 * 3095 * @param ditStructureRule The DIT structure rule to deregister with the 3096 * server. 3097 */ 3098 public static void deregisterDITStructureRule(DITStructureRule 3099 ditStructureRule) 3100 { 3101 directoryServer.schema.deregisterDITStructureRule(ditStructureRule); 3102 } 3103 3104 /** 3105 * Retrieves the set of name forms defined in the Directory Server. 3106 * 3107 * @return The set of name forms defined in the Directory Server. 3108 */ 3109 public static ConcurrentMap<ObjectClass, List<NameForm>> getNameForms() 3110 { 3111 return directoryServer.schema.getNameFormsByObjectClass(); 3112 } 3113 3114 /** 3115 * Retrieves the name forms associated with the specified objectclass. 3116 * 3117 * @param objectClass The objectclass for which to retrieve the associated 3118 * name form. 3119 * 3120 * @return The requested name forms, or <CODE>null</CODE> if no such name 3121 * form is defined in the schema. 3122 */ 3123 public static List<NameForm> getNameForm(ObjectClass objectClass) 3124 { 3125 return directoryServer.schema.getNameForm(objectClass); 3126 } 3127 3128 /** 3129 * Retrieves the name form associated with the specified name or OID. 3130 * 3131 * @param lowerName The name or OID of the name form to retrieve, formatted 3132 * in all lowercase characters. 3133 * 3134 * @return The requested name form, or <CODE>null</CODE> if no such name form 3135 * is defined in the schema. 3136 */ 3137 public static NameForm getNameForm(String lowerName) 3138 { 3139 return directoryServer.schema.getNameForm(lowerName); 3140 } 3141 3142 /** 3143 * Registers the provided name form with the Directory Server. 3144 * 3145 * @param nameForm The name form to register with the server. 3146 * @param overwriteExisting Indicates whether to overwrite an existing 3147 * mapping if there are any conflicts (i.e., 3148 * another name form with the same structural 3149 * objectclass). 3150 * 3151 * @throws DirectoryException If a conflict is encountered and the 3152 * <CODE>overwriteExisting</CODE> flag is set to 3153 * <CODE>false</CODE> 3154 */ 3155 public static void registerNameForm(NameForm nameForm, 3156 boolean overwriteExisting) 3157 throws DirectoryException 3158 { 3159 directoryServer.schema.registerNameForm(nameForm, overwriteExisting); 3160 } 3161 3162 /** 3163 * Deregisters the provided name form with the Directory Server. 3164 * 3165 * @param nameForm The name form to deregister with the server. 3166 */ 3167 public static void deregisterNameForm(NameForm nameForm) 3168 { 3169 directoryServer.schema.deregisterNameForm(nameForm); 3170 } 3171 3172 /** 3173 * Retrieves the set of virtual attribute rules registered with the Directory 3174 * Server. 3175 * 3176 * @return The set of virtual attribute rules registered with the Directory 3177 * Server. 3178 */ 3179 public static Collection<VirtualAttributeRule> getVirtualAttributes() 3180 { 3181 return directoryServer.virtualAttributeConfigManager.getVirtualAttributes(); 3182 } 3183 3184 /** 3185 * Retrieves the set of virtual attribute rules registered with the Directory 3186 * Server that are applicable to the provided entry. 3187 * 3188 * @param entry The entry for which to retrieve the applicable virtual 3189 * attribute rules. 3190 * 3191 * @return The set of virtual attribute rules registered with the Directory 3192 * Server that apply to the given entry. It may be an empty list if 3193 * there are no applicable virtual attribute rules. 3194 */ 3195 public static List<VirtualAttributeRule> getVirtualAttributes(Entry entry) 3196 { 3197 List<VirtualAttributeRule> ruleList = new LinkedList<>(); 3198 for (VirtualAttributeRule rule : getVirtualAttributes()) 3199 { 3200 if (rule.appliesToEntry(entry)) 3201 { 3202 ruleList.add(rule); 3203 } 3204 } 3205 return ruleList; 3206 } 3207 3208 /** 3209 * Registers the provided virtual attribute rule with the Directory Server. 3210 * 3211 * @param rule The virtual attribute rule to be registered. 3212 */ 3213 public static void registerVirtualAttribute(final VirtualAttributeRule rule) 3214 { 3215 getInstance().virtualAttributeConfigManager.register(rule); 3216 } 3217 3218 /** 3219 * Deregisters the provided virtual attribute rule with the Directory Server. 3220 * 3221 * @param rule The virtual attribute rule to be deregistered. 3222 */ 3223 public static void deregisterVirtualAttribute(VirtualAttributeRule rule) 3224 { 3225 getInstance().virtualAttributeConfigManager.deregister(rule); 3226 } 3227 3228 /** 3229 * Retrieves a reference to the JMX MBean server that is associated with the 3230 * Directory Server. 3231 * 3232 * @return The JMX MBean server that is associated with the Directory Server. 3233 */ 3234 public static MBeanServer getJMXMBeanServer() 3235 { 3236 return directoryServer.mBeanServer; 3237 } 3238 3239 /** 3240 * Retrieves the set of JMX MBeans that are associated with the server. 3241 * 3242 * @return The set of JMX MBeans that are associated with the server. 3243 */ 3244 public static ConcurrentHashMap<DN,JMXMBean> getJMXMBeans() 3245 { 3246 return directoryServer.mBeans; 3247 } 3248 3249 /** 3250 * Retrieves the JMX MBean associated with the specified entry in the 3251 * Directory Server configuration. 3252 * 3253 * @param configEntryDN The DN of the configuration entry for which to 3254 * retrieve the associated JMX MBean. 3255 * 3256 * @return The JMX MBean associated with the specified entry in the Directory 3257 * Server configuration, or <CODE>null</CODE> if there is no MBean 3258 * for the specified entry. 3259 */ 3260 public static JMXMBean getJMXMBean(DN configEntryDN) 3261 { 3262 return directoryServer.mBeans.get(configEntryDN); 3263 } 3264 3265 /** 3266 * Registers the provided invokable component with the Directory Server. 3267 * 3268 * @param component The invokable component to register. 3269 */ 3270 public static void registerInvokableComponent(InvokableComponent component) 3271 { 3272 DN componentDN = component.getInvokableComponentEntryDN(); 3273 JMXMBean mBean = directoryServer.mBeans.get(componentDN); 3274 if (mBean == null) 3275 { 3276 mBean = new JMXMBean(componentDN); 3277 mBean.addInvokableComponent(component); 3278 directoryServer.mBeans.put(componentDN, mBean); 3279 } 3280 else 3281 { 3282 mBean.addInvokableComponent(component); 3283 } 3284 } 3285 3286 /** 3287 * Deregisters the provided invokable component with the Directory Server. 3288 * 3289 * @param component The invokable component to deregister. 3290 */ 3291 public static void deregisterInvokableComponent(InvokableComponent component) 3292 { 3293 DN componentDN = component.getInvokableComponentEntryDN(); 3294 JMXMBean mBean = directoryServer.mBeans.get(componentDN); 3295 if (mBean != null) 3296 { 3297 mBean.removeInvokableComponent(component); 3298 } 3299 } 3300 3301 /** 3302 * Registers the provided alert generator with the Directory Server. 3303 * 3304 * @param alertGenerator The alert generator to register. 3305 */ 3306 public static void registerAlertGenerator(AlertGenerator alertGenerator) 3307 { 3308 DN componentDN = alertGenerator.getComponentEntryDN(); 3309 JMXMBean mBean = directoryServer.mBeans.get(componentDN); 3310 if (mBean == null) 3311 { 3312 mBean = new JMXMBean(componentDN); 3313 mBean.addAlertGenerator(alertGenerator); 3314 directoryServer.mBeans.put(componentDN, mBean); 3315 } 3316 else 3317 { 3318 mBean.addAlertGenerator(alertGenerator); 3319 } 3320 } 3321 3322 /** 3323 * Deregisters the provided alert generator with the Directory Server. 3324 * 3325 * @param alertGenerator The alert generator to deregister. 3326 */ 3327 public static void deregisterAlertGenerator(AlertGenerator alertGenerator) 3328 { 3329 DN componentDN = alertGenerator.getComponentEntryDN(); 3330 JMXMBean mBean = directoryServer.mBeans.get(componentDN); 3331 if (mBean != null) 3332 { 3333 mBean.removeAlertGenerator(alertGenerator); 3334 } 3335 } 3336 3337 /** 3338 * Retrieves the set of alert handlers that have been registered with the 3339 * Directory Server. 3340 * 3341 * @return The set of alert handlers that have been registered with the 3342 * Directory Server. 3343 */ 3344 public static List<AlertHandler> getAlertHandlers() 3345 { 3346 return directoryServer.alertHandlers; 3347 } 3348 3349 /** 3350 * Registers the provided alert handler with the Directory Server. 3351 * 3352 * @param alertHandler The alert handler to register. 3353 */ 3354 public static void registerAlertHandler(AlertHandler alertHandler) 3355 { 3356 directoryServer.alertHandlers.add(alertHandler); 3357 } 3358 3359 /** 3360 * Deregisters the provided alert handler with the Directory Server. 3361 * 3362 * @param alertHandler The alert handler to deregister. 3363 */ 3364 public static void deregisterAlertHandler(AlertHandler alertHandler) 3365 { 3366 directoryServer.alertHandlers.remove(alertHandler); 3367 } 3368 3369 /** 3370 * Sends an alert notification with the provided information. 3371 * 3372 * @param generator The alert generator that created the alert. 3373 * @param alertType The alert type name for this alert. 3374 * @param alertMessage A message (possibly <CODE>null</CODE>) that can 3375 */ 3376 public static void sendAlertNotification(AlertGenerator generator, 3377 String alertType, 3378 LocalizableMessage alertMessage) 3379 { 3380 if (directoryServer.alertHandlers == null 3381 || directoryServer.alertHandlers.isEmpty()) 3382 { 3383 // If the Directory Server is still in the process of starting up, then 3384 // create a JMX alert handler to use for this notification. 3385 if (! directoryServer.isRunning) 3386 { 3387 try 3388 { 3389 JMXAlertHandler alertHandler = new JMXAlertHandler(); 3390 alertHandler.initializeAlertHandler(null); 3391 alertHandler.sendAlertNotification(generator, alertType, 3392 alertMessage); 3393 } 3394 catch (Exception e) 3395 { 3396 logger.traceException(e); 3397 } 3398 } 3399 } 3400 else 3401 { 3402 for (AlertHandler alertHandler : directoryServer.alertHandlers) 3403 { 3404 AlertHandlerCfg config = alertHandler.getAlertHandlerConfiguration(); 3405 Set<String> enabledAlerts = config.getEnabledAlertType(); 3406 Set<String> disabledAlerts = config.getDisabledAlertType(); 3407 if (enabledAlerts == null || enabledAlerts.isEmpty()) 3408 { 3409 if (disabledAlerts != null && disabledAlerts.contains(alertType)) 3410 { 3411 continue; 3412 } 3413 } 3414 else 3415 { 3416 if (enabledAlerts.contains(alertType)) 3417 { 3418 if (disabledAlerts != null && disabledAlerts.contains(alertType)) 3419 { 3420 continue; 3421 } 3422 } 3423 else 3424 { 3425 continue; 3426 } 3427 } 3428 3429 alertHandler.sendAlertNotification(generator, alertType, alertMessage); 3430 } 3431 } 3432 3433 String alertID = alertMessage != null ? alertMessage.resourceName() + "-" + alertMessage.ordinal() : "-1"; 3434 logger.info(NOTE_SENT_ALERT_NOTIFICATION, generator.getClassName(), alertType, alertID, alertMessage); 3435 } 3436 3437 /** 3438 * Retrieves the password storage scheme defined in the specified 3439 * configuration entry. 3440 * 3441 * @param configEntryDN The DN of the configuration entry that defines the 3442 * password storage scheme to retrieve. 3443 * 3444 * @return The requested password storage scheme, or {@code null} if no such 3445 * scheme is defined. 3446 */ 3447 public static PasswordStorageScheme getPasswordStorageScheme(DN configEntryDN) 3448 { 3449 return directoryServer.passwordStorageSchemesByDN.get(configEntryDN); 3450 } 3451 3452 /** 3453 * Retrieves the set of password storage schemes defined in the Directory 3454 * Server, as a mapping between the all-lowercase scheme name and the 3455 * corresponding implementation. 3456 * 3457 * @return The set of password storage schemes defined in the Directory 3458 * Server. 3459 */ 3460 public static ConcurrentHashMap<String,PasswordStorageScheme> 3461 getPasswordStorageSchemes() 3462 { 3463 return directoryServer.passwordStorageSchemes; 3464 } 3465 3466 /** 3467 * Retrieves the specified password storage scheme. 3468 * 3469 * @param lowerName The name of the password storage scheme to retrieve, 3470 * formatted in all lowercase characters. 3471 * 3472 * @return The requested password storage scheme, or <CODE>null</CODE> if no 3473 * such scheme is defined. 3474 */ 3475 public static PasswordStorageScheme getPasswordStorageScheme(String lowerName) 3476 { 3477 return directoryServer.passwordStorageSchemes.get(lowerName); 3478 } 3479 3480 /** 3481 * Retrieves the set of authentication password storage schemes defined in the 3482 * Directory Server, as a mapping between the scheme name and the 3483 * corresponding implementation. 3484 * 3485 * @return The set of authentication password storage schemes defined in the 3486 * Directory Server. 3487 */ 3488 public static ConcurrentHashMap<String,PasswordStorageScheme> 3489 getAuthPasswordStorageSchemes() 3490 { 3491 return directoryServer.authPasswordStorageSchemes; 3492 } 3493 3494 /** 3495 * Retrieves the specified authentication password storage scheme. 3496 * 3497 * @param name The case-sensitive name of the authentication password 3498 * storage scheme to retrieve. 3499 * 3500 * @return The requested authentication password storage scheme, or 3501 * <CODE>null</CODE> if no such scheme is defined. 3502 */ 3503 public static PasswordStorageScheme getAuthPasswordStorageScheme(String name) 3504 { 3505 return directoryServer.authPasswordStorageSchemes.get(name); 3506 } 3507 3508 /** 3509 * Registers the provided password storage scheme with the Directory Server. 3510 * If an existing password storage scheme is registered with the same name, 3511 * then it will be replaced with the provided scheme. 3512 * 3513 * @param configEntryDN The DN of the configuration entry that defines the 3514 * password storage scheme. 3515 * @param scheme The password storage scheme to register with the 3516 * Directory Server. 3517 */ 3518 public static void registerPasswordStorageScheme(DN configEntryDN, 3519 PasswordStorageScheme scheme) 3520 { 3521 directoryServer.passwordStorageSchemesByDN.put(configEntryDN, scheme); 3522 3523 String name = toLowerCase(scheme.getStorageSchemeName()); 3524 directoryServer.passwordStorageSchemes.put(name, scheme); 3525 3526 if (scheme.supportsAuthPasswordSyntax()) 3527 { 3528 directoryServer.authPasswordStorageSchemes.put( 3529 scheme.getAuthPasswordSchemeName(), scheme); 3530 } 3531 } 3532 3533 /** 3534 * Deregisters the specified password storage scheme with the Directory 3535 * Server. If no scheme is registered with the specified name, then no action 3536 * will be taken. 3537 * 3538 * @param configEntryDN The DN of the configuration entry that defines the 3539 * password storage scheme. 3540 */ 3541 public static void deregisterPasswordStorageScheme(DN configEntryDN) 3542 { 3543 PasswordStorageScheme scheme = 3544 directoryServer.passwordStorageSchemesByDN.remove(configEntryDN); 3545 3546 if (scheme != null) 3547 { 3548 directoryServer.passwordStorageSchemes.remove( 3549 toLowerCase(scheme.getStorageSchemeName())); 3550 3551 if (scheme.supportsAuthPasswordSyntax()) 3552 { 3553 directoryServer.authPasswordStorageSchemes.remove( 3554 scheme.getAuthPasswordSchemeName()); 3555 } 3556 } 3557 } 3558 3559 /** 3560 * Retrieves the set of password validators that have been registered for use 3561 * with the Directory Server as a mapping between the DN of the associated 3562 * validator configuration entry and the validator implementation. 3563 * 3564 * @return The set of password validators that have been registered for use 3565 * with the Directory Server. 3566 */ 3567 public static ConcurrentMap<DN, 3568 PasswordValidator<? extends PasswordValidatorCfg>> 3569 getPasswordValidators() 3570 { 3571 return directoryServer.passwordValidators; 3572 } 3573 3574 /** 3575 * Retrieves the password validator registered with the provided configuration 3576 * entry DN. 3577 * 3578 * @param configEntryDN The DN of the configuration entry for which to 3579 * retrieve the associated password validator. 3580 * 3581 * @return The requested password validator, or <CODE>null</CODE> if no such 3582 * validator is defined. 3583 */ 3584 public static PasswordValidator<? extends PasswordValidatorCfg> 3585 getPasswordValidator(DN configEntryDN) 3586 { 3587 return directoryServer.passwordValidators.get(configEntryDN); 3588 } 3589 3590 /** 3591 * Registers the provided password validator for use with the Directory 3592 * Server. 3593 * 3594 * @param configEntryDN The DN of the configuration entry that defines the 3595 * specified password validator. 3596 * @param validator The password validator to register with the 3597 * Directory Server. 3598 */ 3599 public static void 3600 registerPasswordValidator(DN configEntryDN, 3601 PasswordValidator<? extends PasswordValidatorCfg> 3602 validator) 3603 { 3604 directoryServer.passwordValidators.put(configEntryDN, validator); 3605 } 3606 3607 /** 3608 * Deregisters the provided password validator for use with the Directory 3609 * Server. 3610 * 3611 * @param configEntryDN The DN of the configuration entry that defines the 3612 * password validator to deregister. 3613 */ 3614 public static void deregisterPasswordValidator(DN configEntryDN) 3615 { 3616 directoryServer.passwordValidators.remove(configEntryDN); 3617 } 3618 3619 /** 3620 * Retrieves the set of account status notification handlers defined in the 3621 * Directory Server, as a mapping between the DN of the configuration entry 3622 * and the notification handler implementation. 3623 * 3624 * @return The set of account status notification handlers defined in the 3625 * Directory Server. 3626 */ 3627 public static ConcurrentMap<DN, AccountStatusNotificationHandler> 3628 getAccountStatusNotificationHandlers() 3629 { 3630 return directoryServer.accountStatusNotificationHandlers; 3631 } 3632 3633 /** 3634 * Retrieves the account status notification handler with the specified 3635 * configuration entry DN. 3636 * 3637 * @param handlerDN The DN of the configuration entry associated with the 3638 * account status notification handler to retrieve. 3639 * 3640 * @return The requested account status notification handler, or 3641 * <CODE>null</CODE> if no such handler is defined in the server. 3642 */ 3643 public static AccountStatusNotificationHandler 3644 getAccountStatusNotificationHandler(DN handlerDN) 3645 { 3646 return directoryServer.accountStatusNotificationHandlers.get(handlerDN); 3647 } 3648 3649 /** 3650 * Registers the provided account status notification handler with the 3651 * Directory Server. 3652 * 3653 * @param handlerDN The DN of the configuration entry that defines the 3654 * provided account status notification handler. 3655 * @param handler The account status notification handler to register with 3656 * the Directory Server. 3657 */ 3658 public static void registerAccountStatusNotificationHandler(DN handlerDN, 3659 AccountStatusNotificationHandler handler) 3660 { 3661 directoryServer.accountStatusNotificationHandlers.put(handlerDN, handler); 3662 } 3663 3664 /** 3665 * Deregisters the specified account status notification handler with the 3666 * Directory Server. 3667 * 3668 * @param handlerDN The DN of the configuration entry for the account status 3669 * notification handler to deregister. 3670 */ 3671 public static void deregisterAccountStatusNotificationHandler(DN handlerDN) 3672 { 3673 directoryServer.accountStatusNotificationHandlers.remove(handlerDN); 3674 } 3675 3676 /** 3677 * Retrieves the set of password generators that have been registered for use 3678 * with the Directory Server as a mapping between the DN of the associated 3679 * generator configuration entry and the generator implementation. 3680 * 3681 * @return The set of password generators that have been registered for use 3682 * with the Directory Server. 3683 */ 3684 public static ConcurrentMap<DN, PasswordGenerator> getPasswordGenerators() 3685 { 3686 return directoryServer.passwordGenerators; 3687 } 3688 3689 /** 3690 * Retrieves the password generator registered with the provided configuration 3691 * entry DN. 3692 * 3693 * @param configEntryDN The DN of the configuration entry for which to 3694 * retrieve the associated password generator. 3695 * 3696 * @return The requested password generator, or <CODE>null</CODE> if no such 3697 * generator is defined. 3698 */ 3699 public static PasswordGenerator getPasswordGenerator(DN configEntryDN) 3700 { 3701 return directoryServer.passwordGenerators.get(configEntryDN); 3702 } 3703 3704 /** 3705 * Registers the provided password generator for use with the Directory 3706 * Server. 3707 * 3708 * @param configEntryDN The DN of the configuration entry that defines the 3709 * specified password generator. 3710 * @param generator The password generator to register with the 3711 * Directory Server. 3712 */ 3713 public static void registerPasswordGenerator(DN configEntryDN, 3714 PasswordGenerator generator) 3715 { 3716 directoryServer.passwordGenerators.put(configEntryDN, generator); 3717 } 3718 3719 /** 3720 * Deregisters the provided password generator for use with the Directory 3721 * Server. 3722 * 3723 * @param configEntryDN The DN of the configuration entry that defines the 3724 * password generator to deregister. 3725 */ 3726 public static void deregisterPasswordGenerator(DN configEntryDN) 3727 { 3728 directoryServer.passwordGenerators.remove(configEntryDN); 3729 } 3730 3731 /** 3732 * Returns an unmodifiable collection containing all of the authentication 3733 * policies registered with the Directory Server. The references returned are 3734 * to the actual authentication policy objects currently in use by the 3735 * directory server and the referenced objects must not be modified. 3736 * 3737 * @return The unmodifiable collection containing all of the authentication 3738 * policies registered with the Directory Server. 3739 */ 3740 public static Collection<AuthenticationPolicy> getAuthenticationPolicies() 3741 { 3742 return Collections 3743 .unmodifiableCollection(directoryServer.authenticationPolicies.values()); 3744 } 3745 3746 /** 3747 * Retrieves the authentication policy registered for the provided 3748 * configuration entry. 3749 * 3750 * @param configEntryDN 3751 * The DN of the configuration entry for which to retrieve the 3752 * associated authentication policy. 3753 * @return The authentication policy registered for the provided configuration 3754 * entry, or <CODE>null</CODE> if there is no such policy. 3755 */ 3756 public static AuthenticationPolicy getAuthenticationPolicy(DN configEntryDN) 3757 { 3758 Reject.ifNull(configEntryDN); 3759 return directoryServer.authenticationPolicies.get(configEntryDN); 3760 } 3761 3762 /** 3763 * Registers the provided authentication policy with the Directory Server. If 3764 * a policy is already registered for the provided configuration entry DN, 3765 * then it will be replaced. 3766 * 3767 * @param configEntryDN 3768 * The DN of the configuration entry that defines the authentication 3769 * policy. 3770 * @param policy 3771 * The authentication policy to register with the server. 3772 */ 3773 public static void registerAuthenticationPolicy(DN configEntryDN, 3774 AuthenticationPolicy policy) 3775 { 3776 Reject.ifNull(configEntryDN, policy); 3777 3778 // Ensure default policy is synchronized. 3779 synchronized (directoryServer.authenticationPolicies) 3780 { 3781 if (directoryServer.defaultPasswordPolicyDN.equals(configEntryDN)) 3782 { 3783 // The correct policy type is enforced by the core config manager. 3784 directoryServer.defaultPasswordPolicy = (PasswordPolicy) policy; 3785 } 3786 3787 AuthenticationPolicy oldPolicy = directoryServer.authenticationPolicies 3788 .put(configEntryDN, policy); 3789 3790 if (oldPolicy != null) 3791 { 3792 oldPolicy.finalizeAuthenticationPolicy(); 3793 } 3794 } 3795 } 3796 3797 /** 3798 * Deregisters the provided authentication policy with the Directory Server. 3799 * If no such policy is registered, then no action will be taken. 3800 * 3801 * @param configEntryDN 3802 * The DN of the configuration entry that defines the authentication 3803 * policy to deregister. 3804 */ 3805 public static void deregisterAuthenticationPolicy(DN configEntryDN) 3806 { 3807 Reject.ifNull(configEntryDN); 3808 3809 // Ensure default policy is synchronized. 3810 synchronized (directoryServer.authenticationPolicies) 3811 { 3812 if (directoryServer.defaultPasswordPolicyDN.equals(configEntryDN)) 3813 { 3814 directoryServer.defaultPasswordPolicy = null; 3815 } 3816 3817 AuthenticationPolicy oldPolicy = directoryServer.authenticationPolicies 3818 .remove(configEntryDN); 3819 if (oldPolicy != null) 3820 { 3821 oldPolicy.finalizeAuthenticationPolicy(); 3822 } 3823 } 3824 } 3825 3826 /** 3827 * Retrieves the DN of the configuration entry for the default password policy 3828 * for the Directory Server. 3829 * 3830 * @return The DN of the configuration entry for the default password policy 3831 * for the Directory Server. 3832 */ 3833 public static DN getDefaultPasswordPolicyDN() 3834 { 3835 synchronized (directoryServer.authenticationPolicies) 3836 { 3837 return directoryServer.defaultPasswordPolicyDN; 3838 } 3839 } 3840 3841 /** 3842 * Specifies the DN of the configuration entry for the default authentication 3843 * policy for the Directory Server. This routine does not check the registered 3844 * authentication policies for the specified DN, since in the case of server 3845 * initialization, the authentication policy entries will not yet have been 3846 * loaded from the configuration backend. 3847 * 3848 * @param defaultPasswordPolicyDN 3849 * The DN of the configuration entry for the default authentication 3850 * policy for the Directory Server. 3851 */ 3852 public static void setDefaultPasswordPolicyDN(DN defaultPasswordPolicyDN) 3853 { 3854 // Ensure default policy is synchronized. 3855 synchronized (directoryServer.authenticationPolicies) 3856 { 3857 directoryServer.defaultPasswordPolicyDN = defaultPasswordPolicyDN; 3858 directoryServer.defaultPasswordPolicy = null; 3859 } 3860 } 3861 3862 /** 3863 * Retrieves the default password policy for the Directory Server. This 3864 * method is equivalent to invoking <CODE>getAuthenticationPolicy</CODE> on 3865 * the DN returned from 3866 * <CODE>DirectoryServer.getDefaultPasswordPolicyDN()</CODE>. 3867 * 3868 * @return The default password policy for the Directory Server. 3869 */ 3870 public static PasswordPolicy getDefaultPasswordPolicy() 3871 { 3872 // Ensure default policy is synchronized. 3873 synchronized (directoryServer.authenticationPolicies) 3874 { 3875 assert null != directoryServer.authenticationPolicies 3876 .get(directoryServer.defaultPasswordPolicyDN) : 3877 "Internal Error: no default password policy defined."; 3878 3879 if (directoryServer.defaultPasswordPolicy == null 3880 && directoryServer.defaultPasswordPolicyDN != null) 3881 { 3882 // The correct policy type is enforced by the core config manager. 3883 directoryServer.defaultPasswordPolicy = (PasswordPolicy) 3884 directoryServer.authenticationPolicies 3885 .get(directoryServer.defaultPasswordPolicyDN); 3886 } 3887 assert directoryServer.authenticationPolicies 3888 .get(directoryServer.defaultPasswordPolicyDN) == 3889 directoryServer.defaultPasswordPolicy : 3890 "Internal Error: inconsistency between defaultPasswordPolicy" 3891 + " cache and value in authenticationPolicies map."; 3892 return directoryServer.defaultPasswordPolicy; 3893 } 3894 } 3895 3896 /** 3897 * Retrieves the log rotation policy registered for the provided configuration 3898 * entry. 3899 * 3900 * @param configEntryDN The DN of the configuration entry for which to 3901 * retrieve the associated rotation policy. 3902 * 3903 * @return The rotation policy registered for the provided configuration 3904 * entry, or <CODE>null</CODE> if there is no such policy. 3905 */ 3906 public static RotationPolicy getRotationPolicy(DN configEntryDN) 3907 { 3908 Reject.ifNull(configEntryDN); 3909 3910 return directoryServer.rotationPolicies.get(configEntryDN); 3911 } 3912 3913 /** 3914 * Registers the provided log rotation policy with the Directory Server. If a 3915 * policy is already registered for the provided configuration entry DN, then 3916 * it will be replaced. 3917 * 3918 * @param configEntryDN The DN of the configuration entry that defines the 3919 * password policy. 3920 * @param policy The rotation policy to register with the server. 3921 */ 3922 public static void registerRotationPolicy(DN configEntryDN, 3923 RotationPolicy policy) 3924 { 3925 Reject.ifNull(configEntryDN, policy); 3926 3927 directoryServer.rotationPolicies.put(configEntryDN, policy); 3928 } 3929 3930 /** 3931 * Deregisters the provided log rotation policy with the Directory Server. 3932 * If no such policy is registered, then no action will be taken. 3933 * 3934 * @param configEntryDN The DN of the configuration entry that defines the 3935 * rotation policy to deregister. 3936 */ 3937 public static void deregisterRotationPolicy(DN configEntryDN) 3938 { 3939 Reject.ifNull(configEntryDN); 3940 3941 directoryServer.rotationPolicies.remove(configEntryDN); 3942 } 3943 3944 /** 3945 * Retrieves the log retention policy registered for the provided 3946 * configuration entry. 3947 * 3948 * @param configEntryDN The DN of the configuration entry for which to 3949 * retrieve the associated retention policy. 3950 * 3951 * @return The retention policy registered for the provided configuration 3952 * entry, or <CODE>null</CODE> if there is no such policy. 3953 */ 3954 public static RetentionPolicy getRetentionPolicy(DN configEntryDN) 3955 { 3956 Reject.ifNull(configEntryDN); 3957 3958 return directoryServer.retentionPolicies.get(configEntryDN); 3959 } 3960 3961 /** 3962 * Registers the provided log retention policy with the Directory Server. 3963 * If a policy is already registered for the provided configuration entry DN, 3964 * then it will be replaced. 3965 * 3966 * @param configEntryDN The DN of the configuration entry that defines the 3967 * password policy. 3968 * @param policy The retention policy to register with the server. 3969 */ 3970 public static void registerRetentionPolicy(DN configEntryDN, 3971 RetentionPolicy policy) 3972 { 3973 Reject.ifNull(configEntryDN, policy); 3974 3975 directoryServer.retentionPolicies.put(configEntryDN, policy); 3976 } 3977 3978 /** 3979 * Deregisters the provided log retention policy with the Directory Server. 3980 * If no such policy is registered, then no action will be taken. 3981 * 3982 * @param configEntryDN The DN of the configuration entry that defines the 3983 * retention policy to deregister. 3984 */ 3985 public static void deregisterRetentionPolicy(DN configEntryDN) 3986 { 3987 Reject.ifNull(configEntryDN); 3988 3989 directoryServer.retentionPolicies.remove(configEntryDN); 3990 } 3991 3992 /** 3993 * Retrieves the set of monitor providers that have been registered with the 3994 * Directory Server, as a mapping between the monitor name (in all lowercase 3995 * characters) and the monitor implementation. 3996 * 3997 * @return The set of monitor providers that have been registered with the 3998 * Directory Server. 3999 */ 4000 public static ConcurrentMap<String, 4001 MonitorProvider<? extends MonitorProviderCfg>> 4002 getMonitorProviders() 4003 { 4004 return directoryServer.monitorProviders; 4005 } 4006 4007 /** 4008 * Retrieves the monitor provider with the specified name. 4009 * 4010 * @param lowerName The name of the monitor provider to retrieve, in all 4011 * lowercase characters. 4012 * 4013 * @return The requested resource monitor, or <CODE>null</CODE> if none 4014 * exists with the specified name. 4015 */ 4016 public static MonitorProvider<? extends MonitorProviderCfg> 4017 getMonitorProvider(String lowerName) 4018 { 4019 return directoryServer.monitorProviders.get(lowerName); 4020 } 4021 4022 /** 4023 * Registers the provided monitor provider with the Directory Server. Note 4024 * that if a monitor provider is already registered with the specified name, 4025 * then it will be replaced with the provided implementation. 4026 * 4027 * @param monitorProvider The monitor provider to register with the 4028 * Directory Server. 4029 */ 4030 public static void registerMonitorProvider( 4031 MonitorProvider<? extends MonitorProviderCfg> 4032 monitorProvider) 4033 { 4034 String lowerName = toLowerCase(monitorProvider.getMonitorInstanceName()); 4035 directoryServer.monitorProviders.put(lowerName, monitorProvider); 4036 4037 // Try to register this monitor provider with an appropriate JMX MBean. 4038 try 4039 { 4040 DN monitorDN = getMonitorProviderDN(monitorProvider); 4041 JMXMBean mBean = directoryServer.mBeans.get(monitorDN); 4042 if (mBean == null) 4043 { 4044 mBean = new JMXMBean(monitorDN); 4045 mBean.addMonitorProvider(monitorProvider); 4046 directoryServer.mBeans.put(monitorDN, mBean); 4047 } 4048 else 4049 { 4050 mBean.addMonitorProvider(monitorProvider); 4051 } 4052 } 4053 catch (Exception e) 4054 { 4055 logger.traceException(e); 4056 } 4057 } 4058 4059 /** 4060 * Deregisters the specified monitor provider from the Directory Server. If no 4061 * such monitor provider is registered, no action will be taken. 4062 * 4063 * @param monitorProvider 4064 * The monitor provider to deregister from the Directory Server. 4065 */ 4066 public static void deregisterMonitorProvider( 4067 MonitorProvider<? extends MonitorProviderCfg> monitorProvider) 4068 { 4069 String monitorName = toLowerCase(monitorProvider.getMonitorInstanceName()); 4070 MonitorProvider<?> provider = directoryServer.monitorProviders 4071 .remove(monitorName); 4072 4073 // Try to deregister the monitor provider as an MBean. 4074 if (provider != null) 4075 { 4076 try 4077 { 4078 DN monitorDN = getMonitorProviderDN(provider); 4079 JMXMBean mBean = directoryServer.mBeans.get(monitorDN); 4080 if (mBean != null) 4081 { 4082 mBean.removeMonitorProvider(provider); 4083 } 4084 } 4085 catch (Exception e) 4086 { 4087 logger.traceException(e); 4088 } 4089 } 4090 } 4091 4092 /** 4093 * Retrieves the entry cache for the Directory Server. 4094 * 4095 * @return The entry cache for the Directory Server. 4096 */ 4097 public static EntryCache getEntryCache() 4098 { 4099 return directoryServer.entryCache; 4100 } 4101 4102 /** 4103 * Specifies the entry cache that should be used by the Directory Server. 4104 * This should only be called by the entry cache configuration manager. 4105 * 4106 * @param entryCache The entry cache for the Directory Server. 4107 */ 4108 public static void setEntryCache(EntryCache entryCache) 4109 { 4110 synchronized (directoryServer) 4111 { 4112 directoryServer.entryCache = entryCache; 4113 } 4114 } 4115 4116 /** 4117 * Retrieves the set of key manager providers registered with the Directory 4118 * Server. 4119 * 4120 * @return The set of key manager providers registered with the Directory 4121 * Server. 4122 */ 4123 public static Map<DN,KeyManagerProvider> getKeyManagerProviders() 4124 { 4125 return directoryServer.keyManagerProviders; 4126 } 4127 4128 /** 4129 * Retrieves the key manager provider registered with the provided entry DN. 4130 * 4131 * @param providerDN The DN with which the key manager provider is 4132 * registered. 4133 * 4134 * @return The key manager provider registered with the provided entry DN, or 4135 * {@code null} if there is no such key manager provider registered 4136 * with the server. 4137 */ 4138 public static KeyManagerProvider getKeyManagerProvider(DN providerDN) 4139 { 4140 return directoryServer.keyManagerProviders.get(providerDN); 4141 } 4142 4143 /** 4144 * Registers the provided key manager provider with the Directory Server. 4145 * 4146 * @param providerDN The DN with which to register the key manager provider. 4147 * @param provider The key manager provider to register with the server. 4148 */ 4149 public static void registerKeyManagerProvider(DN providerDN, 4150 KeyManagerProvider provider) 4151 { 4152 directoryServer.keyManagerProviders.put(providerDN, provider); 4153 } 4154 4155 /** 4156 * Deregisters the specified key manager provider with the Directory Server. 4157 * 4158 * @param providerDN The DN with which the key manager provider is 4159 * registered. 4160 */ 4161 public static void deregisterKeyManagerProvider(DN providerDN) 4162 { 4163 directoryServer.keyManagerProviders.remove(providerDN); 4164 } 4165 4166 /** 4167 * Retrieves the set of trust manager providers registered with the Directory 4168 * Server. 4169 * 4170 * @return The set of trust manager providers registered with the Directory 4171 * Server. 4172 */ 4173 public static Map<DN,TrustManagerProvider> getTrustManagerProviders() 4174 { 4175 return directoryServer.trustManagerProviders; 4176 } 4177 4178 /** 4179 * Retrieves the trust manager provider registered with the provided entry DN. 4180 * 4181 * @param providerDN The DN with which the trust manager provider is 4182 * registered. 4183 * 4184 * @return The trust manager provider registered with the provided entry DN, 4185 * or {@code null} if there is no such trust manager provider 4186 * registered with the server. 4187 */ 4188 public static TrustManagerProvider getTrustManagerProvider(DN providerDN) 4189 { 4190 return directoryServer.trustManagerProviders.get(providerDN); 4191 } 4192 4193 /** 4194 * Registers the provided trust manager provider with the Directory Server. 4195 * 4196 * @param providerDN The DN with which to register the trust manager 4197 * provider. 4198 * @param provider The trust manager provider to register with the server. 4199 */ 4200 public static void registerTrustManagerProvider(DN providerDN, 4201 TrustManagerProvider provider) 4202 { 4203 directoryServer.trustManagerProviders.put(providerDN, provider); 4204 } 4205 4206 /** 4207 * Deregisters the specified trust manager provider with the Directory Server. 4208 * 4209 * @param providerDN The DN with which the trust manager provider is 4210 * registered. 4211 */ 4212 public static void deregisterTrustManagerProvider(DN providerDN) 4213 { 4214 directoryServer.trustManagerProviders.remove(providerDN); 4215 } 4216 4217 /** 4218 * Retrieves the set of certificate mappers registered with the Directory 4219 * Server. 4220 * 4221 * @return The set of certificate mappers registered with the Directory 4222 * Server. 4223 */ 4224 public static Map<DN,CertificateMapper> getCertificateMappers() 4225 { 4226 return directoryServer.certificateMappers; 4227 } 4228 4229 /** 4230 * Retrieves the certificate mapper registered with the provided entry DN. 4231 * 4232 * @param mapperDN The DN with which the certificate mapper is registered. 4233 * 4234 * @return The certificate mapper registered with the provided entry DN, or 4235 * {@code null} if there is no such certificate mapper registered 4236 * with the server. 4237 */ 4238 public static CertificateMapper getCertificateMapper(DN mapperDN) 4239 { 4240 return directoryServer.certificateMappers.get(mapperDN); 4241 } 4242 4243 /** 4244 * Registers the provided certificate mapper with the Directory Server. 4245 * 4246 * @param mapperDN The DN with which to register the certificate mapper. 4247 * @param mapper The certificate mapper to register with the server. 4248 */ 4249 public static void registerCertificateMapper(DN mapperDN, 4250 CertificateMapper mapper) 4251 { 4252 directoryServer.certificateMappers.put(mapperDN, mapper); 4253 } 4254 4255 /** 4256 * Deregisters the specified certificate mapper with the Directory Server. 4257 * 4258 * @param mapperDN The DN with which the certificate mapper is registered. 4259 */ 4260 public static void deregisterCertificateMapper(DN mapperDN) 4261 { 4262 directoryServer.certificateMappers.remove(mapperDN); 4263 } 4264 4265 /** 4266 * Retrieves the set of privileges that should automatically be granted to 4267 * root users when they authenticate. 4268 * 4269 * @return The set of privileges that should automatically be granted to root 4270 * users when they authenticate. 4271 */ 4272 public static Set<Privilege> getRootPrivileges() 4273 { 4274 return directoryServer.rootDNConfigManager.getRootPrivileges(); 4275 } 4276 4277 /** 4278 * Retrieves the DNs for the root users configured in the Directory Server. 4279 * Note that this set should only contain the actual DNs for the root users 4280 * and not any alternate DNs. Also, the contents of the returned set must not 4281 * be altered by the caller. 4282 * 4283 * @return The DNs for the root users configured in the Directory Server. 4284 */ 4285 public static Set<DN> getRootDNs() 4286 { 4287 return directoryServer.rootDNs; 4288 } 4289 4290 /** 4291 * Indicates whether the provided DN is the DN for one of the root users 4292 * configured in the Directory Server. 4293 * 4294 * @param userDN The user DN for which to make the determination. 4295 * 4296 * @return <CODE>true</CODE> if the provided user DN is a Directory Server 4297 * root DN, or <CODE>false</CODE> if not. 4298 */ 4299 public static boolean isRootDN(DN userDN) 4300 { 4301 return directoryServer.rootDNs.contains(userDN); 4302 } 4303 4304 /** 4305 * Registers the provided root DN with the Directory Server. 4306 * 4307 * @param rootDN The root DN to register with the Directory Server. 4308 */ 4309 public static void registerRootDN(DN rootDN) 4310 { 4311 directoryServer.rootDNs.add(rootDN); 4312 } 4313 4314 /** 4315 * Deregisters the provided root DN with the Directory Server. This will have 4316 * no effect if the provided DN is not registered as a root DN. 4317 * 4318 * @param rootDN The root DN to deregister. 4319 */ 4320 public static void deregisterRootDN(DN rootDN) 4321 { 4322 directoryServer.rootDNs.remove(rootDN); 4323 } 4324 4325 /** 4326 * Retrieves the set of alternate bind DNs for root users, mapped between the 4327 * alternate DN and the real DN. The contents of the returned map must not be 4328 * altered by the caller. 4329 * 4330 * @return The set of alternate bind DNs for root users, mapped between the 4331 * alternate DN and the real DN. 4332 */ 4333 public static ConcurrentMap<DN, DN> getAlternateRootBindDNs() 4334 { 4335 return directoryServer.alternateRootBindDNs; 4336 } 4337 4338 /** 4339 * Retrieves the real entry DN for the root user with the provided alternate 4340 * bind DN. 4341 * 4342 * @param alternateRootBindDN The alternate root bind DN for which to 4343 * retrieve the real entry DN. 4344 * 4345 * @return The real entry DN for the root user with the provided alternate 4346 * bind DN, or <CODE>null</CODE> if no such mapping has been defined. 4347 */ 4348 public static DN getActualRootBindDN(DN alternateRootBindDN) 4349 { 4350 return directoryServer.alternateRootBindDNs.get(alternateRootBindDN); 4351 } 4352 4353 /** 4354 * Registers an alternate root bind DN using the provided information. 4355 * 4356 * @param actualRootEntryDN The actual DN for the root user's entry. 4357 * @param alternateRootBindDN The alternate DN that should be interpreted as 4358 * if it were the provided actual root entry DN. 4359 * 4360 * @throws DirectoryException If the provided alternate bind DN is already 4361 * in use for another root user. 4362 */ 4363 public static void registerAlternateRootDN(DN actualRootEntryDN, 4364 DN alternateRootBindDN) 4365 throws DirectoryException 4366 { 4367 DN existingRootEntryDN = 4368 directoryServer.alternateRootBindDNs.putIfAbsent(alternateRootBindDN, 4369 actualRootEntryDN); 4370 if (existingRootEntryDN != null 4371 && !existingRootEntryDN.equals(actualRootEntryDN)) 4372 { 4373 LocalizableMessage message = ERR_CANNOT_REGISTER_DUPLICATE_ALTERNATE_ROOT_BIND_DN. 4374 get(alternateRootBindDN, existingRootEntryDN); 4375 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); 4376 } 4377 } 4378 4379 /** 4380 * Deregisters the provided alternate root bind DN from the server. This will 4381 * have no effect if there was no mapping defined for the provided alternate 4382 * root bind DN. 4383 * 4384 * @param alternateRootBindDN The alternate root bind DN to be deregistered. 4385 * 4386 * @return The actual root entry DN to which the provided alternate bind DN 4387 * was mapped, or <CODE>null</CODE> if there was no mapping for the 4388 * provided DN. 4389 */ 4390 public static DN deregisterAlternateRootBindDN(DN alternateRootBindDN) 4391 { 4392 return directoryServer.alternateRootBindDNs.remove(alternateRootBindDN); 4393 } 4394 4395 /** 4396 * Retrieves the result code that should be used when the Directory Server 4397 * encounters an internal server error. 4398 * 4399 * @return The result code that should be used when the Directory Server 4400 * encounters an internal server error. 4401 */ 4402 public static ResultCode getServerErrorResultCode() 4403 { 4404 return directoryServer.serverErrorResultCode; 4405 } 4406 4407 /** 4408 * Specifies the result code that should be used when the Directory Server 4409 * encounters an internal server error. 4410 * 4411 * @param serverErrorResultCode The result code that should be used when the 4412 * Directory Server encounters an internal 4413 * server error. 4414 */ 4415 public static void setServerErrorResultCode(ResultCode serverErrorResultCode) 4416 { 4417 directoryServer.serverErrorResultCode = serverErrorResultCode; 4418 } 4419 4420 /** 4421 * Indicates whether the Directory Server should automatically add missing RDN 4422 * attributes to an entry whenever it is added. 4423 * 4424 * @return <CODE>true</CODE> if the Directory Server should automatically add 4425 * missing RDN attributes to an entry, or <CODE>false</CODE> if it 4426 * should return an error to the client. 4427 */ 4428 public static boolean addMissingRDNAttributes() 4429 { 4430 return directoryServer.addMissingRDNAttributes; 4431 } 4432 4433 /** 4434 * Specifies whether the Directory Server should automatically add missing RDN 4435 * attributes to an entry whenever it is added. 4436 * 4437 * @param addMissingRDNAttributes Specifies whether the Directory Server 4438 * should automatically add missing RDN 4439 * attributes to an entry whenever it is 4440 * added. 4441 */ 4442 public static void setAddMissingRDNAttributes(boolean addMissingRDNAttributes) 4443 { 4444 directoryServer.addMissingRDNAttributes = addMissingRDNAttributes; 4445 } 4446 4447 /** 4448 * Indicates whether to be more flexible in the set of characters allowed for 4449 * attribute names. The standard requires that only ASCII alphabetic letters, 4450 * numeric digits, and hyphens be allowed, and that the name start with a 4451 * letter. If attribute name exceptions are enabled, then underscores will 4452 * also be allowed, and the name will be allowed to start with a digit. 4453 * 4454 * @return <CODE>true</CODE> if the server should use a more flexible 4455 * syntax for attribute names, or <CODE>false</CODE> if not. 4456 */ 4457 public static boolean allowAttributeNameExceptions() 4458 { 4459 return directoryServer.allowAttributeNameExceptions; 4460 } 4461 4462 /** 4463 * Specifies whether to be more flexible in the set of characters allowed for 4464 * attribute names. 4465 * 4466 * @param allowAttributeNameExceptions Specifies whether to be more flexible 4467 * in the set of characters allowed for 4468 * attribute names. 4469 */ 4470 public static void setAllowAttributeNameExceptions( 4471 boolean allowAttributeNameExceptions) 4472 { 4473 directoryServer.allowAttributeNameExceptions = allowAttributeNameExceptions; 4474 } 4475 4476 /** 4477 * Indicates whether the Directory Server should perform schema checking. 4478 * 4479 * @return <CODE>true</CODE> if the Directory Server should perform schema 4480 * checking, or <CODE>false</CODE> if not. 4481 */ 4482 public static boolean checkSchema() 4483 { 4484 return directoryServer.checkSchema; 4485 } 4486 4487 /** 4488 * Specifies whether the Directory Server should perform schema checking. 4489 * 4490 * @param checkSchema Specifies whether the Directory Server should perform 4491 * schema checking. 4492 */ 4493 public static void setCheckSchema(boolean checkSchema) 4494 { 4495 directoryServer.checkSchema = checkSchema; 4496 } 4497 4498 /** 4499 * Retrieves the policy that should be used regarding enforcement of a single 4500 * structural objectclass per entry. 4501 * 4502 * @return The policy that should be used regarding enforcement of a single 4503 * structural objectclass per entry. 4504 */ 4505 public static AcceptRejectWarn getSingleStructuralObjectClassPolicy() 4506 { 4507 return directoryServer.singleStructuralClassPolicy; 4508 } 4509 4510 /** 4511 * Specifies the policy that should be used regarding enforcement of a single 4512 * structural objectclass per entry. 4513 * 4514 * @param singleStructuralClassPolicy The policy that should be used 4515 * regarding enforcement of a single 4516 * structural objectclass per entry. 4517 */ 4518 public static void setSingleStructuralObjectClassPolicy( 4519 AcceptRejectWarn singleStructuralClassPolicy) 4520 { 4521 directoryServer.singleStructuralClassPolicy = singleStructuralClassPolicy; 4522 } 4523 4524 /** 4525 * Retrieves the policy that should be used when an attribute value is found 4526 * that is not valid according to the associated attribute syntax. 4527 * 4528 * @return The policy that should be used when an attribute value is found 4529 * that is not valid according to the associated attribute syntax. 4530 */ 4531 public static AcceptRejectWarn getSyntaxEnforcementPolicy() 4532 { 4533 return directoryServer.syntaxEnforcementPolicy; 4534 } 4535 4536 /** 4537 * Retrieves the policy that should be used when an attribute value is found 4538 * that is not valid according to the associated attribute syntax. 4539 * 4540 * @param syntaxEnforcementPolicy The policy that should be used when an 4541 * attribute value is found that is not valid 4542 * according to the associated attribute 4543 * syntax. 4544 */ 4545 public static void setSyntaxEnforcementPolicy( 4546 AcceptRejectWarn syntaxEnforcementPolicy) 4547 { 4548 directoryServer.syntaxEnforcementPolicy = syntaxEnforcementPolicy; 4549 } 4550 4551 /** 4552 * Indicates whether the Directory Server should send a response to an 4553 * operation that has been abandoned. Sending such a response is technically 4554 * a violation of the LDAP protocol specification, but not doing so in that 4555 * case can cause problems with clients that are expecting a response and may 4556 * hang until they get one. 4557 * 4558 * @return <CODE>true</CODE> if the Directory Server should send a response 4559 * to an operation that has been abandoned, or <CODE>false</CODE> if 4560 * not. 4561 */ 4562 public static boolean notifyAbandonedOperations() 4563 { 4564 return directoryServer.notifyAbandonedOperations; 4565 } 4566 4567 /** 4568 * Specifies whether the Directory Server should send a response to an 4569 * operation that has been abandoned. Sending such a response is technically 4570 * a violation of the LDAP protocol specification, but not doing so in that 4571 * case can cause problems with clients that are expecting a response and may 4572 * hang until they get one. 4573 * 4574 * @param notifyAbandonedOperations Indicates whether the Directory Server 4575 * should send a response to an operation 4576 * that has been abandoned. 4577 */ 4578 public static void setNotifyAbandonedOperations( 4579 boolean notifyAbandonedOperations) 4580 { 4581 directoryServer.notifyAbandonedOperations = notifyAbandonedOperations; 4582 } 4583 4584 /** 4585 * Retrieves the set of backends that have been registered with the Directory 4586 * Server, as a mapping between the backend ID and the corresponding backend. 4587 * 4588 * @return The set of backends that have been registered with the Directory 4589 * Server. 4590 */ 4591 public static Map<String, Backend> getBackends() 4592 { 4593 return new TreeMap<String, Backend>(directoryServer.backends); 4594 } 4595 4596 /** 4597 * Retrieves the backend with the specified backend ID. 4598 * 4599 * @param backendID The backend ID of the backend to retrieve. 4600 * 4601 * @return The backend with the specified backend ID, or {@code null} if 4602 * there is none. 4603 */ 4604 public static Backend<?> getBackend(String backendID) 4605 { 4606 return directoryServer.backends.get(backendID); 4607 } 4608 4609 /** 4610 * Indicates whether the Directory Server has a backend with the specified 4611 * backend ID. 4612 * 4613 * @param backendID The backend ID for which to make the determination. 4614 * 4615 * @return {@code true} if the Directory Server has a backend with the 4616 * specified backend ID, or {@code false} if not. 4617 */ 4618 public static boolean hasBackend(String backendID) 4619 { 4620 return directoryServer.backends.containsKey(backendID); 4621 } 4622 4623 /** 4624 * Registers the provided backend with the Directory Server. Note that this 4625 * will not register the set of configured suffixes with the server, as that 4626 * must be done by the backend itself. 4627 * 4628 * @param backend The backend to register with the server. Neither the 4629 * backend nor its backend ID may be null. 4630 * 4631 * @throws DirectoryException If the backend ID for the provided backend 4632 * conflicts with the backend ID of an existing 4633 * backend. 4634 */ 4635 public static void registerBackend(Backend<?> backend) throws DirectoryException 4636 { 4637 ifNull(backend); 4638 4639 String backendID = backend.getBackendID(); 4640 ifNull(backendID); 4641 4642 synchronized (directoryServer) 4643 { 4644 TreeMap<String, Backend<?>> newBackends = new TreeMap<>(directoryServer.backends); 4645 if (newBackends.containsKey(backendID)) 4646 { 4647 LocalizableMessage message = ERR_REGISTER_BACKEND_ALREADY_EXISTS.get(backendID); 4648 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 4649 } 4650 else 4651 { 4652 newBackends.put(backendID, backend); 4653 directoryServer.backends = newBackends; 4654 4655 for (String oid : backend.getSupportedControls()) 4656 { 4657 registerSupportedControl(oid); 4658 } 4659 4660 for (String oid : backend.getSupportedFeatures()) 4661 { 4662 registerSupportedFeature(oid); 4663 } 4664 4665 BackendMonitor monitor = new BackendMonitor(backend); 4666 monitor.initializeMonitorProvider(null); 4667 backend.setBackendMonitor(monitor); 4668 registerMonitorProvider(monitor); 4669 } 4670 } 4671 } 4672 4673 /** 4674 * Deregisters the provided backend with the Directory Server. Note that this 4675 * will not deregister the set of configured suffixes with the server, as that 4676 * must be done by the backend itself. 4677 * 4678 * @param backend The backend to deregister with the server. It must not be 4679 * {@code null}. 4680 */ 4681 public static void deregisterBackend(Backend<?> backend) 4682 { 4683 ifNull(backend); 4684 4685 synchronized (directoryServer) 4686 { 4687 TreeMap<String, Backend<?>> newBackends = new TreeMap<>(directoryServer.backends); 4688 newBackends.remove(backend.getBackendID()); 4689 4690 directoryServer.backends = newBackends; 4691 4692 // Don't need anymore the local backend workflow element so we can remove it 4693 for (DN baseDN : backend.getBaseDNs()) 4694 { 4695 LocalBackendWorkflowElement.remove(baseDN); 4696 } 4697 4698 BackendMonitor monitor = backend.getBackendMonitor(); 4699 if (monitor != null) 4700 { 4701 deregisterMonitorProvider(monitor); 4702 monitor.finalizeMonitorProvider(); 4703 backend.setBackendMonitor(null); 4704 } 4705 } 4706 } 4707 4708 /** 4709 * Retrieves the entire set of base DNs registered with the Directory Server, 4710 * mapped from the base DN to the backend responsible for that base DN. The 4711 * same backend may be present multiple times, mapped from different base DNs. 4712 * 4713 * @return The entire set of base DNs registered with the Directory Server. 4714 */ 4715 public static Map<DN,Backend> getBaseDNs() 4716 { 4717 return directoryServer.baseDnRegistry.getBaseDnMap(); 4718 } 4719 4720 /** 4721 * Retrieves the backend with the specified base DN. 4722 * 4723 * @param baseDN The DN that is registered as one of the base DNs for the 4724 * backend to retrieve. 4725 * 4726 * @return The backend with the specified base DN, or {@code null} if there 4727 * is no backend registered with the specified base DN. 4728 */ 4729 public static Backend<?> getBackendWithBaseDN(DN baseDN) 4730 { 4731 return directoryServer.baseDnRegistry.getBaseDnMap().get(baseDN); 4732 } 4733 4734 /** 4735 * Retrieves the backend that should be used to handle operations on the 4736 * specified entry. 4737 * 4738 * @param entryDN The DN of the entry for which to retrieve the 4739 * corresponding backend. 4740 * 4741 * @return The backend that should be used to handle operations on the 4742 * specified entry, or {@code null} if no appropriate backend is 4743 * registered with the server. 4744 */ 4745 public static Backend<?> getBackend(DN entryDN) 4746 { 4747 if (entryDN.isRootDN()) 4748 { 4749 return directoryServer.rootDSEBackend; 4750 } 4751 4752 Map<DN,Backend> baseDNs = directoryServer.baseDnRegistry.getBaseDnMap(); 4753 Backend<?> b = baseDNs.get(entryDN); 4754 while (b == null) 4755 { 4756 entryDN = entryDN.parent(); 4757 if (entryDN == null) 4758 { 4759 return null; 4760 } 4761 4762 b = baseDNs.get(entryDN); 4763 } 4764 4765 return b; 4766 } 4767 4768 /** 4769 * Obtains a copy of the server's base DN registry. The copy can be used 4770 * to test registration/deregistration of base DNs but cannot be used to 4771 * modify the backends. To modify the server's live base DN to backend 4772 * mappings use {@link #registerBaseDN(DN, Backend, boolean)} and 4773 * {@link #deregisterBaseDN(DN)}. 4774 * 4775 * @return copy of the base DN registry 4776 */ 4777 public static BaseDnRegistry copyBaseDnRegistry() 4778 { 4779 return directoryServer.baseDnRegistry.copy(); 4780 } 4781 4782 /** 4783 * Registers the provided base DN with the server. 4784 * 4785 * @param baseDN The base DN to register with the server. It must not be 4786 * {@code null}. 4787 * @param backend The backend responsible for the provided base DN. It 4788 * must not be {@code null}. 4789 * @param isPrivate Indicates whether the base DN should be considered a 4790 * private base DN. If the provided base DN is a naming 4791 * context, then this controls whether it is public or 4792 * private. 4793 * 4794 * @throws DirectoryException If a problem occurs while attempting to 4795 * register the provided base DN. 4796 */ 4797 public static void registerBaseDN(DN baseDN, Backend<?> backend, boolean isPrivate) 4798 throws DirectoryException 4799 { 4800 ifNull(baseDN, backend); 4801 4802 synchronized (directoryServer) 4803 { 4804 List<LocalizableMessage> warnings = 4805 directoryServer.baseDnRegistry.registerBaseDN( 4806 baseDN, backend, isPrivate); 4807 4808 // Since we've committed the changes we need to log any issues 4809 // that this registration has caused 4810 for (LocalizableMessage warning : warnings) { 4811 logger.error(warning); 4812 } 4813 4814 // When a new baseDN is registered with the server we have to create 4815 // a new workflow to handle the base DN. 4816 if (!baseDN.equals(DN.valueOf("cn=config"))) 4817 { 4818 // Now create a workflow for the registered baseDN and register 4819 // the workflow with the default network group, but don't register 4820 // the workflow if the backend happens to be the configuration 4821 // backend because it's too soon for the config backend. 4822 createWorkflow(baseDN, backend); 4823 } 4824 } 4825 } 4826 4827 /** 4828 * Deregisters the provided base DN with the server. 4829 * 4830 * @param baseDN The base DN to deregister with the server. It must not 4831 * be {@code null}. 4832 * 4833 * @throws DirectoryException If a problem occurs while attempting to 4834 * deregister the provided base DN. 4835 */ 4836 public static void deregisterBaseDN(DN baseDN) 4837 throws DirectoryException 4838 { 4839 ifNull(baseDN); 4840 4841 synchronized(directoryServer) { 4842 4843 List<LocalizableMessage> warnings = 4844 directoryServer.baseDnRegistry.deregisterBaseDN(baseDN); 4845 4846 // Since we've committed the changes we need to log any issues 4847 // that this registration has caused 4848 for (LocalizableMessage error : warnings) { 4849 logger.error(error); 4850 } 4851 4852 // Now we need to deregister the workflow that was associated with the base DN 4853 if (!baseDN.equals(DN.valueOf("cn=config"))) 4854 { 4855 LocalBackendWorkflowElement.remove(baseDN); 4856 } 4857 } 4858 } 4859 4860 /** 4861 * Retrieves the set of public naming contexts defined in the Directory 4862 * Server, mapped from the naming context DN to the corresponding backend. 4863 * 4864 * @return The set of public naming contexts defined in the Directory Server. 4865 */ 4866 public static Map<DN,Backend> getPublicNamingContexts() 4867 { 4868 return directoryServer.baseDnRegistry.getPublicNamingContextsMap(); 4869 } 4870 4871 /** 4872 * Retrieves the set of private naming contexts defined in the Directory 4873 * Server, mapped from the naming context DN to the corresponding backend. 4874 * 4875 * @return The set of private naming contexts defined in the Directory 4876 * Server. 4877 */ 4878 public static Map<DN,Backend> getPrivateNamingContexts() 4879 { 4880 return directoryServer.baseDnRegistry.getPrivateNamingContextsMap(); 4881 } 4882 4883 /** 4884 * Indicates whether the specified DN is one of the Directory Server naming 4885 * contexts. 4886 * 4887 * @param dn The DN for which to make the determination. 4888 * 4889 * @return {@code true} if the specified DN is a naming context for the 4890 * Directory Server, or {@code false} if it is not. 4891 */ 4892 public static boolean isNamingContext(DN dn) 4893 { 4894 return directoryServer.baseDnRegistry.containsNamingContext(dn); 4895 } 4896 4897 /** 4898 * Retrieves the root DSE entry for the Directory Server. 4899 * 4900 * @return The root DSE entry for the Directory Server. 4901 */ 4902 public static Entry getRootDSE() 4903 { 4904 return directoryServer.rootDSEBackend.getRootDSE(); 4905 } 4906 4907 /** 4908 * Retrieves the root DSE backend for the Directory Server. 4909 * 4910 * @return The root DSE backend for the Directory Server. 4911 */ 4912 public static RootDSEBackend getRootDSEBackend() 4913 { 4914 return directoryServer.rootDSEBackend; 4915 } 4916 4917 /** 4918 * Retrieves the DN of the entry containing the server schema definitions. 4919 * 4920 * @return The DN of the entry containing the server schema definitions, or 4921 * <CODE>null</CODE> if none has been defined (e.g., if no schema 4922 * backend has been configured). 4923 */ 4924 public static DN getSchemaDN() 4925 { 4926 return directoryServer.schemaDN; 4927 } 4928 4929 /** 4930 * Specifies the DN of the entry containing the server schema definitions. 4931 * 4932 * @param schemaDN The DN of the entry containing the server schema 4933 * definitions. 4934 */ 4935 public static void setSchemaDN(DN schemaDN) 4936 { 4937 directoryServer.schemaDN = schemaDN; 4938 } 4939 4940 /** 4941 * Retrieves the entry with the requested DN. It will first determine which backend should be used 4942 * for this DN and will then use that backend to retrieve the entry. The caller is not required to 4943 * hold any locks on the specified DN. 4944 * 4945 * @param entryDN 4946 * The DN of the entry to retrieve. 4947 * @return The requested entry, or <CODE>null</CODE> if it does not exist. 4948 * @throws DirectoryException 4949 * If a problem occurs while attempting to retrieve the entry. 4950 */ 4951 public static Entry getEntry(DN entryDN) throws DirectoryException 4952 { 4953 if (entryDN.isRootDN()) 4954 { 4955 return directoryServer.rootDSEBackend.getRootDSE(); 4956 } 4957 final Backend<?> backend = getBackend(entryDN); 4958 return backend != null ? backend.getEntry(entryDN) : null; 4959 } 4960 4961 /** 4962 * Indicates whether the specified entry exists in the Directory Server. The 4963 * caller is not required to hold any locks when invoking this method. 4964 * 4965 * @param entryDN The DN of the entry for which to make the determination. 4966 * 4967 * @return <CODE>true</CODE> if the specified entry exists in one of the 4968 * backends, or <CODE>false</CODE> if it does not. 4969 * 4970 * @throws DirectoryException If a problem occurs while attempting to 4971 * make the determination. 4972 */ 4973 public static boolean entryExists(DN entryDN) 4974 throws DirectoryException 4975 { 4976 // If the entry is the root DSE, then it will always exist. 4977 if (entryDN.isRootDN()) 4978 { 4979 return true; 4980 } 4981 4982 // Ask the appropriate backend if the entry exists. 4983 // If it is not appropriate for any backend, then return false. 4984 Backend<?> backend = getBackend(entryDN); 4985 return backend != null && backend.entryExists(entryDN); 4986 } 4987 4988 /** 4989 * Retrieves the set of supported controls registered with the Directory 4990 * Server. 4991 * 4992 * @return The set of supported controls registered with the Directory 4993 * Server. 4994 */ 4995 public static TreeSet<String> getSupportedControls() 4996 { 4997 return directoryServer.supportedControls; 4998 } 4999 5000 /** 5001 * Indicates whether the specified OID is registered with the Directory Server 5002 * as a supported control. 5003 * 5004 * @param controlOID The OID of the control for which to make the 5005 * determination. 5006 * 5007 * @return <CODE>true</CODE> if the specified OID is registered with the 5008 * server as a supported control, or <CODE>false</CODE> if not. 5009 */ 5010 public static boolean isSupportedControl(String controlOID) 5011 { 5012 return directoryServer.supportedControls.contains(controlOID); 5013 } 5014 5015 /** 5016 * Registers the provided OID as a supported control for the Directory Server. 5017 * This will have no effect if the specified control OID is already present in 5018 * the list of supported controls. 5019 * 5020 * @param controlOID The OID of the control to register as a supported 5021 * control. 5022 */ 5023 public static void registerSupportedControl(String controlOID) 5024 { 5025 synchronized (directoryServer.supportedControls) 5026 { 5027 directoryServer.supportedControls.add(controlOID); 5028 } 5029 } 5030 5031 /** 5032 * Deregisters the provided OID as a supported control for the Directory 5033 * Server. This will have no effect if the specified control OID is not 5034 * present in the list of supported controls. 5035 * 5036 * @param controlOID The OID of the control to deregister as a supported 5037 * control. 5038 */ 5039 public static void deregisterSupportedControl(String controlOID) 5040 { 5041 synchronized (directoryServer.supportedControls) 5042 { 5043 directoryServer.supportedControls.remove(controlOID); 5044 } 5045 } 5046 5047 /** 5048 * Retrieves the set of supported features registered with the Directory 5049 * Server. 5050 * 5051 * @return The set of supported features registered with the Directory 5052 * Server. 5053 */ 5054 public static TreeSet<String> getSupportedFeatures() 5055 { 5056 return directoryServer.supportedFeatures; 5057 } 5058 5059 /** 5060 * Indicates whether the specified OID is registered with the Directory Server 5061 * as a supported feature. 5062 * 5063 * @param featureOID The OID of the feature for which to make the 5064 * determination. 5065 * 5066 * @return <CODE>true</CODE> if the specified OID is registered with the 5067 * server as a supported feature, or <CODE>false</CODE> if not. 5068 */ 5069 public static boolean isSupportedFeature(String featureOID) 5070 { 5071 return directoryServer.supportedFeatures.contains(featureOID); 5072 } 5073 5074 /** 5075 * Registers the provided OID as a supported feature for the Directory Server. 5076 * This will have no effect if the specified feature OID is already present in 5077 * the list of supported features. 5078 * 5079 * @param featureOID The OID of the feature to register as a supported 5080 * feature. 5081 */ 5082 public static void registerSupportedFeature(String featureOID) 5083 { 5084 synchronized (directoryServer.supportedFeatures) 5085 { 5086 directoryServer.supportedFeatures.add(featureOID); 5087 } 5088 } 5089 5090 /** 5091 * Deregisters the provided OID as a supported feature for the Directory 5092 * Server. This will have no effect if the specified feature OID is not 5093 * present in the list of supported features. 5094 * 5095 * @param featureOID The OID of the feature to deregister as a supported 5096 * feature. 5097 */ 5098 public static void deregisterSupportedFeature(String featureOID) 5099 { 5100 synchronized (directoryServer.supportedFeatures) 5101 { 5102 directoryServer.supportedFeatures.remove(featureOID); 5103 } 5104 } 5105 5106 /** 5107 * Retrieves the set of extended operations that may be processed by the 5108 * Directory Server. 5109 * 5110 * @return The set of extended operations that may be processed by the 5111 * Directory Server. 5112 */ 5113 public static ConcurrentMap<String, ExtendedOperationHandler> 5114 getSupportedExtensions() 5115 { 5116 return directoryServer.extendedOperationHandlers; 5117 } 5118 5119 /** 5120 * Retrieves the handler for the extended operation for the provided OID. 5121 * 5122 * @param oid The OID of the extended operation to retrieve. 5123 * 5124 * @return The handler for the specified extended operation, or 5125 * <CODE>null</CODE> if there is none. 5126 */ 5127 public static ExtendedOperationHandler getExtendedOperationHandler(String oid) 5128 { 5129 return directoryServer.extendedOperationHandlers.get(oid); 5130 } 5131 5132 /** 5133 * Registers the provided extended operation handler with the Directory 5134 * Server. 5135 * 5136 * @param oid The OID for the extended operation to register. 5137 * @param handler The extended operation handler to register with the 5138 * Directory Server. 5139 */ 5140 public static void registerSupportedExtension(String oid, 5141 ExtendedOperationHandler handler) 5142 { 5143 directoryServer.extendedOperationHandlers.put(toLowerCase(oid), handler); 5144 } 5145 5146 /** 5147 * Deregisters the provided extended operation handler with the Directory 5148 * Server. 5149 * 5150 * @param oid The OID for the extended operation to deregister. 5151 */ 5152 public static void deregisterSupportedExtension(String oid) 5153 { 5154 directoryServer.extendedOperationHandlers.remove(toLowerCase(oid)); 5155 } 5156 5157 /** 5158 * Retrieves the set of SASL mechanisms that are supported by the Directory 5159 * Server. 5160 * 5161 * @return The set of SASL mechanisms that are supported by the Directory 5162 * Server. 5163 */ 5164 public static ConcurrentMap<String, SASLMechanismHandler> 5165 getSupportedSASLMechanisms() 5166 { 5167 return directoryServer.saslMechanismHandlers; 5168 } 5169 5170 /** 5171 * Retrieves the handler for the specified SASL mechanism. 5172 * 5173 * @param name The name of the SASL mechanism to retrieve. 5174 * 5175 * @return The handler for the specified SASL mechanism, or <CODE>null</CODE> 5176 * if there is none. 5177 */ 5178 public static SASLMechanismHandler getSASLMechanismHandler(String name) 5179 { 5180 return directoryServer.saslMechanismHandlers.get(name); 5181 } 5182 5183 /** 5184 * Registers the provided SASL mechanism handler with the Directory Server. 5185 * 5186 * @param name The name of the SASL mechanism to be registered. 5187 * @param handler The SASL mechanism handler to register with the Directory 5188 * Server. 5189 */ 5190 public static void registerSASLMechanismHandler(String name, 5191 SASLMechanismHandler handler) 5192 { 5193 // FIXME -- Should we force this name to be lowercase? If so, then will 5194 // that cause the lower name to be used in the root DSE? 5195 directoryServer.saslMechanismHandlers.put(name, handler); 5196 } 5197 5198 /** 5199 * Deregisters the provided SASL mechanism handler with the Directory Server. 5200 * 5201 * @param name The name of the SASL mechanism to be deregistered. 5202 */ 5203 public static void deregisterSASLMechanismHandler(String name) 5204 { 5205 // FIXME -- Should we force this name to be lowercase? 5206 directoryServer.saslMechanismHandlers.remove(name); 5207 } 5208 5209 /** 5210 * Retrieves the supported LDAP versions for the Directory Server. 5211 * 5212 * @return The supported LDAP versions for the Directory Server. 5213 */ 5214 public static Set<Integer> getSupportedLDAPVersions() 5215 { 5216 return directoryServer.supportedLDAPVersions.keySet(); 5217 } 5218 5219 /** 5220 * Registers the provided LDAP protocol version as supported within the 5221 * Directory Server. 5222 * 5223 * @param supportedLDAPVersion The LDAP protocol version to register as 5224 * supported. 5225 * @param connectionHandler The connection handler that supports the 5226 * provided LDAP version. Note that multiple 5227 * connection handlers can provide support for 5228 * the same LDAP versions. 5229 */ 5230 public static synchronized void registerSupportedLDAPVersion( 5231 int supportedLDAPVersion, 5232 ConnectionHandler connectionHandler) 5233 { 5234 List<ConnectionHandler> handlers = directoryServer.supportedLDAPVersions.get(supportedLDAPVersion); 5235 if (handlers == null) 5236 { 5237 directoryServer.supportedLDAPVersions.put(supportedLDAPVersion, newLinkedList(connectionHandler)); 5238 } 5239 else if (!handlers.contains(connectionHandler)) 5240 { 5241 handlers.add(connectionHandler); 5242 } 5243 } 5244 5245 /** 5246 * Deregisters the provided LDAP protocol version as supported within the 5247 * Directory Server. 5248 * 5249 * @param supportedLDAPVersion The LDAP protocol version to deregister. 5250 * @param connectionHandler The connection handler that no longer 5251 * supports the provided LDAP version. 5252 */ 5253 public static synchronized void deregisterSupportedLDAPVersion( 5254 int supportedLDAPVersion, 5255 ConnectionHandler connectionHandler) 5256 { 5257 List<ConnectionHandler> handlers = 5258 directoryServer.supportedLDAPVersions.get(supportedLDAPVersion); 5259 if (handlers != null) 5260 { 5261 handlers.remove(connectionHandler); 5262 if (handlers.isEmpty()) 5263 { 5264 directoryServer.supportedLDAPVersions.remove(supportedLDAPVersion); 5265 } 5266 } 5267 } 5268 5269 /** 5270 * Retrieves the set of identity mappers defined in the Directory Server 5271 * configuration, as a mapping between the DN of the configuration entry and 5272 * the identity mapper. 5273 * 5274 * @return The set of identity mappers defined in the Directory Server 5275 * configuration. 5276 */ 5277 public static ConcurrentMap<DN, IdentityMapper> getIdentityMappers() 5278 { 5279 return directoryServer.identityMappers; 5280 } 5281 5282 /** 5283 * Retrieves the Directory Server identity mapper whose configuration resides 5284 * in the specified configuration entry. 5285 * 5286 * @param configEntryDN The DN of the configuration entry for the identity 5287 * mapper to retrieve. 5288 * 5289 * @return The requested identity mapper, or <CODE>null</CODE> if the 5290 * provided entry DN is not associated with an active identity 5291 * mapper. 5292 */ 5293 public static IdentityMapper getIdentityMapper(DN configEntryDN) 5294 { 5295 return directoryServer.identityMappers.get(configEntryDN); 5296 } 5297 5298 /** 5299 * Registers the provided identity mapper for use with the Directory Server. 5300 * 5301 * @param configEntryDN The DN of the configuration entry in which the 5302 * identity mapper definition resides. 5303 * @param identityMapper The identity mapper to be registered. 5304 */ 5305 public static void registerIdentityMapper(DN configEntryDN, 5306 IdentityMapper identityMapper) 5307 { 5308 directoryServer.identityMappers.put(configEntryDN, identityMapper); 5309 } 5310 5311 /** 5312 * Deregisters the provided identity mapper for use with the Directory Server. 5313 * 5314 * @param configEntryDN The DN of the configuration entry in which the 5315 * identity mapper definition resides. 5316 */ 5317 public static void deregisterIdentityMapper(DN configEntryDN) 5318 { 5319 directoryServer.identityMappers.remove(configEntryDN); 5320 } 5321 5322 /** 5323 * Retrieves the DN of the configuration entry for the identity mapper that 5324 * should be used in conjunction with proxied authorization V2 controls. 5325 * 5326 * @return The DN of the configuration entry for the identity mapper that 5327 * should be used in conjunction with proxied authorization V2 5328 * controls, or <CODE>null</CODE> if none is defined. 5329 */ 5330 public static DN getProxiedAuthorizationIdentityMapperDN() 5331 { 5332 return directoryServer.proxiedAuthorizationIdentityMapperDN; 5333 } 5334 5335 /** 5336 * Specifies the DN of the configuration entry for the identity mapper that 5337 * should be used in conjunction with proxied authorization V2 controls. 5338 * 5339 * @param proxiedAuthorizationIdentityMapperDN The DN of the configuration 5340 * entry for the identity mapper 5341 * that should be used in 5342 * conjunction with proxied 5343 * authorization V2 controls. 5344 */ 5345 public static void setProxiedAuthorizationIdentityMapperDN( 5346 DN proxiedAuthorizationIdentityMapperDN) 5347 { 5348 directoryServer.proxiedAuthorizationIdentityMapperDN = 5349 proxiedAuthorizationIdentityMapperDN; 5350 } 5351 5352 /** 5353 * Retrieves the identity mapper that should be used to resolve authorization 5354 * IDs contained in proxied authorization V2 controls. 5355 * 5356 * @return The identity mapper that should be used to resolve authorization 5357 * IDs contained in proxied authorization V2 controls, or 5358 * <CODE>null</CODE> if none is defined. 5359 */ 5360 public static IdentityMapper getProxiedAuthorizationIdentityMapper() 5361 { 5362 if (directoryServer.proxiedAuthorizationIdentityMapperDN == null) 5363 { 5364 return null; 5365 } 5366 5367 return directoryServer.identityMappers.get( 5368 directoryServer.proxiedAuthorizationIdentityMapperDN); 5369 } 5370 5371 /** 5372 * Retrieves the set of connection handlers configured in the Directory 5373 * Server. The returned list must not be altered. 5374 * 5375 * @return The set of connection handlers configured in the Directory Server. 5376 */ 5377 public static List<ConnectionHandler> getConnectionHandlers() 5378 { 5379 return directoryServer.connectionHandlers; 5380 } 5381 5382 /** 5383 * Registers the provided connection handler with the Directory Server. 5384 * 5385 * @param handler The connection handler to register with the Directory 5386 * Server. 5387 */ 5388 public static void registerConnectionHandler( 5389 ConnectionHandler<? extends ConnectionHandlerCfg> 5390 handler) 5391 { 5392 synchronized (directoryServer.connectionHandlers) 5393 { 5394 directoryServer.connectionHandlers.add(handler); 5395 5396 ConnectionHandlerMonitor monitor = new ConnectionHandlerMonitor(handler); 5397 monitor.initializeMonitorProvider(null); 5398 handler.setConnectionHandlerMonitor(monitor); 5399 registerMonitorProvider(monitor); 5400 } 5401 } 5402 5403 /** 5404 * Deregisters the provided connection handler with the Directory Server. 5405 * 5406 * @param handler The connection handler to deregister with the Directory 5407 * Server. 5408 */ 5409 public static void deregisterConnectionHandler(ConnectionHandler handler) 5410 { 5411 synchronized (directoryServer.connectionHandlers) 5412 { 5413 directoryServer.connectionHandlers.remove(handler); 5414 5415 ConnectionHandlerMonitor monitor = handler.getConnectionHandlerMonitor(); 5416 if (monitor != null) 5417 { 5418 deregisterMonitorProvider(monitor); 5419 monitor.finalizeMonitorProvider(); 5420 handler.setConnectionHandlerMonitor(null); 5421 } 5422 } 5423 } 5424 5425 /** 5426 * Starts the connection handlers defined in the Directory Server 5427 * Configuration. 5428 * 5429 * @throws ConfigException If there are more than one connection handlers 5430 * using the same host port or no connection handler 5431 * are enabled or we could not bind to any of the 5432 * listeners. 5433 */ 5434 private void startConnectionHandlers() throws ConfigException 5435 { 5436 Set<HostPort> usedListeners = new LinkedHashSet<>(); 5437 Set<LocalizableMessage> errorMessages = new LinkedHashSet<>(); 5438 // Check that the port specified in the connection handlers is available. 5439 for (ConnectionHandler<?> c : connectionHandlers) 5440 { 5441 for (HostPort listener : c.getListeners()) 5442 { 5443 if (!usedListeners.add(listener)) 5444 { 5445 // The port was already specified: this is a configuration error, 5446 // log a message. 5447 LocalizableMessage message = ERR_HOST_PORT_ALREADY_SPECIFIED.get(c.getConnectionHandlerName(), listener); 5448 logger.error(message); 5449 errorMessages.add(message); 5450 } 5451 } 5452 } 5453 5454 if (!errorMessages.isEmpty()) 5455 { 5456 throw new ConfigException(ERR_ERROR_STARTING_CONNECTION_HANDLERS.get()); 5457 } 5458 5459 // If there are no connection handlers log a message. 5460 if (connectionHandlers.isEmpty()) 5461 { 5462 logger.error(ERR_NOT_AVAILABLE_CONNECTION_HANDLERS); 5463 throw new ConfigException(ERR_ERROR_STARTING_CONNECTION_HANDLERS.get()); 5464 } 5465 5466 // At this point, we should be ready to go. 5467 for (ConnectionHandler handler : connectionHandlers) 5468 { 5469 handler.start(); 5470 } 5471 } 5472 5473 /** 5474 * Retrieves a reference to the Directory Server work queue. 5475 * 5476 * @return A reference to the Directory Server work queue. 5477 */ 5478 public static WorkQueue getWorkQueue() 5479 { 5480 return directoryServer.workQueue; 5481 } 5482 5483 /** 5484 * Runs all the necessary checks prior to adding an operation to the work 5485 * queue. It throws a DirectoryException if one of the check fails. 5486 * 5487 * @param operation 5488 * The operation to be added to the work queue. 5489 * @throws DirectoryException 5490 * If a check failed preventing the operation from being added to 5491 * the queue 5492 */ 5493 private static void checkCanEnqueueRequest(Operation operation) 5494 throws DirectoryException 5495 { 5496 ClientConnection clientConnection = operation.getClientConnection(); 5497 //Reject or accept the unauthenticated requests based on the configuration 5498 // settings. 5499 if ((directoryServer.rejectUnauthenticatedRequests || 5500 directoryServer.lockdownMode) && 5501 !clientConnection.getAuthenticationInfo().isAuthenticated()) 5502 { 5503 switch(operation.getOperationType()) 5504 { 5505 case ADD: 5506 case COMPARE: 5507 case DELETE: 5508 case SEARCH: 5509 case MODIFY: 5510 case MODIFY_DN: 5511 LocalizableMessage message = directoryServer.lockdownMode 5512 ? NOTE_REJECT_OPERATION_IN_LOCKDOWN_MODE.get() 5513 : ERR_REJECT_UNAUTHENTICATED_OPERATION.get(); 5514 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 5515 5516 case EXTENDED: 5517 ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation; 5518 String requestOID = extOp.getRequestOID(); 5519 if (!OID_START_TLS_REQUEST.equals(requestOID)) 5520 { 5521 message = directoryServer.lockdownMode 5522 ? NOTE_REJECT_OPERATION_IN_LOCKDOWN_MODE.get() 5523 : ERR_REJECT_UNAUTHENTICATED_OPERATION.get(); 5524 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 5525 } 5526 break; 5527 5528 } 5529 } 5530 5531 // If the associated user is required to change their password before 5532 // continuing, then make sure the associated operation is one that could 5533 // result in the password being changed. If not, then reject it. 5534 if (clientConnection.mustChangePassword()) 5535 { 5536 switch (operation.getOperationType()) 5537 { 5538 case ADD: 5539 case COMPARE: 5540 case DELETE: 5541 case MODIFY_DN: 5542 case SEARCH: 5543 // See if the request included the password policy request control. 5544 // If it did, then add a corresponding response control. 5545 for (Control c : operation.getRequestControls()) 5546 { 5547 if (OID_PASSWORD_POLICY_CONTROL.equals(c.getOID())) 5548 { 5549 operation.addResponseControl(new PasswordPolicyResponseControl( 5550 null, 0, PasswordPolicyErrorType.CHANGE_AFTER_RESET)); 5551 break; 5552 } 5553 } 5554 5555 DN user = clientConnection.getAuthenticationInfo() 5556 .getAuthorizationDN(); 5557 LocalizableMessage message = ERR_ENQUEUE_MUST_CHANGE_PASSWORD 5558 .get(user != null ? user : "anonymous"); 5559 throw new DirectoryException( 5560 ResultCode.CONSTRAINT_VIOLATION, message); 5561 5562 case EXTENDED: 5563 // We will only allow the password modify and StartTLS extended 5564 // operations. 5565 ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation; 5566 String requestOID = extOp.getRequestOID(); 5567 if (!OID_PASSWORD_MODIFY_REQUEST.equals(requestOID) 5568 && !OID_START_TLS_REQUEST.equals(requestOID)) 5569 { 5570 // See if the request included the password policy request control. 5571 // If it did, then add a corresponding response control. 5572 for (Control c : operation.getRequestControls()) 5573 { 5574 if (OID_PASSWORD_POLICY_CONTROL.equals(c.getOID())) 5575 { 5576 operation.addResponseControl(new PasswordPolicyResponseControl( 5577 null, 0, PasswordPolicyErrorType.CHANGE_AFTER_RESET)); 5578 break; 5579 } 5580 } 5581 5582 user = clientConnection.getAuthenticationInfo() 5583 .getAuthorizationDN(); 5584 message = ERR_ENQUEUE_MUST_CHANGE_PASSWORD 5585 .get(user != null ? user : "anonymous"); 5586 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, 5587 message); 5588 } 5589 5590 break; 5591 5592 // Bind, unbind, and abandon will always be allowed. 5593 5594 // Modify may or may not be allowed, but we'll leave that 5595 // determination up to the modify operation itself. 5596 } 5597 } 5598 } 5599 5600 /** 5601 * Adds the provided operation to the work queue so that it will be processed 5602 * by one of the worker threads. 5603 * 5604 * @param operation The operation to be added to the work queue. 5605 * 5606 * @throws DirectoryException If a problem prevents the operation from being 5607 * added to the queue (e.g., the queue is full). 5608 */ 5609 public static void enqueueRequest(Operation operation) 5610 throws DirectoryException 5611 { 5612 checkCanEnqueueRequest(operation); 5613 directoryServer.workQueue.submitOperation(operation); 5614 } 5615 5616 /** 5617 * Tries to add the provided operation to the work queue if not full so that 5618 * it will be processed by one of the worker threads. 5619 * 5620 * @param operation 5621 * The operation to be added to the work queue. 5622 * @return true if the operation could be enqueued, false otherwise 5623 * @throws DirectoryException 5624 * If a problem prevents the operation from being added to the queue 5625 * (e.g., the queue is full). 5626 */ 5627 public static boolean tryEnqueueRequest(Operation operation) 5628 throws DirectoryException 5629 { 5630 checkCanEnqueueRequest(operation); 5631 return directoryServer.workQueue.trySubmitOperation(operation); 5632 } 5633 5634 /** 5635 * Retrieves the set of synchronization providers that have been registered 5636 * with the Directory Server. 5637 * 5638 * @return The set of synchronization providers that have been registered 5639 * with the Directory Server. 5640 */ 5641 public static List<SynchronizationProvider<SynchronizationProviderCfg>> 5642 getSynchronizationProviders() 5643 { 5644 return directoryServer.synchronizationProviders; 5645 } 5646 5647 /** 5648 * Registers the provided synchronization provider with the Directory Server. 5649 * 5650 * @param provider The synchronization provider to register. 5651 */ 5652 public static void registerSynchronizationProvider( 5653 SynchronizationProvider<SynchronizationProviderCfg> provider) 5654 { 5655 directoryServer.synchronizationProviders.add(provider); 5656 5657 provider.completeSynchronizationProvider(); 5658 } 5659 5660 /** 5661 * Deregisters the provided synchronization provider with the Directory 5662 * Server. 5663 * 5664 * @param provider The synchronization provider to deregister. 5665 */ 5666 public static void deregisterSynchronizationProvider(SynchronizationProvider 5667 provider) 5668 { 5669 directoryServer.synchronizationProviders.remove(provider); 5670 } 5671 5672 /** 5673 * Retrieves a set containing the names of the allowed tasks that may be 5674 * invoked in the server. 5675 * 5676 * @return A set containing the names of the allowed tasks that may be 5677 * invoked in the server. 5678 */ 5679 public static Set<String> getAllowedTasks() 5680 { 5681 return directoryServer.allowedTasks; 5682 } 5683 5684 /** 5685 * Specifies the set of allowed tasks that may be invoked in the server. 5686 * 5687 * @param allowedTasks A set containing the names of the allowed tasks that 5688 * may be invoked in the server. 5689 */ 5690 public static void setAllowedTasks(Set<String> allowedTasks) 5691 { 5692 directoryServer.allowedTasks = allowedTasks; 5693 } 5694 5695 /** 5696 * Retrieves the set of privileges that have been disabled. 5697 * 5698 * @return The set of privileges that have been disabled. 5699 */ 5700 public static Set<Privilege> getDisabledPrivileges() 5701 { 5702 return directoryServer.disabledPrivileges; 5703 } 5704 5705 /** 5706 * Indicates whether the specified privilege is disabled. 5707 * 5708 * @param privilege The privilege for which to make the determination. 5709 * 5710 * @return {@code true} if the specified privilege is disabled, or 5711 * {@code false} if not. 5712 */ 5713 public static boolean isDisabled(Privilege privilege) 5714 { 5715 return directoryServer.disabledPrivileges.contains(privilege); 5716 } 5717 5718 /** 5719 * Specifies the set of privileges that should be disabled in the server. 5720 * 5721 * @param disabledPrivileges The set of privileges that should be disabled 5722 * in the server. 5723 */ 5724 public static void setDisabledPrivileges(Set<Privilege> disabledPrivileges) 5725 { 5726 directoryServer.disabledPrivileges = disabledPrivileges; 5727 } 5728 5729 /** 5730 * Indicates whether responses to failed bind operations should include a 5731 * message explaining the reason for the failure. 5732 * 5733 * @return {@code true} if bind responses should include error messages, or 5734 * {@code false} if not. 5735 */ 5736 public static boolean returnBindErrorMessages() 5737 { 5738 return directoryServer.returnBindErrorMessages; 5739 } 5740 5741 /** 5742 * Specifies whether responses to failed bind operations should include a 5743 * message explaining the reason for the failure. 5744 * 5745 * @param returnBindErrorMessages Specifies whether responses to failed bind 5746 * operations should include a message 5747 * explaining the reason for the failure. 5748 */ 5749 public static void setReturnBindErrorMessages(boolean returnBindErrorMessages) 5750 { 5751 directoryServer.returnBindErrorMessages = returnBindErrorMessages; 5752 } 5753 5754 /** 5755 * Retrieves the maximum length of time in milliseconds that client 5756 * connections should be allowed to remain idle without being disconnected. 5757 * 5758 * @return The maximum length of time in milliseconds that client connections 5759 * should be allowed to remain idle without being disconnected. 5760 */ 5761 public static long getIdleTimeLimit() 5762 { 5763 return directoryServer.idleTimeLimit; 5764 } 5765 5766 /** 5767 * Specifies the maximum length of time in milliseconds that client 5768 * connections should be allowed to remain idle without being disconnected. 5769 * 5770 * @param idleTimeLimit The maximum length of time in milliseconds that 5771 * client connections should be allowed to remain idle 5772 * without being disconnected. 5773 */ 5774 public static void setIdleTimeLimit(long idleTimeLimit) 5775 { 5776 directoryServer.idleTimeLimit = idleTimeLimit; 5777 } 5778 5779 /** 5780 * Indicates whether the Directory Server should save a copy of its 5781 * configuration whenever it is started successfully. 5782 * 5783 * @return {@code true} if the server should save a copy of its configuration 5784 * whenever it is started successfully, or {@code false} if not. 5785 */ 5786 public static boolean saveConfigOnSuccessfulStartup() 5787 { 5788 return directoryServer.saveConfigOnSuccessfulStartup; 5789 } 5790 5791 /** 5792 * Specifies whether the Directory Server should save a copy of its 5793 * configuration whenever it is started successfully. 5794 * 5795 * @param saveConfigOnSuccessfulStartup Specifies whether the server should 5796 * save a copy of its configuration 5797 * whenever it is started successfully. 5798 */ 5799 public static void setSaveConfigOnSuccessfulStartup( 5800 boolean saveConfigOnSuccessfulStartup) 5801 { 5802 directoryServer.saveConfigOnSuccessfulStartup = 5803 saveConfigOnSuccessfulStartup; 5804 } 5805 5806 /** 5807 * Registers the provided backup task listener with the Directory Server. 5808 * 5809 * @param listener The backup task listener to register with the Directory 5810 * Server. 5811 */ 5812 public static void registerBackupTaskListener(BackupTaskListener listener) 5813 { 5814 directoryServer.backupTaskListeners.addIfAbsent(listener); 5815 } 5816 5817 /** 5818 * Deregisters the provided backup task listener with the Directory Server. 5819 * 5820 * @param listener The backup task listener to deregister with the Directory 5821 * Server. 5822 */ 5823 public static void deregisterBackupTaskListener(BackupTaskListener listener) 5824 { 5825 directoryServer.backupTaskListeners.remove(listener); 5826 } 5827 5828 /** 5829 * Notifies the registered backup task listeners that the server will be 5830 * beginning a backup task with the provided information. 5831 * 5832 * @param backend The backend in which the backup is to be performed. 5833 * @param config The configuration for the backup to be performed. 5834 */ 5835 public static void notifyBackupBeginning(Backend<?> backend, BackupConfig config) 5836 { 5837 for (BackupTaskListener listener : directoryServer.backupTaskListeners) 5838 { 5839 try 5840 { 5841 listener.processBackupBegin(backend, config); 5842 } 5843 catch (Exception e) 5844 { 5845 logger.traceException(e); 5846 } 5847 } 5848 } 5849 5850 /** 5851 * Notifies the registered backup task listeners that the server has completed 5852 * processing on a backup task with the provided information. 5853 * 5854 * @param backend The backend in which the backup was performed. 5855 * @param config The configuration for the backup that was performed. 5856 * @param successful Indicates whether the backup completed successfully. 5857 */ 5858 public static void notifyBackupEnded(Backend<?> backend, BackupConfig config, boolean successful) 5859 { 5860 for (BackupTaskListener listener : directoryServer.backupTaskListeners) 5861 { 5862 try 5863 { 5864 listener.processBackupEnd(backend, config, successful); 5865 } 5866 catch (Exception e) 5867 { 5868 logger.traceException(e); 5869 } 5870 } 5871 } 5872 5873 /** 5874 * Registers the provided restore task listener with the Directory Server. 5875 * 5876 * @param listener The restore task listener to register with the Directory 5877 * Server. 5878 */ 5879 public static void registerRestoreTaskListener(RestoreTaskListener listener) 5880 { 5881 directoryServer.restoreTaskListeners.addIfAbsent(listener); 5882 } 5883 5884 /** 5885 * Deregisters the provided restore task listener with the Directory Server. 5886 * 5887 * @param listener The restore task listener to deregister with the 5888 * Directory Server. 5889 */ 5890 public static void deregisterRestoreTaskListener(RestoreTaskListener listener) 5891 { 5892 directoryServer.restoreTaskListeners.remove(listener); 5893 } 5894 5895 /** 5896 * Notifies the registered restore task listeners that the server will be 5897 * beginning a restore task with the provided information. 5898 * 5899 * @param backend The backend in which the restore is to be performed. 5900 * @param config The configuration for the restore to be performed. 5901 */ 5902 public static void notifyRestoreBeginning(Backend<?> backend, RestoreConfig config) 5903 { 5904 for (RestoreTaskListener listener : directoryServer.restoreTaskListeners) 5905 { 5906 try 5907 { 5908 listener.processRestoreBegin(backend, config); 5909 } 5910 catch (Exception e) 5911 { 5912 logger.traceException(e); 5913 } 5914 } 5915 } 5916 5917 /** 5918 * Notifies the registered restore task listeners that the server has 5919 * completed processing on a restore task with the provided information. 5920 * 5921 * @param backend The backend in which the restore was performed. 5922 * @param config The configuration for the restore that was performed. 5923 * @param successful Indicates whether the restore completed successfully. 5924 */ 5925 public static void notifyRestoreEnded(Backend<?> backend, RestoreConfig config, boolean successful) 5926 { 5927 for (RestoreTaskListener listener : directoryServer.restoreTaskListeners) 5928 { 5929 try 5930 { 5931 listener.processRestoreEnd(backend, config, successful); 5932 } 5933 catch (Exception e) 5934 { 5935 logger.traceException(e); 5936 } 5937 } 5938 } 5939 5940 /** 5941 * Registers the provided LDIF export task listener with the Directory Server. 5942 * 5943 * @param listener The export task listener to register with the Directory 5944 * Server. 5945 */ 5946 public static void registerExportTaskListener(ExportTaskListener listener) 5947 { 5948 directoryServer.exportTaskListeners.addIfAbsent(listener); 5949 } 5950 5951 /** 5952 * Deregisters the provided LDIF export task listener with the Directory 5953 * Server. 5954 * 5955 * @param listener The export task listener to deregister with the Directory 5956 * Server. 5957 */ 5958 public static void deregisterExportTaskListener(ExportTaskListener listener) 5959 { 5960 directoryServer.exportTaskListeners.remove(listener); 5961 } 5962 5963 /** 5964 * Notifies the registered LDIF export task listeners that the server will be 5965 * beginning an export task with the provided information. 5966 * 5967 * @param backend The backend in which the export is to be performed. 5968 * @param config The configuration for the export to be performed. 5969 */ 5970 public static void notifyExportBeginning(Backend<?> backend, LDIFExportConfig config) 5971 { 5972 for (ExportTaskListener listener : directoryServer.exportTaskListeners) 5973 { 5974 try 5975 { 5976 listener.processExportBegin(backend, config); 5977 } 5978 catch (Exception e) 5979 { 5980 logger.traceException(e); 5981 } 5982 } 5983 } 5984 5985 /** 5986 * Notifies the registered LDIF export task listeners that the server has 5987 * completed processing on an export task with the provided information. 5988 * 5989 * @param backend The backend in which the export was performed. 5990 * @param config The configuration for the export that was performed. 5991 * @param successful Indicates whether the export completed successfully. 5992 */ 5993 public static void notifyExportEnded(Backend<?> backend, LDIFExportConfig config, boolean successful) 5994 { 5995 for (ExportTaskListener listener : directoryServer.exportTaskListeners) 5996 { 5997 try 5998 { 5999 listener.processExportEnd(backend, config, successful); 6000 } 6001 catch (Exception e) 6002 { 6003 logger.traceException(e); 6004 } 6005 } 6006 } 6007 6008 /** 6009 * Registers the provided LDIF import task listener with the Directory Server. 6010 * 6011 * @param listener The import task listener to register with the Directory 6012 * Server. 6013 */ 6014 public static void registerImportTaskListener(ImportTaskListener listener) 6015 { 6016 directoryServer.importTaskListeners.addIfAbsent(listener); 6017 } 6018 6019 /** 6020 * Deregisters the provided LDIF import task listener with the Directory 6021 * Server. 6022 * 6023 * @param listener The import task listener to deregister with the Directory 6024 * Server. 6025 */ 6026 public static void deregisterImportTaskListener(ImportTaskListener listener) 6027 { 6028 directoryServer.importTaskListeners.remove(listener); 6029 } 6030 6031 /** 6032 * Notifies the registered LDIF import task listeners that the server will be 6033 * beginning an import task with the provided information. 6034 * 6035 * @param backend The backend in which the import is to be performed. 6036 * @param config The configuration for the import to be performed. 6037 */ 6038 public static void notifyImportBeginning(Backend<?> backend, LDIFImportConfig config) 6039 { 6040 for (ImportTaskListener listener : directoryServer.importTaskListeners) 6041 { 6042 try 6043 { 6044 listener.processImportBegin(backend, config); 6045 } 6046 catch (Exception e) 6047 { 6048 logger.traceException(e); 6049 } 6050 } 6051 } 6052 6053 /** 6054 * Notifies the registered LDIF import task listeners that the server has 6055 * completed processing on an import task with the provided information. 6056 * 6057 * @param backend The backend in which the import was performed. 6058 * @param config The configuration for the import that was performed. 6059 * @param successful Indicates whether the import completed successfully. 6060 */ 6061 public static void notifyImportEnded(Backend<?> backend, LDIFImportConfig config, boolean successful) 6062 { 6063 for (ImportTaskListener listener : directoryServer.importTaskListeners) 6064 { 6065 try 6066 { 6067 listener.processImportEnd(backend, config, successful); 6068 } 6069 catch (Exception e) 6070 { 6071 logger.traceException(e); 6072 } 6073 } 6074 } 6075 6076 /** 6077 * Registers the provided initialization completed listener with the 6078 * Directory Server so that it will be notified when the server 6079 * initialization completes. 6080 * 6081 * @param listener The initialization competed listener to register with 6082 * the Directory Server. 6083 */ 6084 public static void registerInitializationCompletedListener( 6085 InitializationCompletedListener listener) { 6086 directoryServer.initializationCompletedListeners.add(listener); 6087 } 6088 6089 /** 6090 * Deregisters the provided initialization completed listener with the 6091 * Directory Server. 6092 * 6093 * @param listener The initialization completed listener to deregister with 6094 * the Directory Server. 6095 */ 6096 public static void deregisterInitializationCompletedListener( 6097 InitializationCompletedListener listener) { 6098 directoryServer.initializationCompletedListeners.remove(listener); 6099 } 6100 6101 /** 6102 * Registers the provided shutdown listener with the Directory Server so that 6103 * it will be notified when the server shuts down. 6104 * 6105 * @param listener The shutdown listener to register with the Directory 6106 * Server. 6107 */ 6108 public static void registerShutdownListener(ServerShutdownListener listener) 6109 { 6110 directoryServer.shutdownListeners.add(listener); 6111 } 6112 6113 /** 6114 * Deregisters the provided shutdown listener with the Directory Server. 6115 * 6116 * @param listener The shutdown listener to deregister with the Directory 6117 * Server. 6118 */ 6119 public static void deregisterShutdownListener(ServerShutdownListener listener) 6120 { 6121 directoryServer.shutdownListeners.remove(listener); 6122 } 6123 6124 /** 6125 * Initiates the Directory Server shutdown process. Note that once this has 6126 * started, it should not be interrupted. 6127 * 6128 * @param className The fully-qualified name of the Java class that 6129 * initiated the shutdown. 6130 * @param reason The human-readable reason that the directory server is 6131 * shutting down. 6132 */ 6133 public static void shutDown(String className, LocalizableMessage reason) 6134 { 6135 synchronized (directoryServer) 6136 { 6137 if (directoryServer.shuttingDown) 6138 { 6139 // We already know that the server is shutting down, so we don't need to 6140 // do anything. 6141 return; 6142 } 6143 6144 directoryServer.shuttingDown = true; 6145 } 6146 6147 // Send an alert notification that the server is shutting down. 6148 sendAlertNotification(directoryServer, ALERT_TYPE_SERVER_SHUTDOWN, 6149 NOTE_SERVER_SHUTDOWN.get(className, reason)); 6150 6151 // Create a shutdown monitor that will watch the rest of the shutdown 6152 // process to ensure that everything goes smoothly. 6153 ServerShutdownMonitor shutdownMonitor = new ServerShutdownMonitor(); 6154 shutdownMonitor.start(); 6155 6156 // Shut down the connection handlers. 6157 for (ConnectionHandler handler : directoryServer.connectionHandlers) 6158 { 6159 try 6160 { 6161 handler.finalizeConnectionHandler( 6162 INFO_CONNHANDLER_CLOSED_BY_SHUTDOWN.get()); 6163 } 6164 catch (Exception e) 6165 { 6166 logger.traceException(e); 6167 } 6168 } 6169 directoryServer.connectionHandlers.clear(); 6170 6171 if (directoryServer.workQueue != null) 6172 { 6173 directoryServer.workQueue.finalizeWorkQueue(reason); 6174 directoryServer.workQueue.waitUntilIdle(ServerShutdownMonitor.WAIT_TIME); 6175 } 6176 6177 // shutdown replication 6178 for (SynchronizationProvider provider : 6179 directoryServer.synchronizationProviders) 6180 { 6181 provider.finalizeSynchronizationProvider(); 6182 } 6183 6184 // Call the shutdown plugins, and then finalize all the plugins defined in 6185 // the server. 6186 if (directoryServer.pluginConfigManager != null) 6187 { 6188 directoryServer.pluginConfigManager.invokeShutdownPlugins(reason); 6189 directoryServer.pluginConfigManager.finalizePlugins(); 6190 } 6191 6192 // Deregister the shutdown hook. 6193 if (directoryServer.shutdownHook != null) 6194 { 6195 try 6196 { 6197 Runtime.getRuntime().removeShutdownHook(directoryServer.shutdownHook); 6198 } 6199 catch (Exception e) {} 6200 } 6201 6202 // Notify all the shutdown listeners. 6203 for (ServerShutdownListener shutdownListener : 6204 directoryServer.shutdownListeners) 6205 { 6206 try 6207 { 6208 shutdownListener.processServerShutdown(reason); 6209 } 6210 catch (Exception e) 6211 { 6212 logger.traceException(e); 6213 } 6214 } 6215 6216 // Shut down all of the alert handlers. 6217 for (AlertHandler alertHandler : directoryServer.alertHandlers) 6218 { 6219 alertHandler.finalizeAlertHandler(); 6220 } 6221 6222 // Deregister all of the JMX MBeans. 6223 if (directoryServer.mBeanServer != null) 6224 { 6225 Set mBeanSet = directoryServer.mBeanServer.queryMBeans(null, null); 6226 for (Object o : mBeanSet) 6227 { 6228 if (o instanceof DirectoryServerMBean) 6229 { 6230 try 6231 { 6232 DirectoryServerMBean mBean = (DirectoryServerMBean) o; 6233 directoryServer.mBeanServer.unregisterMBean(mBean.getObjectName()); 6234 } 6235 catch (Exception e) 6236 { 6237 logger.traceException(e); 6238 } 6239 } 6240 } 6241 } 6242 6243 // Finalize all of the SASL mechanism handlers. 6244 for (SASLMechanismHandler handler : 6245 directoryServer.saslMechanismHandlers.values()) 6246 { 6247 try 6248 { 6249 handler.finalizeSASLMechanismHandler(); 6250 } 6251 catch (Exception e) 6252 { 6253 logger.traceException(e); 6254 } 6255 } 6256 6257 // Finalize all of the extended operation handlers. 6258 for (ExtendedOperationHandler handler : 6259 directoryServer.extendedOperationHandlers.values()) 6260 { 6261 try 6262 { 6263 handler.finalizeExtendedOperationHandler(); 6264 } 6265 catch (Exception e) 6266 { 6267 logger.traceException(e); 6268 } 6269 } 6270 6271 // Finalize the password policy map. 6272 for (DN configEntryDN : directoryServer.authenticationPolicies.keySet()) 6273 { 6274 DirectoryServer.deregisterAuthenticationPolicy(configEntryDN); 6275 } 6276 6277 // Finalize password policies and their config manager. 6278 if (directoryServer.authenticationPolicyConfigManager != null) 6279 { 6280 directoryServer.authenticationPolicyConfigManager 6281 .finalizeAuthenticationPolicies(); 6282 } 6283 6284 // Finalize the access control handler 6285 AccessControlHandler accessControlHandler = 6286 AccessControlConfigManager.getInstance().getAccessControlHandler(); 6287 if (accessControlHandler != null) 6288 { 6289 accessControlHandler.finalizeAccessControlHandler(); 6290 } 6291 6292 // Perform any necessary cleanup work for the group manager. 6293 if (directoryServer.groupManager != null) 6294 { 6295 directoryServer.groupManager.finalizeGroupManager(); 6296 } 6297 6298 // Finalize the subentry manager. 6299 if (directoryServer.subentryManager != null) 6300 { 6301 directoryServer.subentryManager.finalizeSubentryManager(); 6302 } 6303 6304 // Shut down all the other components that may need special handling. 6305 // NYI 6306 6307 // Shut down the monitor providers. 6308 for (MonitorProvider monitor : directoryServer.monitorProviders.values()) 6309 { 6310 try 6311 { 6312 monitor.finalizeMonitorProvider(); 6313 } 6314 catch (Exception e) 6315 { 6316 logger.traceException(e); 6317 } 6318 } 6319 6320 // Shut down the backends. 6321 for (Backend<?> backend : directoryServer.backends.values()) 6322 { 6323 try 6324 { 6325 // Deregister all the local backend workflow elements that have been 6326 // registered with the server. 6327 LocalBackendWorkflowElement.removeAll(); 6328 6329 for (BackendInitializationListener listener : 6330 directoryServer.backendInitializationListeners) 6331 { 6332 listener.performBackendFinalizationProcessing(backend); 6333 } 6334 6335 backend.finalizeBackend(); 6336 6337 // Remove the shared lock for this backend. 6338 try 6339 { 6340 String lockFile = LockFileManager.getBackendLockFileName(backend); 6341 StringBuilder failureReason = new StringBuilder(); 6342 if (! LockFileManager.releaseLock(lockFile, failureReason)) 6343 { 6344 logger.warn(WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK, backend.getBackendID(), failureReason); 6345 // FIXME -- Do we need to send an admin alert? 6346 } 6347 } 6348 catch (Exception e2) 6349 { 6350 logger.traceException(e2); 6351 6352 logger.warn(WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK, 6353 backend.getBackendID(), stackTraceToSingleLineString(e2)); 6354 // FIXME -- Do we need to send an admin alert? 6355 } 6356 } 6357 catch (Exception e) 6358 { 6359 logger.traceException(e); 6360 } 6361 } 6362 6363 // Finalize the entry cache. 6364 EntryCache ec = DirectoryServer.getEntryCache(); 6365 if (ec != null) 6366 { 6367 ec.finalizeEntryCache(); 6368 } 6369 6370 // Release exclusive lock held on server.lock file 6371 try { 6372 String serverLockFileName = LockFileManager.getServerLockFileName(); 6373 StringBuilder failureReason = new StringBuilder(); 6374 if (!LockFileManager.releaseLock(serverLockFileName, failureReason)) { 6375 logger.info(NOTE_SERVER_SHUTDOWN, className, failureReason); 6376 } 6377 serverLocked = false; 6378 } catch (Exception e) { 6379 logger.traceException(e); 6380 } 6381 6382 // Force a new InternalClientConnection to be created on restart. 6383 InternalConnectionHandler.clearRootClientConnectionAtShutdown(); 6384 6385 // Log a final message indicating that the server is stopped (which should 6386 // be true for all practical purposes), and then shut down all the error 6387 // loggers. 6388 logger.info(NOTE_SERVER_STOPPED); 6389 6390 AccessLogger.getInstance().removeAllLogPublishers(); 6391 ErrorLogger.getInstance().removeAllLogPublishers(); 6392 DebugLogger.getInstance().removeAllLogPublishers(); 6393 6394 // Now that the loggers are disabled we can shutdown the timer. 6395 TimeThread.stop(); 6396 6397 // Just in case there's something that isn't shut down properly, wait for 6398 // the monitor to give the OK to stop. 6399 shutdownMonitor.waitForMonitor(); 6400 6401 // At this point, the server is no longer running. We should destroy the 6402 // handle to the previous instance, but we will want to get a new instance 6403 // in case the server is to be started again later in the same JVM. Before 6404 // doing that, destroy the previous instance. 6405 DirectoryEnvironmentConfig envConfig = directoryServer.environmentConfig; 6406 directoryServer.destroy(); 6407 directoryServer = getNewInstance(envConfig); 6408 } 6409 6410 /** 6411 * Destroy key structures in the current Directory Server instance in a manner 6412 * that can help detect any inappropriate cached references to server 6413 * components. 6414 */ 6415 private void destroy() 6416 { 6417 checkSchema = true; 6418 isBootstrapped = false; 6419 isRunning = false; 6420 lockdownMode = true; 6421 rejectUnauthenticatedRequests = true; 6422 shuttingDown = true; 6423 6424 configClass = null; 6425 configFile = null; 6426 configHandler = null; 6427 coreConfigManager = null; 6428 compressedSchema = null; 6429 cryptoManager = null; 6430 entryCache = null; 6431 environmentConfig = null; 6432 objectClassAttributeType = null; 6433 schemaDN = null; 6434 shutdownHook = null; 6435 workQueue = null; 6436 6437 if (baseDnRegistry != null) 6438 { 6439 baseDnRegistry.clear(); 6440 baseDnRegistry = null; 6441 } 6442 6443 if (backends != null) 6444 { 6445 backends.clear(); 6446 backends = null; 6447 } 6448 6449 if (schema != null) 6450 { 6451 schema.destroy(); 6452 schema = null; 6453 } 6454 } 6455 6456 /** 6457 * Causes the Directory Server to perform an in-core restart. This will 6458 * cause virtually all components of the Directory Server to shut down, and 6459 * once that has completed it will be restarted. 6460 * 6461 * @param className The fully-qualified name of the Java class that 6462 * initiated the shutdown. 6463 * @param reason The human-readable reason that the directory server is 6464 * shutting down. 6465 */ 6466 public static void restart(String className, LocalizableMessage reason) 6467 { 6468 restart(className, reason, directoryServer.environmentConfig); 6469 } 6470 6471 /** 6472 * Causes the Directory Server to perform an in-core restart. This will 6473 * cause virtually all components of the Directory Server to shut down, and 6474 * once that has completed it will be restarted. 6475 * 6476 * @param className The fully-qualified name of the Java class that 6477 * initiated the shutdown. 6478 * @param reason The human-readable reason that the directory server is 6479 * shutting down. 6480 * @param config The environment configuration to use for the server. 6481 */ 6482 public static void restart(String className, LocalizableMessage reason, 6483 DirectoryEnvironmentConfig config) 6484 { 6485 try 6486 { 6487 shutDown(className, reason); 6488 reinitialize(config); 6489 directoryServer.startServer(); 6490 } 6491 catch (Exception e) 6492 { 6493 System.err.println("ERROR: Unable to perform an in-core restart:"); 6494 e.printStackTrace(); 6495 System.err.println("Halting the JVM so that it must be manually " + 6496 "restarted."); 6497 6498 Runtime.getRuntime().halt(1); 6499 } 6500 } 6501 6502 /** 6503 * Reinitializes the server following a shutdown, preparing it for a call to 6504 * {@code startServer}. 6505 * 6506 * @return The new Directory Server instance created during the 6507 * re-initialization process. 6508 * 6509 * @throws InitializationException If a problem occurs while trying to 6510 * initialize the config handler or 6511 * bootstrap that server. 6512 */ 6513 public static DirectoryServer reinitialize() 6514 throws InitializationException 6515 { 6516 return reinitialize(directoryServer.environmentConfig); 6517 } 6518 6519 /** 6520 * Reinitializes the server following a shutdown, preparing it for a call to 6521 * {@code startServer}. 6522 * 6523 * @param config The environment configuration for the Directory Server. 6524 * 6525 * @return The new Directory Server instance created during the 6526 * re-initialization process. 6527 * 6528 * @throws InitializationException If a problem occurs while trying to 6529 * initialize the config handler or 6530 * bootstrap that server. 6531 */ 6532 public static DirectoryServer reinitialize(DirectoryEnvironmentConfig config) 6533 throws InitializationException 6534 { 6535 // Ensure that the timer thread has started. 6536 TimeThread.start(); 6537 6538 getNewInstance(config); 6539 directoryServer.bootstrapServer(); 6540 directoryServer.initializeConfiguration(); 6541 return directoryServer; 6542 } 6543 6544 /** 6545 * Retrieves the maximum number of concurrent client connections that may be 6546 * established. 6547 * 6548 * @return The maximum number of concurrent client connections that may be 6549 * established, or -1 if there is no limit. 6550 */ 6551 public static long getMaxAllowedConnections() 6552 { 6553 return directoryServer.maxAllowedConnections; 6554 } 6555 6556 /** 6557 * Specifies the maximum number of concurrent client connections that may be 6558 * established. A value that is less than or equal to zero will indicate that 6559 * no limit should be enforced. 6560 * 6561 * @param maxAllowedConnections The maximum number of concurrent client 6562 * connections that may be established. 6563 */ 6564 public static void setMaxAllowedConnections(long maxAllowedConnections) 6565 { 6566 if (maxAllowedConnections > 0) 6567 { 6568 directoryServer.maxAllowedConnections = maxAllowedConnections; 6569 } 6570 else 6571 { 6572 directoryServer.maxAllowedConnections = -1; 6573 } 6574 } 6575 6576 /** 6577 * Indicates that a new connection has been accepted and increments the 6578 * associated counters. 6579 * 6580 * @param clientConnection The client connection that has been established. 6581 * 6582 * @return The connection ID that should be used for this connection, or -1 6583 * if the connection has been rejected for some reason (e.g., the 6584 * maximum number of concurrent connections have already been 6585 * established). 6586 */ 6587 public static long newConnectionAccepted(ClientConnection clientConnection) 6588 { 6589 synchronized (directoryServer.establishedConnections) 6590 { 6591 if (directoryServer.lockdownMode) 6592 { 6593 InetAddress remoteAddress = clientConnection.getRemoteAddress(); 6594 if (remoteAddress != null && !remoteAddress.isLoopbackAddress()) 6595 { 6596 return -1; 6597 } 6598 } 6599 6600 final long maxAllowed = directoryServer.maxAllowedConnections; 6601 if (0 < maxAllowed && maxAllowed <= directoryServer.currentConnections) 6602 { 6603 return -1; 6604 } 6605 6606 directoryServer.establishedConnections.add(clientConnection); 6607 directoryServer.currentConnections++; 6608 6609 if (directoryServer.currentConnections > directoryServer.maxConnections) 6610 { 6611 directoryServer.maxConnections = directoryServer.currentConnections; 6612 } 6613 6614 return directoryServer.totalConnections++; 6615 } 6616 } 6617 6618 /** 6619 * Indicates that the specified client connection has been closed. 6620 * 6621 * @param clientConnection The client connection that has been closed. 6622 */ 6623 public static void connectionClosed(ClientConnection clientConnection) 6624 { 6625 synchronized (directoryServer.establishedConnections) 6626 { 6627 directoryServer.establishedConnections.remove(clientConnection); 6628 directoryServer.currentConnections--; 6629 } 6630 } 6631 6632 /** 6633 * Retrieves the number of client connections that are currently established. 6634 * 6635 * @return The number of client connections that are currently established. 6636 */ 6637 public static long getCurrentConnections() 6638 { 6639 return directoryServer.currentConnections; 6640 } 6641 6642 /** 6643 * Retrieves the maximum number of client connections that have been 6644 * established concurrently. 6645 * 6646 * @return The maximum number of client connections that have been 6647 * established concurrently. 6648 */ 6649 public static long getMaxConnections() 6650 { 6651 return directoryServer.maxConnections; 6652 } 6653 6654 /** 6655 * Retrieves the total number of client connections that have been established 6656 * since the Directory Server started. 6657 * 6658 * @return The total number of client connections that have been established 6659 * since the Directory Server started. 6660 */ 6661 public static long getTotalConnections() 6662 { 6663 return directoryServer.totalConnections; 6664 } 6665 6666 /** 6667 * Retrieves the full version string for the Directory Server. 6668 * 6669 * @return The full version string for the Directory Server. 6670 */ 6671 public static String getVersionString() 6672 { 6673 return FULL_VERSION_STRING; 6674 } 6675 6676 /** 6677 * Prints out the version string for the Directory Server. 6678 * 6679 * 6680 * @param outputStream The output stream to which the version information 6681 * should be written. 6682 * 6683 * @throws IOException If a problem occurs while attempting to write the 6684 * version information to the provided output stream. 6685 */ 6686 public static void printVersion(OutputStream outputStream) 6687 throws IOException 6688 { 6689 outputStream.write(PRINTABLE_VERSION_STRING.getBytes()); 6690 6691 // Print extensions' extra information 6692 String extensionInformation = 6693 ClassLoaderProvider.getInstance().printExtensionInformation(); 6694 if ( extensionInformation != null ) { 6695 outputStream.write(extensionInformation.getBytes()); 6696 } 6697 } 6698 6699 /** 6700 * Retrieves the default maximum number of entries that should be returned for 6701 * a search. 6702 * 6703 * @return The default maximum number of entries that should be returned for 6704 * a search. 6705 */ 6706 public static int getSizeLimit() 6707 { 6708 return directoryServer.sizeLimit; 6709 } 6710 6711 /** 6712 * Specifies the default maximum number of entries that should be returned for 6713 * a search. 6714 * 6715 * @param sizeLimit The default maximum number of entries that should be 6716 * returned for a search. 6717 */ 6718 public static void setSizeLimit(int sizeLimit) 6719 { 6720 directoryServer.sizeLimit = sizeLimit; 6721 } 6722 6723 /** 6724 * Retrieves the default maximum number of entries that should checked for 6725 * matches during a search. 6726 * 6727 * @return The default maximum number of entries that should checked for 6728 * matches during a search. 6729 */ 6730 public static int getLookthroughLimit() 6731 { 6732 return directoryServer.lookthroughLimit; 6733 } 6734 6735 /** 6736 * Specifies the default maximum number of entries that should be checked for 6737 * matches during a search. 6738 * 6739 * @param lookthroughLimit The default maximum number of entries that should 6740 * be check for matches during a search. 6741 */ 6742 public static void setLookthroughLimit(int lookthroughLimit) 6743 { 6744 directoryServer.lookthroughLimit = lookthroughLimit; 6745 } 6746 6747 /** 6748 * Specifies the maximum number of simultaneous persistent 6749 * searches that are allowed. 6750 * 6751 * @param maxPSearches The maximum number of simultaneous persistent 6752 * searches that are allowed. 6753 */ 6754 public static void setMaxPersistentSearchLimit(int maxPSearches) 6755 { 6756 directoryServer.maxPSearches = maxPSearches; 6757 } 6758 6759 /** 6760 * Registers a new persistent search by increasing the count 6761 * of active persistent searches. After receiving a persistent 6762 * search request, a Local or Remote WFE must call this method to 6763 * let the core server manage the count of concurrent persistent 6764 * searches. 6765 */ 6766 public static void registerPersistentSearch() 6767 { 6768 directoryServer.activePSearches.incrementAndGet(); 6769 } 6770 6771 /** 6772 * Deregisters a canceled persistent search. After a persistent 6773 * search is canceled, the handler must call this method to let 6774 * the core server manage the count of concurrent persistent 6775 * searches. 6776 */ 6777 public static void deregisterPersistentSearch() 6778 { 6779 directoryServer.activePSearches.decrementAndGet(); 6780 } 6781 6782 /** 6783 * Indicates whether a new persistent search is allowed. 6784 * 6785 * @return <CODE>true</CODE>if a new persistent search is allowed 6786 * or <CODE>false</CODE>f if not. 6787 */ 6788 public static boolean allowNewPersistentSearch() 6789 { 6790 //-1 indicates that there is no limit. 6791 return directoryServer.maxPSearches == -1 6792 || directoryServer.activePSearches.get() < directoryServer.maxPSearches; 6793 } 6794 6795 /** 6796 * Retrieves the default maximum length of time in seconds that should be 6797 * allowed when processing a search. 6798 * 6799 * @return The default maximum length of time in seconds that should be 6800 * allowed when processing a search. 6801 */ 6802 public static int getTimeLimit() 6803 { 6804 return directoryServer.timeLimit; 6805 } 6806 6807 /** 6808 * Specifies the default maximum length of time in seconds that should be 6809 * allowed when processing a search. 6810 * 6811 * @param timeLimit The default maximum length of time in seconds that 6812 * should be allowed when processing a search. 6813 */ 6814 public static void setTimeLimit(int timeLimit) 6815 { 6816 directoryServer.timeLimit = timeLimit; 6817 } 6818 6819 /** 6820 * Specifies whether to collect nanosecond resolution processing times for 6821 * operations. 6822 * 6823 * @param useNanoTime <code>true</code> if nanosecond resolution times 6824 * should be collected or <code>false</code> to 6825 * only collect in millisecond resolution. 6826 */ 6827 public static void setUseNanoTime(boolean useNanoTime) 6828 { 6829 directoryServer.useNanoTime = useNanoTime; 6830 } 6831 6832 /** 6833 * Retrieves whether operation processing times should be collected with 6834 * nanosecond resolution. 6835 * 6836 * @return <code>true</code> if nanosecond resolution times are collected 6837 * or <code>false</code> if only millisecond resolution times are 6838 * being collected. 6839 */ 6840 public static boolean getUseNanoTime() 6841 { 6842 return directoryServer.useNanoTime; 6843 } 6844 6845 /** 6846 * Retrieves the writability mode for the Directory Server. This will only 6847 * be applicable for user suffixes. 6848 * 6849 * @return The writability mode for the Directory Server. 6850 */ 6851 public static WritabilityMode getWritabilityMode() 6852 { 6853 return directoryServer.writabilityMode; 6854 } 6855 6856 /** 6857 * Specifies the writability mode for the Directory Server. This will only 6858 * be applicable for user suffixes. 6859 * 6860 * @param writabilityMode Specifies the writability mode for the Directory 6861 * Server. 6862 */ 6863 public static void setWritabilityMode(WritabilityMode writabilityMode) 6864 { 6865 directoryServer.writabilityMode = writabilityMode; 6866 } 6867 6868 /** 6869 * Indicates whether simple bind requests that contain a bind DN will also be 6870 * required to have a password. 6871 * 6872 * @return <CODE>true</CODE> if simple bind requests containing a bind DN 6873 * will be required to have a password, or <CODE>false</CODE> if not 6874 * (and therefore will be treated as anonymous binds). 6875 */ 6876 public static boolean bindWithDNRequiresPassword() 6877 { 6878 return directoryServer.bindWithDNRequiresPassword; 6879 } 6880 6881 /** 6882 * Specifies whether simple bind requests that contain a bind DN will also be 6883 * required to have a password. 6884 * 6885 * @param bindWithDNRequiresPassword Indicates whether simple bind requests 6886 * that contain a bind DN will also be 6887 * required to have a password. 6888 */ 6889 public static void setBindWithDNRequiresPassword(boolean 6890 bindWithDNRequiresPassword) 6891 { 6892 directoryServer.bindWithDNRequiresPassword = bindWithDNRequiresPassword; 6893 } 6894 6895 /** 6896 * Indicates whether an unauthenticated request should be rejected. 6897 * 6898 * @return <CODE>true</CODE>if an unauthenticated request should be 6899 * rejected, or <CODE>false</CODE>f if not. 6900 */ 6901 public static boolean rejectUnauthenticatedRequests() 6902 { 6903 return directoryServer.rejectUnauthenticatedRequests; 6904 } 6905 6906 /** 6907 * Specifies whether an unauthenticated request should be rejected. 6908 * 6909 * @param rejectUnauthenticatedRequests Indicates whether an 6910 * unauthenticated request should 6911 * be rejected. 6912 */ 6913 public static void setRejectUnauthenticatedRequests(boolean 6914 rejectUnauthenticatedRequests) 6915 { 6916 directoryServer.rejectUnauthenticatedRequests = 6917 rejectUnauthenticatedRequests; 6918 } 6919 6920 /** 6921 * Indicates whether the Directory Server is currently configured to operate 6922 * in the lockdown mode, in which all non-root requests will be rejected and 6923 * all connection attempts from non-loopback clients will be rejected. 6924 * 6925 * @return {@code true} if the Directory Server is currently configured to 6926 * operate in the lockdown mode, or {@code false} if not. 6927 */ 6928 public static boolean lockdownMode() 6929 { 6930 return directoryServer.lockdownMode; 6931 } 6932 6933 /** 6934 * Specifies whether the server should operate in lockdown mode. 6935 * 6936 * @param lockdownMode Indicates whether the Directory Server should operate 6937 * in lockdown mode. 6938 */ 6939 public static void setLockdownMode(boolean lockdownMode) 6940 { 6941 directoryServer.lockdownMode = lockdownMode; 6942 6943 if (lockdownMode) 6944 { 6945 LocalizableMessage message = WARN_DIRECTORY_SERVER_ENTERING_LOCKDOWN_MODE.get(); 6946 logger.warn(message); 6947 6948 sendAlertNotification(directoryServer, ALERT_TYPE_ENTERING_LOCKDOWN_MODE, 6949 message); 6950 } 6951 else 6952 { 6953 LocalizableMessage message = NOTE_DIRECTORY_SERVER_LEAVING_LOCKDOWN_MODE.get(); 6954 logger.info(message); 6955 6956 sendAlertNotification(directoryServer, ALERT_TYPE_LEAVING_LOCKDOWN_MODE, 6957 message); 6958 } 6959 } 6960 6961 /** 6962 * Sets the message to be displayed on the command-line when the user asks for 6963 * the usage. 6964 * @param msg the message to be displayed on the command-line when the user 6965 * asks for the usage. 6966 */ 6967 public static void setToolDescription (LocalizableMessage msg) 6968 { 6969 toolDescription = msg; 6970 } 6971 6972 /** 6973 * Retrieves the DN of the configuration entry with which this alert generator 6974 * is associated. 6975 * 6976 * @return The DN of the configuration entry with which this alert generator 6977 * is associated. 6978 */ 6979 @Override 6980 public DN getComponentEntryDN() 6981 { 6982 try 6983 { 6984 if (configHandler == null) 6985 { 6986 // The config handler hasn't been initialized yet. Just return the DN 6987 // of the root DSE. 6988 return DN.rootDN(); 6989 } 6990 6991 return configHandler.getConfigRootEntry().getDN(); 6992 } 6993 catch (Exception e) 6994 { 6995 logger.traceException(e); 6996 6997 // This could theoretically happen if an alert needs to be sent before the 6998 // configuration is initialized. In that case, just return an empty DN. 6999 return DN.rootDN(); 7000 } 7001 } 7002 7003 /** 7004 * Retrieves the fully-qualified name of the Java class for this alert 7005 * generator implementation. 7006 * 7007 * @return The fully-qualified name of the Java class for this alert 7008 * generator implementation. 7009 */ 7010 @Override 7011 public String getClassName() 7012 { 7013 return DirectoryServer.class.getName(); 7014 } 7015 7016 /** 7017 * Retrieves information about the set of alerts that this generator may 7018 * produce. The map returned should be between the notification type for a 7019 * particular notification and the human-readable description for that 7020 * notification. This alert generator must not generate any alerts with types 7021 * that are not contained in this list. 7022 * 7023 * @return Information about the set of alerts that this generator may 7024 * produce. 7025 */ 7026 @Override 7027 public Map<String, String> getAlerts() 7028 { 7029 Map<String, String> alerts = new LinkedHashMap<>(); 7030 7031 alerts.put(ALERT_TYPE_SERVER_STARTED, ALERT_DESCRIPTION_SERVER_STARTED); 7032 alerts.put(ALERT_TYPE_SERVER_SHUTDOWN, ALERT_DESCRIPTION_SERVER_SHUTDOWN); 7033 alerts.put(ALERT_TYPE_ENTERING_LOCKDOWN_MODE, 7034 ALERT_DESCRIPTION_ENTERING_LOCKDOWN_MODE); 7035 alerts.put(ALERT_TYPE_LEAVING_LOCKDOWN_MODE, 7036 ALERT_DESCRIPTION_LEAVING_LOCKDOWN_MODE); 7037 7038 return alerts; 7039 } 7040 7041 /** 7042 * Indicates whether the server is currently in the process of shutting down. 7043 * @return <CODE>true</CODE> if this server is currently in the process of 7044 * shutting down and <CODE>false</CODE> otherwise. 7045 */ 7046 public boolean isShuttingDown() 7047 { 7048 return shuttingDown; 7049 } 7050 7051 /** 7052 * Parses the provided command-line arguments and uses that information to 7053 * bootstrap and start the Directory Server. 7054 * 7055 * @param args The command-line arguments provided to this program. 7056 */ 7057 public static void main(String[] args) 7058 { 7059 // Define the arguments that may be provided to the server. 7060 BooleanArgument checkStartability = null; 7061 BooleanArgument quietMode = null; 7062 IntegerArgument timeout = null; 7063 BooleanArgument windowsNetStart = null; 7064 BooleanArgument displayUsage = null; 7065 BooleanArgument fullVersion = null; 7066 BooleanArgument noDetach = null; 7067 BooleanArgument systemInfo = null; 7068 BooleanArgument useLastKnownGoodConfig = null; 7069 StringArgument configClass = null; 7070 StringArgument configFile = null; 7071 7072 // Create the command-line argument parser for use with this program. 7073 LocalizableMessage theToolDescription = DirectoryServer.toolDescription; 7074 ArgumentParser argParser = 7075 new ArgumentParser("org.opends.server.core.DirectoryServer", 7076 theToolDescription, false); 7077 argParser.setShortToolDescription(REF_SHORT_DESC_START_DS.get()); 7078 7079 // Initialize all the command-line argument types and register them with the 7080 // parser. 7081 try 7082 { 7083 configClass = new StringArgument("configclass", 'C', "configClass", 7084 true, false, true, 7085 INFO_CONFIGCLASS_PLACEHOLDER.get(), 7086 ConfigFileHandler.class.getName(), null, 7087 INFO_DSCORE_DESCRIPTION_CONFIG_CLASS.get()); 7088 configClass.setHidden(true); 7089 argParser.addArgument(configClass); 7090 7091 configFile = new StringArgument("configfile", 'f', "configFile", 7092 true, false, true, 7093 INFO_CONFIGFILE_PLACEHOLDER.get(), null, 7094 null, 7095 INFO_DSCORE_DESCRIPTION_CONFIG_FILE.get()); 7096 configFile.setHidden(true); 7097 argParser.addArgument(configFile); 7098 7099 checkStartability = new BooleanArgument("checkstartability", null, 7100 "checkStartability", 7101 INFO_DSCORE_DESCRIPTION_CHECK_STARTABILITY.get()); 7102 checkStartability.setHidden(true); 7103 argParser.addArgument(checkStartability); 7104 7105 windowsNetStart = new BooleanArgument("windowsnetstart", null, "windowsNetStart", 7106 INFO_DSCORE_DESCRIPTION_WINDOWS_NET_START.get()); 7107 windowsNetStart.setHidden(true); 7108 argParser.addArgument(windowsNetStart); 7109 7110 fullVersion = new BooleanArgument("fullversion", 'F', "fullVersion", 7111 INFO_DSCORE_DESCRIPTION_FULLVERSION.get()); 7112 fullVersion.setHidden(true); 7113 argParser.addArgument(fullVersion); 7114 7115 systemInfo = new BooleanArgument("systeminfo", 's', "systemInfo", 7116 INFO_DSCORE_DESCRIPTION_SYSINFO.get()); 7117 argParser.addArgument(systemInfo); 7118 7119 useLastKnownGoodConfig = 7120 new BooleanArgument("lastknowngoodconfig", 'L', 7121 "useLastKnownGoodConfig", 7122 INFO_DSCORE_DESCRIPTION_LASTKNOWNGOODCFG.get()); 7123 argParser.addArgument(useLastKnownGoodConfig); 7124 7125 noDetach = new BooleanArgument("nodetach", 'N', "nodetach", 7126 INFO_DSCORE_DESCRIPTION_NODETACH.get()); 7127 argParser.addArgument(noDetach); 7128 7129 quietMode = CommonArguments.getQuiet(); 7130 argParser.addArgument(quietMode); 7131 7132 // Not used in this class, but required by the start-ds script 7133 // (see issue #3814) 7134 timeout = new IntegerArgument("timeout", 't', "timeout", true, false, 7135 true, INFO_SECONDS_PLACEHOLDER.get(), 7136 DEFAULT_TIMEOUT, 7137 null, true, 0, false, 7138 0, INFO_DSCORE_DESCRIPTION_TIMEOUT.get()); 7139 argParser.addArgument(timeout); 7140 7141 displayUsage = CommonArguments.getShowUsage(); 7142 argParser.addArgument(displayUsage); 7143 argParser.setUsageArgument(displayUsage); 7144 argParser.setVersionHandler(new DirectoryServerVersionHandler()); 7145 } 7146 catch (ArgumentException ae) 7147 { 7148 LocalizableMessage message = ERR_DSCORE_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()); 7149 System.err.println(message); 7150 System.exit(1); 7151 } 7152 7153 // Parse the command-line arguments provided to this program. 7154 try 7155 { 7156 argParser.parseArguments(args); 7157 } 7158 catch (ArgumentException ae) 7159 { 7160 argParser.displayMessageAndUsageReference(System.err, ERR_DSCORE_ERROR_PARSING_ARGS.get(ae.getMessage())); 7161 System.exit(1); 7162 } 7163 7164 // If we should just display usage information, then print it and exit. 7165 if (checkStartability.isPresent()) 7166 { 7167 // This option should only be used if a PID file already exists in the 7168 // server logs directory, and we need to check which of the following 7169 // conditions best describes the current usage: 7170 // - We're trying to start the server, but it's already running. The 7171 // attempt to start the server should fail, and the server process will 7172 // exit with a result code of 98. 7173 // - We're trying to start the server and it's not already running. We 7174 // won't start it in this invocation, but the script used to get to this 7175 // point should go ahead and overwrite the PID file and retry the 7176 // startup process. The server process will exit with a result code of 7177 // 99. 7178 // - We're not trying to start the server, but instead are trying to do 7179 // something else like display the version number. In that case, we 7180 // don't need to write the PID file at all and can just execute the 7181 // intended command. If that command was successful, then we'll have an 7182 // exit code of NOTHING_TO_DO (0). Otherwise, it will have an exit code 7183 // that is something other than NOTHING_TO_DO, SERVER_ALREADY_STARTED, 7184 // START_AS_DETACH, START_AS_NON_DETACH, START_AS_WINDOWS_SERVICE, 7185 // START_AS_DETACH_QUIET, START_AS_NON_DETACH_QUIET to indicate that a 7186 // problem occurred. 7187 if (argParser.usageOrVersionDisplayed()) 7188 { 7189 // We're just trying to display usage, and that's already been done so 7190 // exit with a code of zero. 7191 System.exit(NOTHING_TO_DO); 7192 } 7193 else if (fullVersion.isPresent() || systemInfo.isPresent()) 7194 { 7195 // We're not really trying to start, so rebuild the argument list 7196 // without the "--checkStartability" argument and try again. Exit with 7197 // whatever that exits with. 7198 List<String> newArgList = new LinkedList<>(); 7199 for (String arg : args) 7200 { 7201 if (!"--checkstartability".equalsIgnoreCase(arg)) 7202 { 7203 newArgList.add(arg); 7204 } 7205 } 7206 String[] newArgs = new String[newArgList.size()]; 7207 newArgList.toArray(newArgs); 7208 main(newArgs); 7209 System.exit(NOTHING_TO_DO); 7210 } 7211 else 7212 { 7213 System.exit(checkStartability(argParser)); 7214 } 7215 } 7216 else if (argParser.usageOrVersionDisplayed()) 7217 { 7218 System.exit(0); 7219 } 7220 else if (fullVersion.isPresent()) 7221 { 7222 printFullVersionInformation(); 7223 return; 7224 } 7225 else if (systemInfo.isPresent()) 7226 { 7227 RuntimeInformation.printInfo(); 7228 return; 7229 } 7230 else if (noDetach.isPresent() && timeout.isPresent()) { 7231 argParser.displayMessageAndUsageReference(System.err, ERR_DSCORE_ERROR_NODETACH_TIMEOUT.get()); 7232 System.exit(1); 7233 } 7234 7235 // At this point, we know that we're going to try to start the server. 7236 // Attempt to grab an exclusive lock for the Directory Server process. 7237 String lockFile = LockFileManager.getServerLockFileName(); 7238 try 7239 { 7240 StringBuilder failureReason = new StringBuilder(); 7241 if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason)) 7242 { 7243 System.err.println(ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile, failureReason)); 7244 System.exit(1); 7245 } 7246 } 7247 catch (Exception e) 7248 { 7249 logger.traceException(e); 7250 7251 System.err.println(ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get( 7252 lockFile, stackTraceToSingleLineString(e))); 7253 System.exit(1); 7254 } 7255 serverLocked = true; 7256 7257 // Create an environment configuration for the server and populate a number 7258 // of appropriate properties. 7259 DirectoryEnvironmentConfig environmentConfig = new DirectoryEnvironmentConfig(); 7260 try 7261 { 7262 environmentConfig.setProperty(PROPERTY_CONFIG_CLASS, configClass.getValue()); 7263 environmentConfig.setProperty(PROPERTY_CONFIG_FILE, configFile.getValue()); 7264 environmentConfig.setProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG, 7265 String.valueOf(useLastKnownGoodConfig.isPresent())); 7266 } 7267 catch (Exception e) 7268 { 7269 // This shouldn't happen. For the methods we are using, the exception is 7270 // just a guard against making changes with the server running. 7271 System.err.println("WARNING: Unable to set environment properties in environment config : " 7272 + stackTraceToSingleLineString(e)); 7273 } 7274 7275 // Configure the JVM to delete the PID file on exit, if it exists. 7276 boolean pidFileMarkedForDeletion = false; 7277 boolean startingFileMarkedForDeletion = false; 7278 try 7279 { 7280 String pidFilePath; 7281 String startingFilePath; 7282 File instanceRoot = environmentConfig.getInstanceRoot(); 7283 if (instanceRoot == null) 7284 { 7285 pidFilePath = "logs/server.pid"; 7286 startingFilePath = "logs/server.starting"; 7287 } 7288 else 7289 { 7290 pidFilePath = instanceRoot.getAbsolutePath() + File.separator + "logs" 7291 + File.separator + "server.pid"; 7292 startingFilePath = instanceRoot.getAbsolutePath() + File.separator 7293 + "logs" + File.separator + "server.starting"; 7294 } 7295 7296 File pidFile = new File(pidFilePath); 7297 if (pidFile.exists()) 7298 { 7299 pidFile.deleteOnExit(); 7300 pidFileMarkedForDeletion = true; 7301 } 7302 7303 File startingFile = new File(startingFilePath); 7304 if (startingFile.exists()) 7305 { 7306 startingFile.deleteOnExit(); 7307 startingFileMarkedForDeletion = true; 7308 } 7309 } catch (Exception e) {} 7310 7311 // Redirect standard output and standard error to the server.out file. If 7312 // the server hasn't detached from the terminal, then also continue writing 7313 // to the original standard output and standard error. Also, configure the 7314 // JVM to delete the PID and server.starting files on exit, if they exist. 7315 PrintStream serverOutStream; 7316 try 7317 { 7318 File serverRoot = environmentConfig.getServerRoot(); 7319 if (serverRoot == null) 7320 { 7321 System.err.println("WARNING: Unable to determine server root in " + 7322 "order to redirect standard output and standard error."); 7323 } 7324 else 7325 { 7326 File instanceRoot = environmentConfig.getInstanceRoot(); 7327 File logDir = new File(instanceRoot.getAbsolutePath() + File.separator 7328 + "logs"); 7329 if (logDir.exists()) 7330 { 7331 FileOutputStream fos = 7332 new FileOutputStream(new File(logDir, "server.out"), true); 7333 serverOutStream = new PrintStream(fos); 7334 7335 if (noDetach.isPresent() && !quietMode.isPresent()) 7336 { 7337 MultiOutputStream multiStream = 7338 new MultiOutputStream(System.out, serverOutStream); 7339 serverOutStream = new PrintStream(multiStream); 7340 } 7341 7342 System.setOut(serverOutStream); 7343 System.setErr(serverOutStream); 7344 7345 if (! pidFileMarkedForDeletion) 7346 { 7347 File f = new File(logDir, "server.pid"); 7348 if (f.exists()) 7349 { 7350 f.deleteOnExit(); 7351 } 7352 } 7353 7354 if (! startingFileMarkedForDeletion) 7355 { 7356 File f = new File(logDir, "server.starting"); 7357 if (f.exists()) 7358 { 7359 f.deleteOnExit(); 7360 } 7361 } 7362 } 7363 else 7364 { 7365 System.err.println("WARNING: Unable to redirect standard output " + 7366 "and standard error because the logs directory " + 7367 logDir.getAbsolutePath() + " does not exist."); 7368 } 7369 } 7370 } 7371 catch (Exception e) 7372 { 7373 System.err.println("WARNING: Unable to redirect standard output and " + 7374 "standard error: " + stackTraceToSingleLineString(e)); 7375 } 7376 7377 // Install the default loggers so the startup messages 7378 // will be printed. 7379 ErrorLogPublisher startupErrorLogPublisher = 7380 TextErrorLogPublisher.getServerStartupTextErrorPublisher(new TextWriter.STDOUT()); 7381 ErrorLogger.getInstance().addLogPublisher(startupErrorLogPublisher); 7382 7383 DebugLogPublisher startupDebugLogPublisher = 7384 DebugLogger.getInstance().addPublisherIfRequired(new TextWriter.STDOUT()); 7385 7386 // Bootstrap and start the Directory Server. 7387 DirectoryServer theDirectoryServer = DirectoryServer.getInstance(); 7388 try 7389 { 7390 theDirectoryServer.setEnvironmentConfig(environmentConfig); 7391 theDirectoryServer.bootstrapServer(); 7392 theDirectoryServer.initializeConfiguration(configClass.getValue(), 7393 configFile.getValue()); 7394 } 7395 catch (InitializationException ie) 7396 { 7397 logger.traceException(ie); 7398 7399 LocalizableMessage message = ERR_DSCORE_CANNOT_BOOTSTRAP.get(ie.getMessage()); 7400 System.err.println(message); 7401 System.exit(1); 7402 } 7403 catch (Exception e) 7404 { 7405 LocalizableMessage message = ERR_DSCORE_CANNOT_BOOTSTRAP.get( 7406 stackTraceToSingleLineString(e)); 7407 System.err.println(message); 7408 System.exit(1); 7409 } 7410 7411 try 7412 { 7413 theDirectoryServer.startServer(); 7414 } 7415 catch (InitializationException ie) 7416 { 7417 logger.traceException(ie); 7418 7419 LocalizableMessage message = ERR_DSCORE_CANNOT_START.get(ie.getMessage()); 7420 shutDown(theDirectoryServer.getClass().getName(), message); 7421 } 7422 catch (ConfigException ce) 7423 { 7424 logger.traceException(ce); 7425 7426 LocalizableMessage message = ERR_DSCORE_CANNOT_START.get(ce.getMessage() + 7427 (ce.getCause() != null ? " " + ce.getCause().getLocalizedMessage() : "")); 7428 shutDown(theDirectoryServer.getClass().getName(), message); 7429 } 7430 catch (Exception e) 7431 { 7432 LocalizableMessage message = ERR_DSCORE_CANNOT_START.get( 7433 stackTraceToSingleLineString(e)); 7434 shutDown(theDirectoryServer.getClass().getName(), message); 7435 } 7436 7437 ErrorLogger.getInstance().removeLogPublisher(startupErrorLogPublisher); 7438 if (startupDebugLogPublisher != null) 7439 { 7440 DebugLogger.getInstance().removeLogPublisher(startupDebugLogPublisher); 7441 } 7442 } 7443 7444 /** 7445 * Construct the DN of a monitor provider entry. 7446 * @param provider The monitor provider for which a DN is desired. 7447 * @return The DN of the monitor provider entry. 7448 */ 7449 public static DN getMonitorProviderDN(MonitorProvider provider) 7450 { 7451 String monitorName = provider.getMonitorInstanceName(); 7452 try 7453 { 7454 // Get a complete DN which could be a tree naming schema 7455 return DN.valueOf("cn="+monitorName+","+DN_MONITOR_ROOT); 7456 } 7457 catch (DirectoryException e) 7458 { 7459 // Cannot reach this point. 7460 throw new RuntimeException(); 7461 } 7462 } 7463 7464 /** 7465 * Gets the class loader to be used with this directory server 7466 * application. 7467 * <p> 7468 * The class loader will automatically load classes from plugins 7469 * where required. 7470 * 7471 * @return Returns the class loader to be used with this directory 7472 * server application. 7473 */ 7474 public static ClassLoader getClassLoader() 7475 { 7476 return ClassLoaderProvider.getInstance().getClassLoader(); 7477 } 7478 7479 /** 7480 * Loads the named class using this directory server application's 7481 * class loader. 7482 * <p> 7483 * This method provided as a convenience and is equivalent to 7484 * calling: 7485 * 7486 * <pre> 7487 * Class.forName(name, true, DirectoryServer.getClassLoader()); 7488 * </pre> 7489 * 7490 * @param name 7491 * The fully qualified name of the desired class. 7492 * @return Returns the class object representing the desired class. 7493 * @throws LinkageError 7494 * If the linkage fails. 7495 * @throws ExceptionInInitializerError 7496 * If the initialization provoked by this method fails. 7497 * @throws ClassNotFoundException 7498 * If the class cannot be located by the specified class 7499 * loader. 7500 * @see Class#forName(String, boolean, ClassLoader) 7501 */ 7502 public static Class<?> loadClass(String name) throws LinkageError, 7503 ExceptionInInitializerError, ClassNotFoundException 7504 { 7505 return Class.forName(name, true, DirectoryServer.getClassLoader()); 7506 } 7507 7508 /** 7509 * Returns the error code that we return when we are checking the startability 7510 * of the server. 7511 * If there are conflicting arguments (like asking to run the server in non 7512 * detach mode when the server is configured to run as a window service) it 7513 * returns CHECK_ERROR (1). 7514 * @param argParser the ArgumentParser with the arguments already parsed. 7515 * @return the error code that we return when we are checking the startability 7516 * of the server. 7517 */ 7518 private static int checkStartability(ArgumentParser argParser) 7519 { 7520 int returnValue; 7521 boolean isServerRunning; 7522 7523 BooleanArgument noDetach = 7524 (BooleanArgument)argParser.getArgumentForLongID("nodetach"); 7525 BooleanArgument quietMode = 7526 (BooleanArgument)argParser.getArgumentForLongID(ArgumentConstants.OPTION_LONG_QUIET); 7527 BooleanArgument windowsNetStart = 7528 (BooleanArgument)argParser.getArgumentForLongID("windowsnetstart"); 7529 7530 boolean noDetachPresent = noDetach.isPresent(); 7531 boolean windowsNetStartPresent = windowsNetStart.isPresent(); 7532 7533 // We're trying to start the server, so see if it's already running by 7534 // trying to grab an exclusive lock on the server lock file. If it 7535 // succeeds, then the server isn't running and we can try to start. 7536 // Otherwise, the server is running and this attempt should fail. 7537 String lockFile = LockFileManager.getServerLockFileName(); 7538 try 7539 { 7540 StringBuilder failureReason = new StringBuilder(); 7541 if (LockFileManager.acquireExclusiveLock(lockFile, failureReason)) 7542 { 7543 // The server isn't running, so it can be started. 7544 LockFileManager.releaseLock(lockFile, failureReason); 7545 isServerRunning = false; 7546 } 7547 else 7548 { 7549 // The server's already running. 7550 System.err.println(ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile, failureReason)); 7551 isServerRunning = true; 7552 } 7553 } 7554 catch (Exception e) 7555 { 7556 // We'll treat this as if the server is running because we won't 7557 // be able to start it anyway. 7558 LocalizableMessage message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile, 7559 getExceptionMessage(e)); 7560 System.err.println(message); 7561 isServerRunning = true; 7562 } 7563 7564 boolean configuredAsService = isRunningAsWindowsService(); 7565 7566 if (isServerRunning) 7567 { 7568 if (configuredAsService && !windowsNetStartPresent) 7569 { 7570 returnValue = START_AS_WINDOWS_SERVICE; 7571 } 7572 else 7573 { 7574 returnValue = SERVER_ALREADY_STARTED; 7575 } 7576 } 7577 else 7578 { 7579 if (configuredAsService) 7580 { 7581 if (noDetachPresent) 7582 { 7583 // Conflicting arguments 7584 returnValue = CHECK_ERROR; 7585 LocalizableMessage message = ERR_DSCORE_ERROR_NODETACH_AND_WINDOW_SERVICE.get(); 7586 System.err.println(message); 7587 7588 } 7589 else 7590 { 7591 if (windowsNetStartPresent) 7592 { 7593 // start-ds.bat is being called through net start, so return 7594 // START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE so that the batch 7595 // file actually starts the server. 7596 returnValue = START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE; 7597 } 7598 else 7599 { 7600 returnValue = START_AS_WINDOWS_SERVICE; 7601 } 7602 } 7603 } 7604 else 7605 { 7606 if (noDetachPresent) 7607 { 7608 if (quietMode.isPresent()) 7609 { 7610 returnValue = START_AS_NON_DETACH_QUIET; 7611 } 7612 else 7613 { 7614 returnValue = START_AS_NON_DETACH; 7615 } 7616 } 7617 else if (quietMode.isPresent()) 7618 { 7619 returnValue = START_AS_DETACH_QUIET; 7620 } 7621 else 7622 { 7623 returnValue = START_AS_DETACH; 7624 } 7625 } 7626 } 7627 return returnValue; 7628 } 7629 7630 /** 7631 * Returns true if this server is configured to run as a windows service. 7632 * @return <CODE>true</CODE> if this server is configured to run as a windows 7633 * service and <CODE>false</CODE> otherwise. 7634 */ 7635 public static boolean isRunningAsWindowsService() 7636 { 7637 return OperatingSystem.isWindows() 7638 && serviceState() == SERVICE_STATE_ENABLED; 7639 } 7640 7641 // TODO JNR remove error CoreMessages.ERR_REGISTER_WORKFLOW_ELEMENT_ALREADY_EXISTS 7642 7643 /** Print messages for start-ds "-F" option (full version information). */ 7644 private static void printFullVersionInformation() { 7645 /* 7646 * This option is used by the upgrade to identify the server build and it 7647 * can eventually also be used to be sent to the support in case of an 7648 * issue. Since this is not a public interface and since it is better 7649 * to always have it in English for the support team, the message is 7650 * not localized. 7651 */ 7652 String separator = ": "; 7653 System.out.println(getVersionString()); 7654 System.out.println(SetupUtils.BUILD_ID+separator+BUILD_ID); 7655 System.out.println(SetupUtils.MAJOR_VERSION+separator+MAJOR_VERSION); 7656 System.out.println(SetupUtils.MINOR_VERSION+separator+MINOR_VERSION); 7657 System.out.println(SetupUtils.POINT_VERSION+separator+POINT_VERSION); 7658 System.out.println(SetupUtils.VERSION_QUALIFIER+separator+ 7659 VERSION_QUALIFIER); 7660 if (BUILD_NUMBER > 0) 7661 { 7662 System.out.println(SetupUtils.BUILD_NUMBER+separator+ 7663 new DecimalFormat("000").format(BUILD_NUMBER)); 7664 } 7665 System.out.println(SetupUtils.REVISION_NUMBER+separator+REVISION_NUMBER); 7666 System.out.println(SetupUtils.URL_REPOSITORY+separator+URL_REPOSITORY); 7667 System.out.println(SetupUtils.FIX_IDS+separator+FIX_IDS); 7668 System.out.println(SetupUtils.DEBUG_BUILD+separator+DEBUG_BUILD); 7669 System.out.println(SetupUtils.BUILD_OS+separator+BUILD_OS); 7670 System.out.println(SetupUtils.BUILD_USER+separator+BUILD_USER); 7671 System.out.println(SetupUtils.BUILD_JAVA_VERSION+separator+ 7672 BUILD_JAVA_VERSION); 7673 System.out.println(SetupUtils.BUILD_JAVA_VENDOR+separator+ 7674 BUILD_JAVA_VENDOR); 7675 System.out.println(SetupUtils.BUILD_JVM_VERSION+separator+ 7676 BUILD_JVM_VERSION); 7677 System.out.println(SetupUtils.BUILD_JVM_VENDOR+separator+BUILD_JVM_VENDOR); 7678 System.out.println(SetupUtils.INCOMPATIBILITY_EVENTS+separator+ 7679 Utils.joinAsString(",", VersionCompatibilityIssue.getAllEvents())); 7680 7681 // Print extensions' extra information 7682 String extensionInformation = 7683 ClassLoaderProvider.getInstance().printExtensionInformation(); 7684 if ( extensionInformation != null ) { 7685 System.out.print(extensionInformation); 7686 } 7687 } 7688 7689 /** 7690 * Sets the threshold capacity beyond which internal cached buffers used for 7691 * encoding and decoding entries and protocol messages will be trimmed after 7692 * use. 7693 * 7694 * @param maxInternalBufferSize 7695 * The threshold capacity beyond which internal cached buffers used 7696 * for encoding and decoding entries and protocol messages will be 7697 * trimmed after use. 7698 */ 7699 public static void setMaxInternalBufferSize(int maxInternalBufferSize) 7700 { 7701 directoryServer.maxInternalBufferSize = maxInternalBufferSize; 7702 } 7703 7704 /** 7705 * Returns the threshold capacity beyond which internal cached buffers used 7706 * for encoding and decoding entries and protocol messages will be trimmed 7707 * after use. 7708 * 7709 * @return The threshold capacity beyond which internal cached buffers used 7710 * for encoding and decoding entries and protocol messages will be 7711 * trimmed after use. 7712 */ 7713 public static int getMaxInternalBufferSize() 7714 { 7715 return directoryServer.maxInternalBufferSize; 7716 } 7717 7718 /** 7719 * Returns the lock manager which will be used for coordinating access to LDAP entries. 7720 * 7721 * @return the lock manager which will be used for coordinating access to LDAP entries. 7722 */ 7723 public static LockManager getLockManager() 7724 { 7725 return directoryServer.lockManager; 7726 } 7727}