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