001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.core;
028
029 import org.opends.server.admin.ClassLoaderProvider;
030 import org.opends.server.admin.server.ServerManagementContext;
031 import org.opends.server.admin.std.meta.GlobalCfgDefn.WorkflowConfigurationMode;
032 import org.opends.server.admin.std.server.*;
033 import org.opends.server.api.AccountStatusNotificationHandler;
034 import org.opends.server.api.AlertGenerator;
035 import org.opends.server.api.AlertHandler;
036 import org.opends.server.api.ApproximateMatchingRule;
037 import org.opends.server.api.AttributeSyntax;
038 import org.opends.server.api.Backend;
039 import org.opends.server.api.BackendInitializationListener;
040 import org.opends.server.api.BackupTaskListener;
041 import org.opends.server.api.CertificateMapper;
042 import org.opends.server.api.ChangeNotificationListener;
043 import org.opends.server.api.ClientConnection;
044 import org.opends.server.api.CompressedSchema;
045 import org.opends.server.api.ConfigAddListener;
046 import org.opends.server.api.ConfigChangeListener;
047 import org.opends.server.api.ConfigDeleteListener;
048 import org.opends.server.api.ConfigHandler;
049 import org.opends.server.api.ConnectionHandler;
050 import org.opends.server.api.DirectoryServerMBean;
051 import org.opends.server.api.EntryCache;
052 import org.opends.server.api.EqualityMatchingRule;
053 import org.opends.server.api.ExportTaskListener;
054 import org.opends.server.api.ExtendedOperationHandler;
055 import org.opends.server.api.IdentityMapper;
056 import org.opends.server.api.ImportTaskListener;
057 import org.opends.server.api.InvokableComponent;
058 import org.opends.server.api.KeyManagerProvider;
059 import org.opends.server.api.MatchingRule;
060 import org.opends.server.api.MonitorProvider;
061 import org.opends.server.api.OrderingMatchingRule;
062 import org.opends.server.api.PasswordGenerator;
063 import org.opends.server.api.PasswordStorageScheme;
064 import org.opends.server.api.PasswordValidator;
065 import org.opends.server.api.RestoreTaskListener;
066 import org.opends.server.api.SASLMechanismHandler;
067 import org.opends.server.api.ServerShutdownListener;
068 import org.opends.server.api.SubstringMatchingRule;
069 import org.opends.server.api.SynchronizationProvider;
070 import org.opends.server.api.TrustManagerProvider;
071 import org.opends.server.api.WorkQueue;
072 import org.opends.server.api.AccessControlHandler;
073 import org.opends.server.api.plugin.PluginType;
074 import org.opends.server.api.plugin.PluginResult;
075 import org.opends.server.backends.RootDSEBackend;
076 import static org.opends.server.config.ConfigConstants.DN_MONITOR_ROOT;
077 import static org.opends.server.config.ConfigConstants.ENV_VAR_INSTANCE_ROOT;
078 import org.opends.server.config.ConfigEntry;
079 import org.opends.server.config.ConfigException;
080 import org.opends.server.config.JMXMBean;
081 import org.opends.server.controls.PasswordPolicyErrorType;
082 import org.opends.server.controls.PasswordPolicyResponseControl;
083 import org.opends.server.extensions.ConfigFileHandler;
084 import org.opends.server.extensions.JMXAlertHandler;
085 import static org.opends.server.loggers.AccessLogger.*;
086 import static org.opends.server.loggers.ErrorLogger.*;
087 import org.opends.server.loggers.*;
088 import static org.opends.server.loggers.debug.DebugLogger.*;
089 import org.opends.server.loggers.debug.DebugTracer;
090 import org.opends.server.loggers.debug.DebugLogger;
091 import org.opends.server.loggers.debug.TextDebugLogPublisher;
092
093 import org.opends.messages.MessageDescriptor;
094 import org.opends.messages.Message;
095 import static org.opends.messages.CoreMessages.*;
096 import static org.opends.messages.ToolMessages.*;
097 import org.opends.server.monitors.BackendMonitor;
098 import org.opends.server.monitors.ConnectionHandlerMonitor;
099 import org.opends.server.schema.AttributeTypeSyntax;
100 import org.opends.server.schema.BinarySyntax;
101 import org.opends.server.schema.BooleanEqualityMatchingRule;
102 import org.opends.server.schema.BooleanSyntax;
103 import org.opends.server.schema.CaseExactEqualityMatchingRule;
104 import org.opends.server.schema.CaseExactIA5EqualityMatchingRule;
105 import org.opends.server.schema.CaseExactIA5SubstringMatchingRule;
106 import org.opends.server.schema.CaseExactOrderingMatchingRule;
107 import org.opends.server.schema.CaseExactSubstringMatchingRule;
108 import org.opends.server.schema.CaseIgnoreEqualityMatchingRule;
109 import org.opends.server.schema.CaseIgnoreIA5EqualityMatchingRule;
110 import org.opends.server.schema.CaseIgnoreIA5SubstringMatchingRule;
111 import org.opends.server.schema.CaseIgnoreOrderingMatchingRule;
112 import org.opends.server.schema.CaseIgnoreSubstringMatchingRule;
113 import org.opends.server.schema.DirectoryStringSyntax;
114 import org.opends.server.schema.DistinguishedNameEqualityMatchingRule;
115 import org.opends.server.schema.DistinguishedNameSyntax;
116 import org.opends.server.schema.DoubleMetaphoneApproximateMatchingRule;
117 import org.opends.server.schema.GeneralizedTimeEqualityMatchingRule;
118 import org.opends.server.schema.GeneralizedTimeOrderingMatchingRule;
119 import org.opends.server.schema.GeneralizedTimeSyntax;
120 import org.opends.server.schema.IA5StringSyntax;
121 import org.opends.server.schema.IntegerEqualityMatchingRule;
122 import org.opends.server.schema.IntegerOrderingMatchingRule;
123 import org.opends.server.schema.IntegerSyntax;
124 import org.opends.server.schema.OIDSyntax;
125 import org.opends.server.schema.ObjectClassSyntax;
126 import org.opends.server.schema.ObjectIdentifierEqualityMatchingRule;
127 import org.opends.server.schema.OctetStringEqualityMatchingRule;
128 import org.opends.server.schema.OctetStringOrderingMatchingRule;
129 import org.opends.server.schema.OctetStringSubstringMatchingRule;
130 import static org.opends.server.schema.SchemaConstants.*;
131 import org.opends.server.schema.TelephoneNumberEqualityMatchingRule;
132 import org.opends.server.schema.TelephoneNumberSubstringMatchingRule;
133 import org.opends.server.schema.TelephoneNumberSyntax;
134 import org.opends.server.tools.ConfigureWindowsService;
135 import org.opends.server.types.AbstractOperation;
136 import org.opends.server.types.AcceptRejectWarn;
137 import org.opends.server.types.AttributeType;
138 import org.opends.server.types.AttributeUsage;
139 import org.opends.server.types.AttributeValue;
140 import org.opends.server.types.BackupConfig;
141 import org.opends.server.types.Control;
142 import org.opends.server.crypto.CryptoManagerImpl;
143 import org.opends.server.types.DITContentRule;
144 import org.opends.server.types.DITStructureRule;
145 import org.opends.server.types.DN;
146 import org.opends.server.types.DebugLogLevel;
147 import org.opends.server.types.DirectoryException;
148 import org.opends.server.types.Entry;
149 import org.opends.server.types.HostPort;
150 import org.opends.server.types.InitializationException;
151 import org.opends.server.types.LDIFExportConfig;
152 import org.opends.server.types.LDIFImportConfig;
153 import org.opends.server.types.MatchingRuleUse;
154 import org.opends.server.types.Modification;
155 import org.opends.server.types.NameForm;
156 import org.opends.server.types.ObjectClass;
157 import org.opends.server.types.ObjectClassType;
158 import org.opends.server.types.OperatingSystem;
159 import org.opends.server.types.OperationType;
160 import org.opends.server.types.Privilege;
161 import org.opends.server.types.RDN;
162 import org.opends.server.types.RestoreConfig;
163 import org.opends.server.types.ResultCode;
164 import org.opends.server.types.Schema;
165 import org.opends.server.types.VirtualAttributeRule;
166 import org.opends.server.types.WritabilityMode;
167 import org.opends.server.types.DirectoryEnvironmentConfig;
168 import org.opends.server.types.LockManager;
169 import static org.opends.server.util.DynamicConstants.*;
170 import static org.opends.server.util.ServerConstants.*;
171 import static org.opends.server.util.StaticUtils.*;
172 import static org.opends.server.util.Validator.ensureNotNull;
173 import org.opends.server.util.*;
174 import org.opends.server.util.args.ArgumentException;
175 import org.opends.server.util.args.ArgumentParser;
176 import org.opends.server.util.args.BooleanArgument;
177 import org.opends.server.util.args.StringArgument;
178 import org.opends.server.workflowelement.*;
179 import org.opends.server.workflowelement.localbackend.*;
180 import org.opends.server.protocols.internal.InternalConnectionHandler;
181 import org.opends.server.protocols.internal.InternalClientConnection;
182 import org.opends.server.crypto.CryptoManagerSync;
183 import static org.opends.messages.ConfigMessages.*;
184
185 import javax.management.MBeanServer;
186 import javax.management.MBeanServerFactory;
187 import java.io.File;
188 import java.io.FileOutputStream;
189 import java.io.IOException;
190 import java.io.OutputStream;
191 import java.io.PrintStream;
192 import java.net.InetAddress;
193 import java.text.DecimalFormat;
194 import java.util.*;
195 import java.util.concurrent.ConcurrentHashMap;
196 import java.util.concurrent.CopyOnWriteArrayList;
197 import java.util.concurrent.CopyOnWriteArraySet;
198
199
200 /**
201 * This class defines the core of the Directory Server. It manages the startup
202 * and shutdown processes and coordinates activities between all other
203 * components.
204 */
205 public class DirectoryServer
206 implements Thread.UncaughtExceptionHandler, AlertGenerator
207 {
208 /**
209 * The tracer object for the debug logger.
210 */
211 private static final DebugTracer TRACER = getTracer();
212
213 /**
214 * The fully-qualified name of this class.
215 */
216 private static final String CLASS_NAME =
217 "org.opends.server.core.DirectoryServer";
218
219
220 /**
221 * The singleton Directory Server instance.
222 */
223 private static DirectoryServer directoryServer = new DirectoryServer();
224
225
226
227 /**
228 * Indicates whether the server currently holds an exclusive lock on the
229 * server lock fiie.
230 */
231 private static boolean serverLocked = false;
232
233
234 /**
235 * Return codes used when the hidden option --checkStartability is used.
236 * NOTE: when checkstartability is specified is recommended not to allocate
237 * a lot of memory for the JVM (Using -Xms and -Xmx options) as there might
238 * be calls to Runtime.exec.
239 */
240 /**
241 * Returned when the user specified the --checkStartability option with other
242 * options like printing the usage, dumping messages, displaying version, etc.
243 */
244 private static int NOTHING_TO_DO = 0;
245 /**
246 * Returned when the user specified the --checkStartability option with
247 * some incompatible arguments.
248 */
249 private static int CHECK_ERROR = 1;
250 /**
251 * The server is already started.
252 */
253 private static int SERVER_ALREADY_STARTED = 98;
254 /**
255 * The server must be started as detached process.
256 */
257 private static int START_AS_DETACH = 99;
258 /**
259 * The server must be started as a non-detached process.
260 */
261 private static int START_AS_NON_DETACH = 100;
262 /**
263 * The server must be started as a window service.
264 */
265 private static int START_AS_WINDOWS_SERVICE = 101;
266 /**
267 * The server must be started as detached and it is being called from the
268 * Windows Service.
269 */
270 private static int START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE = 102;
271 /**
272 * The server must be started as detached process and should not produce any
273 * output.
274 */
275 private static int START_AS_DETACH_QUIET = 103;
276
277 // The policy to use regarding single structural objectclass enforcement.
278 private AcceptRejectWarn singleStructuralClassPolicy;
279
280 // The policy to use regarding syntax enforcement.
281 private AcceptRejectWarn syntaxEnforcementPolicy;
282
283 // The account status notification handler config manager for the server.
284 private AccountStatusNotificationHandlerConfigManager
285 accountStatusNotificationHandlerConfigManager;
286
287 // The default syntax to use for binary attributes.
288 private AttributeSyntax<AttributeSyntaxCfg> defaultBinarySyntax;
289
290 // The default syntax to use for Boolean attributes.
291 private AttributeSyntax<AttributeSyntaxCfg> defaultBooleanSyntax;
292
293 // The default syntax to use for DN attributes.
294 private AttributeSyntax<AttributeSyntaxCfg> defaultDNSyntax;
295
296 // The default syntax to use for integer attributes.
297 private AttributeSyntax<AttributeSyntaxCfg> defaultIntegerSyntax;
298
299 // The default syntax to use for string attributes.
300 private AttributeSyntax<DirectoryStringAttributeSyntaxCfg>
301 defaultStringSyntax;
302
303 // The default attribute syntax to use for attributes with no defined syntax.
304 private AttributeSyntax<DirectoryStringAttributeSyntaxCfg> defaultSyntax;
305
306 // The attribute type used to reference the "objectclass" attribute.
307 private AttributeType objectClassAttributeType;
308
309 // The authenticated users manager for the server.
310 private AuthenticatedUsers authenticatedUsers;
311
312 // The configuration manager that will handle the server backends.
313 private BackendConfigManager backendConfigManager;
314
315 // Indicates whether to automatically add missing RDN attributes to entries
316 // during an add request.
317 private boolean addMissingRDNAttributes;
318
319 // Indicates whether to allow attribute name exceptions (i.e., attribute names
320 // can contain underscores and may start with a digit).
321 private boolean allowAttributeNameExceptions;
322
323 // Indicates whether a simple bind request containing a DN must also provide a
324 // password.
325 private boolean bindWithDNRequiresPassword;
326
327 // Indicates whether the Directory Server should perform schema checking for
328 // update operations.
329 private boolean checkSchema;
330
331 // Indicates whether the server has been bootstrapped.
332 private boolean isBootstrapped;
333
334 // Indicates whether the server has been bootstrapped for client use.
335 private boolean isClientBootstrapped;
336
337 // Indicates whether the server is currently online.
338 private boolean isRunning;
339
340 // Indicates whether the server is currently in "lockdown mode".
341 private boolean lockdownMode;
342
343 // Indicates whether the server should send a response to operations that have
344 // been abandoned.
345 private boolean notifyAbandonedOperations;
346
347 // Indicates whether to save a copy of the configuration on successful
348 // startup.
349 private boolean saveConfigOnSuccessfulStartup;
350
351 // Indicates whether the server is currently in the process of shutting down.
352 private boolean shuttingDown;
353
354 // Indicates whether the server should reject unauthenticated requests.
355 private boolean rejectUnauthenticatedRequests;
356
357 // Indicates whether bind responses should include failure reason messages.
358 private boolean returnBindErrorMessages;
359
360 // The configuration manager that will handle the certificate mapper.
361 private CertificateMapperConfigManager certificateMapperConfigManager;
362
363 // The class used to provide the config handler implementation.
364 private Class configClass;
365
366 // The configuration handler for the Directory Server.
367 private ConfigHandler configHandler;
368
369 // The set of account status notification handlers defined in the server.
370 private ConcurrentHashMap<DN,AccountStatusNotificationHandler>
371 accountStatusNotificationHandlers;
372
373 // The set of certificate mappers registered with the server.
374 private ConcurrentHashMap<DN,CertificateMapper> certificateMappers;
375
376 // The set of alternate bind DNs for the root users.
377 private ConcurrentHashMap<DN,DN> alternateRootBindDNs;
378
379 // The set of identity mappers registered with the server (mapped between
380 // the configuration entry Dn and the mapper).
381 private ConcurrentHashMap<DN,IdentityMapper> identityMappers;
382
383 // The set of JMX MBeans that have been registered with the server (mapped
384 // between the associated configuration entry DN and the MBean).
385 private ConcurrentHashMap<DN,JMXMBean> mBeans;
386
387 // The set of key manager providers registered with the server.
388 private ConcurrentHashMap<DN,KeyManagerProvider> keyManagerProviders;
389
390 // The set of password generators registered with the Directory Server, as a
391 // mapping between the DN of the associated configuration entry and the
392 // generator implementation.
393 private ConcurrentHashMap<DN,PasswordGenerator> passwordGenerators;
394
395 // The set of password policies registered with the Directory Server, as a
396 // mapping between the DN of the associated configuration entry and the policy
397 // implementation.
398 private ConcurrentHashMap<DN,PasswordPolicyConfig> passwordPolicies;
399
400 // The set of password validators registered with the Directory Server, as a
401 // mapping between the DN of the associated configuration entry and the
402 // validator implementation.
403 private ConcurrentHashMap<DN,
404 PasswordValidator<? extends PasswordValidatorCfg>>
405 passwordValidators;
406
407 // The set of trust manager providers registered with the server.
408 private ConcurrentHashMap<DN,TrustManagerProvider> trustManagerProviders;
409
410 // The set of log rotation policies registered with the Directory Server, as
411 // a mapping between the DN of the associated configuration entry and the
412 // policy implementation.
413 private ConcurrentHashMap<DN, RotationPolicy> rotationPolicies;
414
415 // The set of log retention policies registered with the Directory Server, as
416 // a mapping between the DN of the associated configuration entry and the
417 // policy implementation.
418 private ConcurrentHashMap<DN, RetentionPolicy> retentionPolicies;
419
420 // The set supported LDAP protocol versions.
421 private ConcurrentHashMap<Integer,List<ConnectionHandler>>
422 supportedLDAPVersions;
423
424 // The set of extended operation handlers registered with the server (mapped
425 // between the OID of the extended operation and the handler).
426 private ConcurrentHashMap<String,ExtendedOperationHandler>
427 extendedOperationHandlers;
428
429 // The set of monitor providers registered with the Directory Server, as a
430 // mapping between the monitor name and the corresponding implementation.
431 private ConcurrentHashMap<String,
432 MonitorProvider<? extends MonitorProviderCfg>>
433 monitorProviders;
434
435 // The set of password storage schemes defined in the server (mapped between
436 // the lowercase scheme name and the storage scheme) that support the
437 // authentication password syntax.
438 private ConcurrentHashMap<String,PasswordStorageScheme>
439 authPasswordStorageSchemes;
440
441 // The set of password storage schemes defined in the server (mapped between
442 // the lowercase scheme name and the storage scheme).
443 private ConcurrentHashMap<String,PasswordStorageScheme>
444 passwordStorageSchemes;
445
446 // The set of password storage schemes defined in the server (mapped between
447 // the DN of the configuration entry and the storage scheme).
448 private ConcurrentHashMap<DN,PasswordStorageScheme>
449 passwordStorageSchemesByDN;
450
451 // The set of SASL mechanism handlers registered with the server (mapped
452 // between the mechanism name and the handler).
453 private ConcurrentHashMap<String,SASLMechanismHandler> saslMechanismHandlers;
454
455 // The connection handler configuration manager for the Directory Server.
456 private ConnectionHandlerConfigManager connectionHandlerConfigManager;
457
458 // The set of alert handlers registered with the Directory Server.
459 private CopyOnWriteArrayList<AlertHandler> alertHandlers;
460
461 // The set of backup task listeners registered with the Directory Server.
462 private CopyOnWriteArrayList<BackupTaskListener> backupTaskListeners;
463
464 // The set of change notification listeners registered with the Directory
465 // Server.
466 private CopyOnWriteArrayList<ChangeNotificationListener>
467 changeNotificationListeners;
468
469 // The set of connection handlers registered with the Directory Server.
470 private CopyOnWriteArrayList<ConnectionHandler> connectionHandlers;
471
472 // The set of export task listeners registered with the Directory Server.
473 private CopyOnWriteArrayList<ExportTaskListener> exportTaskListeners;
474
475 // The set of import task listeners registered with the Directory Server.
476 private CopyOnWriteArrayList<ImportTaskListener> importTaskListeners;
477
478 // The set of persistent searches registered with the Directory Server.
479 private CopyOnWriteArrayList<PersistentSearch> persistentSearches;
480
481 // The set of restore task listeners registered with the Directory Server.
482 private CopyOnWriteArrayList<RestoreTaskListener> restoreTaskListeners;
483
484 // The set of shutdown listeners that have been registered with the Directory
485 // Server.
486 private CopyOnWriteArrayList<ServerShutdownListener> shutdownListeners;
487
488 // The set of synchronization providers that have been registered with the
489 // Directory Server.
490 private
491 CopyOnWriteArrayList<SynchronizationProvider<SynchronizationProviderCfg>>
492 synchronizationProviders;
493
494 // The set of virtual attributes defined in the server.
495 private CopyOnWriteArrayList<VirtualAttributeRule> virtualAttributes;
496
497 // The set of backend initialization listeners registered with the Directory
498 // Server.
499 private CopyOnWriteArraySet<BackendInitializationListener>
500 backendInitializationListeners;
501
502 // The set of root DNs registered with the Directory Server.
503 private CopyOnWriteArraySet<DN> rootDNs;
504
505 // The core configuration manager for the Directory Server.
506 private CoreConfigManager coreConfigManager;
507
508 // The crypto manager for the Directory Server.
509 private CryptoManagerImpl cryptoManager;
510
511 // The default compressed schema manager.
512 private DefaultCompressedSchema compressedSchema;
513
514 // The environment configuration for the Directory Server.
515 private DirectoryEnvironmentConfig environmentConfig;
516
517 // The shutdown hook that has been registered with the server.
518 private DirectoryServerShutdownHook shutdownHook;
519
520 // The DN of the default password policy configuration entry.
521 private DN defaultPasswordPolicyDN;
522
523 // The DN of the identity mapper that will be used to resolve authorization
524 // IDs contained in the proxied authorization V2 control.
525 private DN proxiedAuthorizationIdentityMapperDN;
526
527 // The DN of the entry containing the server schema definitions.
528 private DN schemaDN;
529
530 // The Directory Server entry cache.
531 private EntryCache entryCache;
532
533 // The configuration manager for the entry cache.
534 private EntryCacheConfigManager entryCacheConfigManager;
535
536 // The configuration manager for extended operation handlers.
537 private ExtendedOperationConfigManager extendedOperationConfigManager;
538
539 // The path to the file containing the Directory Server configuration, or the
540 // information needed to bootstrap the configuration handler.
541 private File configFile;
542
543 // The group manager for the Directory Server.
544 private GroupManager groupManager;
545
546 // The configuration manager for identity mappers.
547 private IdentityMapperConfigManager identityMapperConfigManager;
548
549 // The maximum number of entries that should be returned for a search unless
550 // overridden on a per-user basis.
551 private int sizeLimit;
552
553 // The maximum length of time in seconds that should be allowed for a search
554 // unless overridden on a per-user basis.
555 private int timeLimit;
556
557 // The maxiumum number of candidates that should be check for matches during
558 // a search.
559 private int lookthroughLimit;
560
561 // Whether to use collect operation processing times in nanosecond resolution
562 private boolean useNanoTime;
563
564 // The key manager provider configuration manager for the Directory Server.
565 private KeyManagerProviderConfigManager keyManagerProviderConfigManager;
566
567 // The set of connections that are currently established.
568 private LinkedHashSet<ClientConnection> establishedConnections;
569
570 // The sets of mail server properties
571 private List<Properties> mailServerPropertySets;
572
573 // The set of schema changes made by editing the schema configuration files
574 // with the server offline.
575 private List<Modification> offlineSchemaChanges;
576
577 // The log rotation policy config manager for the Directory Server.
578 private LogRotationPolicyConfigManager rotationPolicyConfigManager;
579
580 // The log retention policy config manager for the Directory Server.
581 private LogRetentionPolicyConfigManager retentionPolicyConfigManager;
582
583 // The logger configuration manager for the Directory Server.
584 private LoggerConfigManager loggerConfigManager;
585
586 // The number of connections currently established to the server.
587 private long currentConnections;
588
589 // The idle time limit for the server.
590 private long idleTimeLimit;
591
592 // The maximum number of connections that will be allowed at any given time.
593 private long maxAllowedConnections;
594
595 // The maximum number of connections established at one time.
596 private long maxConnections;
597
598 // The time that this Directory Server instance was started.
599 private long startUpTime;
600
601 // The total number of connections established since startup.
602 private long totalConnections;
603
604 // The MBean server used to handle JMX interaction.
605 private MBeanServer mBeanServer;
606
607 // The monitor config manager for the Directory Server.
608 private MonitorConfigManager monitorConfigManager;
609
610 // The operating system on which the server is running.
611 private OperatingSystem operatingSystem;
612
613 // The configuration handler used to manage the password generators.
614 private PasswordGeneratorConfigManager passwordGeneratorConfigManager;
615
616 // The default password policy for the Directory Server.
617 private PasswordPolicyConfig defaultPasswordPolicyConfig;
618
619 // The configuration handler used to manage the password policies.
620 private PasswordPolicyConfigManager passwordPolicyConfigManager;
621
622 // The configuration handler used to manage the password storage schemes.
623 private PasswordStorageSchemeConfigManager storageSchemeConfigManager;
624
625 // The configuration handler used to manage the password validators.
626 private PasswordValidatorConfigManager passwordValidatorConfigManager;
627
628 // The plugin config manager for the Directory Server.
629 private PluginConfigManager pluginConfigManager;
630
631 // The result code that should be used for internal "server" errors.
632 private ResultCode serverErrorResultCode;
633
634 // The special backend used for the Directory Server root DSE.
635 private RootDSEBackend rootDSEBackend;
636
637 // The root DN config manager for the server.
638 private RootDNConfigManager rootDNConfigManager;
639
640 // The SASL mechanism config manager for the Directory Server.
641 private SASLConfigManager saslConfigManager;
642
643 // The schema for the Directory Server.
644 private Schema schema;
645
646 // The schema configuration manager for the Directory Server.
647 private SchemaConfigManager schemaConfigManager;
648
649 // The set of disabled privileges.
650 private Set<Privilege> disabledPrivileges;
651
652 // The set of allowed task classes.
653 private Set<String> allowedTasks;
654
655 // The time that the server was started, formatted in UTC time.
656 private String startTimeUTC;
657
658 // The synchronization provider configuration manager for the Directory
659 // Server.
660 private SynchronizationProviderConfigManager
661 synchronizationProviderConfigManager;
662
663 // The thread group for all threads associated with the Directory Server.
664 private ThreadGroup directoryThreadGroup;
665
666
667 // Registry for base DN and naming context information.
668 private BaseDnRegistry baseDnRegistry;
669
670
671 // The set of backends registered with the server.
672 private TreeMap<String,Backend> backends;
673
674 // The mapping between backends and their unique indentifiers for their
675 // offline state, representing either checksum or other unique value to
676 // be used for detecting any offline modifications to a given backend.
677 private ConcurrentHashMap<String,Long> offlineBackendsStateIDs;
678
679 // The set of supported controls registered with the Directory Server.
680 private TreeSet<String> supportedControls;
681
682 // The set of supported feature OIDs registered with the Directory Server.
683 private TreeSet<String> supportedFeatures;
684
685 // The trust manager provider configuration manager for the Directory Server.
686 private TrustManagerProviderConfigManager trustManagerProviderConfigManager;
687
688 // The virtual attribute provider configuration manager for the Directory
689 // Server.
690 private VirtualAttributeConfigManager virtualAttributeConfigManager;
691
692 // The work queue that will be used to service client requests.
693 private WorkQueue workQueue;
694
695 // The writability mode for the Directory Server.
696 private WritabilityMode writabilityMode;
697
698 // The workflow configuration mode (auto or manual).
699 private WorkflowConfigurationMode workflowConfigurationMode;
700
701 // The network group config manager for the Directory Server.
702 // This config manager is used when the workflow configuration
703 // mode is 'manual'.
704 private NetworkGroupConfigManager networkGroupConfigManager;
705
706 // The workflow config manager for the Directory Server.
707 // This config manager is used when the workflow configuration
708 // mode is 'manual'.
709 private WorkflowConfigManager workflowConfigManager;
710
711 // The workflow element config manager for the Directory Server.
712 // This config manager is used when the workflow configuration
713 // mode is 'manual'.
714 private WorkflowElementConfigManager workflowElementConfigManager;
715
716
717
718 /**
719 * Creates a new instance of the Directory Server. This will allow only a
720 * single instance of the server per JVM.
721 */
722 private DirectoryServer()
723 {
724 this(new DirectoryEnvironmentConfig());
725 }
726
727
728
729 /**
730 * Creates a new instance of the Directory Server. This will allow only a
731 * single instance of the server per JVM.
732 *
733 * @param config The environment configuration to use for the Directory
734 * Server instance.
735 */
736 private DirectoryServer(DirectoryEnvironmentConfig config)
737 {
738 environmentConfig = config;
739 isBootstrapped = false;
740 isClientBootstrapped = false;
741 isRunning = false;
742 shuttingDown = false;
743 lockdownMode = false;
744 serverErrorResultCode = ResultCode.OTHER;
745
746 operatingSystem = OperatingSystem.forName(System.getProperty("os.name"));
747 }
748
749
750
751 /**
752 * Retrieves the instance of the Directory Server that is associated with this
753 * JVM.
754 *
755 * @return The instance of the Directory Server that is associated with this
756 * JVM.
757 */
758 public static DirectoryServer getInstance()
759 {
760 return directoryServer;
761 }
762
763
764
765 /**
766 * Creates a new instance of the Directory Server and replaces the static
767 * reference to it. This should only be used in the context of an in-core
768 * restart after the existing server has been shut down.
769 *
770 * @param config The environment configuration for the Directory Server.
771 *
772 * @return The new instance of the Directory Server that is associated with
773 * this JVM.
774 */
775 private static DirectoryServer
776 getNewInstance(DirectoryEnvironmentConfig config)
777 {
778 synchronized (directoryServer)
779 {
780 return directoryServer = new DirectoryServer(config);
781 }
782 }
783
784
785
786 /**
787 * Retrieves the environment configuration for the Directory Server.
788 *
789 * @return The environment configuration for the Directory Server.
790 */
791 public static DirectoryEnvironmentConfig getEnvironmentConfig()
792 {
793 return directoryServer.environmentConfig;
794 }
795
796
797
798 /**
799 * Sets the environment configuration for the Directory Server. This method
800 * may only be invoked when the server is not running.
801 *
802 * @param config The environment configuration for the Directory Server.
803 *
804 * @throws InitializationException If the Directory Server is currently
805 * running.
806 */
807 public void setEnvironmentConfig(DirectoryEnvironmentConfig config)
808 throws InitializationException
809 {
810 if (isRunning)
811 {
812 throw new InitializationException(
813 ERR_CANNOT_SET_ENVIRONMENT_CONFIG_WHILE_RUNNING.get());
814 }
815
816 environmentConfig = config;
817 }
818
819
820
821 /**
822 * Indicates whether the Directory Server is currently running.
823 *
824 * @return {@code true} if the server is currently running, or {@code false}
825 * if not.
826 */
827 public static boolean isRunning()
828 {
829 return directoryServer.isRunning;
830 }
831
832
833
834 /**
835 * Bootstraps the appropriate Directory Server structures that may be needed
836 * by client-side tools. This is not intended for use in running the server
837 * itself.
838 */
839 public static void bootstrapClient()
840 {
841 synchronized (directoryServer)
842 {
843 if (directoryServer.isClientBootstrapped)
844 {
845 return;
846 }
847
848
849 // Set default values for variables that may be needed during schema
850 // processing.
851 directoryServer.syntaxEnforcementPolicy = AcceptRejectWarn.REJECT;
852
853
854 // Create the server schema and initialize and register a minimal set of
855 // matching rules and attribute syntaxes.
856 directoryServer.schema = new Schema();
857 directoryServer.bootstrapMatchingRules();
858 directoryServer.bootstrapAttributeSyntaxes();
859
860
861 // Perform any additional initialization that might be necessary before
862 // loading the configuration.
863 directoryServer.alertHandlers = new CopyOnWriteArrayList<AlertHandler>();
864 directoryServer.passwordStorageSchemes =
865 new ConcurrentHashMap<String,PasswordStorageScheme>();
866 directoryServer.passwordStorageSchemesByDN =
867 new ConcurrentHashMap<DN,PasswordStorageScheme>();
868 directoryServer.passwordGenerators =
869 new ConcurrentHashMap<DN,PasswordGenerator>();
870 directoryServer.authPasswordStorageSchemes =
871 new ConcurrentHashMap<String,PasswordStorageScheme>();
872 directoryServer.passwordValidators =
873 new ConcurrentHashMap<DN,
874 PasswordValidator<? extends PasswordValidatorCfg>>();
875 directoryServer.accountStatusNotificationHandlers =
876 new ConcurrentHashMap<DN,AccountStatusNotificationHandler>();
877 directoryServer.rootDNs = new CopyOnWriteArraySet<DN>();
878 directoryServer.alternateRootBindDNs = new ConcurrentHashMap<DN,DN>();
879 directoryServer.keyManagerProviders =
880 new ConcurrentHashMap<DN,KeyManagerProvider>();
881 directoryServer.trustManagerProviders =
882 new ConcurrentHashMap<DN,TrustManagerProvider>();
883 directoryServer.rotationPolicies =
884 new ConcurrentHashMap<DN, RotationPolicy>();
885 directoryServer.retentionPolicies =
886 new ConcurrentHashMap<DN, RetentionPolicy>();
887 directoryServer.certificateMappers =
888 new ConcurrentHashMap<DN,CertificateMapper>();
889 directoryServer.passwordPolicies =
890 new ConcurrentHashMap<DN,PasswordPolicyConfig>();
891 directoryServer.defaultPasswordPolicyDN = null;
892 directoryServer.defaultPasswordPolicyConfig = null;
893 directoryServer.monitorProviders =
894 new ConcurrentHashMap<String,
895 MonitorProvider<? extends MonitorProviderCfg>>();
896 directoryServer.backends = new TreeMap<String,Backend>();
897 directoryServer.offlineBackendsStateIDs =
898 new ConcurrentHashMap<String,Long>();
899 directoryServer.backendInitializationListeners =
900 new CopyOnWriteArraySet<BackendInitializationListener>();
901 directoryServer.baseDnRegistry = new BaseDnRegistry();
902 directoryServer.changeNotificationListeners =
903 new CopyOnWriteArrayList<ChangeNotificationListener>();
904 directoryServer.persistentSearches =
905 new CopyOnWriteArrayList<PersistentSearch>();
906 directoryServer.shutdownListeners =
907 new CopyOnWriteArrayList<ServerShutdownListener>();
908 directoryServer.synchronizationProviders =
909 new CopyOnWriteArrayList<SynchronizationProvider
910 <SynchronizationProviderCfg>>();
911 directoryServer.supportedControls = new TreeSet<String>();
912 directoryServer.supportedFeatures = new TreeSet<String>();
913 directoryServer.supportedLDAPVersions =
914 new ConcurrentHashMap<Integer,List<ConnectionHandler>>();
915 directoryServer.virtualAttributes =
916 new CopyOnWriteArrayList<VirtualAttributeRule>();
917 directoryServer.connectionHandlers =
918 new CopyOnWriteArrayList<ConnectionHandler>();
919 directoryServer.identityMappers =
920 new ConcurrentHashMap<DN,IdentityMapper>();
921 directoryServer.extendedOperationHandlers =
922 new ConcurrentHashMap<String,ExtendedOperationHandler>();
923 directoryServer.saslMechanismHandlers =
924 new ConcurrentHashMap<String,SASLMechanismHandler>();
925 directoryServer.authenticatedUsers = new AuthenticatedUsers();
926 directoryServer.offlineSchemaChanges = new LinkedList<Modification>();
927 directoryServer.backupTaskListeners =
928 new CopyOnWriteArrayList<BackupTaskListener>();
929 directoryServer.restoreTaskListeners =
930 new CopyOnWriteArrayList<RestoreTaskListener>();
931 directoryServer.exportTaskListeners =
932 new CopyOnWriteArrayList<ExportTaskListener>();
933 directoryServer.importTaskListeners =
934 new CopyOnWriteArrayList<ImportTaskListener>();
935 directoryServer.allowedTasks = new LinkedHashSet<String>(0);
936 directoryServer.disabledPrivileges = new LinkedHashSet<Privilege>(0);
937 directoryServer.returnBindErrorMessages = false;
938 directoryServer.idleTimeLimit = 0L;
939 }
940 }
941
942
943
944 /**
945 * Bootstraps the Directory Server by initializing all the necessary
946 * structures that should be in place before the configuration may be read.
947 * This step must be completed before the server may be started or the
948 * configuration is loaded, but it will not be allowed while the server is
949 * running.
950 *
951 * @throws InitializationException If a problem occurs while attempting to
952 * bootstrap the server.
953 */
954 public void bootstrapServer()
955 throws InitializationException
956 {
957 // First, make sure that the server isn't currently running. If it isn't,
958 // then make sure that no other thread will try to start or bootstrap the
959 // server before this thread is done.
960 synchronized (directoryServer)
961 {
962 if (isRunning)
963 {
964 Message message = ERR_CANNOT_BOOTSTRAP_WHILE_RUNNING.get();
965 throw new InitializationException(message);
966 }
967
968 isBootstrapped = false;
969 shuttingDown = false;
970 }
971
972
973 // Create the thread group that should be used for all Directory Server
974 // threads.
975 directoryThreadGroup = new ThreadGroup("Directory Server Thread Group");
976
977
978 // Add a shutdown hook so that the server can be notified when the JVM
979 // starts shutting down.
980 shutdownHook = new DirectoryServerShutdownHook();
981 Runtime.getRuntime().addShutdownHook(shutdownHook);
982
983
984 // Register this class as the default uncaught exception handler for the
985 // JVM. The uncaughtException method will be called if a thread dies
986 // because it did not properly handle an exception.
987 Thread.setDefaultUncaughtExceptionHandler(this);
988
989
990 // Create the MBean server that we will use for JMX interaction.
991 initializeJMX();
992
993
994 logError(INFO_DIRECTORY_BOOTSTRAPPING.get());
995
996
997 // Perform all the bootstrapping that is shared with the client-side
998 // processing.
999 bootstrapClient();
1000
1001
1002 // Initialize the variables that will be used for connection tracking.
1003 establishedConnections = new LinkedHashSet<ClientConnection>(1000);
1004 currentConnections = 0;
1005 maxConnections = 0;
1006 totalConnections = 0;
1007
1008
1009 // Create the plugin config manager, but don't initialize it yet. This will
1010 // make it possible to process internal operations before the plugins have
1011 // been loaded.
1012 pluginConfigManager = new PluginConfigManager();
1013
1014
1015 // If we have gotten here, then the configuration should be properly
1016 // bootstrapped.
1017 synchronized (directoryServer)
1018 {
1019 isBootstrapped = true;
1020 }
1021 }
1022
1023
1024
1025 /**
1026 * Performs a minimal set of JMX initialization. This may be used by the core
1027 * Directory Server or by command-line tools.
1028 *
1029 * @throws InitializationException If a problem occurs while attempting to
1030 * initialize the JMX subsystem.
1031 */
1032 public static void initializeJMX()
1033 throws InitializationException
1034 {
1035 try
1036 {
1037 // FIXME -- Should we use the plaform Mbean Server or
1038 // should we use a private one ?
1039 directoryServer.mBeanServer = MBeanServerFactory.newMBeanServer();
1040 // directoryServer.mBeanServer =
1041 // ManagementFactory.getPlatformMBeanServer();
1042
1043 directoryServer.mBeans = new ConcurrentHashMap<DN,JMXMBean>();
1044 registerAlertGenerator(directoryServer);
1045 }
1046 catch (Exception e)
1047 {
1048 if (debugEnabled())
1049 {
1050 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1051 }
1052
1053 Message message = ERR_CANNOT_CREATE_MBEAN_SERVER.get(String.valueOf(e));
1054 throw new InitializationException(message, e);
1055 }
1056 }
1057
1058
1059
1060 /**
1061 * Instantiates the configuration handler and loads the Directory Server
1062 * configuration.
1063 *
1064 * @param configClass The fully-qualified name of the Java class that will
1065 * serve as the configuration handler for the Directory
1066 * Server.
1067 * @param configFile The path to the file that will hold either the entire
1068 * server configuration or enough information to allow
1069 * the server to access the configuration in some other
1070 * repository.
1071 *
1072 * @throws InitializationException If a problem occurs while trying to
1073 * initialize the config handler.
1074 */
1075 public void initializeConfiguration(String configClass, String configFile)
1076 throws InitializationException
1077 {
1078 Class cfgClass;
1079 try
1080 {
1081 cfgClass = Class.forName(configClass);
1082 }
1083 catch (Exception e)
1084 {
1085 if (debugEnabled())
1086 {
1087 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1088 }
1089
1090 Message message =
1091 ERR_CANNOT_LOAD_CONFIG_HANDLER_CLASS.get(
1092 configClass, stackTraceToSingleLineString(e));
1093 throw new InitializationException(message, e);
1094 }
1095
1096 File cfgFile = new File(configFile);
1097
1098 environmentConfig.setConfigClass(cfgClass);
1099 environmentConfig.setConfigFile(cfgFile);
1100 initializeConfiguration();
1101 }
1102
1103
1104
1105 /**
1106 * Instantiates the configuration handler and loads the Directory Server
1107 * configuration.
1108 *
1109 * @throws InitializationException If a problem occurs while trying to
1110 * initialize the config handler.
1111 */
1112 public void initializeConfiguration()
1113 throws InitializationException
1114 {
1115 this.configClass = environmentConfig.getConfigClass();
1116 this.configFile = environmentConfig.getConfigFile();
1117
1118
1119 // Make sure that administration framework definition classes are loaded.
1120 ClassLoaderProvider provider = ClassLoaderProvider.getInstance();
1121 if (! provider.isEnabled())
1122 {
1123 provider.enable();
1124 }
1125
1126
1127 // Load and instantiate the configuration handler class.
1128 Class handlerClass = configClass;
1129 try
1130 {
1131 configHandler = (ConfigHandler) handlerClass.newInstance();
1132 }
1133 catch (Exception e)
1134 {
1135 if (debugEnabled())
1136 {
1137 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1138 }
1139
1140 Message message =
1141 ERR_CANNOT_INSTANTIATE_CONFIG_HANDLER.get(
1142 String.valueOf(configClass),
1143 e.getLocalizedMessage());
1144 throw new InitializationException(message, e);
1145 }
1146
1147
1148 // Perform the handler-specific initialization.
1149 try
1150 {
1151 configHandler.initializeConfigHandler(configFile.getAbsolutePath(),
1152 false);
1153 }
1154 catch (InitializationException ie)
1155 {
1156 if (debugEnabled())
1157 {
1158 TRACER.debugCaught(DebugLogLevel.ERROR, ie);
1159 }
1160
1161 throw ie;
1162 }
1163 catch (Exception e)
1164 {
1165 if (debugEnabled())
1166 {
1167 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1168 }
1169
1170 Message message =
1171 ERR_CANNOT_INITIALIZE_CONFIG_HANDLER.get(
1172 String.valueOf(configClass),
1173 String.valueOf(configFile),
1174 e.getLocalizedMessage());
1175 throw new InitializationException(message);
1176 }
1177
1178 }
1179
1180
1181
1182 /**
1183 * Retrieves the path to the configuration file used to initialize the
1184 * Directory Server.
1185 *
1186 * @return The path to the configuration file used to initialize the
1187 * Directory Server.
1188 */
1189 public static String getConfigFile()
1190 {
1191 return directoryServer.configFile.getAbsolutePath();
1192 }
1193
1194
1195
1196 /**
1197 * Starts up the Directory Server. It must have already been bootstrapped
1198 * and cannot be running.
1199 *
1200 * @throws ConfigException If there is a problem with the Directory Server
1201 * configuration that prevents a critical component
1202 * from being instantiated.
1203 *
1204 * @throws InitializationException If some other problem occurs while
1205 * attempting to initialize and start the
1206 * Directory Server.
1207 */
1208 public void startServer()
1209 throws ConfigException, InitializationException
1210 {
1211 synchronized (directoryServer)
1212 {
1213 if (! isBootstrapped)
1214 {
1215 Message message = ERR_CANNOT_START_BEFORE_BOOTSTRAP.get();
1216 throw new InitializationException(message);
1217 }
1218
1219 if (isRunning)
1220 {
1221 Message message = ERR_CANNOT_START_WHILE_RUNNING.get();
1222 throw new InitializationException(message);
1223 }
1224
1225
1226 logError(NOTE_DIRECTORY_SERVER_STARTING.get(getVersionString(),
1227 BUILD_ID, REVISION_NUMBER));
1228
1229 RuntimeInformation.logInfo();
1230 // Acquire an exclusive lock for the Directory Server process.
1231 if (! serverLocked)
1232 {
1233 String lockFile = LockFileManager.getServerLockFileName();
1234 try
1235 {
1236 StringBuilder failureReason = new StringBuilder();
1237 if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
1238 {
1239 Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(
1240 lockFile, String.valueOf(failureReason));
1241 throw new InitializationException(message);
1242 }
1243
1244 serverLocked = true;
1245 }
1246 catch (InitializationException ie)
1247 {
1248 throw ie;
1249 }
1250 catch (Exception e)
1251 {
1252 if (debugEnabled())
1253 {
1254 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1255 }
1256
1257 Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(
1258 lockFile, stackTraceToSingleLineString(e));
1259 throw new InitializationException(message, e);
1260 }
1261 }
1262
1263
1264 // Determine whether or not we should start the connection handlers.
1265 boolean startConnectionHandlers =
1266 (! environmentConfig.disableConnectionHandlers());
1267
1268
1269 // Initialize all the schema elements.
1270 initializeSchema();
1271
1272
1273 // Initialize the core Directory Server configuration.
1274 coreConfigManager = new CoreConfigManager();
1275 coreConfigManager.initializeCoreConfig();
1276
1277
1278 // Initialize the Directory Server crypto manager.
1279 initializeCryptoManager();
1280
1281
1282 // Initialize the log rotation policies.
1283 rotationPolicyConfigManager = new LogRotationPolicyConfigManager();
1284 rotationPolicyConfigManager.initializeLogRotationPolicyConfig();
1285
1286 // Initialize the log retention policies.
1287 retentionPolicyConfigManager = new LogRetentionPolicyConfigManager();
1288 retentionPolicyConfigManager.initializeLogRetentionPolicyConfig();
1289
1290
1291 // Initialize the server loggers.
1292 loggerConfigManager = new LoggerConfigManager();
1293 loggerConfigManager.initializeLoggerConfig();
1294
1295
1296 // Initialize the server alert handlers.
1297 initializeAlertHandlers();
1298
1299
1300 // Initialize the default entry cache. We have to have one before
1301 // <CODE>initializeBackends()</CODE> method kicks in further down.
1302 entryCacheConfigManager = new EntryCacheConfigManager();
1303 entryCacheConfigManager.initializeDefaultEntryCache();
1304
1305
1306 // Initialize the key manager provider.
1307 keyManagerProviderConfigManager = new KeyManagerProviderConfigManager();
1308 keyManagerProviderConfigManager.initializeKeyManagerProviders();
1309
1310
1311 // Initialize the trust manager provider.
1312 trustManagerProviderConfigManager =
1313 new TrustManagerProviderConfigManager();
1314 trustManagerProviderConfigManager.initializeTrustManagerProviders();
1315
1316
1317 // Initialize the certificate mapper.
1318 certificateMapperConfigManager = new CertificateMapperConfigManager();
1319 certificateMapperConfigManager.initializeCertificateMappers();
1320
1321
1322 // Initialize the identity mappers.
1323 initializeIdentityMappers();
1324
1325
1326 // Initialize the root DNs.
1327 rootDNConfigManager = new RootDNConfigManager();
1328 rootDNConfigManager.initializeRootDNs();
1329
1330
1331 // Initialize the group manager.
1332 initializeGroupManager();
1333
1334 // Initialize the access control handler.
1335 AccessControlConfigManager.getInstance().initializeAccessControl();
1336
1337 // Initialize all the backends and their associated suffixes
1338 // and initialize the workflows when workflow configuration mode
1339 // is auto.
1340 initializeBackends();
1341
1342 // When workflow configuration mode is manual, do configure the
1343 // workflows now, else just configure the remaining workflows
1344 // (rootDSE and config backend).
1345 if (workflowConfigurationModeIsAuto())
1346 {
1347 createAndRegisterRemainingWorkflows();
1348 }
1349 else
1350 {
1351 configureWorkflowsManual();
1352 }
1353
1354 // Check for and initialize user configured entry cache if any,
1355 // if not stick with default entry cache initialized earlier.
1356 entryCacheConfigManager.initializeEntryCache();
1357
1358 // Reset the map as we can no longer guarantee offline state.
1359 directoryServer.offlineBackendsStateIDs.clear();
1360
1361 // Register the supported controls and supported features.
1362 initializeSupportedControls();
1363 initializeSupportedFeatures();
1364
1365
1366 // Initialize all the extended operation handlers.
1367 initializeExtendedOperations();
1368
1369
1370 // Initialize all the SASL mechanism handlers.
1371 initializeSASLMechanisms();
1372
1373
1374 // Initialize all the virtual attribute handlers.
1375 initializeVirtualAttributes();
1376
1377
1378 // Initialize all the connection handlers.
1379 if (startConnectionHandlers)
1380 {
1381 initializeConnectionHandlers();
1382 }
1383
1384
1385 // Initialize all the monitor providers.
1386 monitorConfigManager = new MonitorConfigManager();
1387 monitorConfigManager.initializeMonitorProviders();
1388
1389
1390 // Initialize all the password policy components.
1391 initializePasswordPolicyComponents();
1392
1393
1394 // Load and initialize all the plugins, and then call the registered
1395 // startup plugins.
1396 initializePlugins();
1397
1398
1399 // Initialize any synchronization providers that may be defined.
1400 synchronizationProviderConfigManager =
1401 new SynchronizationProviderConfigManager();
1402 synchronizationProviderConfigManager.initializeSynchronizationProviders();
1403
1404
1405 // Create and initialize the work queue.
1406 workQueue = new WorkQueueConfigManager().initializeWorkQueue();
1407
1408
1409 PluginResult.Startup startupPluginResult =
1410 pluginConfigManager.invokeStartupPlugins();
1411 if (! startupPluginResult.continueProcessing())
1412 {
1413 Message message = ERR_STARTUP_PLUGIN_ERROR.
1414 get(startupPluginResult.getErrorMessage(),
1415 startupPluginResult.getErrorMessage().getDescriptor().getId());
1416 throw new InitializationException(message);
1417 }
1418
1419
1420 if (startConnectionHandlers)
1421 {
1422 startConnectionHandlers();
1423 new IdleTimeLimitThread().start();
1424 }
1425
1426
1427 // Create an object to synchronize ADS with the crypto manager.
1428 new CryptoManagerSync();
1429
1430 // If we should write a copy of the config on successful startup, then do
1431 // so now.
1432 if (saveConfigOnSuccessfulStartup)
1433 {
1434 configHandler.writeSuccessfulStartupConfig();
1435 }
1436
1437
1438 // Mark the current time as the start time and indicate that the server is
1439 // now running.
1440 startUpTime = System.currentTimeMillis();
1441 startTimeUTC = TimeThread.getGMTTime();
1442 isRunning = true;
1443
1444 Message message = NOTE_DIRECTORY_SERVER_STARTED.get();
1445 logError(message);
1446 sendAlertNotification(this, ALERT_TYPE_SERVER_STARTED, message);
1447
1448 // Force the root connection to be initialized.
1449 InternalClientConnection.getRootConnection();
1450
1451 // If a server.starting file exists, then remove it.
1452 File serverStartingFile =
1453 new File(configHandler.getServerRoot() + File.separator +
1454 "logs" + File.separator + "server.starting");
1455 if (serverStartingFile.exists())
1456 {
1457 serverStartingFile.delete();
1458 }
1459 }
1460 }
1461
1462
1463
1464 /**
1465 * Registers a basic set of matching rules with the server that should always
1466 * be available regardless of the server configuration and may be needed for
1467 * configuration processing.
1468 */
1469 private void bootstrapMatchingRules()
1470 {
1471 try
1472 {
1473 ApproximateMatchingRule matchingRule =
1474 new DoubleMetaphoneApproximateMatchingRule();
1475 matchingRule.initializeMatchingRule(null);
1476 registerApproximateMatchingRule(matchingRule, true);
1477 }
1478 catch (Exception e)
1479 {
1480 if (debugEnabled())
1481 {
1482 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1483 }
1484
1485 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1486 get(DoubleMetaphoneApproximateMatchingRule.class.getName(),
1487 stackTraceToSingleLineString(e));
1488 logError(message);
1489 }
1490
1491
1492 try
1493 {
1494 EqualityMatchingRule matchingRule = new BooleanEqualityMatchingRule();
1495 matchingRule.initializeMatchingRule(null);
1496 registerEqualityMatchingRule(matchingRule, true);
1497 }
1498 catch (Exception e)
1499 {
1500 if (debugEnabled())
1501 {
1502 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1503 }
1504
1505 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1506 get(BooleanEqualityMatchingRule.class.getName(),
1507 stackTraceToSingleLineString(e));
1508 logError(message);
1509 }
1510
1511
1512 try
1513 {
1514 EqualityMatchingRule matchingRule = new CaseExactEqualityMatchingRule();
1515 matchingRule.initializeMatchingRule(null);
1516 registerEqualityMatchingRule(matchingRule, true);
1517 }
1518 catch (Exception e)
1519 {
1520 if (debugEnabled())
1521 {
1522 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1523 }
1524
1525 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1526 get(CaseExactEqualityMatchingRule.class.getName(),
1527 stackTraceToSingleLineString(e));
1528 logError(message);
1529 }
1530
1531
1532 try
1533 {
1534 EqualityMatchingRule matchingRule =
1535 new CaseExactIA5EqualityMatchingRule();
1536 matchingRule.initializeMatchingRule(null);
1537 registerEqualityMatchingRule(matchingRule, true);
1538 }
1539 catch (Exception e)
1540 {
1541 if (debugEnabled())
1542 {
1543 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1544 }
1545
1546 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1547 get(CaseExactIA5EqualityMatchingRule.class.getName(),
1548 stackTraceToSingleLineString(e));
1549 logError(message);
1550 }
1551
1552
1553 try
1554 {
1555 EqualityMatchingRule matchingRule = new CaseIgnoreEqualityMatchingRule();
1556 matchingRule.initializeMatchingRule(null);
1557 registerEqualityMatchingRule(matchingRule, true);
1558 }
1559 catch (Exception e)
1560 {
1561 if (debugEnabled())
1562 {
1563 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1564 }
1565
1566 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1567 get(CaseIgnoreEqualityMatchingRule.class.getName(),
1568 stackTraceToSingleLineString(e));
1569 logError(message);
1570 }
1571
1572
1573 try
1574 {
1575 EqualityMatchingRule matchingRule =
1576 new CaseIgnoreIA5EqualityMatchingRule();
1577 matchingRule.initializeMatchingRule(null);
1578 registerEqualityMatchingRule(matchingRule, true);
1579 }
1580 catch (Exception e)
1581 {
1582 if (debugEnabled())
1583 {
1584 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1585 }
1586
1587 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1588 get(CaseIgnoreIA5EqualityMatchingRule.class.getName(),
1589 stackTraceToSingleLineString(e));
1590 logError(message);
1591 }
1592
1593
1594 try
1595 {
1596 EqualityMatchingRule matchingRule =
1597 new DistinguishedNameEqualityMatchingRule();
1598 matchingRule.initializeMatchingRule(null);
1599 registerEqualityMatchingRule(matchingRule, true);
1600 }
1601 catch (Exception e)
1602 {
1603 if (debugEnabled())
1604 {
1605 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1606 }
1607
1608 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1609 get(DistinguishedNameEqualityMatchingRule.class.getName(),
1610 stackTraceToSingleLineString(e));
1611 logError(message);
1612 }
1613
1614
1615 try
1616 {
1617 EqualityMatchingRule matchingRule =
1618 new GeneralizedTimeEqualityMatchingRule();
1619 matchingRule.initializeMatchingRule(null);
1620 registerEqualityMatchingRule(matchingRule, true);
1621 }
1622 catch (Exception e)
1623 {
1624 if (debugEnabled())
1625 {
1626 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1627 }
1628
1629 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1630 get(GeneralizedTimeEqualityMatchingRule.class.getName(),
1631 stackTraceToSingleLineString(e));
1632 logError(message);
1633 }
1634
1635
1636 try
1637 {
1638 EqualityMatchingRule matchingRule = new IntegerEqualityMatchingRule();
1639 matchingRule.initializeMatchingRule(null);
1640 registerEqualityMatchingRule(matchingRule, true);
1641 }
1642 catch (Exception e)
1643 {
1644 if (debugEnabled())
1645 {
1646 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1647 }
1648
1649 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1650 get(IntegerEqualityMatchingRule.class.getName(),
1651 stackTraceToSingleLineString(e));
1652 logError(message);
1653 }
1654
1655
1656 try
1657 {
1658 EqualityMatchingRule matchingRule = new OctetStringEqualityMatchingRule();
1659 matchingRule.initializeMatchingRule(null);
1660 registerEqualityMatchingRule(matchingRule, true);
1661 }
1662 catch (Exception e)
1663 {
1664 if (debugEnabled())
1665 {
1666 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1667 }
1668
1669 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1670 get(OctetStringEqualityMatchingRule.class.getName(),
1671 stackTraceToSingleLineString(e));
1672 logError(message);
1673 }
1674
1675
1676 try
1677 {
1678 EqualityMatchingRule matchingRule =
1679 new ObjectIdentifierEqualityMatchingRule();
1680 matchingRule.initializeMatchingRule(null);
1681 registerEqualityMatchingRule(matchingRule, true);
1682 }
1683 catch (Exception e)
1684 {
1685 if (debugEnabled())
1686 {
1687 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1688 }
1689
1690 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1691 get(ObjectIdentifierEqualityMatchingRule.class.getName(),
1692 stackTraceToSingleLineString(e));
1693 logError(message);
1694 }
1695
1696
1697 try
1698 {
1699 EqualityMatchingRule matchingRule =
1700 new TelephoneNumberEqualityMatchingRule();
1701 matchingRule.initializeMatchingRule(null);
1702 registerEqualityMatchingRule(matchingRule, true);
1703 }
1704 catch (Exception e)
1705 {
1706 if (debugEnabled())
1707 {
1708 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1709 }
1710
1711 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1712 get(TelephoneNumberEqualityMatchingRule.class.getName(),
1713 stackTraceToSingleLineString(e));
1714 logError(message);
1715 }
1716
1717
1718 try
1719 {
1720 OrderingMatchingRule matchingRule = new CaseExactOrderingMatchingRule();
1721 matchingRule.initializeMatchingRule(null);
1722 registerOrderingMatchingRule(matchingRule, true);
1723 }
1724 catch (Exception e)
1725 {
1726 if (debugEnabled())
1727 {
1728 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1729 }
1730
1731 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1732 get(CaseExactOrderingMatchingRule.class.getName(),
1733 stackTraceToSingleLineString(e));
1734 logError(message);
1735 }
1736
1737
1738 try
1739 {
1740 OrderingMatchingRule matchingRule = new CaseIgnoreOrderingMatchingRule();
1741 matchingRule.initializeMatchingRule(null);
1742 registerOrderingMatchingRule(matchingRule, true);
1743 }
1744 catch (Exception e)
1745 {
1746 if (debugEnabled())
1747 {
1748 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1749 }
1750
1751 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1752 get(CaseIgnoreOrderingMatchingRule.class.getName(),
1753 stackTraceToSingleLineString(e));
1754 logError(message);
1755 }
1756
1757
1758 try
1759 {
1760 OrderingMatchingRule matchingRule =
1761 new GeneralizedTimeOrderingMatchingRule();
1762 matchingRule.initializeMatchingRule(null);
1763 registerOrderingMatchingRule(matchingRule, true);
1764 }
1765 catch (Exception e)
1766 {
1767 if (debugEnabled())
1768 {
1769 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1770 }
1771
1772 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1773 get(GeneralizedTimeOrderingMatchingRule.class.getName(),
1774 stackTraceToSingleLineString(e));
1775 logError(message);
1776 }
1777
1778
1779 try
1780 {
1781 OrderingMatchingRule matchingRule = new IntegerOrderingMatchingRule();
1782 matchingRule.initializeMatchingRule(null);
1783 registerOrderingMatchingRule(matchingRule, true);
1784 }
1785 catch (Exception e)
1786 {
1787 if (debugEnabled())
1788 {
1789 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1790 }
1791
1792 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1793 get(IntegerOrderingMatchingRule.class.getName(),
1794 stackTraceToSingleLineString(e));
1795 logError(message);
1796 }
1797
1798
1799 try
1800 {
1801 OrderingMatchingRule matchingRule = new OctetStringOrderingMatchingRule();
1802 matchingRule.initializeMatchingRule(null);
1803 registerOrderingMatchingRule(matchingRule, true);
1804 }
1805 catch (Exception e)
1806 {
1807 if (debugEnabled())
1808 {
1809 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1810 }
1811
1812 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1813 get(OctetStringOrderingMatchingRule.class.getName(),
1814 stackTraceToSingleLineString(e));
1815 logError(message);
1816 }
1817
1818
1819 try
1820 {
1821 SubstringMatchingRule matchingRule = new CaseExactSubstringMatchingRule();
1822 matchingRule.initializeMatchingRule(null);
1823 registerSubstringMatchingRule(matchingRule, true);
1824 }
1825 catch (Exception e)
1826 {
1827 if (debugEnabled())
1828 {
1829 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1830 }
1831
1832 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1833 get(CaseExactSubstringMatchingRule.class.getName(),
1834 stackTraceToSingleLineString(e));
1835 logError(message);
1836 }
1837
1838
1839 try
1840 {
1841 SubstringMatchingRule matchingRule =
1842 new CaseExactIA5SubstringMatchingRule();
1843 matchingRule.initializeMatchingRule(null);
1844 registerSubstringMatchingRule(matchingRule, true);
1845 }
1846 catch (Exception e)
1847 {
1848 if (debugEnabled())
1849 {
1850 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1851 }
1852
1853 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1854 get(CaseExactIA5SubstringMatchingRule.class.getName(),
1855 stackTraceToSingleLineString(e));
1856 logError(message);
1857 }
1858
1859
1860 try
1861 {
1862 SubstringMatchingRule matchingRule =
1863 new CaseIgnoreSubstringMatchingRule();
1864 matchingRule.initializeMatchingRule(null);
1865 registerSubstringMatchingRule(matchingRule, true);
1866 }
1867 catch (Exception e)
1868 {
1869 if (debugEnabled())
1870 {
1871 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1872 }
1873
1874 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1875 get(CaseIgnoreSubstringMatchingRule.class.getName(),
1876 stackTraceToSingleLineString(e));
1877 logError(message);
1878 }
1879
1880
1881 try
1882 {
1883 SubstringMatchingRule matchingRule =
1884 new CaseIgnoreIA5SubstringMatchingRule();
1885 matchingRule.initializeMatchingRule(null);
1886 registerSubstringMatchingRule(matchingRule, true);
1887 }
1888 catch (Exception e)
1889 {
1890 if (debugEnabled())
1891 {
1892 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1893 }
1894
1895 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1896 get(CaseIgnoreIA5SubstringMatchingRule.class.getName(),
1897 stackTraceToSingleLineString(e));
1898 logError(message);
1899 }
1900
1901
1902 try
1903 {
1904 SubstringMatchingRule matchingRule =
1905 new OctetStringSubstringMatchingRule();
1906 matchingRule.initializeMatchingRule(null);
1907 registerSubstringMatchingRule(matchingRule, true);
1908 }
1909 catch (Exception e)
1910 {
1911 if (debugEnabled())
1912 {
1913 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1914 }
1915
1916 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1917 get(OctetStringSubstringMatchingRule.class.getName(),
1918 stackTraceToSingleLineString(e));
1919 logError(message);
1920 }
1921
1922
1923 try
1924 {
1925 SubstringMatchingRule matchingRule =
1926 new TelephoneNumberSubstringMatchingRule();
1927 matchingRule.initializeMatchingRule(null);
1928 registerSubstringMatchingRule(matchingRule, true);
1929 }
1930 catch (Exception e)
1931 {
1932 if (debugEnabled())
1933 {
1934 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1935 }
1936
1937 Message message = ERR_CANNOT_BOOTSTRAP_MATCHING_RULE.
1938 get(TelephoneNumberSubstringMatchingRule.class.getName(),
1939 stackTraceToSingleLineString(e));
1940 logError(message);
1941 }
1942 }
1943
1944
1945
1946 /**
1947 * Registers a basic set of attribute syntaxes with the server that should
1948 * always be available regardless of the server configuration and may be
1949 * needed for configuration processing.
1950 */
1951 private void bootstrapAttributeSyntaxes()
1952 {
1953 try
1954 {
1955 AttributeTypeSyntax syntax = new AttributeTypeSyntax();
1956 syntax.initializeSyntax(null);
1957 registerAttributeSyntax(syntax, true);
1958 }
1959 catch (Exception e)
1960 {
1961 if (debugEnabled())
1962 {
1963 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1964 }
1965
1966 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.get(
1967 AttributeTypeSyntax.class.getName(), stackTraceToSingleLineString(e));
1968 logError(message);
1969 }
1970
1971
1972 try
1973 {
1974 defaultBinarySyntax = new BinarySyntax();
1975 defaultBinarySyntax.initializeSyntax(null);
1976 registerAttributeSyntax(defaultBinarySyntax, true);
1977 }
1978 catch (Exception e)
1979 {
1980 if (debugEnabled())
1981 {
1982 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1983 }
1984
1985 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.get(
1986 BinarySyntax.class.getName(), stackTraceToSingleLineString(e));
1987 logError(message);
1988 }
1989
1990
1991 try
1992 {
1993 defaultBooleanSyntax = new BooleanSyntax();
1994 defaultBooleanSyntax.initializeSyntax(null);
1995 registerAttributeSyntax(defaultBooleanSyntax, true);
1996 }
1997 catch (Exception e)
1998 {
1999 if (debugEnabled())
2000 {
2001 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2002 }
2003
2004 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.get(
2005 BooleanSyntax.class.getName(), stackTraceToSingleLineString(e));
2006 logError(message);
2007 }
2008
2009
2010 try
2011 {
2012 defaultStringSyntax = new DirectoryStringSyntax();
2013 defaultStringSyntax.initializeSyntax(null);
2014 registerAttributeSyntax(defaultStringSyntax, true);
2015 defaultSyntax = defaultStringSyntax;
2016 }
2017 catch (Exception e)
2018 {
2019 if (debugEnabled())
2020 {
2021 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2022 }
2023
2024 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.
2025 get(DirectoryStringSyntax.class.getName(),
2026 stackTraceToSingleLineString(e));
2027 logError(message);
2028 }
2029
2030
2031 try
2032 {
2033 defaultDNSyntax = new DistinguishedNameSyntax();
2034 defaultDNSyntax.initializeSyntax(null);
2035 registerAttributeSyntax(defaultDNSyntax, true);
2036 }
2037 catch (Exception e)
2038 {
2039 if (debugEnabled())
2040 {
2041 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2042 }
2043
2044 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.
2045 get(DistinguishedNameSyntax.class.getName(),
2046 stackTraceToSingleLineString(e));
2047 logError(message);
2048 }
2049
2050
2051 try
2052 {
2053 IA5StringSyntax syntax = new IA5StringSyntax();
2054 syntax.initializeSyntax(null);
2055 registerAttributeSyntax(syntax, true);
2056 }
2057 catch (Exception e)
2058 {
2059 if (debugEnabled())
2060 {
2061 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2062 }
2063
2064 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.get(
2065 IA5StringSyntax.class.getName(), stackTraceToSingleLineString(e));
2066 logError(message);
2067 }
2068
2069
2070 try
2071 {
2072 defaultIntegerSyntax = new IntegerSyntax();
2073 defaultIntegerSyntax.initializeSyntax(null);
2074 registerAttributeSyntax(defaultIntegerSyntax, true);
2075 }
2076 catch (Exception e)
2077 {
2078 if (debugEnabled())
2079 {
2080 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2081 }
2082
2083 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.get(
2084 IntegerSyntax.class.getName(), stackTraceToSingleLineString(e));
2085 logError(message);
2086 }
2087
2088
2089 try
2090 {
2091 GeneralizedTimeSyntax syntax = new GeneralizedTimeSyntax();
2092 syntax.initializeSyntax(null);
2093 registerAttributeSyntax(syntax, true);
2094 }
2095 catch (Exception e)
2096 {
2097 if (debugEnabled())
2098 {
2099 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2100 }
2101
2102 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.
2103 get(GeneralizedTimeSyntax.class.getName(),
2104 stackTraceToSingleLineString(e));
2105 logError(message);
2106 }
2107
2108
2109 try
2110 {
2111 ObjectClassSyntax syntax = new ObjectClassSyntax();
2112 syntax.initializeSyntax(null);
2113 registerAttributeSyntax(syntax, true);
2114 }
2115 catch (Exception e)
2116 {
2117 if (debugEnabled())
2118 {
2119 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2120 }
2121
2122 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.get(
2123 ObjectClassSyntax.class.getName(), stackTraceToSingleLineString(e));
2124 logError(message);
2125 }
2126
2127
2128 try
2129 {
2130 OIDSyntax syntax = new OIDSyntax();
2131 syntax.initializeSyntax(null);
2132 registerAttributeSyntax(syntax, true);
2133 }
2134 catch (Exception e)
2135 {
2136 if (debugEnabled())
2137 {
2138 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2139 }
2140
2141 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.get(
2142 OIDSyntax.class.getName(), stackTraceToSingleLineString(e));
2143 logError(message);
2144 }
2145
2146
2147 try
2148 {
2149 TelephoneNumberSyntax syntax = new TelephoneNumberSyntax();
2150 syntax.initializeSyntax(null);
2151 registerAttributeSyntax(syntax, true);
2152 }
2153 catch (Exception e)
2154 {
2155 if (debugEnabled())
2156 {
2157 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2158 }
2159
2160 Message message = ERR_CANNOT_BOOTSTRAP_SYNTAX.
2161 get(TelephoneNumberSyntax.class.getName(),
2162 stackTraceToSingleLineString(e));
2163 logError(message);
2164 }
2165 }
2166
2167
2168
2169 /**
2170 * Retrieves the authenticated users manager for the Directory Server.
2171 *
2172 * @return The authenticated users manager for the Directory Server.
2173 */
2174 public static AuthenticatedUsers getAuthenticatedUsers()
2175 {
2176 return directoryServer.authenticatedUsers;
2177 }
2178
2179
2180
2181 /**
2182 * Initializes the crypto manager for the Directory Server.
2183 *
2184 * @throws ConfigException If a configuration problem is identified while
2185 * initializing the crypto manager.
2186 *
2187 * @throws InitializationException If a problem occurs while initializing
2188 * the crypto manager that is not related
2189 * to the server configuration.
2190 */
2191 public void initializeCryptoManager()
2192 throws ConfigException, InitializationException
2193 {
2194 RootCfg root =
2195 ServerManagementContext.getInstance().getRootConfiguration();
2196 CryptoManagerCfg cryptoManagerCfg = root.getCryptoManager();
2197 cryptoManager = new CryptoManagerImpl(cryptoManagerCfg);
2198 }
2199
2200
2201
2202 /**
2203 * Retrieves a reference to the Directory Server crypto manager.
2204 *
2205 * @return A reference to the Directory Server crypto manager.
2206 */
2207 public static CryptoManagerImpl getCryptoManager()
2208 {
2209 return directoryServer.cryptoManager;
2210 }
2211
2212
2213
2214 /**
2215 * Indicates whether the Directory Server is configured with information about
2216 * one or more mail servers and may therefore be used to send e-mail messages.
2217 *
2218 * @return {@code true} if the Directory Server is configured to be able to
2219 * send e-mail messages, or {@code false} if not.
2220 */
2221 public static boolean mailServerConfigured()
2222 {
2223 return ((directoryServer.mailServerPropertySets != null) &&
2224 (! directoryServer.mailServerPropertySets.isEmpty()));
2225 }
2226
2227
2228
2229 /**
2230 * Specifies the set of mail server properties that should be used for SMTP
2231 * communication.
2232 *
2233 * @param mailServerPropertySets A list of {@code Properties} objects that
2234 * provide information that can be used to
2235 * communicate with SMTP servers.
2236 */
2237 public static void setMailServerPropertySets(List<Properties>
2238 mailServerPropertySets)
2239 {
2240 directoryServer.mailServerPropertySets = mailServerPropertySets;
2241 }
2242
2243
2244
2245 /**
2246 * Retrieves the sets of information about the mail servers configured for use
2247 * by the Directory Server.
2248 *
2249 * @return The sets of information about the mail servers configured for use
2250 * by the Directory Server.
2251 */
2252 public static List<Properties> getMailServerPropertySets()
2253 {
2254 return directoryServer.mailServerPropertySets;
2255 }
2256
2257
2258
2259 /**
2260 * Initializes the set of alert handlers defined in the Directory Server.
2261 *
2262 * @throws ConfigException If there is a configuration problem with any of
2263 * the alert handlers.
2264 *
2265 * @throws InitializationException If a problem occurs while initializing
2266 * the alert handlers that is not related to
2267 * the server configuration.
2268 */
2269 private void initializeAlertHandlers()
2270 throws ConfigException, InitializationException
2271 {
2272 new AlertHandlerConfigManager().initializeAlertHandlers();
2273 }
2274
2275
2276
2277
2278 /**
2279 * Initializes the schema elements for the Directory Server, including the
2280 * matching rules, attribute syntaxes, attribute types, and object classes.
2281 *
2282 * @throws ConfigException If there is a configuration problem with any of
2283 * the schema elements.
2284 *
2285 * @throws InitializationException If a problem occurs while initializing
2286 * the schema elements that is not related
2287 * to the server configuration.
2288 */
2289 public void initializeSchema()
2290 throws ConfigException, InitializationException
2291 {
2292 // Create the schema configuration manager, and initialize the schema from
2293 // the configuration.
2294 schemaConfigManager = new SchemaConfigManager();
2295 schema = schemaConfigManager.getSchema();
2296
2297 schemaConfigManager.initializeMatchingRules();
2298 schemaConfigManager.initializeAttributeSyntaxes();
2299 schemaConfigManager.initializeSchemaFromFiles();
2300
2301 // With server schema in place set compressed schema.
2302 compressedSchema = new DefaultCompressedSchema();
2303
2304 // At this point we have a problem, because none of the configuration is
2305 // usable because it was all read before we had a schema (and therefore all
2306 // of the attribute types and objectclasses are bogus and won't let us find
2307 // anything). So we have to re-read the configuration so that we can
2308 // continue the necessary startup process. In the process, we want to
2309 // preserve any configuration add/delete/change listeners that might have
2310 // been registered with the old configuration (which will primarily be
2311 // schema elements) so they can be re-registered with the new configuration.
2312 LinkedHashMap<String,List<ConfigAddListener>> addListeners =
2313 new LinkedHashMap<String,List<ConfigAddListener>>();
2314 LinkedHashMap<String,List<ConfigDeleteListener>> deleteListeners =
2315 new LinkedHashMap<String,List<ConfigDeleteListener>>();
2316 LinkedHashMap<String,List<ConfigChangeListener>> changeListeners =
2317 new LinkedHashMap<String,List<ConfigChangeListener>>();
2318 getChangeListeners(configHandler.getConfigRootEntry(), addListeners,
2319 deleteListeners, changeListeners);
2320
2321 try
2322 {
2323 configHandler.finalizeConfigHandler();
2324 }
2325 catch (Exception e)
2326 {
2327 if (debugEnabled())
2328 {
2329 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2330 }
2331 }
2332
2333 try
2334 {
2335 configHandler.initializeConfigHandler(configFile.getAbsolutePath(), true);
2336 }
2337 catch (InitializationException ie)
2338 {
2339 if (debugEnabled())
2340 {
2341 TRACER.debugCaught(DebugLogLevel.ERROR, ie);
2342 }
2343
2344 throw ie;
2345 }
2346 catch (Exception e)
2347 {
2348 if (debugEnabled())
2349 {
2350 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2351 }
2352
2353 Message message =
2354 ERR_CANNOT_INITIALIZE_CONFIG_HANDLER.get(
2355 String.valueOf(configClass),
2356 String.valueOf(configFile),
2357 e.getLocalizedMessage());
2358 throw new InitializationException(message);
2359 }
2360
2361
2362 // Re-register all of the change listeners with the configuration.
2363 for (String dnStr : addListeners.keySet())
2364 {
2365 try
2366 {
2367 DN dn = DN.decode(dnStr);
2368 for (ConfigAddListener listener : addListeners.get(dnStr))
2369 {
2370 configHandler.getConfigEntry(dn).registerAddListener(listener);
2371 }
2372 }
2373 catch (DirectoryException de)
2374 {
2375 // This should never happen, so we'll just re-throw it.
2376 throw new InitializationException(de.getMessageObject());
2377 }
2378 }
2379
2380 for (String dnStr : deleteListeners.keySet())
2381 {
2382 try
2383 {
2384 DN dn = DN.decode(dnStr);
2385 for (ConfigDeleteListener listener : deleteListeners.get(dnStr))
2386 {
2387 configHandler.getConfigEntry(dn).registerDeleteListener(listener);
2388 }
2389 }
2390 catch (DirectoryException de)
2391 {
2392 // This should never happen, so we'll just re-throw it.
2393 throw new InitializationException(de.getMessageObject());
2394 }
2395 }
2396
2397 for (String dnStr : changeListeners.keySet())
2398 {
2399 try
2400 {
2401 DN dn = DN.decode(dnStr);
2402 for (ConfigChangeListener listener : changeListeners.get(dnStr))
2403 {
2404 configHandler.getConfigEntry(dn).registerChangeListener(listener);
2405 }
2406 }
2407 catch (DirectoryException de)
2408 {
2409 // This should never happen, so we'll just re-throw it.
2410 throw new InitializationException(de.getMessageObject());
2411 }
2412 }
2413 }
2414
2415
2416
2417 /**
2418 * Retrieves the default compressed schema manager for the Directory Server.
2419 *
2420 * @return The default compressed schema manager for the Directory Server.
2421 */
2422 public static CompressedSchema getDefaultCompressedSchema()
2423 {
2424 return directoryServer.compressedSchema;
2425 }
2426
2427
2428
2429 /**
2430 * Gets all of the add, delete, and change listeners from the provided
2431 * configuration entry and all of its descendants and puts them in the
2432 * appropriate lists.
2433 *
2434 * @param configEntry The configuration entry to be processed, along
2435 * with all of its descendants.
2436 * @param addListeners The set of add listeners mapped to the DN of the
2437 * corresponding configuration entry.
2438 * @param deleteListeners The set of delete listeners mapped to the DN of
2439 * the corresponding configuration entry.
2440 * @param changeListeners The set of change listeners mapped to the DN of
2441 * the corresponding configuration entry.
2442 */
2443 private void getChangeListeners(ConfigEntry configEntry,
2444 LinkedHashMap<String,List<ConfigAddListener>> addListeners,
2445 LinkedHashMap<String,List<ConfigDeleteListener>> deleteListeners,
2446 LinkedHashMap<String,List<ConfigChangeListener>> changeListeners)
2447 {
2448 CopyOnWriteArrayList<ConfigAddListener> cfgAddListeners =
2449 configEntry.getAddListeners();
2450 if ((cfgAddListeners != null) && (cfgAddListeners.size() > 0))
2451 {
2452 addListeners.put(configEntry.getDN().toString(), cfgAddListeners);
2453 }
2454
2455 CopyOnWriteArrayList<ConfigDeleteListener> cfgDeleteListeners =
2456 configEntry.getDeleteListeners();
2457 if ((cfgDeleteListeners != null) && (cfgDeleteListeners.size() > 0))
2458 {
2459 deleteListeners.put(configEntry.getDN().toString(), cfgDeleteListeners);
2460 }
2461
2462 CopyOnWriteArrayList<ConfigChangeListener> cfgChangeListeners =
2463 configEntry.getChangeListeners();
2464 if ((cfgChangeListeners != null) && (cfgChangeListeners.size() > 0))
2465 {
2466 changeListeners.put(configEntry.getDN().toString(), cfgChangeListeners);
2467 }
2468
2469 for (ConfigEntry child : configEntry.getChildren().values())
2470 {
2471 getChangeListeners(child, addListeners, deleteListeners, changeListeners);
2472 }
2473 }
2474
2475
2476
2477 /**
2478 * Retrieves the set of backend initialization listeners that have been
2479 * registered with the Directory Server. The contents of the returned set
2480 * must not be altered.
2481 *
2482 * @return The set of backend initialization listeners that have been
2483 * registered with the Directory Server.
2484 */
2485 public static Set<BackendInitializationListener>
2486 getBackendInitializationListeners()
2487 {
2488 return directoryServer.backendInitializationListeners;
2489 }
2490
2491
2492
2493 /**
2494 * Registers the provided backend initialization listener with the Directory
2495 * Server.
2496 *
2497 * @param listener The backend initialization listener to register with the
2498 * Directory Server.
2499 */
2500 public static void registerBackendInitializationListener(
2501 BackendInitializationListener listener)
2502 {
2503 directoryServer.backendInitializationListeners.add(listener);
2504 }
2505
2506
2507
2508 /**
2509 * Deegisters the provided backend initialization listener with the Directory
2510 * Server.
2511 *
2512 * @param listener The backend initialization listener to deregister with
2513 * the Directory Server.
2514 */
2515 public static void deregisterBackendInitializationListener(
2516 BackendInitializationListener listener)
2517 {
2518 directoryServer.backendInitializationListeners.remove(listener);
2519 }
2520
2521
2522
2523 /**
2524 * Initializes the set of backends defined in the Directory Server.
2525 *
2526 * @throws ConfigException If there is a configuration problem with any of
2527 * the backends.
2528 *
2529 * @throws InitializationException If a problem occurs while initializing
2530 * the backends that is not related to the
2531 * server configuration.
2532 */
2533 private void initializeBackends()
2534 throws ConfigException, InitializationException
2535 {
2536 backendConfigManager = new BackendConfigManager();
2537 backendConfigManager.initializeBackendConfig();
2538
2539
2540 // Make sure to initialize the root DSE backend separately after all other
2541 // backends.
2542 RootDSEBackendCfg rootDSECfg;
2543 try
2544 {
2545 RootCfg root =
2546 ServerManagementContext.getInstance().getRootConfiguration();
2547 rootDSECfg = root.getRootDSEBackend();
2548 }
2549 catch (Exception e)
2550 {
2551 if (debugEnabled())
2552 {
2553 TRACER.debugCaught(DebugLogLevel.ERROR, e);
2554 }
2555
2556 Message message = ERR_CANNOT_GET_ROOT_DSE_CONFIG_ENTRY.get(
2557 stackTraceToSingleLineString(e));
2558 throw new InitializationException(message, e);
2559 }
2560
2561 rootDSEBackend = new RootDSEBackend();
2562 rootDSEBackend.configureBackend(rootDSECfg);
2563 rootDSEBackend.initializeBackend();
2564 }
2565
2566
2567 /**
2568 * Deregisters a workflow with the default network group and
2569 * deregisters the workflow with the server. This method is
2570 * intended to be called when workflow configuration mode is
2571 * auto.
2572 *
2573 * @param baseDN the DN of the workflow to deregister
2574 */
2575 private static void deregisterWorkflowWithDefaultNetworkGroup(
2576 DN baseDN
2577 )
2578 {
2579 // Get the default network group and deregister all the workflows
2580 // being configured for the backend (there is one worklfow per
2581 // backend base DN).
2582 NetworkGroup defaultNetworkGroup = NetworkGroup.getDefaultNetworkGroup();
2583 Workflow workflow = defaultNetworkGroup.deregisterWorkflow(baseDN);
2584 WorkflowImpl workflowImpl = (WorkflowImpl) workflow;
2585 workflowImpl.deregister();
2586 }
2587
2588
2589 /**
2590 * Creates a set of workflows for a given backend and registers the
2591 * workflows with the default network group. There are as many workflows
2592 * as base DNs defined in the backend. This method is intended
2593 * to be called when workflow configuration mode is auto.
2594 *
2595 * @param backend the backend handled by the workflow
2596 *
2597 * @throws DirectoryException If the workflow ID for the provided
2598 * workflow conflicts with the workflow
2599 * ID of an existing workflow.
2600 */
2601 public static void createAndRegisterWorkflowsWithDefaultNetworkGroup(
2602 Backend backend
2603 ) throws DirectoryException
2604 {
2605 // Create a worklfow for each backend base DN and register the workflow
2606 // with the default network group.
2607 for (DN curBaseDN: backend.getBaseDNs())
2608 {
2609 WorkflowImpl workflowImpl = createWorkflow(curBaseDN, backend);
2610 registerWorkflowWithDefaultNetworkGroup(workflowImpl);
2611 }
2612 }
2613
2614
2615 /**
2616 * Creates one workflow for a given base DN in a backend.
2617 *
2618 * @param baseDN the base DN of the workflow to create
2619 * @param backend the backend handled by the workflow
2620 *
2621 * @return the newly created workflow
2622 *
2623 * @throws DirectoryException If the workflow ID for the provided
2624 * workflow conflicts with the workflow
2625 * ID of an existing workflow.
2626 */
2627 public static WorkflowImpl createWorkflow(
2628 DN baseDN,
2629 Backend backend
2630 ) throws DirectoryException
2631 {
2632 String backendID = backend.getBackendID();
2633
2634 // Create a root workflow element to encapsulate the backend
2635 LocalBackendWorkflowElement rootWE =
2636 LocalBackendWorkflowElement.createAndRegister(backendID, backend);
2637
2638 // The workflow ID is "backendID + baseDN".
2639 // We cannot use backendID as workflow identifier because a backend
2640 // may handle several base DNs. We cannot use baseDN either because
2641 // we might want to configure several workflows handling the same
2642 // baseDN through different network groups. So a mix of both
2643 // backendID and baseDN should be ok.
2644 String workflowID = backend.getBackendID() + "#" + baseDN.toString();
2645
2646 // Create the worklfow for the base DN and register the workflow with
2647 // the server.
2648 WorkflowImpl workflowImpl = new WorkflowImpl(
2649 workflowID, baseDN, (WorkflowElement) rootWE);
2650 workflowImpl.register();
2651
2652 return workflowImpl;
2653 }
2654
2655
2656 /**
2657 * Registers a workflow with the default network group. This method
2658 * is intended to be called when workflow configuration mode is auto.
2659 *
2660 * @param workflowImpl The workflow to register with the
2661 * default network group
2662 *
2663 * @throws DirectoryException If the workflow is already registered with
2664 * the default network group
2665 */
2666 private static void registerWorkflowWithDefaultNetworkGroup(
2667 WorkflowImpl workflowImpl
2668 ) throws DirectoryException
2669 {
2670 NetworkGroup defaultNetworkGroup = NetworkGroup.getDefaultNetworkGroup();
2671 defaultNetworkGroup.registerWorkflow(workflowImpl);
2672 }
2673
2674
2675 /**
2676 * Creates the missing workflows, one for the config backend and one for
2677 * the rootDSE backend.
2678 *
2679 * This method should be invoked whatever may be the workflow
2680 * configuration mode because config backend and rootDSE backend
2681 * will not have any configuration section, ever.
2682 *
2683 * @throws ConfigException If there is a configuration problem with any of
2684 * the workflows.
2685 */
2686 private void createAndRegisterRemainingWorkflows()
2687 throws ConfigException
2688 {
2689 try
2690 {
2691 createAndRegisterWorkflowsWithDefaultNetworkGroup (configHandler);
2692 createAndRegisterWorkflowsWithDefaultNetworkGroup (rootDSEBackend);
2693 }
2694 catch (DirectoryException de)
2695 {
2696 throw new ConfigException(de.getMessageObject());
2697 }
2698 }
2699
2700
2701 /**
2702 * Reconfigures the workflows when configuration mode has changed.
2703 * This method is invoked when workflows need to be reconfigured
2704 * while the server is running. If the reconfiguration is valid
2705 * then the method update the workflow configuration mode.
2706 *
2707 * @param oldMode the current workflow configuration mode
2708 * @param newMode the new workflow configuration mode
2709 */
2710 public static void reconfigureWorkflows(
2711 WorkflowConfigurationMode oldMode,
2712 WorkflowConfigurationMode newMode)
2713 {
2714 if ((oldMode == WorkflowConfigurationMode.AUTO)
2715 && (newMode == WorkflowConfigurationMode.MANUAL))
2716 {
2717 // move to manual mode
2718 try
2719 {
2720 directoryServer.configureWorkflowsManual();
2721 setWorkflowConfigurationMode(newMode);
2722 }
2723 catch (Exception e)
2724 {
2725 // rollback to auto mode
2726 try
2727 {
2728 directoryServer.configureWorkflowsAuto();
2729 }
2730 catch (Exception ee)
2731 {
2732 // rollback to auto mode is failing too!!
2733 // well, just log an error message and suggest the admin
2734 // to restart the server with the last valid config...
2735 Message message = ERR_CONFIG_WORKFLOW_CANNOT_CONFIGURE_MANUAL.get();
2736 logError(message);
2737 }
2738 }
2739 }
2740 else if ((oldMode == WorkflowConfigurationMode.MANUAL)
2741 && (newMode == WorkflowConfigurationMode.AUTO))
2742 {
2743 // move to auto mode
2744 try
2745 {
2746 directoryServer.configureWorkflowsAuto();
2747 setWorkflowConfigurationMode(newMode);
2748 }
2749 catch (Exception e)
2750 {
2751 // rollback to manual mode
2752 try
2753 {
2754 directoryServer.configureWorkflowsManual();
2755 }
2756 catch (Exception ee)
2757 {
2758 // rollback to auto mode is failing too!!
2759 // well, just log an error message and suggest the admin
2760 // to restart the server with the last valid config...
2761 Message message = ERR_CONFIG_WORKFLOW_CANNOT_CONFIGURE_AUTO.get();
2762 logError(message);
2763 }
2764 }
2765 }
2766 }
2767
2768
2769 /**
2770 * Configures the workflows when configuration mode is manual.
2771 *
2772 * @throws ConfigException If there is a problem with the Directory Server
2773 * configuration that prevents a critical component
2774 * from being instantiated.
2775 *
2776 * @throws InitializationException If some other problem occurs while
2777 * attempting to initialize and start the
2778 * Directory Server.
2779 */
2780 private void configureWorkflowsManual()
2781 throws ConfigException, InitializationException
2782 {
2783 // First of all re-initialize the current workflow configuration
2784 NetworkGroup.resetConfig();
2785 WorkflowImpl.resetConfig();
2786 WorkflowElement.resetConfig();
2787
2788 // Then configure the workflows
2789 workflowElementConfigManager = new WorkflowElementConfigManager();
2790 workflowElementConfigManager.initializeWorkflowElements();
2791
2792 workflowConfigManager = new WorkflowConfigManager();
2793 workflowConfigManager.initializeWorkflows();
2794
2795 networkGroupConfigManager = new NetworkGroupConfigManager();
2796 networkGroupConfigManager.initializeNetworkGroups();
2797
2798 // We now need to complete the workflow creation for the
2799 // config backend and rootDSE backend.
2800 createAndRegisterRemainingWorkflows();
2801 }
2802
2803
2804 /**
2805 * Configures the workflows when configuration mode is auto.
2806 *
2807 * @throws ConfigException If there is a problem with the Directory Server
2808 * configuration that prevents a critical component
2809 * from being instantiated.
2810 */
2811 private void configureWorkflowsAuto() throws ConfigException
2812 {
2813 // First of all re-initialize the current workflow configuration
2814 NetworkGroup.resetConfig();
2815 WorkflowImpl.resetConfig();
2816 WorkflowElement.resetConfig();
2817
2818 // For each base DN in a backend create a workflow and register
2819 // the workflow with the default network group
2820 Map<String, Backend> backends = getBackends();
2821 for (String backendID: backends.keySet())
2822 {
2823 Backend backend = backends.get(backendID);
2824 for (DN baseDN: backend.getBaseDNs())
2825 {
2826 WorkflowImpl workflowImpl;
2827 try
2828 {
2829 workflowImpl = createWorkflow(baseDN, backend);
2830 registerWorkflowWithDefaultNetworkGroup(workflowImpl);
2831 }
2832 catch (DirectoryException e)
2833 {
2834 // TODO Auto-generated catch block
2835 throw new ConfigException(e.getMessageObject());
2836 }
2837 }
2838 }
2839
2840 // We now need to complete the workflow creation for the
2841 // config backend and rootDSE backend.
2842 createAndRegisterRemainingWorkflows();
2843 }
2844
2845
2846 /**
2847 * Initializes the Directory Server group manager.
2848 *
2849 * @throws ConfigException If there is a configuration problem with any of
2850 * the group implementations.
2851 *
2852 * @throws InitializationException If a problem occurs while initializing
2853 * the group manager that is not related to
2854 * the server configuration.
2855 */
2856 public void initializeGroupManager()
2857 throws ConfigException, InitializationException
2858 {
2859 groupManager = new GroupManager();
2860 groupManager.initializeGroupImplementations();
2861
2862 // The configuration backend has already been registered by this point
2863 // so we need to handle it explicitly.
2864 groupManager.performBackendInitializationProcessing(configHandler);
2865 }
2866
2867
2868
2869 /**
2870 * Retrieves the Directory Server group manager.
2871 *
2872 * @return The Directory Server group manager.
2873 */
2874 public static GroupManager getGroupManager()
2875 {
2876 return directoryServer.groupManager;
2877 }
2878
2879
2880
2881 /**
2882 * Initializes the set of supported controls for the Directory Server.
2883 *
2884 * @throws ConfigException If there is a configuration problem with the
2885 * list of supported controls.
2886 *
2887 * @throws InitializationException If a problem occurs while initializing
2888 * the set of supported controls that is not
2889 * related to the server configuration.
2890 */
2891 private void initializeSupportedControls()
2892 throws ConfigException, InitializationException
2893 {
2894 supportedControls.add(OID_LDAP_ASSERTION);
2895 supportedControls.add(OID_LDAP_READENTRY_PREREAD);
2896 supportedControls.add(OID_LDAP_READENTRY_POSTREAD);
2897 supportedControls.add(OID_LDAP_NOOP_OPENLDAP_ASSIGNED);
2898 supportedControls.add(OID_PERSISTENT_SEARCH);
2899 supportedControls.add(OID_PROXIED_AUTH_V1);
2900 supportedControls.add(OID_PROXIED_AUTH_V2);
2901 supportedControls.add(OID_AUTHZID_REQUEST);
2902 supportedControls.add(OID_MATCHED_VALUES);
2903 supportedControls.add(OID_LDAP_SUBENTRIES);
2904 supportedControls.add(OID_PASSWORD_POLICY_CONTROL);
2905 supportedControls.add(OID_REAL_ATTRS_ONLY);
2906 supportedControls.add(OID_VIRTUAL_ATTRS_ONLY);
2907 supportedControls.add(OID_ACCOUNT_USABLE_CONTROL);
2908 }
2909
2910
2911
2912 /**
2913 * Initializes the set of supported features for the Directory Server.
2914 *
2915 * @throws ConfigException If there is a configuration problem with the
2916 * list of supported features.
2917 *
2918 * @throws InitializationException If a problem occurs while initializing
2919 * the set of supported features that is not
2920 * related to the server configuration.
2921 */
2922 private void initializeSupportedFeatures()
2923 throws ConfigException, InitializationException
2924 {
2925 supportedFeatures.add(OID_ALL_OPERATIONAL_ATTRS_FEATURE);
2926 supportedFeatures.add(OID_MODIFY_INCREMENT_FEATURE);
2927 supportedFeatures.add(OID_TRUE_FALSE_FILTERS_FEATURE);
2928 }
2929
2930
2931
2932 /**
2933 * Initializes the set of identity mappers for the Directory Server.
2934 *
2935 * @throws ConfigException If there is a configuration problem with any of
2936 * the extended operation handlers.
2937 *
2938 * @throws InitializationException If a problem occurs while initializing
2939 * the extended operation handlers that is
2940 * not related to the server configuration.
2941 */
2942 private void initializeIdentityMappers()
2943 throws ConfigException, InitializationException
2944 {
2945 identityMapperConfigManager = new IdentityMapperConfigManager();
2946 identityMapperConfigManager.initializeIdentityMappers();
2947 }
2948
2949
2950
2951 /**
2952 * Initializes the set of extended operation handlers for the Directory
2953 * Server.
2954 *
2955 * @throws ConfigException If there is a configuration problem with any of
2956 * the extended operation handlers.
2957 *
2958 * @throws InitializationException If a problem occurs while initializing
2959 * the extended operation handlers that is
2960 * not related to the server configuration.
2961 */
2962 private void initializeExtendedOperations()
2963 throws ConfigException, InitializationException
2964 {
2965 extendedOperationConfigManager = new ExtendedOperationConfigManager();
2966 extendedOperationConfigManager.initializeExtendedOperationHandlers();
2967 }
2968
2969
2970
2971 /**
2972 * Initializes the set of SASL mechanism handlers for the Directory Server.
2973 *
2974 * @throws ConfigException If there is a configuration problem with any of
2975 * the SASL mechanism handlers.
2976 *
2977 * @throws InitializationException If a problem occurs while initializing
2978 * the SASL mechanism handlers that is not
2979 * related to the server configuration.
2980 */
2981 private void initializeSASLMechanisms()
2982 throws ConfigException, InitializationException
2983 {
2984 saslConfigManager = new SASLConfigManager();
2985 saslConfigManager.initializeSASLMechanismHandlers();
2986 }
2987
2988
2989
2990 /**
2991 * Initializes the set of virtual attributes that should be defined in the
2992 * Directory Server.
2993 *
2994 * @throws ConfigException If there is a configuration problem with any of
2995 * the virtual attribute handlers.
2996 *
2997 * @throws InitializationException If a problem occurs while initializing
2998 * the virtual attribute handlers that is
2999 * not related to the server configuration.
3000 */
3001 private void initializeVirtualAttributes()
3002 throws ConfigException, InitializationException
3003 {
3004 virtualAttributeConfigManager = new VirtualAttributeConfigManager();
3005 virtualAttributeConfigManager.initializeVirtualAttributes();
3006 }
3007
3008
3009
3010 /**
3011 * Initializes the set of connection handlers that should be defined in the
3012 * Directory Server.
3013 *
3014 * @throws ConfigException If there is a configuration problem with any of
3015 * the connection handlers.
3016 *
3017 * @throws InitializationException If a problem occurs while initializing
3018 * the connection handlers that is not
3019 * related to the server configuration.
3020 */
3021 private void initializeConnectionHandlers()
3022 throws ConfigException, InitializationException
3023 {
3024 connectionHandlerConfigManager = new ConnectionHandlerConfigManager();
3025 connectionHandlerConfigManager.initializeConnectionHandlerConfig();
3026 }
3027
3028
3029
3030 /**
3031 * Initializes the set of password policy components for use by the Directory
3032 * Server.
3033 *
3034 * @throws ConfigException If there is a configuration problem with any of
3035 * the password policy components.
3036 *
3037 * @throws InitializationException If a problem occurs while initializing
3038 * the password policy components that is
3039 * not related to the server configuration.
3040 */
3041 public void initializePasswordPolicyComponents()
3042 throws ConfigException, InitializationException
3043 {
3044 // Initialize all the password storage schemes.
3045 storageSchemeConfigManager = new PasswordStorageSchemeConfigManager();
3046 storageSchemeConfigManager.initializePasswordStorageSchemes();
3047
3048
3049 // Initialize all the password validators.
3050 passwordValidatorConfigManager = new PasswordValidatorConfigManager();
3051 passwordValidatorConfigManager.initializePasswordValidators();
3052
3053
3054 // Initialize all the password generators.
3055 passwordGeneratorConfigManager = new PasswordGeneratorConfigManager();
3056 passwordGeneratorConfigManager.initializePasswordGenerators();
3057
3058
3059 // Initialize the account status notification handlers.
3060 accountStatusNotificationHandlerConfigManager =
3061 new AccountStatusNotificationHandlerConfigManager();
3062 accountStatusNotificationHandlerConfigManager.
3063 initializeNotificationHandlers();
3064
3065
3066 // Initialize all the password policies.
3067 passwordPolicyConfigManager = new PasswordPolicyConfigManager();
3068 passwordPolicyConfigManager.initializePasswordPolicies();
3069 }
3070
3071
3072
3073 /**
3074 * Retrieves the operating system on which the Directory Server is running.
3075 *
3076 * @return The operating system on which the Directory Server is running.
3077 */
3078 public static OperatingSystem getOperatingSystem()
3079 {
3080 return directoryServer.operatingSystem;
3081 }
3082
3083
3084
3085 /**
3086 * Retrieves the thread group that should be used by all threads associated
3087 * with the Directory Server.
3088 *
3089 * @return The thread group that should be used by all threads associated
3090 * with the Directory Server.
3091 */
3092 public static ThreadGroup getDirectoryThreadGroup()
3093 {
3094 return directoryServer.directoryThreadGroup;
3095 }
3096
3097
3098
3099 /**
3100 * Retrieves a reference to the Directory Server configuration handler.
3101 *
3102 * @return A reference to the Directory Server configuration handler.
3103 */
3104 public static ConfigHandler getConfigHandler()
3105 {
3106 return directoryServer.configHandler;
3107 }
3108
3109
3110
3111 /**
3112 * Initializes the set of plugins defined in the Directory Server.
3113 *
3114 * @throws ConfigException If there is a configuration problem with any of
3115 * the Directory Server plugins.
3116 *
3117 * @throws InitializationException If a problem occurs while initializing
3118 * the plugins that is not related to the
3119 * server configuration.
3120 */
3121 public void initializePlugins()
3122 throws ConfigException, InitializationException
3123 {
3124 pluginConfigManager.initializePluginConfig(null);
3125 }
3126
3127
3128
3129 /**
3130 * Initializes the set of plugins defined in the Directory Server. Only the
3131 * specified types of plugins will be initialized.
3132 *
3133 * @param pluginTypes The set of plugin types for the plugins to
3134 * initialize.
3135 *
3136 * @throws ConfigException If there is a configuration problem with any of
3137 * the Directory Server plugins.
3138 *
3139 * @throws InitializationException If a problem occurs while initializing
3140 * the plugins that is not related to the
3141 * server configuration.
3142 */
3143 public void initializePlugins(Set<PluginType> pluginTypes)
3144 throws ConfigException, InitializationException
3145 {
3146 pluginConfigManager = new PluginConfigManager();
3147 pluginConfigManager.initializePluginConfig(pluginTypes);
3148 }
3149
3150
3151
3152 /**
3153 * Retrieves a reference to the Directory Server plugin configuration manager.
3154 *
3155 * @return A reference to the Directory Server plugin configuration manager.
3156 */
3157 public static PluginConfigManager getPluginConfigManager()
3158 {
3159 return directoryServer.pluginConfigManager;
3160 }
3161
3162
3163
3164 /**
3165 * Retrieves the requested entry from the Directory Server configuration.
3166 *
3167 * @param entryDN The DN of the configuration entry to retrieve.
3168 *
3169 * @return The requested entry from the Directory Server configuration.
3170 *
3171 * @throws ConfigException If a problem occurs while trying to retrieve the
3172 * requested entry.
3173 */
3174 public static ConfigEntry getConfigEntry(DN entryDN)
3175 throws ConfigException
3176 {
3177 return directoryServer.configHandler.getConfigEntry(entryDN);
3178 }
3179
3180
3181
3182 /**
3183 * Retrieves the path to the root directory for this instance of the Directory
3184 * Server.
3185 *
3186 * @return The path to the root directory for this instance of the Directory
3187 * Server.
3188 */
3189 public static String getServerRoot()
3190 {
3191 if (directoryServer.configHandler == null)
3192 {
3193 File serverRoot = directoryServer.environmentConfig.getServerRoot();
3194 if (serverRoot != null)
3195 {
3196 return serverRoot.getAbsolutePath();
3197 }
3198
3199 // We don't know where the server root is, so we'll have to assume it's
3200 // the current working directory.
3201 return System.getProperty("user.dir");
3202 }
3203 else
3204 {
3205 return directoryServer.configHandler.getServerRoot();
3206 }
3207 }
3208
3209 /**
3210 * Retrieves the time that the Directory Server was started, in milliseconds
3211 * since the epoch.
3212 *
3213 * @return The time that the Directory Server was started, in milliseconds
3214 * since the epoch.
3215 */
3216 public static long getStartTime()
3217 {
3218 return directoryServer.startUpTime;
3219 }
3220
3221
3222
3223 /**
3224 * Retrieves the time that the Directory Server was started, formatted in UTC.
3225 *
3226 * @return The time that the Directory Server was started, formatted in UTC.
3227 */
3228 public static String getStartTimeUTC()
3229 {
3230 return directoryServer.startTimeUTC;
3231 }
3232
3233
3234
3235 /**
3236 * Retrieves a reference to the Directory Server schema.
3237 *
3238 * @return A reference to the Directory Server schema.
3239 */
3240 public static Schema getSchema()
3241 {
3242 return directoryServer.schema;
3243 }
3244
3245
3246
3247 /**
3248 * Replaces the Directory Server schema with the provided schema.
3249 *
3250 * @param schema The new schema to use for the Directory Server.
3251 */
3252 public static void setSchema(Schema schema)
3253 {
3254 directoryServer.schema = schema;
3255 }
3256
3257
3258
3259 /**
3260 * Retrieves a list of modifications detailing any schema changes that may
3261 * have been made with the server offline (e.g., by directly editing the
3262 * schema configuration files). Note that this information will not be
3263 * available until the server backends (and in particular, the schema backend)
3264 * have been initialized.
3265 *
3266 * @return A list of modifications detailing any schema changes that may have
3267 * been made with the server offline, or an empty list if no offline
3268 * schema changes have been detected.
3269 */
3270 public static List<Modification> getOfflineSchemaChanges()
3271 {
3272 return directoryServer.offlineSchemaChanges;
3273 }
3274
3275
3276
3277 /**
3278 * Specifies a list of modifications detailing any schema changes that may
3279 * have been made with the server offline.
3280 *
3281 * @param offlineSchemaChanges A list of modifications detailing any schema
3282 * changes that may have been made with the
3283 * server offline. It must not be {@code null}.
3284 */
3285 public static void setOfflineSchemaChanges(List<Modification>
3286 offlineSchemaChanges)
3287 {
3288 ensureNotNull(offlineSchemaChanges);
3289
3290 directoryServer.offlineSchemaChanges = offlineSchemaChanges;
3291 }
3292
3293
3294
3295 /**
3296 * Retrieves the set of matching rules registered with the Directory Server.
3297 * The mapping will be between the lowercase name or OID for each matching
3298 * rule and the matching rule implementation. The same matching rule instance
3299 * may be included multiple times with different keys.
3300 *
3301 * @return The set of matching rules registered with the Directory Server.
3302 */
3303 public static ConcurrentHashMap<String,MatchingRule> getMatchingRules()
3304 {
3305 return directoryServer.schema.getMatchingRules();
3306 }
3307
3308
3309
3310 /**
3311 * Retrieves the set of encoded matching rules that have been defined in the
3312 * Directory Server.
3313 *
3314 * @return The set of encoded matching rules that have been defined in the
3315 * Directory Server.
3316 */
3317 public static LinkedHashSet<AttributeValue> getMatchingRuleSet()
3318 {
3319 return directoryServer.schema.getMatchingRuleSet();
3320 }
3321
3322
3323
3324 /**
3325 * Retrieves the matching rule with the specified name or OID.
3326 *
3327 * @param lowerName The lowercase name or OID for the matching rule to
3328 * retrieve.
3329 *
3330 * @return The requested matching rule, or <CODE>null</CODE> if no such
3331 * matching rule has been defined in the server.
3332 */
3333 public static MatchingRule getMatchingRule(String lowerName)
3334 {
3335 return directoryServer.schema.getMatchingRule(lowerName);
3336 }
3337
3338
3339
3340 /**
3341 * Registers the provided matching rule with the Directory Server.
3342 *
3343 * @param matchingRule The matching rule to register with the server.
3344 * @param overwriteExisting Indicates whether to overwrite an existing
3345 * mapping if there are any conflicts (i.e.,
3346 * another matching rule with the same OID or
3347 * name).
3348 *
3349 * @throws DirectoryException If a conflict is encountered and the
3350 * <CODE>overwriteExisting</CODE> flag is set to
3351 * <CODE>false</CODE>
3352 */
3353 public static void registerMatchingRule(MatchingRule matchingRule,
3354 boolean overwriteExisting)
3355 throws DirectoryException
3356 {
3357 directoryServer.schema.registerMatchingRule(matchingRule,
3358 overwriteExisting);
3359 }
3360
3361
3362
3363 /**
3364 * Deregisters the provided matching rule with the Directory Server.
3365 *
3366 * @param matchingRule The matching rule to deregister with the server.
3367 */
3368 public static void deregisterMatchingRule(MatchingRule matchingRule)
3369 {
3370 directoryServer.schema.deregisterMatchingRule(matchingRule);
3371 }
3372
3373
3374
3375 /**
3376 * Retrieves the set of approximate matching rules registered with the
3377 * Directory Server. The mapping will be between the lowercase name or OID
3378 * for each approximate matching rule and the matching rule implementation.
3379 * The same approximate matching rule instance may be included multiple times
3380 * with different keys.
3381 *
3382 * @return The set of approximate matching rules registered with the
3383 * Directory Server.
3384 */
3385 public static ConcurrentHashMap<String,ApproximateMatchingRule>
3386 getApproximateMatchingRules()
3387 {
3388 return directoryServer.schema.getApproximateMatchingRules();
3389 }
3390
3391
3392
3393 /**
3394 * Retrieves the approximate matching rule with the specified name or OID.
3395 *
3396 * @param lowerName The lowercase name or OID for the approximate matching
3397 * rule to retrieve.
3398 *
3399 * @return The requested approximate matching rule, or <CODE>null</CODE> if
3400 * no such matching rule has been defined in the server.
3401 */
3402 public static ApproximateMatchingRule
3403 getApproximateMatchingRule(String lowerName)
3404 {
3405 return directoryServer.schema.getApproximateMatchingRule(lowerName);
3406 }
3407
3408
3409
3410 /**
3411 * Registers the provided approximate matching rule with the Directory
3412 * Server.
3413 *
3414 * @param matchingRule The matching rule to register with the server.
3415 * @param overwriteExisting Indicates whether to overwrite an existing
3416 * mapping if there are any conflicts (i.e.,
3417 * another matching rule with the same OID or
3418 * name).
3419 *
3420 * @throws DirectoryException If a conflict is encountered and the
3421 * <CODE>overwriteExisting</CODE> flag is set to
3422 * <CODE>false</CODE>
3423 */
3424 public static void registerApproximateMatchingRule(ApproximateMatchingRule
3425 matchingRule,
3426 boolean overwriteExisting)
3427 throws DirectoryException
3428 {
3429 directoryServer.schema.registerApproximateMatchingRule(matchingRule,
3430 overwriteExisting);
3431 }
3432
3433
3434
3435 /**
3436 * Deregisters the provided approximate matching rule with the Directory
3437 * Server.
3438 *
3439 * @param matchingRule The matching rule to deregister with the server.
3440 */
3441 public static void deregisterApproximateMatchingRule(ApproximateMatchingRule
3442 matchingRule)
3443 {
3444 directoryServer.schema.deregisterApproximateMatchingRule(matchingRule);
3445 }
3446
3447
3448
3449 /**
3450 * Retrieves the set of equality matching rules registered with the Directory
3451 * Server. The mapping will be between the lowercase name or OID for each
3452 * equality matching rule and the matching rule implementation. The same
3453 * equality matching rule instance may be included multiple times with
3454 * different keys.
3455 *
3456 * @return The set of equality matching rules registered with the Directory
3457 * Server.
3458 */
3459 public static ConcurrentHashMap<String,EqualityMatchingRule>
3460 getEqualityMatchingRules()
3461 {
3462 return directoryServer.schema.getEqualityMatchingRules();
3463 }
3464
3465
3466
3467 /**
3468 * Retrieves the equality matching rule with the specified name or OID.
3469 *
3470 * @param lowerName The lowercase name or OID for the equality matching rule
3471 * to retrieve.
3472 *
3473 * @return The requested equality matching rule, or <CODE>null</CODE> if no
3474 * such matching rule has been defined in the server.
3475 */
3476 public static EqualityMatchingRule getEqualityMatchingRule(String lowerName)
3477 {
3478 return directoryServer.schema.getEqualityMatchingRule(lowerName);
3479 }
3480
3481
3482
3483 /**
3484 * Registers the provided equality matching rule with the Directory Server.
3485 *
3486 * @param matchingRule The matching rule to register with the server.
3487 * @param overwriteExisting Indicates whether to overwrite an existing
3488 * mapping if there are any conflicts (i.e.,
3489 * another matching rule with the same OID or
3490 * name).
3491 *
3492 * @throws DirectoryException If a conflict is encountered and the
3493 * <CODE>overwriteExisting</CODE> flag is set to
3494 * <CODE>false</CODE>
3495 */
3496 public static void registerEqualityMatchingRule(EqualityMatchingRule
3497 matchingRule,
3498 boolean overwriteExisting)
3499 throws DirectoryException
3500 {
3501 directoryServer.schema.registerEqualityMatchingRule(matchingRule,
3502 overwriteExisting);
3503 }
3504
3505
3506
3507 /**
3508 * Deregisters the provided equality matching rule with the Directory Server.
3509 *
3510 * @param matchingRule The matching rule to deregister with the server.
3511 */
3512 public static void deregisterEqualityMatchingRule(EqualityMatchingRule
3513 matchingRule)
3514 {
3515 directoryServer.schema.deregisterEqualityMatchingRule(matchingRule);
3516 }
3517
3518
3519
3520 /**
3521 * Retrieves the set of ordering matching rules registered with the Directory
3522 * Server. The mapping will be between the lowercase name or OID for each
3523 * ordering matching rule and the matching rule implementation. The same
3524 * ordering matching rule instance may be included multiple times with
3525 * different keys.
3526 *
3527 * @return The set of ordering matching rules registered with the Directory
3528 * Server.
3529 */
3530 public static ConcurrentHashMap<String,OrderingMatchingRule>
3531 getOrderingMatchingRules()
3532 {
3533 return directoryServer.schema.getOrderingMatchingRules();
3534 }
3535
3536
3537
3538 /**
3539 * Retrieves the ordering matching rule with the specified name or OID.
3540 *
3541 * @param lowerName The lowercase name or OID for the ordering matching rule
3542 * to retrieve.
3543 *
3544 * @return The requested ordering matching rule, or <CODE>null</CODE> if no
3545 * such matching rule has been defined in the server.
3546 */
3547 public static OrderingMatchingRule getOrderingMatchingRule(String lowerName)
3548 {
3549 return directoryServer.schema.getOrderingMatchingRule(lowerName);
3550 }
3551
3552
3553
3554 /**
3555 * Registers the provided ordering matching rule with the Directory Server.
3556 *
3557 * @param matchingRule The matching rule to register with the server.
3558 * @param overwriteExisting Indicates whether to overwrite an existing
3559 * mapping if there are any conflicts (i.e.,
3560 * another matching rule with the same OID or
3561 * name).
3562 *
3563 * @throws DirectoryException If a conflict is encountered and the
3564 * <CODE>overwriteExisting</CODE> flag is set to
3565 * <CODE>false</CODE>
3566 */
3567 public static void registerOrderingMatchingRule(OrderingMatchingRule
3568 matchingRule,
3569 boolean overwriteExisting)
3570 throws DirectoryException
3571 {
3572 directoryServer.schema.registerOrderingMatchingRule(matchingRule,
3573 overwriteExisting);
3574 }
3575
3576
3577
3578 /**
3579 * Deregisters the provided ordering matching rule with the Directory Server.
3580 *
3581 * @param matchingRule The matching rule to deregister with the server.
3582 */
3583 public static void deregisterOrderingMatchingRule(OrderingMatchingRule
3584 matchingRule)
3585 {
3586 directoryServer.schema.deregisterOrderingMatchingRule(matchingRule);
3587 }
3588
3589
3590
3591 /**
3592 * Retrieves the set of substring matching rules registered with the Directory
3593 * Server. The mapping will be between the lowercase name or OID for each
3594 * substring matching rule and the matching rule implementation. The same
3595 * substring matching rule instance may be included multiple times with
3596 * different keys.
3597 *
3598 * @return The set of substring matching rules registered with the Directory
3599 * Server.
3600 */
3601 public static ConcurrentHashMap<String,SubstringMatchingRule>
3602 getSubstringMatchingRules()
3603 {
3604 return directoryServer.schema.getSubstringMatchingRules();
3605 }
3606
3607
3608
3609 /**
3610 * Retrieves the substring matching rule with the specified name or OID.
3611 *
3612 * @param lowerName The lowercase name or OID for the substring matching
3613 * rule to retrieve.
3614 *
3615 * @return The requested substring matching rule, or <CODE>null</CODE> if no
3616 * such matching rule has been defined in the server.
3617 */
3618 public static SubstringMatchingRule getSubstringMatchingRule(String lowerName)
3619 {
3620 return directoryServer.schema.getSubstringMatchingRule(lowerName);
3621 }
3622
3623
3624
3625 /**
3626 * Registers the provided substring matching rule with the Directory Server.
3627 *
3628 * @param matchingRule The matching rule to register with the server.
3629 * @param overwriteExisting Indicates whether to overwrite an existing
3630 * mapping if there are any conflicts (i.e.,
3631 * another matching rule with the same OID or
3632 * name).
3633 *
3634 * @throws DirectoryException If a conflict is encountered and the
3635 * <CODE>overwriteExisting</CODE> flag is set to
3636 * <CODE>false</CODE>
3637 */
3638 public static void registerSubstringMatchingRule(SubstringMatchingRule
3639 matchingRule,
3640 boolean overwriteExisting)
3641 throws DirectoryException
3642 {
3643 directoryServer.schema.registerSubstringMatchingRule(matchingRule,
3644 overwriteExisting);
3645 }
3646
3647
3648
3649 /**
3650 * Deregisters the provided substring matching rule with the Directory Server.
3651 *
3652 * @param matchingRule The matching rule to deregister with the server.
3653 */
3654 public static void deregisterSubstringMatchingRule(SubstringMatchingRule
3655 matchingRule)
3656 {
3657 directoryServer.schema.deregisterSubstringMatchingRule(matchingRule);
3658 }
3659
3660
3661
3662 /**
3663 * Retrieves the set of objectclasses defined in the Directory Server.
3664 *
3665 * @return The set of objectclasses defined in the Directory Server.
3666 */
3667 public static ConcurrentHashMap<String,ObjectClass> getObjectClasses()
3668 {
3669 return directoryServer.schema.getObjectClasses();
3670 }
3671
3672
3673
3674 /**
3675 * Retrieves the set of encoded objectclasses that have been defined in the
3676 * Directory Server.
3677 *
3678 * @return The set of encoded objectclasses that have been defined in the
3679 * Directory Server.
3680 */
3681 public static LinkedHashSet<AttributeValue> getObjectClassSet()
3682 {
3683 return directoryServer.schema.getObjectClassSet();
3684 }
3685
3686
3687
3688 /**
3689 * Retrieves the objectclass for the provided lowercase name or OID.
3690 *
3691 * @param lowerName The lowercase name or OID for the objectclass to
3692 * retrieve.
3693 *
3694 * @return The requested objectclass, or <CODE>null</CODE> if there is no
3695 * such objectclass defined in the server schema.
3696 */
3697 public static ObjectClass getObjectClass(String lowerName)
3698 {
3699 return directoryServer.schema.getObjectClass(lowerName);
3700 }
3701
3702
3703
3704 /**
3705 * Retrieves the objectclass for the provided lowercase name or OID. It can
3706 * optionally return a generated "default" version if the requested
3707 * objectclass is not defined in the schema.
3708 *
3709 * @param lowerName The lowercase name or OID for the objectclass to
3710 * retrieve.
3711 * @param returnDefault Indicates whether to generate a default version if
3712 * the requested objectclass is not defined in the
3713 * server schema.
3714 *
3715 * @return The objectclass type, or <CODE>null</CODE> if there is no
3716 * objectclass with the specified name or OID defined in the server
3717 * schema and a default class should not be returned.
3718 */
3719 public static ObjectClass getObjectClass(String lowerName,
3720 boolean returnDefault)
3721 {
3722 ObjectClass oc = directoryServer.schema.getObjectClass(lowerName);
3723 if (returnDefault && (oc == null))
3724 {
3725 oc = getDefaultObjectClass(lowerName);
3726 }
3727
3728 return oc;
3729 }
3730
3731
3732
3733 /**
3734 * Registers the provided objectclass with the Directory Server.
3735 *
3736 * @param objectClass The objectclass instance to register with the
3737 * server.
3738 * @param overwriteExisting Indicates whether to overwrite an existing
3739 * mapping if there are any conflicts (i.e.,
3740 * another objectclass with the same OID or
3741 * name).
3742 *
3743 * @throws DirectoryException If a conflict is encountered and the
3744 * <CODE>overwriteExisting</CODE> flag is set to
3745 * <CODE>false</CODE>
3746 */
3747 public static void registerObjectClass(ObjectClass objectClass,
3748 boolean overwriteExisting)
3749 throws DirectoryException
3750 {
3751 directoryServer.schema.registerObjectClass(objectClass, overwriteExisting);
3752 }
3753
3754
3755
3756 /**
3757 * Deregisters the provided objectclass with the Directory Server.
3758 *
3759 * @param objectClass The objectclass instance to deregister with the
3760 * server.
3761 */
3762 public static void deregisterObjectClass(ObjectClass objectClass)
3763 {
3764 directoryServer.schema.deregisterObjectClass(objectClass);
3765 }
3766
3767
3768
3769 /**
3770 * Retrieves the "top" objectClass, which should be the topmost objectclass in
3771 * the inheritance chain for most other objectclasses. If no such objectclass
3772 * could be found, then one will be constructed.
3773 *
3774 * @return The "top" objectClass.
3775 */
3776 public static ObjectClass getTopObjectClass()
3777 {
3778 ObjectClass objectClass =
3779 directoryServer.schema.getObjectClass(TOP_OBJECTCLASS_NAME);
3780 if (objectClass == null)
3781 {
3782 String definition =
3783 "( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass " +
3784 "X-ORIGIN 'RFC 2256' )";
3785
3786 objectClass = new ObjectClass(definition, TOP_OBJECTCLASS_NAME,
3787 Collections.singleton(TOP_OBJECTCLASS_NAME),
3788 TOP_OBJECTCLASS_OID,
3789 TOP_OBJECTCLASS_DESCRIPTION, null, null,
3790 null, ObjectClassType.ABSTRACT, false,
3791 null);
3792 }
3793
3794 return objectClass;
3795 }
3796
3797
3798
3799 /**
3800 * Causes the Directory Server to construct a new objectclass
3801 * definition with the provided name and with no required or allowed
3802 * attributes. This should only be used if there is no objectclass
3803 * for the specified name. It will not register the created
3804 * objectclass with the Directory Server.
3805 *
3806 * @param name
3807 * The name to use for the objectclass, as provided by the
3808 * user.
3809 * @return The constructed objectclass definition.
3810 */
3811 public static ObjectClass getDefaultObjectClass(String name)
3812 {
3813 String lowerName = toLowerCase(name);
3814 ObjectClass objectClass = directoryServer.schema.getObjectClass(lowerName);
3815 if (objectClass == null)
3816 {
3817 String oid = lowerName + "-oid";
3818 String definition = "( " + oid + " NAME '" + name + "' ABSTRACT )";
3819
3820 objectClass = new ObjectClass(definition, name,
3821 Collections.singleton(name), oid, null,
3822 getTopObjectClass(), null, null,
3823 ObjectClassType.STRUCTURAL, false, null);
3824 }
3825
3826 return objectClass;
3827 }
3828
3829
3830
3831 /**
3832 * Causes the Directory Server to construct a new auxiliary objectclass
3833 * definition with the provided name and with no required or allowed
3834 * attributes. This should only be used if there is no objectclass for the
3835 * specified name. It will not register the created objectclass with the
3836 * Directory Server.
3837 *
3838 * @param name The name to use for the objectclass, as provided by the user.
3839 *
3840 * @return The constructed objectclass definition.
3841 */
3842 public static ObjectClass getDefaultAuxiliaryObjectClass(String name)
3843 {
3844 String lowerName = toLowerCase(name);
3845 ObjectClass objectClass = directoryServer.schema.getObjectClass(lowerName);
3846 if (objectClass == null)
3847 {
3848 String oid = lowerName + "-oid";
3849 String definition = "( " + oid + " NAME '" + name + "' ABSTRACT )";
3850
3851 objectClass = new ObjectClass(definition, name,
3852 Collections.singleton(name), oid, null,
3853 getTopObjectClass(), null, null,
3854 ObjectClassType.AUXILIARY, false, null);
3855 }
3856
3857 return objectClass;
3858 }
3859
3860
3861
3862 /**
3863 * Retrieves the set of attribute type definitions that have been
3864 * defined in the Directory Server.
3865 *
3866 * @return The set of attribute type definitions that have been
3867 * defined in the Directory Server.
3868 */
3869 public static ConcurrentHashMap<String,AttributeType> getAttributeTypes()
3870 {
3871 return directoryServer.schema.getAttributeTypes();
3872 }
3873
3874
3875
3876 /**
3877 * Retrieves the set of encoded attribute types that have been defined in the
3878 * Directory Server.
3879 *
3880 * @return The set of encoded attribute types that have been defined in the
3881 * Directory Server.
3882 */
3883 public static LinkedHashSet<AttributeValue> getAttributeTypeSet()
3884 {
3885 return directoryServer.schema.getAttributeTypeSet();
3886 }
3887
3888
3889
3890 /**
3891 * Retrieves the attribute type for the provided lowercase name or OID.
3892 *
3893 * @param lowerName The lowercase attribute name or OID for the attribute
3894 * type to retrieve.
3895 *
3896 * @return The requested attribute type, or <CODE>null</CODE> if there is no
3897 * attribute with the specified type defined in the server schema.
3898 */
3899 public static AttributeType getAttributeType(String lowerName)
3900 {
3901 return directoryServer.schema.getAttributeType(lowerName);
3902 }
3903
3904
3905
3906 /**
3907 * Retrieves the attribute type for the provided lowercase name or OID. It
3908 * can optionally return a generated "default" version if the requested
3909 * attribute type is not defined in the schema.
3910 *
3911 * @param lowerName The lowercase name or OID for the attribute type to
3912 * retrieve.
3913 * @param returnDefault Indicates whether to generate a default version if
3914 * the requested attribute type is not defined in the
3915 * server schema.
3916 *
3917 * @return The requested attribute type, or <CODE>null</CODE> if there is no
3918 * attribute with the specified type defined in the server schema and
3919 * a default type should not be returned.
3920 */
3921 public static AttributeType getAttributeType(String lowerName,
3922 boolean returnDefault)
3923 {
3924 AttributeType type = directoryServer.schema.getAttributeType(lowerName);
3925 if (returnDefault && (type == null))
3926 {
3927 type = getDefaultAttributeType(lowerName);
3928 }
3929
3930 return type;
3931 }
3932
3933
3934
3935 /**
3936 * Registers the provided attribute type with the Directory Server.
3937 *
3938 * @param attributeType The attribute type to register with the
3939 * Directory Server.
3940 * @param overwriteExisting Indicates whether to overwrite an existing
3941 * mapping if there are any conflicts (i.e.,
3942 * another attribute type with the same OID or
3943 * name).
3944 *
3945 * @throws DirectoryException If a conflict is encountered and the
3946 * <CODE>overwriteExisting</CODE> flag is set to
3947 * <CODE>false</CODE>
3948 */
3949 public static void registerAttributeType(AttributeType attributeType,
3950 boolean overwriteExisting)
3951 throws DirectoryException
3952 {
3953 directoryServer.schema.registerAttributeType(attributeType,
3954 overwriteExisting);
3955 }
3956
3957
3958
3959 /**
3960 * Deregisters the provided attribute type with the Directory Server.
3961 *
3962 * @param attributeType The attribute type to deregister with the Directory
3963 * Server.
3964 */
3965 public static void deregisterAttributeType(AttributeType attributeType)
3966 {
3967 directoryServer.schema.deregisterAttributeType(attributeType);
3968 }
3969
3970
3971
3972 /**
3973 * Retrieves the attribute type for the "objectClass" attribute.
3974 *
3975 * @return The attribute type for the "objectClass" attribute.
3976 */
3977 public static AttributeType getObjectClassAttributeType()
3978 {
3979 if (directoryServer.objectClassAttributeType == null)
3980 {
3981 directoryServer.objectClassAttributeType =
3982 directoryServer.schema.getAttributeType(
3983 OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
3984
3985 if (directoryServer.objectClassAttributeType == null)
3986 {
3987 AttributeSyntax oidSyntax =
3988 directoryServer.schema.getSyntax(SYNTAX_OID_NAME);
3989 if (oidSyntax == null)
3990 {
3991 try
3992 {
3993 OIDSyntax newOIDSyntax = new OIDSyntax();
3994 newOIDSyntax.initializeSyntax(null);
3995 oidSyntax = newOIDSyntax;
3996 directoryServer.schema.registerSyntax(oidSyntax, true);
3997 }
3998 catch (Exception e)
3999 {
4000 if (debugEnabled())
4001 {
4002 TRACER.debugCaught(DebugLogLevel.ERROR, e);
4003 }
4004 }
4005 }
4006
4007 String definition =
4008 "( 2.5.4.0 NAME 'objectClass' EQUALITY objectIdentifierMatch " +
4009 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 X-ORIGIN 'RFC 2256' )";
4010
4011 directoryServer.objectClassAttributeType =
4012 new AttributeType(definition, "objectClass",
4013 Collections.singleton("objectClass"),
4014 OBJECTCLASS_ATTRIBUTE_TYPE_OID, null, null,
4015 oidSyntax, AttributeUsage.USER_APPLICATIONS,
4016 false, false, false, false);
4017 try
4018 {
4019 directoryServer.schema.registerAttributeType(
4020 directoryServer.objectClassAttributeType, true);
4021 }
4022 catch (Exception e)
4023 {
4024 // This should never happen.
4025 if (debugEnabled())
4026 {
4027 TRACER.debugCaught(DebugLogLevel.ERROR, e);
4028 }
4029 }
4030 }
4031 }
4032
4033 return directoryServer.objectClassAttributeType;
4034 }
4035
4036
4037
4038 /**
4039 * Causes the Directory Server to construct a new attribute type definition
4040 * with the provided name and using the default attribute syntax. This should
4041 * only be used if there is no real attribute type for the specified name.
4042 *
4043 * @param name The name to use for the attribute type, as provided by the
4044 * user.
4045 *
4046 * @return The constructed attribute type definition.
4047 */
4048 public static AttributeType getDefaultAttributeType(String name)
4049 {
4050 return getDefaultAttributeType(name, getDefaultAttributeSyntax());
4051 }
4052
4053
4054
4055 /**
4056 * Causes the Directory Server to construct a new attribute type definition
4057 * with the provided name and syntax. This should only be used if there is no
4058 * real attribute type for the specified name.
4059 *
4060 * @param name The name to use for the attribute type, as provided by the
4061 * user.
4062 * @param syntax The syntax to use for the attribute type.
4063 *
4064 * @return The constructed attribute type definition.
4065 */
4066 public static AttributeType getDefaultAttributeType(String name,
4067 AttributeSyntax syntax)
4068 {
4069 String oid = toLowerCase(name) + "-oid";
4070 String definition = "( " + oid + " NAME '" + name + "' SYNTAX " +
4071 syntax.getOID() + " )";
4072
4073 return new AttributeType(definition, name, Collections.singleton(name),
4074 oid, null, null, syntax,
4075 AttributeUsage.USER_APPLICATIONS, false, false,
4076 false, false);
4077 }
4078
4079
4080
4081 /**
4082 * Retrieves the set of attribute syntaxes defined in the Directory Server.
4083 *
4084 * @return The set of attribute syntaxes defined in the Directory Server.
4085 */
4086 public static ConcurrentHashMap<String,AttributeSyntax> getAttributeSyntaxes()
4087 {
4088 return directoryServer.schema.getSyntaxes();
4089 }
4090
4091
4092
4093 /**
4094 * Retrieves the set of encoded attribute syntaxes that have been defined in
4095 * the Directory Server.
4096 *
4097 * @return The set of encoded attribute syntaxes that have been defined in
4098 * the Directory Server.
4099 */
4100 public static LinkedHashSet<AttributeValue> getAttributeSyntaxSet()
4101 {
4102 return directoryServer.schema.getSyntaxSet();
4103 }
4104
4105
4106
4107 /**
4108 * Retrieves the requested attribute syntax.
4109 *
4110 * @param oid The OID of the syntax to retrieve.
4111 * @param allowDefault Indicates whether to return the default attribute
4112 * syntax if the requested syntax is unknown.
4113 *
4114 * @return The requested attribute syntax, the default syntax if the
4115 * requested syntax is unknown and the caller has indicated that the
4116 * default is acceptable, or <CODE>null</CODE> otherwise.
4117 */
4118 public static AttributeSyntax getAttributeSyntax(String oid,
4119 boolean allowDefault)
4120 {
4121 AttributeSyntax syntax = directoryServer.schema.getSyntax(oid);
4122 if ((syntax == null) && allowDefault)
4123 {
4124 return getDefaultAttributeSyntax();
4125 }
4126
4127 return syntax;
4128 }
4129
4130
4131
4132 /**
4133 * Registers the provided attribute syntax with the Directory Server.
4134 *
4135 * @param syntax The attribute syntax to register with the
4136 * Directory Server.
4137 * @param overwriteExisting Indicates whether to overwrite an existing
4138 * mapping if there are any conflicts (i.e.,
4139 * another attribute syntax with the same OID or
4140 * name).
4141 *
4142 * @throws DirectoryException If a conflict is encountered and the
4143 * <CODE>overwriteExisting</CODE> flag is set to
4144 * <CODE>false</CODE>
4145 */
4146 public static void registerAttributeSyntax(AttributeSyntax syntax,
4147 boolean overwriteExisting)
4148 throws DirectoryException
4149 {
4150 directoryServer.schema.registerSyntax(syntax, overwriteExisting);
4151 }
4152
4153
4154
4155 /**
4156 * Deregisters the provided attribute syntax with the Directory Server.
4157 *
4158 * @param syntax The attribute syntax to deregister with the Directory
4159 * Server.
4160 */
4161 public static void deregisterAttributeSyntax(AttributeSyntax syntax)
4162 {
4163 directoryServer.schema.deregisterSyntax(syntax);
4164 }
4165
4166
4167
4168 /**
4169 * Retrieves the default attribute syntax that should be used for attributes
4170 * that are not defined in the server schema.
4171 *
4172 * @return The default attribute syntax that should be used for attributes
4173 * that are not defined in the server schema.
4174 */
4175 public static AttributeSyntax getDefaultAttributeSyntax()
4176 {
4177 return directoryServer.defaultSyntax;
4178 }
4179
4180
4181
4182 /**
4183 * Retrieves the default attribute syntax that should be used for attributes
4184 * that are not defined in the server schema and are meant to store binary
4185 * values.
4186 *
4187 * @return The default attribute syntax that should be used for attributes
4188 * that are not defined in the server schema and are meant to store
4189 * binary values.
4190 */
4191 public static AttributeSyntax getDefaultBinarySyntax()
4192 {
4193 return directoryServer.defaultBinarySyntax;
4194 }
4195
4196
4197
4198 /**
4199 * Retrieves the default attribute syntax that should be used for attributes
4200 * that are not defined in the server schema and are meant to store Boolean
4201 * values.
4202 *
4203 * @return The default attribute syntax that should be used for attributes
4204 * that are not defined in the server schema and are meant to store
4205 * Boolean values.
4206 */
4207 public static AttributeSyntax getDefaultBooleanSyntax()
4208 {
4209 return directoryServer.defaultBooleanSyntax;
4210 }
4211
4212
4213
4214 /**
4215 * Retrieves the default attribute syntax that should be used for attributes
4216 * that are not defined in the server schema and are meant to store DN values.
4217 *
4218 * @return The default attribute syntax that should be used for attributes
4219 * that are not defined in the server schema and are meant to store
4220 * DN values.
4221 */
4222 public static AttributeSyntax getDefaultDNSyntax()
4223 {
4224 return directoryServer.defaultDNSyntax;
4225 }
4226
4227
4228
4229 /**
4230 * Retrieves the default attribute syntax that should be used for attributes
4231 * that are not defined in the server schema and are meant to store integer
4232 * values.
4233 *
4234 * @return The default attribute syntax that should be used for attributes
4235 * that are not defined in the server schema and are meant to store
4236 * integer values.
4237 */
4238 public static AttributeSyntax getDefaultIntegerSyntax()
4239 {
4240 return directoryServer.defaultIntegerSyntax;
4241 }
4242
4243
4244
4245 /**
4246 * Retrieves the default attribute syntax that should be used for attributes
4247 * that are not defined in the server schema and are meant to store string
4248 * values.
4249 *
4250 * @return The default attribute syntax that should be used for attributes
4251 * that are not defined in the server schema and are meant to store
4252 * string values.
4253 */
4254 public static AttributeSyntax getDefaultStringSyntax()
4255 {
4256 return directoryServer.defaultStringSyntax;
4257 }
4258
4259
4260
4261 /**
4262 * Retrieves the set of matching rule uses defined in the Directory Server.
4263 *
4264 * @return The set of matching rule uses defined in the Directory Server.
4265 */
4266 public static ConcurrentHashMap<MatchingRule,MatchingRuleUse>
4267 getMatchingRuleUses()
4268 {
4269 return directoryServer.schema.getMatchingRuleUses();
4270 }
4271
4272
4273
4274 /**
4275 * Retrieves the set of encoded matching rule uses that have been defined in
4276 * the Directory Server.
4277 *
4278 * @return The set of encoded matching rule uses that have been defined in
4279 * the Directory Server.
4280 */
4281 public static LinkedHashSet<AttributeValue> getMatchingRuleUseSet()
4282 {
4283 return directoryServer.schema.getMatchingRuleUseSet();
4284 }
4285
4286
4287
4288 /**
4289 * Retrieves the matching rule use associated with the provided matching rule.
4290 *
4291 * @param matchingRule The matching rule for which to retrieve the matching
4292 * rule use.
4293 *
4294 * @return The matching rule use for the provided matching rule, or
4295 * <CODE>null</CODE> if none is defined.
4296 */
4297 public static MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule)
4298 {
4299 return directoryServer.schema.getMatchingRuleUse(matchingRule);
4300 }
4301
4302
4303
4304 /**
4305 * Registers the provided matching rule use with the Directory Server.
4306 *
4307 * @param matchingRuleUse The matching rule use to register with the
4308 * server.
4309 * @param overwriteExisting Indicates whether to overwrite an existing
4310 * mapping if there are any conflicts (i.e.,
4311 * another matching rule use with the same matching
4312 * rule).
4313 *
4314 * @throws DirectoryException If a conflict is encountered and the
4315 * <CODE>overwriteExisting</CODE> flag is set to
4316 * <CODE>false</CODE>
4317 */
4318 public static void registerMatchingRuleUse(MatchingRuleUse matchingRuleUse,
4319 boolean overwriteExisting)
4320 throws DirectoryException
4321 {
4322 directoryServer.schema.registerMatchingRuleUse(matchingRuleUse,
4323 overwriteExisting);
4324 }
4325
4326
4327
4328 /**
4329 * Deregisters the provided matching rule use with the Directory Server.
4330 *
4331 * @param matchingRuleUse The matching rule use to deregister with the
4332 * server.
4333 */
4334 public static void deregisterMatchingRuleUse(MatchingRuleUse matchingRuleUse)
4335 {
4336 directoryServer.schema.deregisterMatchingRuleUse(matchingRuleUse);
4337 }
4338
4339
4340
4341 /**
4342 * Retrieves the set of DIT content rules defined in the Directory Server.
4343 *
4344 * @return The set of DIT content rules defined in the Directory Server.
4345 */
4346 public static ConcurrentHashMap<ObjectClass,DITContentRule>
4347 getDITContentRules()
4348 {
4349 return directoryServer.schema.getDITContentRules();
4350 }
4351
4352
4353
4354 /**
4355 * Retrieves the set of encoded DIT content rules that have been defined in
4356 * the Directory Server.
4357 *
4358 * @return The set of encoded DIT content rules that have been defined in the
4359 * Directory Server.
4360 */
4361 public static LinkedHashSet<AttributeValue> getDITContentRuleSet()
4362 {
4363 return directoryServer.schema.getDITContentRuleSet();
4364 }
4365
4366
4367
4368 /**
4369 * Retrieves the DIT content rule associated with the specified objectclass.
4370 *
4371 * @param objectClass The objectclass for which to retrieve the associated
4372 * DIT content rule.
4373 *
4374 * @return The requested DIT content rule, or <CODE>null</CODE> if no such
4375 * rule is defined in the schema.
4376 */
4377 public static DITContentRule getDITContentRule(ObjectClass objectClass)
4378 {
4379 return directoryServer.schema.getDITContentRule(objectClass);
4380 }
4381
4382
4383
4384 /**
4385 * Registers the provided DIT content rule with the Directory Server.
4386 *
4387 * @param ditContentRule The DIT content rule to register with the
4388 * server.
4389 * @param overwriteExisting Indicates whether to overwrite an existing
4390 * mapping if there are any conflicts (i.e.,
4391 * another DIT content rule with the same
4392 * structural objectclass).
4393 *
4394 * @throws DirectoryException If a conflict is encountered and the
4395 * <CODE>overwriteExisting</CODE> flag is set to
4396 * <CODE>false</CODE>
4397 */
4398 public static void registerDITContentRule(DITContentRule ditContentRule,
4399 boolean overwriteExisting)
4400 throws DirectoryException
4401 {
4402 directoryServer.schema.registerDITContentRule(ditContentRule,
4403 overwriteExisting);
4404 }
4405
4406
4407
4408 /**
4409 * Deregisters the provided DIT content rule with the Directory Server.
4410 *
4411 * @param ditContentRule The DIT content rule to deregister with the server.
4412 */
4413 public static void deregisterDITContentRule(DITContentRule ditContentRule)
4414 {
4415 directoryServer.schema.deregisterDITContentRule(ditContentRule);
4416 }
4417
4418
4419
4420 /**
4421 * Retrieves the set of DIT structure rules defined in the Directory Server.
4422 *
4423 * @return The set of DIT structure rules defined in the Directory Server.
4424 */
4425 public static ConcurrentHashMap<NameForm,DITStructureRule>
4426 getDITStructureRules()
4427 {
4428 return directoryServer.schema.getDITStructureRulesByNameForm();
4429 }
4430
4431
4432
4433 /**
4434 * Retrieves the set of encoded DIT structure rules that have been defined in
4435 * the Directory Server.
4436 *
4437 * @return The set of encoded DIT structure rules that have been defined in
4438 * the Directory Server.
4439 */
4440 public static LinkedHashSet<AttributeValue> getDITStructureRuleSet()
4441 {
4442 return directoryServer.schema.getDITStructureRuleSet();
4443 }
4444
4445
4446
4447 /**
4448 * Retrieves the DIT structure rule associated with the provided rule ID.
4449 *
4450 * @param ruleID The rule ID for which to retrieve the associated DIT
4451 * structure rule.
4452 *
4453 * @return The requested DIT structure rule, or <CODE>null</CODE> if no such
4454 * rule is defined.
4455 */
4456 public static DITStructureRule getDITStructureRule(int ruleID)
4457 {
4458 return directoryServer.schema.getDITStructureRule(ruleID);
4459 }
4460
4461
4462
4463 /**
4464 * Retrieves the DIT structure rule associated with the provided name form.
4465 *
4466 * @param nameForm The name form for which to retrieve the associated DIT
4467 * structure rule.
4468 *
4469 * @return The requested DIT structure rule, or <CODE>null</CODE> if no such
4470 * rule is defined.
4471 */
4472 public static DITStructureRule getDITStructureRule(NameForm nameForm)
4473 {
4474 return directoryServer.schema.getDITStructureRule(nameForm);
4475 }
4476
4477
4478
4479 /**
4480 * Registers the provided DIT structure rule with the Directory Server.
4481 *
4482 * @param ditStructureRule The DIT structure rule to register with the
4483 * server.
4484 * @param overwriteExisting Indicates whether to overwrite an existing
4485 * mapping if there are any conflicts (i.e.,
4486 * another DIT structure rule with the same name
4487 * form).
4488 *
4489 * @throws DirectoryException If a conflict is encountered and the
4490 * <CODE>overwriteExisting</CODE> flag is set to
4491 * <CODE>false</CODE>
4492 */
4493 public static void registerDITStructureRule(DITStructureRule ditStructureRule,
4494 boolean overwriteExisting)
4495 throws DirectoryException
4496 {
4497 directoryServer.schema.registerDITStructureRule(ditStructureRule,
4498 overwriteExisting);
4499 }
4500
4501
4502
4503 /**
4504 * Deregisters the provided DIT structure rule with the Directory Server.
4505 *
4506 * @param ditStructureRule The DIT structure rule to deregister with the
4507 * server.
4508 */
4509 public static void deregisterDITStructureRule(DITStructureRule
4510 ditStructureRule)
4511 {
4512 directoryServer.schema.deregisterDITStructureRule(ditStructureRule);
4513 }
4514
4515
4516
4517 /**
4518 * Retrieves the set of name forms defined in the Directory Server.
4519 *
4520 * @return The set of name forms defined in the Directory Server.
4521 */
4522 public static ConcurrentHashMap<ObjectClass,NameForm> getNameForms()
4523 {
4524 return directoryServer.schema.getNameFormsByObjectClass();
4525 }
4526
4527
4528
4529 /**
4530 * Retrieves the set of encoded name forms that have been defined in the
4531 * Directory Server.
4532 *
4533 * @return The set of encoded name forms that have been defined in the
4534 * Directory Server.
4535 */
4536 public static LinkedHashSet<AttributeValue> getNameFormSet()
4537 {
4538 return directoryServer.schema.getNameFormSet();
4539 }
4540
4541
4542
4543 /**
4544 * Retrieves the name form associated with the specified objectclass.
4545 *
4546 * @param objectClass The objectclass for which to retrieve the associated
4547 * name form.
4548 *
4549 * @return The requested name form, or <CODE>null</CODE> if no such name form
4550 * is defined in the schema.
4551 */
4552 public static NameForm getNameForm(ObjectClass objectClass)
4553 {
4554 return directoryServer.schema.getNameForm(objectClass);
4555 }
4556
4557
4558
4559 /**
4560 * Retrieves the name form associated with the specified name or OID.
4561 *
4562 * @param lowerName The name or OID of the name form to retrieve, formatted
4563 * in all lowercase characters.
4564 *
4565 * @return The requested name form, or <CODE>null</CODE> if no such name form
4566 * is defined in the schema.
4567 */
4568 public static NameForm getNameForm(String lowerName)
4569 {
4570 return directoryServer.schema.getNameForm(lowerName);
4571 }
4572
4573
4574
4575 /**
4576 * Registers the provided name form with the Directory Server.
4577 *
4578 * @param nameForm The name form to register with the server.
4579 * @param overwriteExisting Indicates whether to overwrite an existing
4580 * mapping if there are any conflicts (i.e.,
4581 * another name form with the same structural
4582 * objectclass).
4583 *
4584 * @throws DirectoryException If a conflict is encountered and the
4585 * <CODE>overwriteExisting</CODE> flag is set to
4586 * <CODE>false</CODE>
4587 */
4588 public static void registerNameForm(NameForm nameForm,
4589 boolean overwriteExisting)
4590 throws DirectoryException
4591 {
4592 directoryServer.schema.registerNameForm(nameForm, overwriteExisting);
4593 }
4594
4595
4596
4597 /**
4598 * Deregisters the provided name form with the Directory Server.
4599 *
4600 * @param nameForm The name form to deregister with the server.
4601 */
4602 public static void deregisterNameForm(NameForm nameForm)
4603 {
4604 directoryServer.schema.deregisterNameForm(nameForm);
4605 }
4606
4607
4608
4609 /**
4610 * Retrieves the set of virtual attribute rules registered with the Directory
4611 * Server.
4612 *
4613 * @return The set of virtual attribute rules registered with the Directory
4614 * Server.
4615 */
4616 public static List<VirtualAttributeRule> getVirtualAttributes()
4617 {
4618 return directoryServer.virtualAttributes;
4619 }
4620
4621
4622
4623 /**
4624 * Retrieves the set of virtual attribute rules registered with the Directory
4625 * Server that are applicable to the provided entry.
4626 *
4627 * @param entry The entry for which to retrieve the applicable virtual
4628 * attribute rules.
4629 *
4630 * @return The set of virtual attribute rules registered with the Directory
4631 * Server that apply to the given entry. It may be an empty list if
4632 * there are no applicable virtual attribute rules.
4633 */
4634 public static List<VirtualAttributeRule> getVirtualAttributes(Entry entry)
4635 {
4636 LinkedList<VirtualAttributeRule> ruleList =
4637 new LinkedList<VirtualAttributeRule>();
4638
4639 for (VirtualAttributeRule rule : directoryServer.virtualAttributes)
4640 {
4641 if (rule.appliesToEntry(entry))
4642 {
4643 ruleList.add(rule);
4644 }
4645 }
4646
4647 return ruleList;
4648 }
4649
4650
4651
4652 /**
4653 * Registers the provided virtual attribute rule with the Directory Server.
4654 *
4655 * @param rule The virtual attribute rule to be registered.
4656 */
4657 public static void registerVirtualAttribute(VirtualAttributeRule rule)
4658 {
4659 synchronized (directoryServer.virtualAttributes)
4660 {
4661 directoryServer.virtualAttributes.add(rule);
4662 }
4663 }
4664
4665
4666
4667 /**
4668 * Deregisters the provided virtual attribute rule with the Directory Server.
4669 *
4670 * @param rule The virutal attribute rule to be deregistered.
4671 */
4672 public static void deregisterVirtualAttribute(VirtualAttributeRule rule)
4673 {
4674 synchronized (directoryServer.virtualAttributes)
4675 {
4676 directoryServer.virtualAttributes.remove(rule);
4677 }
4678 }
4679
4680
4681
4682 /**
4683 * Replaces the specified virtual attribute rule in the set of virtual
4684 * attributes registered with the Directory Server. If the old rule cannot
4685 * be found in the list, then the set of registered virtual attributes is not
4686 * updated.
4687 *
4688 * @param oldRule The existing rule that should be replaced with the new
4689 * rule.
4690 * @param newRule The new rule that should be used in place of the existing
4691 * rule.
4692 *
4693 * @return {@code true} if the old rule was found and replaced with the new
4694 * version, or {@code false} if it was not.
4695 */
4696 public static boolean replaceVirtualAttribute(VirtualAttributeRule oldRule,
4697 VirtualAttributeRule newRule)
4698 {
4699 synchronized (directoryServer.virtualAttributes)
4700 {
4701 int pos = directoryServer.virtualAttributes.indexOf(oldRule);
4702 if (pos >= 0)
4703 {
4704 directoryServer.virtualAttributes.set(pos, newRule);
4705 return true;
4706 }
4707 else
4708 {
4709 return false;
4710 }
4711 }
4712 }
4713
4714
4715
4716 /**
4717 * Retrieves a reference to the JMX MBean server that is associated with the
4718 * Directory Server.
4719 *
4720 * @return The JMX MBean server that is associated with the Directory Server.
4721 */
4722 public static MBeanServer getJMXMBeanServer()
4723 {
4724 return directoryServer.mBeanServer;
4725 }
4726
4727
4728
4729 /**
4730 * Retrieves the set of JMX MBeans that are associated with the server.
4731 *
4732 * @return The set of JMX MBeans that are associated with the server.
4733 */
4734 public static ConcurrentHashMap<DN,JMXMBean> getJMXMBeans()
4735 {
4736 return directoryServer.mBeans;
4737 }
4738
4739
4740
4741 /**
4742 * Retrieves the JMX MBean associated with the specified entry in the
4743 * Directory Server configuration.
4744 *
4745 * @param configEntryDN The DN of the configuration entry for which to
4746 * retrieve the associated JMX MBean.
4747 *
4748 * @return The JMX MBean associated with the specified entry in the Directory
4749 * Server configuration, or <CODE>null</CODE> if there is no MBean
4750 * for the specified entry.
4751 */
4752 public static JMXMBean getJMXMBean(DN configEntryDN)
4753 {
4754 return directoryServer.mBeans.get(configEntryDN);
4755 }
4756
4757
4758
4759 /**
4760 * Registers the provided invokable component with the Directory Server.
4761 *
4762 * @param component The invokable component to register.
4763 */
4764 public static void registerInvokableComponent(InvokableComponent component)
4765 {
4766 DN componentDN = component.getInvokableComponentEntryDN();
4767 JMXMBean mBean = directoryServer.mBeans.get(componentDN);
4768 if (mBean == null)
4769 {
4770 mBean = new JMXMBean(componentDN);
4771 mBean.addInvokableComponent(component);
4772 directoryServer.mBeans.put(componentDN, mBean);
4773 }
4774 else
4775 {
4776 mBean.addInvokableComponent(component);
4777 }
4778 }
4779
4780
4781
4782 /**
4783 * Deregisters the provided invokable component with the Directory Server.
4784 *
4785 * @param component The invokable component to deregister.
4786 */
4787 public static void deregisterInvokableComponent(InvokableComponent component)
4788 {
4789 DN componentDN = component.getInvokableComponentEntryDN();
4790 JMXMBean mBean = directoryServer.mBeans.get(componentDN);
4791 if (mBean != null)
4792 {
4793 mBean.removeInvokableComponent(component);
4794 }
4795 }
4796
4797
4798
4799 /**
4800 * Registers the provided alert generator with the Directory Server.
4801 *
4802 * @param alertGenerator The alert generator to register.
4803 */
4804 public static void registerAlertGenerator(AlertGenerator alertGenerator)
4805 {
4806 DN componentDN = alertGenerator.getComponentEntryDN();
4807 JMXMBean mBean = directoryServer.mBeans.get(componentDN);
4808 if (mBean == null)
4809 {
4810 mBean = new JMXMBean(componentDN);
4811 mBean.addAlertGenerator(alertGenerator);
4812 directoryServer.mBeans.put(componentDN, mBean);
4813 }
4814 else
4815 {
4816 mBean.addAlertGenerator(alertGenerator);
4817 }
4818 }
4819
4820
4821
4822 /**
4823 * Deregisters the provided alert generator with the Directory Server.
4824 *
4825 * @param alertGenerator The alert generator to deregister.
4826 */
4827 public static void deregisterAlertGenerator(AlertGenerator alertGenerator)
4828 {
4829 DN componentDN = alertGenerator.getComponentEntryDN();
4830 JMXMBean mBean = directoryServer.mBeans.get(componentDN);
4831 if (mBean != null)
4832 {
4833 mBean.removeAlertGenerator(alertGenerator);
4834 }
4835 }
4836
4837
4838
4839 /**
4840 * Retrieves the set of alert handlers that have been registered with the
4841 * Directory Server.
4842 *
4843 * @return The set of alert handlers that have been registered with the
4844 * Directory Server.
4845 */
4846 public static CopyOnWriteArrayList<AlertHandler> getAlertHandlers()
4847 {
4848 return directoryServer.alertHandlers;
4849 }
4850
4851
4852
4853 /**
4854 * Registers the provided alert handler with the Directory Server.
4855 *
4856 * @param alertHandler The alert handler to register.
4857 */
4858 public static void registerAlertHandler(AlertHandler alertHandler)
4859 {
4860 directoryServer.alertHandlers.add(alertHandler);
4861 }
4862
4863
4864
4865 /**
4866 * Deregisters the provided alert handler with the Directory Server.
4867 *
4868 * @param alertHandler The alert handler to deregister.
4869 */
4870 public static void deregisterAlertHandler(AlertHandler alertHandler)
4871 {
4872 directoryServer.alertHandlers.remove(alertHandler);
4873 }
4874
4875
4876
4877 /**
4878 * Sends an alert notification with the provided information.
4879 *
4880 * @param generator The alert generator that created the alert.
4881 * @param alertType The alert type name for this alert.
4882 * @param alertMessage A message (possibly <CODE>null</CODE>) that can
4883 */
4884 public static void sendAlertNotification(AlertGenerator generator,
4885 String alertType,
4886 Message alertMessage)
4887 {
4888 if ((directoryServer.alertHandlers == null) ||
4889 directoryServer.alertHandlers.isEmpty())
4890 {
4891 // If the Directory Server is still in the process of starting up, then
4892 // create a JMX alert handler to use for this notification.
4893 if (! directoryServer.isRunning)
4894 {
4895 try
4896 {
4897 JMXAlertHandler alertHandler = new JMXAlertHandler();
4898 alertHandler.initializeAlertHandler(null);
4899 alertHandler.sendAlertNotification(generator, alertType,
4900 alertMessage);
4901 }
4902 catch (Exception e)
4903 {
4904 if (debugEnabled())
4905 {
4906 TRACER.debugCaught(DebugLogLevel.ERROR, e);
4907 }
4908 }
4909 }
4910 }
4911 else
4912 {
4913 for (AlertHandler alertHandler : directoryServer.alertHandlers)
4914 {
4915 AlertHandlerCfg config = alertHandler.getAlertHandlerConfiguration();
4916 Set<String> enabledAlerts = config.getEnabledAlertType();
4917 Set<String> disabledAlerts = config.getDisabledAlertType();
4918 if ((enabledAlerts == null) || enabledAlerts.isEmpty())
4919 {
4920 if ((disabledAlerts != null) && disabledAlerts.contains(alertType))
4921 {
4922 continue;
4923 }
4924 }
4925 else
4926 {
4927 if (enabledAlerts.contains(alertType))
4928 {
4929 if ((disabledAlerts != null) && disabledAlerts.contains(alertType))
4930 {
4931 continue;
4932 }
4933 }
4934 else
4935 {
4936 continue;
4937 }
4938 }
4939
4940 alertHandler.sendAlertNotification(generator, alertType, alertMessage);
4941 }
4942 }
4943
4944
4945 Message message = NOTE_SENT_ALERT_NOTIFICATION.get(
4946 generator.getClassName(), alertType,
4947 alertMessage != null ?
4948 String.valueOf(alertMessage.getDescriptor().getId()) :
4949 String.valueOf(MessageDescriptor.NULL_ID),
4950 alertMessage);
4951 logError(message);
4952 }
4953
4954
4955
4956 /**
4957 * Retrieves the password storage scheme defined in the specified
4958 * configuration entry.
4959 *
4960 * @param configEntryDN The DN of the configuration entry that defines the
4961 * password storage scheme to retrieve.
4962 *
4963 * @return The requested password storage scheme, or {@code null} if no such
4964 * scheme is defined.
4965 */
4966 public static PasswordStorageScheme getPasswordStorageScheme(DN configEntryDN)
4967 {
4968 return directoryServer.passwordStorageSchemesByDN.get(configEntryDN);
4969 }
4970
4971
4972
4973 /**
4974 * Retrieves the set of password storage schemes defined in the Directory
4975 * Server, as a mapping between the all-lowercase scheme name and the
4976 * corresponding implementation.
4977 *
4978 * @return The set of password storage schemes defined in the Directory
4979 * Server.
4980 */
4981 public static ConcurrentHashMap<String,PasswordStorageScheme>
4982 getPasswordStorageSchemes()
4983 {
4984 return directoryServer.passwordStorageSchemes;
4985 }
4986
4987
4988
4989 /**
4990 * Retrieves the specified password storage scheme.
4991 *
4992 * @param lowerName The name of the password storage scheme to retrieve,
4993 * formatted in all lowercase characters.
4994 *
4995 * @return The requested password storage scheme, or <CODE>null</CODE> if no
4996 * such scheme is defined.
4997 */
4998 public static PasswordStorageScheme getPasswordStorageScheme(String lowerName)
4999 {
5000 return directoryServer.passwordStorageSchemes.get(lowerName);
5001 }
5002
5003
5004
5005 /**
5006 * Retrieves the set of authentication password storage schemes defined in the
5007 * Directory Server, as a mapping between the scheme name and the
5008 * corresponding implementation.
5009 *
5010 * @return The set of authentication password storage schemes defined in the
5011 * Directory Server.
5012 */
5013 public static ConcurrentHashMap<String,PasswordStorageScheme>
5014 getAuthPasswordStorageSchemes()
5015 {
5016 return directoryServer.authPasswordStorageSchemes;
5017 }
5018
5019
5020
5021 /**
5022 * Retrieves the specified authentication password storage scheme.
5023 *
5024 * @param name The case-sensitive name of the authentication password
5025 * storage scheme to retrieve.
5026 *
5027 * @return The requested authentication password storage scheme, or
5028 * <CODE>null</CODE> if no such scheme is defined.
5029 */
5030 public static PasswordStorageScheme getAuthPasswordStorageScheme(String name)
5031 {
5032 return directoryServer.authPasswordStorageSchemes.get(name);
5033 }
5034
5035
5036
5037 /**
5038 * Registers the provided password storage scheme with the Directory Server.
5039 * If an existing password storage scheme is registered with the same name,
5040 * then it will be replaced with the provided scheme.
5041 *
5042 * @param configEntryDN The DN of the configuration entry that defines the
5043 * password storage scheme.
5044 * @param scheme The password storage scheme to register with the
5045 * Directory Server.
5046 */
5047 public static void registerPasswordStorageScheme(DN configEntryDN,
5048 PasswordStorageScheme scheme)
5049 {
5050 directoryServer.passwordStorageSchemesByDN.put(configEntryDN, scheme);
5051
5052 String name = toLowerCase(scheme.getStorageSchemeName());
5053 directoryServer.passwordStorageSchemes.put(name, scheme);
5054
5055 if (scheme.supportsAuthPasswordSyntax())
5056 {
5057 directoryServer.authPasswordStorageSchemes.put(
5058 scheme.getAuthPasswordSchemeName(), scheme);
5059 }
5060 }
5061
5062
5063
5064 /**
5065 * Deregisters the specified password storage scheme with the Directory
5066 * Server. If no scheme is registered with the specified name, then no action
5067 * will be taken.
5068 *
5069 * @param configEntryDN The DN of the configuration entry that defines the
5070 * password storage scheme.
5071 */
5072 public static void deregisterPasswordStorageScheme(DN configEntryDN)
5073 {
5074 PasswordStorageScheme scheme =
5075 directoryServer.passwordStorageSchemesByDN.remove(configEntryDN);
5076
5077 if (scheme != null)
5078 {
5079 directoryServer.passwordStorageSchemes.remove(
5080 toLowerCase(scheme.getStorageSchemeName()));
5081
5082 if (scheme.supportsAuthPasswordSyntax())
5083 {
5084 directoryServer.authPasswordStorageSchemes.remove(
5085 scheme.getAuthPasswordSchemeName());
5086 }
5087 }
5088 }
5089
5090
5091
5092 /**
5093 * Retrieves the set of password validators that have been registered for use
5094 * with the Directory Server as a mapping between the DN of the associated
5095 * validator configuration entry and the validator implementation.
5096 *
5097 * @return The set of password validators that have been registered for use
5098 * with the Directory Server.
5099 */
5100 public static
5101 ConcurrentHashMap<DN,
5102 PasswordValidator<? extends PasswordValidatorCfg>>
5103 getPasswordValidators()
5104 {
5105 return directoryServer.passwordValidators;
5106 }
5107
5108
5109
5110 /**
5111 * Retrieves the password validator registered with the provided configuration
5112 * entry DN.
5113 *
5114 * @param configEntryDN The DN of the configuration entry for which to
5115 * retrieve the associated password validator.
5116 *
5117 * @return The requested password validator, or <CODE>null</CODE> if no such
5118 * validator is defined.
5119 */
5120 public static PasswordValidator<? extends PasswordValidatorCfg>
5121 getPasswordValidator(DN configEntryDN)
5122 {
5123 return directoryServer.passwordValidators.get(configEntryDN);
5124 }
5125
5126
5127
5128 /**
5129 * Registers the provided password validator for use with the Directory
5130 * Server.
5131 *
5132 * @param configEntryDN The DN of the configuration entry that defines the
5133 * specified password validator.
5134 * @param validator The password validator to register with the
5135 * Directory Server.
5136 */
5137 public static void
5138 registerPasswordValidator(DN configEntryDN,
5139 PasswordValidator<? extends PasswordValidatorCfg>
5140 validator)
5141 {
5142 directoryServer.passwordValidators.put(configEntryDN, validator);
5143 }
5144
5145
5146
5147 /**
5148 * Deregisters the provided password validator for use with the Directory
5149 * Server.
5150 *
5151 * @param configEntryDN The DN of the configuration entry that defines the
5152 * password validator to deregister.
5153 */
5154 public static void deregisterPasswordValidator(DN configEntryDN)
5155 {
5156 directoryServer.passwordValidators.remove(configEntryDN);
5157 }
5158
5159
5160
5161 /**
5162 * Retrieves the set of account status notification handlers defined in the
5163 * Directory Server, as a mapping between the DN of the configuration entry
5164 * and the notification handler implementation.
5165 *
5166 * @return The set of account status notification handlers defined in the
5167 * Directory Server.
5168 */
5169 public static ConcurrentHashMap<DN,AccountStatusNotificationHandler>
5170 getAccountStatusNotificationHandlers()
5171 {
5172 return directoryServer.accountStatusNotificationHandlers;
5173 }
5174
5175
5176
5177 /**
5178 * Retrieves the account status notification handler with the specified
5179 * configuration entry DN.
5180 *
5181 * @param handlerDN The DN of the configuration entry associated with the
5182 * account status notification handler to retrieve.
5183 *
5184 * @return The requested account status notification handler, or
5185 * <CODE>null</CODE> if no such handler is defined in the server.
5186 */
5187 public static AccountStatusNotificationHandler
5188 getAccountStatusNotificationHandler(DN handlerDN)
5189 {
5190 return directoryServer.accountStatusNotificationHandlers.get(handlerDN);
5191 }
5192
5193
5194
5195 /**
5196 * Registers the provided account status notification handler with the
5197 * Directory Server.
5198 *
5199 * @param handlerDN The DN of the configuration entry that defines the
5200 * provided account status notification handler.
5201 * @param handler The account status notification handler to register with
5202 * the Directory Server.
5203 */
5204 public static void registerAccountStatusNotificationHandler(DN handlerDN,
5205 AccountStatusNotificationHandler handler)
5206 {
5207 directoryServer.accountStatusNotificationHandlers.put(handlerDN, handler);
5208 }
5209
5210
5211
5212 /**
5213 * Deregisters the specified account status notification handler with the
5214 * Directory Server.
5215 *
5216 * @param handlerDN The DN of the configuration entry for the account status
5217 * notification handler to deregister.
5218 */
5219 public static void deregisterAccountStatusNotificationHandler(DN handlerDN)
5220 {
5221 directoryServer.accountStatusNotificationHandlers.remove(handlerDN);
5222 }
5223
5224
5225
5226
5227 /**
5228 * Retrieves the set of password generators that have been registered for use
5229 * with the Directory Server as a mapping between the DN of the associated
5230 * generator configuration entry and the generator implementation.
5231 *
5232 * @return The set of password generators that have been registered for use
5233 * with the Directory Server.
5234 */
5235 public static ConcurrentHashMap<DN,PasswordGenerator> getPasswordGenerators()
5236 {
5237 return directoryServer.passwordGenerators;
5238 }
5239
5240
5241
5242 /**
5243 * Retrieves the password generator registered with the provided configuration
5244 * entry DN.
5245 *
5246 * @param configEntryDN The DN of the configuration entry for which to
5247 * retrieve the associated password generator.
5248 *
5249 * @return The requested password generator, or <CODE>null</CODE> if no such
5250 * generator is defined.
5251 */
5252 public static PasswordGenerator getPasswordGenerator(DN configEntryDN)
5253 {
5254 return directoryServer.passwordGenerators.get(configEntryDN);
5255 }
5256
5257
5258
5259 /**
5260 * Registers the provided password generator for use with the Directory
5261 * Server.
5262 *
5263 * @param configEntryDN The DN of the configuration entry that defines the
5264 * specified password generator.
5265 * @param generator The password generator to register with the
5266 * Directory Server.
5267 */
5268 public static void registerPasswordGenerator(DN configEntryDN,
5269 PasswordGenerator generator)
5270 {
5271 directoryServer.passwordGenerators.put(configEntryDN, generator);
5272 }
5273
5274
5275
5276 /**
5277 * Deregisters the provided password generator for use with the Directory
5278 * Server.
5279 *
5280 * @param configEntryDN The DN of the configuration entry that defines the
5281 * password generator to deregister.
5282 */
5283 public static void deregisterPasswordGenerator(DN configEntryDN)
5284 {
5285 directoryServer.passwordGenerators.remove(configEntryDN);
5286 }
5287
5288
5289
5290 /**
5291 * Retrieves the set of password policies registered with the Directory
5292 * Server. The references returned are to the actual password policy objects
5293 * currently in use by the directory server and the referenced objects must
5294 * not be modified.
5295 *
5296 * @return The set of password policies registered with the Directory Server.
5297 */
5298 public static PasswordPolicy[] getPasswordPolicies()
5299 {
5300 // The password policy objects are returned in an array to prevent the
5301 // caller from modifying the map structure.
5302 PasswordPolicyConfig[] values = directoryServer.passwordPolicies.values()
5303 .toArray(new PasswordPolicyConfig[0]);
5304 PasswordPolicy[] policies = new PasswordPolicy[values.length];
5305 for( int i = 0 ; i < values.length; ++i)
5306 {
5307 policies[i] = values[i].getPolicy();
5308 }
5309
5310 return policies;
5311 }
5312
5313
5314
5315 /**
5316 * Retrieves the password policy registered for the provided configuration
5317 * entry.
5318 *
5319 * @param configEntryDN The DN of the configuration entry for which to
5320 * retrieve the associated password policy.
5321 *
5322 * @return The password policy registered for the provided configuration
5323 * entry, or <CODE>null</CODE> if there is no such policy.
5324 */
5325 public static PasswordPolicy getPasswordPolicy(DN configEntryDN)
5326 {
5327 Validator.ensureNotNull(configEntryDN);
5328
5329 PasswordPolicyConfig config
5330 = directoryServer.passwordPolicies.get(configEntryDN);
5331 return (null == config) ? null : config.getPolicy();
5332 }
5333
5334
5335 /**
5336 * Retrieves the password policy registered for the provided configuration
5337 * entry.
5338 *
5339 * @param configEntryDN The DN of the configuration entry for which to
5340 * retrieve the associated password policy.
5341 *
5342 * @return The password policy config registered for the provided
5343 * configuration entry, or <CODE>null</CODE> if there is
5344 * no such policy.
5345 */
5346 public static PasswordPolicyConfig getPasswordPolicyConfig(DN configEntryDN)
5347 {
5348 Validator.ensureNotNull(configEntryDN);
5349
5350 return directoryServer.passwordPolicies.get(configEntryDN);
5351 }
5352
5353
5354 /**
5355 * Registers the provided password policy with the Directory Server. If a
5356 * policy is already registered for the provided configuration entry DN, then
5357 * it will be replaced.
5358 *
5359 * @param configEntryDN The DN of the configuration entry that defines the
5360 * password policy.
5361 * @param config The password policy config to register with the
5362 * server.
5363 */
5364 public static void registerPasswordPolicy(DN configEntryDN,
5365 PasswordPolicyConfig config)
5366 {
5367 Validator.ensureNotNull(configEntryDN, config);
5368
5369 directoryServer.passwordPolicies.put(configEntryDN, config);
5370 }
5371
5372
5373
5374 /**
5375 * Deregisters the provided password policy with the Directory Server. If no
5376 * such policy is registered, then no action will be taken.
5377 *
5378 * @param configEntryDN The DN of the configuration entry that defines the
5379 * password policy to deregister.
5380 */
5381 public static void deregisterPasswordPolicy(DN configEntryDN)
5382 {
5383 Validator.ensureNotNull(configEntryDN);
5384
5385 if (directoryServer.defaultPasswordPolicyDN.equals(configEntryDN))
5386 {
5387 directoryServer.defaultPasswordPolicyConfig = null;
5388 }
5389
5390 PasswordPolicyConfig config
5391 = directoryServer.passwordPolicies.remove(configEntryDN);
5392 }
5393
5394
5395
5396 /**
5397 * Retrieves the DN of the configuration entry for the default password policy
5398 * for the Directory Server.
5399 *
5400 * @return The DN of the configuration entry for the default password policy
5401 * for the Directory Server.
5402 */
5403 public static DN getDefaultPasswordPolicyDN()
5404 {
5405 return directoryServer.defaultPasswordPolicyDN;
5406 }
5407
5408
5409
5410 /**
5411 * Specifies the DN of the configuration entry for the default password policy
5412 * for the Directory Server. This routine does not check the registered
5413 * password policies for the specified DN, since in the case of server
5414 * initialization, the password policy entries will not yet have been loaded
5415 * from the configuration backend.
5416 *
5417 * @param defaultPasswordPolicyDN The DN of the configuration entry for the
5418 * default password policy for the Directory
5419 * Server.
5420 */
5421 public static void setDefaultPasswordPolicyDN(DN defaultPasswordPolicyDN)
5422 {
5423 directoryServer.defaultPasswordPolicyDN = defaultPasswordPolicyDN;
5424 directoryServer.defaultPasswordPolicyConfig = null;
5425 }
5426
5427
5428
5429 /**
5430 * Retrieves the default password policy for the Directory Server. This method
5431 * is equivalent to invoking <CODE>getPasswordPolicy</CODE> on the DN returned
5432 * from <CODE>DirectoryServer.getDefaultPasswordPolicyDN()</CODE>.
5433 *
5434 * @return The default password policy for the Directory Server.
5435 */
5436 public static PasswordPolicy getDefaultPasswordPolicy()
5437 {
5438 assert null != directoryServer.passwordPolicies.get(
5439 directoryServer.defaultPasswordPolicyDN)
5440 : "Internal Error: no default password policy defined." ;
5441
5442 if ((directoryServer.defaultPasswordPolicyConfig == null) &&
5443 (directoryServer.defaultPasswordPolicyDN != null))
5444 {
5445 directoryServer.defaultPasswordPolicyConfig =
5446 directoryServer.passwordPolicies.get(
5447 directoryServer.defaultPasswordPolicyDN);
5448 }
5449 assert directoryServer.passwordPolicies.get(
5450 directoryServer.defaultPasswordPolicyDN)
5451 == directoryServer.defaultPasswordPolicyConfig
5452 : "Internal Error: inconsistency between defaultPasswordPolicyConfig"
5453 + " cache and value in passwordPolicies map.";
5454 return directoryServer.defaultPasswordPolicyConfig.getPolicy();
5455 }
5456
5457
5458 /**
5459 * Retrieves the log rotation policy registered for the provided configuration
5460 * entry.
5461 *
5462 * @param configEntryDN The DN of the configuration entry for which to
5463 * retrieve the associated rotation policy.
5464 *
5465 * @return The rotation policy registered for the provided configuration
5466 * entry, or <CODE>null</CODE> if there is no such policy.
5467 */
5468 public static RotationPolicy getRotationPolicy(DN configEntryDN)
5469 {
5470 Validator.ensureNotNull(configEntryDN);
5471
5472 return directoryServer.rotationPolicies.get(configEntryDN);
5473 }
5474
5475 /**
5476 * Registers the provided log rotation policy with the Directory Server. If a
5477 * policy is already registered for the provided configuration entry DN, then
5478 * it will be replaced.
5479 *
5480 * @param configEntryDN The DN of the configuration entry that defines the
5481 * password policy.
5482 * @param policy The rotation policy to register with the server.
5483 */
5484 public static void registerRotationPolicy(DN configEntryDN,
5485 RotationPolicy policy)
5486 {
5487 Validator.ensureNotNull(configEntryDN, policy);
5488
5489 directoryServer.rotationPolicies.put(configEntryDN, policy);
5490 }
5491
5492
5493
5494 /**
5495 * Deregisters the provided log rotation policy with the Directory Server.
5496 * If no such policy is registered, then no action will be taken.
5497 *
5498 * @param configEntryDN The DN of the configuration entry that defines the
5499 * rotation policy to deregister.
5500 */
5501 public static void deregisterRotationPolicy(DN configEntryDN)
5502 {
5503 Validator.ensureNotNull(configEntryDN);
5504
5505 directoryServer.rotationPolicies.remove(configEntryDN);
5506 }
5507
5508 /**
5509 * Retrieves the log retention policy registered for the provided
5510 * configuration entry.
5511 *
5512 * @param configEntryDN The DN of the configuration entry for which to
5513 * retrieve the associated retention policy.
5514 *
5515 * @return The retention policy registered for the provided configuration
5516 * entry, or <CODE>null</CODE> if there is no such policy.
5517 */
5518 public static RetentionPolicy getRetentionPolicy(DN configEntryDN)
5519 {
5520 Validator.ensureNotNull(configEntryDN);
5521
5522 return directoryServer.retentionPolicies.get(configEntryDN);
5523 }
5524
5525 /**
5526 * Registers the provided log retention policy with the Directory Server.
5527 * If a policy is already registered for the provided configuration entry DN,
5528 * then it will be replaced.
5529 *
5530 * @param configEntryDN The DN of the configuration entry that defines the
5531 * password policy.
5532 * @param policy The retention policy to register with the server.
5533 */
5534 public static void registerRetentionPolicy(DN configEntryDN,
5535 RetentionPolicy policy)
5536 {
5537 Validator.ensureNotNull(configEntryDN, policy);
5538
5539 directoryServer.retentionPolicies.put(configEntryDN, policy);
5540 }
5541
5542
5543
5544 /**
5545 * Deregisters the provided log retention policy with the Directory Server.
5546 * If no such policy is registered, then no action will be taken.
5547 *
5548 * @param configEntryDN The DN of the configuration entry that defines the
5549 * retention policy to deregister.
5550 */
5551 public static void deregisterRetentionPolicy(DN configEntryDN)
5552 {
5553 Validator.ensureNotNull(configEntryDN);
5554
5555 directoryServer.retentionPolicies.remove(configEntryDN);
5556 }
5557
5558 /**
5559 * Retrieves the set of monitor providers that have been registered with the
5560 * Directory Server, as a mapping between the monitor name (in all lowercase
5561 * characters) and the monitor implementation.
5562 *
5563 * @return The set of monitor providers that have been registered with the
5564 * Directory Server.
5565 */
5566 public static ConcurrentHashMap<String,
5567 MonitorProvider<? extends MonitorProviderCfg>>
5568 getMonitorProviders()
5569 {
5570 return directoryServer.monitorProviders;
5571 }
5572
5573
5574
5575 /**
5576 * Retrieves the monitor provider with the specified name.
5577 *
5578 * @param lowerName The name of the monitor provider to retrieve, in all
5579 * lowercase characters.
5580 *
5581 * @return The requested resource monitor, or <CODE>null</CODE> if none
5582 * exists with the specified name.
5583 */
5584 public static MonitorProvider<? extends MonitorProviderCfg>
5585 getMonitorProvider(String lowerName)
5586 {
5587 return directoryServer.monitorProviders.get(lowerName);
5588 }
5589
5590
5591
5592 /**
5593 * Registers the provided monitor provider with the Directory Server. Note
5594 * that if a monitor provider is already registered with the specified name,
5595 * then it will be replaced with the provided implementation.
5596 *
5597 * @param monitorProvider The monitor provider to register with the
5598 * Directory Server.
5599 */
5600 public static void registerMonitorProvider(
5601 MonitorProvider<? extends MonitorProviderCfg>
5602 monitorProvider)
5603 {
5604 String lowerName = toLowerCase(monitorProvider.getMonitorInstanceName());
5605 directoryServer.monitorProviders.put(lowerName, monitorProvider);
5606
5607
5608 // Try to register this monitor provider with an appropriate JMX MBean.
5609 try
5610 {
5611 DN monitorDN = getMonitorProviderDN(monitorProvider);
5612 JMXMBean mBean = directoryServer.mBeans.get(monitorDN);
5613 if (mBean == null)
5614 {
5615 mBean = new JMXMBean(monitorDN);
5616 mBean.addMonitorProvider(monitorProvider);
5617 directoryServer.mBeans.put(monitorDN, mBean);
5618 }
5619 else
5620 {
5621 mBean.addMonitorProvider(monitorProvider);
5622 }
5623 }
5624 catch (Exception e)
5625 {
5626 if (debugEnabled())
5627 {
5628 TRACER.debugCaught(DebugLogLevel.ERROR, e);
5629 }
5630 }
5631 }
5632
5633
5634
5635 /**
5636 * Deregisters the specified monitor provider from the Directory Server. If
5637 * no such monitor provider is registered, no action will be taken.
5638 *
5639 * @param lowerName The name of the monitor provider to deregister, in all
5640 * lowercase characters.
5641 */
5642 public static void deregisterMonitorProvider(String lowerName)
5643 {
5644 MonitorProvider provider =
5645 directoryServer.monitorProviders.remove(toLowerCase(lowerName));
5646
5647
5648 // Try to deregister the monitor provider as an MBean.
5649 if (provider != null)
5650 {
5651 try
5652 {
5653 DN monitorDN = getMonitorProviderDN(provider);
5654 JMXMBean mBean = directoryServer.mBeans.get(monitorDN);
5655 if (mBean != null)
5656 {
5657 mBean.removeMonitorProvider(provider);
5658 }
5659 }
5660 catch (Exception e)
5661 {
5662 if (debugEnabled())
5663 {
5664 TRACER.debugCaught(DebugLogLevel.ERROR, e);
5665 }
5666 }
5667 }
5668 }
5669
5670
5671
5672 /**
5673 * Retrieves the entry cache for the Directory Server.
5674 *
5675 * @return The entry cache for the Directory Server.
5676 */
5677 public static EntryCache getEntryCache()
5678 {
5679 return directoryServer.entryCache;
5680 }
5681
5682
5683
5684 /**
5685 * Specifies the entry cache that should be used by the Directory Server.
5686 * This should only be called by the entry cache configuration manager.
5687 *
5688 * @param entryCache The entry cache for the Directory Server.
5689 */
5690 public static void setEntryCache(EntryCache entryCache)
5691 {
5692 synchronized (directoryServer)
5693 {
5694 directoryServer.entryCache = entryCache;
5695 }
5696 }
5697
5698
5699
5700 /**
5701 * Retrieves the set of key manager providers registered with the Directory
5702 * Server.
5703 *
5704 * @return The set of key manager providers registered with the Directory
5705 * Server.
5706 */
5707 public static Map<DN,KeyManagerProvider> getKeyManagerProviders()
5708 {
5709 return directoryServer.keyManagerProviders;
5710 }
5711
5712
5713
5714 /**
5715 * Retrieves the key manager provider registered with the provided entry DN.
5716 *
5717 * @param providerDN The DN with which the key manager provider is
5718 * registered.
5719 *
5720 * @return The key manager provider registered with the provided entry DN, or
5721 * {@code null} if there is no such key manager provider registered
5722 * with the server.
5723 */
5724 public static KeyManagerProvider getKeyManagerProvider(DN providerDN)
5725 {
5726 return directoryServer.keyManagerProviders.get(providerDN);
5727 }
5728
5729
5730
5731 /**
5732 * Registers the provided key manager provider with the Directory Server.
5733 *
5734 * @param providerDN The DN with which to register the key manager provider.
5735 * @param provider The key manager provider to register with the server.
5736 */
5737 public static void registerKeyManagerProvider(DN providerDN,
5738 KeyManagerProvider provider)
5739 {
5740 directoryServer.keyManagerProviders.put(providerDN, provider);
5741 }
5742
5743
5744
5745 /**
5746 * Deregisters the specified key manager provider with the Directory Server.
5747 *
5748 * @param providerDN The DN with which the key manager provider is
5749 * registered.
5750 */
5751 public static void deregisterKeyManagerProvider(DN providerDN)
5752 {
5753 directoryServer.keyManagerProviders.remove(providerDN);
5754 }
5755
5756
5757
5758 /**
5759 * Retrieves the set of trust manager providers registered with the Directory
5760 * Server.
5761 *
5762 * @return The set of trust manager providers registered with the Directory
5763 * Server.
5764 */
5765 public static Map<DN,TrustManagerProvider> getTrustManagerProviders()
5766 {
5767 return directoryServer.trustManagerProviders;
5768 }
5769
5770
5771
5772 /**
5773 * Retrieves the trust manager provider registered with the provided entry DN.
5774 *
5775 * @param providerDN The DN with which the trust manager provider is
5776 * registered.
5777 *
5778 * @return The trust manager provider registered with the provided entry DN,
5779 * or {@code null} if there is no such trust manager provider
5780 * registered with the server.
5781 */
5782 public static TrustManagerProvider getTrustManagerProvider(DN providerDN)
5783 {
5784 return directoryServer.trustManagerProviders.get(providerDN);
5785 }
5786
5787
5788
5789 /**
5790 * Registers the provided trust manager provider with the Directory Server.
5791 *
5792 * @param providerDN The DN with which to register the trust manager
5793 * provider.
5794 * @param provider The trust manager provider to register with the server.
5795 */
5796 public static void registerTrustManagerProvider(DN providerDN,
5797 TrustManagerProvider provider)
5798 {
5799 directoryServer.trustManagerProviders.put(providerDN, provider);
5800 }
5801
5802
5803
5804 /**
5805 * Deregisters the specified trust manager provider with the Directory Server.
5806 *
5807 * @param providerDN The DN with which the trust manager provider is
5808 * registered.
5809 */
5810 public static void deregisterTrustManagerProvider(DN providerDN)
5811 {
5812 directoryServer.trustManagerProviders.remove(providerDN);
5813 }
5814
5815
5816
5817 /**
5818 * Retrieves the set of certificate mappers registered with the Directory
5819 * Server.
5820 *
5821 * @return The set of certificate mappers registered with the Directory
5822 * Server.
5823 */
5824 public static Map<DN,CertificateMapper> getCertificateMappers()
5825 {
5826 return directoryServer.certificateMappers;
5827 }
5828
5829
5830
5831 /**
5832 * Retrieves the certificate mapper registered with the provided entry DN.
5833 *
5834 * @param mapperDN The DN with which the certificate mapper is registered.
5835 *
5836 * @return The certificate mapper registered with the provided entry DN, or
5837 * {@code null} if there is no such certificate mapper registered
5838 * with the server.
5839 */
5840 public static CertificateMapper getCertificateMapper(DN mapperDN)
5841 {
5842 return directoryServer.certificateMappers.get(mapperDN);
5843 }
5844
5845
5846
5847 /**
5848 * Registers the provided certificate mapper with the Directory Server.
5849 *
5850 * @param mapperDN The DN with which to register the certificate mapper.
5851 * @param mapper The certificate mapper to register with the server.
5852 */
5853 public static void registerCertificateMapper(DN mapperDN,
5854 CertificateMapper mapper)
5855 {
5856 directoryServer.certificateMappers.put(mapperDN, mapper);
5857 }
5858
5859
5860
5861 /**
5862 * Deregisters the specified certificate mapper with the Directory Server.
5863 *
5864 * @param mapperDN The DN with which the certificate mapper is registered.
5865 */
5866 public static void deregisterCertificateMapper(DN mapperDN)
5867 {
5868 directoryServer.certificateMappers.remove(mapperDN);
5869 }
5870
5871
5872
5873
5874 /**
5875 * Retrieves the set of privileges that should automatically be granted to
5876 * root users when they authenticate.
5877 *
5878 * @return The set of privileges that should automatically be granted to root
5879 * users when they authenticate.
5880 */
5881 public static Set<Privilege> getRootPrivileges()
5882 {
5883 return directoryServer.rootDNConfigManager.getRootPrivileges();
5884 }
5885
5886
5887
5888 /**
5889 * Retrieves the DNs for the root users configured in the Directory Server.
5890 * Note that this set should only contain the actual DNs for the root users
5891 * and not any alternate DNs. Also, the contents of the returned set must not
5892 * be altered by the caller.
5893 *
5894 * @return The DNs for the root users configured in the Directory Server.
5895 */
5896 public static CopyOnWriteArraySet<DN> getRootDNs()
5897 {
5898 return directoryServer.rootDNs;
5899 }
5900
5901
5902
5903 /**
5904 * Indicates whether the provided DN is the DN for one of the root users
5905 * configured in the Directory Server.
5906 *
5907 * @param userDN The user DN for which to make the determination.
5908 *
5909 * @return <CODE>true</CODE> if the provided user DN is a Directory Server
5910 * root DN, or <CODE>false</CODE> if not.
5911 */
5912 public static boolean isRootDN(DN userDN)
5913 {
5914 return directoryServer.rootDNs.contains(userDN);
5915 }
5916
5917
5918
5919 /**
5920 * Registers the provided root DN with the Directory Server.
5921 *
5922 * @param rootDN The root DN to register with the Directory Server.
5923 */
5924 public static void registerRootDN(DN rootDN)
5925 {
5926 directoryServer.rootDNs.add(rootDN);
5927 }
5928
5929
5930
5931 /**
5932 * Deregisters the provided root DN with the Directory Server. This will have
5933 * no effect if the provided DN is not registered as a root DN.
5934 *
5935 * @param rootDN The root DN to deregister.
5936 */
5937 public static void deregisterRootDN(DN rootDN)
5938 {
5939 directoryServer.rootDNs.remove(rootDN);
5940 }
5941
5942
5943
5944 /**
5945 * Retrieves the set of alternate bind DNs for root users, mapped between the
5946 * alternate DN and the real DN. The contents of the returned map must not be
5947 * altered by the caller.
5948 *
5949 * @return The set of alternate bind DNs for root users, mapped between the
5950 * alternate DN and the real DN.
5951 */
5952 public static ConcurrentHashMap<DN,DN> getAlternateRootBindDNs()
5953 {
5954 return directoryServer.alternateRootBindDNs;
5955 }
5956
5957
5958
5959 /**
5960 * Retrieves the real entry DN for the root user with the provided alternate
5961 * bind DN.
5962 *
5963 * @param alternateRootBindDN The alternate root bind DN for which to
5964 * retrieve the real entry DN.
5965 *
5966 * @return The real entry DN for the root user with the provided alternate
5967 * bind DN, or <CODE>null</CODE> if no such mapping has been defined.
5968 */
5969 public static DN getActualRootBindDN(DN alternateRootBindDN)
5970 {
5971 return directoryServer.alternateRootBindDNs.get(alternateRootBindDN);
5972 }
5973
5974
5975
5976 /**
5977 * Registers an alternate root bind DN using the provided information.
5978 *
5979 * @param actualRootEntryDN The actual DN for the root user's entry.
5980 * @param alternateRootBindDN The alternate DN that should be interpreted as
5981 * if it were the provided actual root entry DN.
5982 *
5983 * @throws DirectoryException If the provided alternate bind DN is already
5984 * in use for another root user.
5985 */
5986 public static void registerAlternateRootDN(DN actualRootEntryDN,
5987 DN alternateRootBindDN)
5988 throws DirectoryException
5989 {
5990 DN existingRootEntryDN =
5991 directoryServer.alternateRootBindDNs.putIfAbsent(alternateRootBindDN,
5992 actualRootEntryDN);
5993 if ((existingRootEntryDN != null) &&
5994 (! existingRootEntryDN.equals(actualRootEntryDN)))
5995 {
5996 Message message = ERR_CANNOT_REGISTER_DUPLICATE_ALTERNATE_ROOT_BIND_DN.
5997 get(String.valueOf(alternateRootBindDN),
5998 String.valueOf(existingRootEntryDN));
5999 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
6000 }
6001 }
6002
6003
6004
6005 /**
6006 * Deregisters the provided alternate root bind DN from the server. This will
6007 * have no effect if there was no mapping defined for the provided alternate
6008 * root bind DN.
6009 *
6010 * @param alternateRootBindDN The alternate root bind DN to be deregistered.
6011 *
6012 * @return The actual root entry DN to which the provided alternate bind DN
6013 * was mapped, or <CODE>null</CODE> if there was no mapping for the
6014 * provided DN.
6015 */
6016 public static DN deregisterAlternateRootBindDN(DN alternateRootBindDN)
6017 {
6018 return directoryServer.alternateRootBindDNs.remove(alternateRootBindDN);
6019 }
6020
6021
6022
6023 /**
6024 * Retrieves the result code that should be used when the Directory Server
6025 * encounters an internal server error.
6026 *
6027 * @return The result code that should be used when the Directory Server
6028 * encounters an internal server error.
6029 */
6030 public static ResultCode getServerErrorResultCode()
6031 {
6032 return directoryServer.serverErrorResultCode;
6033 }
6034
6035
6036
6037 /**
6038 * Specifies the result code that should be used when the Directory Server
6039 * encounters an internal server error.
6040 *
6041 * @param serverErrorResultCode The result code that should be used when the
6042 * Directory Server encounters an internal
6043 * server error.
6044 */
6045 public static void setServerErrorResultCode(ResultCode serverErrorResultCode)
6046 {
6047 directoryServer.serverErrorResultCode = serverErrorResultCode;
6048 }
6049
6050
6051
6052 /**
6053 * Indicates whether the Directory Server should automatically add missing RDN
6054 * attributes to an entry whenever it is added.
6055 *
6056 * @return <CODE>true</CODE> if the Directory Server should automatically add
6057 * missing RDN attributes to an entry, or <CODE>false</CODE> if it
6058 * should return an error to the client.
6059 */
6060 public static boolean addMissingRDNAttributes()
6061 {
6062 return directoryServer.addMissingRDNAttributes;
6063 }
6064
6065
6066
6067 /**
6068 * Specifies whether the Directory Server should automatically add missing RDN
6069 * attributes to an entry whenever it is added.
6070 *
6071 * @param addMissingRDNAttributes Specifies whether the Directory Server
6072 * should automatically add missing RDN
6073 * attributes to an entry whenever it is
6074 * added.
6075 */
6076 public static void setAddMissingRDNAttributes(boolean addMissingRDNAttributes)
6077 {
6078 directoryServer.addMissingRDNAttributes = addMissingRDNAttributes;
6079 }
6080
6081
6082
6083 /**
6084 * Indicates whether to be more flexible in the set of characters allowed for
6085 * attribute names. The standard requires that only ASCII alphabetic letters,
6086 * numeric digits, and hyphens be allowed, and that the name start with a
6087 * letter. If attribute name exceptions are enabled, then underscores will
6088 * also be allowed, and the name will be allowed to start with a digit.
6089 *
6090 * @return <CODE>true</CODE> if the server should use a more flexible
6091 * syntax for attribute names, or <CODE>false</CODE> if not.
6092 */
6093 public static boolean allowAttributeNameExceptions()
6094 {
6095 return directoryServer.allowAttributeNameExceptions;
6096 }
6097
6098
6099
6100 /**
6101 * Specifies whether to be more flexible in the set of characters allowed for
6102 * attribute names.
6103 *
6104 * @param allowAttributeNameExceptions Specifies whether to be more flexible
6105 * in the set of characters allowed for
6106 * attribute names.
6107 */
6108 public static void setAllowAttributeNameExceptions(
6109 boolean allowAttributeNameExceptions)
6110 {
6111 directoryServer.allowAttributeNameExceptions = allowAttributeNameExceptions;
6112 }
6113
6114
6115
6116 /**
6117 * Indicates whether the Directory Server should perform schema checking.
6118 *
6119 * @return <CODE>true</CODE> if the Directory Server should perform schema
6120 * checking, or <CODE>false</CODE> if not.
6121 */
6122 public static boolean checkSchema()
6123 {
6124 return directoryServer.checkSchema;
6125 }
6126
6127
6128
6129 /**
6130 * Specifies whether the Directory Server should perform schema checking.
6131 *
6132 * @param checkSchema Specifies whether the Directory Server should perform
6133 * schema checking.
6134 */
6135 public static void setCheckSchema(boolean checkSchema)
6136 {
6137 directoryServer.checkSchema = checkSchema;
6138 }
6139
6140
6141
6142 /**
6143 * Retrieves the policy that should be used regarding enforcement of a single
6144 * structural objectclass per entry.
6145 *
6146 * @return The policy that should be used regarding enforcement of a single
6147 * structural objectclass per entry.
6148 */
6149 public static AcceptRejectWarn getSingleStructuralObjectClassPolicy()
6150 {
6151 return directoryServer.singleStructuralClassPolicy;
6152 }
6153
6154
6155
6156 /**
6157 * Specifies the policy that should be used regarding enforcement of a single
6158 * structural objectclass per entry.
6159 *
6160 * @param singleStructuralClassPolicy The policy that should be used
6161 * regarding enforcement of a single
6162 * structural objectclass per entry.
6163 */
6164 public static void setSingleStructuralObjectClassPolicy(
6165 AcceptRejectWarn singleStructuralClassPolicy)
6166 {
6167 directoryServer.singleStructuralClassPolicy = singleStructuralClassPolicy;
6168 }
6169
6170
6171
6172 /**
6173 * Retrieves the policy that should be used when an attribute value is found
6174 * that is not valid according to the associated attribute syntax.
6175 *
6176 * @return The policy that should be used when an attribute value is found
6177 * that is not valid according to the associated attribute syntax.
6178 */
6179 public static AcceptRejectWarn getSyntaxEnforcementPolicy()
6180 {
6181 return directoryServer.syntaxEnforcementPolicy;
6182 }
6183
6184
6185
6186 /**
6187 * Retrieves the policy that should be used when an attribute value is found
6188 * that is not valid according to the associated attribute syntax.
6189 *
6190 * @param syntaxEnforcementPolicy The policy that should be used when an
6191 * attribute value is found that is not valid
6192 * according to the associated attribute
6193 * syntax.
6194 */
6195 public static void setSyntaxEnforcementPolicy(
6196 AcceptRejectWarn syntaxEnforcementPolicy)
6197 {
6198 directoryServer.syntaxEnforcementPolicy = syntaxEnforcementPolicy;
6199 }
6200
6201
6202
6203 /**
6204 * Indicates whether the Directory Server should send a response to an
6205 * operation that has been abandoned. Sending such a response is technically
6206 * a violation of the LDAP protocol specification, but not doing so in that
6207 * case can cause problems with clients that are expecting a response and may
6208 * hang until they get one.
6209 *
6210 * @return <CODE>true</CODE> if the Directory Server should send a response
6211 * to an operation that has been abandoned, or <CODE>false</CODE> if
6212 * not.
6213 */
6214 public static boolean notifyAbandonedOperations()
6215 {
6216 return directoryServer.notifyAbandonedOperations;
6217 }
6218
6219
6220
6221 /**
6222 * Specifies whether the Directory Server should send a response to an
6223 * operation that has been abandoned. Sending such a response is technically
6224 * a violation of the LDAP protocol specification, but not doing so in that
6225 * case can cause problems with clients that are expecting a response and may
6226 * hang until they get one.
6227 *
6228 * @param notifyAbandonedOperations Indicates whether the Directory Server
6229 * should send a response to an operation
6230 * that has been abandoned.
6231 */
6232 public static void setNotifyAbandonedOperations(
6233 boolean notifyAbandonedOperations)
6234 {
6235 directoryServer.notifyAbandonedOperations = notifyAbandonedOperations;
6236 }
6237
6238
6239
6240 /**
6241 * Retrieves the set of backends that have been registered with the Directory
6242 * Server, as a mapping between the backend ID and the corresponding backend.
6243 *
6244 * @return The set of backends that have been registered with the Directory
6245 * Server.
6246 */
6247 public static Map<String,Backend> getBackends()
6248 {
6249 return directoryServer.backends;
6250 }
6251
6252
6253
6254 /**
6255 * Retrieves the backend with the specified backend ID.
6256 *
6257 * @param backendID The backend ID of the backend to retrieve.
6258 *
6259 * @return The backend with the specified backend ID, or {@code null} if
6260 * there is none.
6261 */
6262 public static Backend getBackend(String backendID)
6263 {
6264 return directoryServer.backends.get(backendID);
6265 }
6266
6267
6268
6269 /**
6270 * Indicates whether the Directory Server has a backend with the specified
6271 * backend ID.
6272 *
6273 * @param backendID The backend ID for which to make the determination.
6274 *
6275 * @return {@code true} if the Directory Server has a backend with the
6276 * specified backend ID, or {@code false} if not.
6277 */
6278 public static boolean hasBackend(String backendID)
6279 {
6280 return directoryServer.backends.containsKey(backendID);
6281 }
6282
6283
6284
6285 /**
6286 * Registers the provided backend with the Directory Server. Note that this
6287 * will not register the set of configured suffixes with the server, as that
6288 * must be done by the backend itself.
6289 *
6290 * @param backend The backend to register with the server. Neither the
6291 * backend nor its backend ID may be null.
6292 *
6293 * @throws DirectoryException If the backend ID for the provided backend
6294 * conflicts with the backend ID of an existing
6295 * backend.
6296 */
6297 public static void registerBackend(Backend backend)
6298 throws DirectoryException
6299 {
6300 ensureNotNull(backend);
6301
6302 String backendID = backend.getBackendID();
6303 ensureNotNull(backendID);
6304
6305 synchronized (directoryServer)
6306 {
6307 TreeMap<String, Backend> newBackends =
6308 new TreeMap<String, Backend>(directoryServer.backends);
6309 if (newBackends.containsKey(backendID))
6310 {
6311 Message message = ERR_REGISTER_BACKEND_ALREADY_EXISTS.get(backendID);
6312 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
6313 }
6314 else
6315 {
6316 newBackends.put(backendID, backend);
6317 directoryServer.backends = newBackends;
6318
6319 for (String oid : backend.getSupportedControls())
6320 {
6321 registerSupportedControl(oid);
6322 }
6323
6324 for (String oid : backend.getSupportedFeatures())
6325 {
6326 registerSupportedFeature(oid);
6327 }
6328
6329 BackendMonitor monitor = new BackendMonitor(backend);
6330 monitor.initializeMonitorProvider(null);
6331 backend.setBackendMonitor(monitor);
6332 registerMonitorProvider(monitor);
6333 }
6334 }
6335 }
6336
6337
6338
6339 /**
6340 * Deregisters the provided backend with the Directory Server. Note that this
6341 * will not deregister the set of configured suffixes with the server, as that
6342 * must be done by the backend itself.
6343 *
6344 * @param backend The backend to deregister with the server. It must not be
6345 * {@code null}.
6346 */
6347 public static void deregisterBackend(Backend backend)
6348 {
6349 ensureNotNull(backend);
6350
6351 synchronized (directoryServer)
6352 {
6353 TreeMap<String,Backend> newBackends =
6354 new TreeMap<String,Backend>(directoryServer.backends);
6355 newBackends.remove(backend.getBackendID());
6356
6357 directoryServer.backends = newBackends;
6358
6359 // Don't need anymore the local backend workflow element so we
6360 // can remove it. We do remove the workflow element only when
6361 // the workflow configuration mode is auto because in manual
6362 // mode the config manager is doing the job.
6363 if (workflowConfigurationModeIsAuto())
6364 {
6365 LocalBackendWorkflowElement.remove(backend.getBackendID());
6366 }
6367
6368
6369 BackendMonitor monitor = backend.getBackendMonitor();
6370 if (monitor != null)
6371 {
6372 String instanceName = toLowerCase(monitor.getMonitorInstanceName());
6373 deregisterMonitorProvider(instanceName);
6374 monitor.finalizeMonitorProvider();
6375 backend.setBackendMonitor(null);
6376 }
6377 }
6378 }
6379
6380
6381
6382 /**
6383 * This method returns a map that contains a unique offline state id,
6384 * such as checksum, for every server backend that has registered one.
6385 *
6386 * @return <CODE>Map</CODE> backend to checksum map for offline state.
6387 */
6388 public static Map<String,Long> getOfflineBackendsStateIDs() {
6389 return Collections.unmodifiableMap(directoryServer.offlineBackendsStateIDs);
6390 }
6391
6392
6393
6394 /**
6395 * This method allows any server backend to register its unique offline
6396 * state, such as checksum, in a global map other server components can
6397 * access to determine if any changes were made to given backend while
6398 * offline.
6399 *
6400 * @param backend As returned by <CODE>getBackendID()</CODE> method.
6401 *
6402 * @param id Unique offline state identifier such as checksum.
6403 */
6404 public static void registerOfflineBackendStateID(String backend, long id) {
6405 // Zero means failed checksum so just skip it.
6406 if (id != 0) {
6407 directoryServer.offlineBackendsStateIDs.put(backend, id);
6408 }
6409 }
6410
6411
6412
6413 /**
6414 * Retrieves the entire set of base DNs registered with the Directory Server,
6415 * mapped from the base DN to the backend responsible for that base DN. The
6416 * same backend may be present multiple times, mapped from different base DNs.
6417 *
6418 * @return The entire set of base DNs registered with the Directory Server.
6419 */
6420 public static Map<DN,Backend> getBaseDNs()
6421 {
6422 return directoryServer.baseDnRegistry.getBaseDnMap();
6423 }
6424
6425
6426
6427 /**
6428 * Retrieves the backend with the specified base DN.
6429 *
6430 * @param baseDN The DN that is registered as one of the base DNs for the
6431 * backend to retrieve.
6432 *
6433 * @return The backend with the specified base DN, or {@code null} if there
6434 * is no backend registered with the specified base DN.
6435 */
6436 public static Backend getBackendWithBaseDN(DN baseDN)
6437 {
6438 return directoryServer.baseDnRegistry.getBaseDnMap().get(baseDN);
6439 }
6440
6441
6442
6443 /**
6444 * Retrieves the backend that should be used to handle operations on the
6445 * specified entry.
6446 *
6447 * @param entryDN The DN of the entry for which to retrieve the
6448 * corresponding backend.
6449 *
6450 * @return The backend that should be used to handle operations on the
6451 * specified entry, or {@code null} if no appropriate backend is
6452 * registered with the server.
6453 */
6454 public static Backend getBackend(DN entryDN)
6455 {
6456 if (entryDN.isNullDN())
6457 {
6458 return directoryServer.rootDSEBackend;
6459 }
6460
6461 Map<DN,Backend> baseDNs = directoryServer.baseDnRegistry.getBaseDnMap();
6462 Backend b = baseDNs.get(entryDN);
6463 while (b == null)
6464 {
6465 entryDN = entryDN.getParent();
6466 if (entryDN == null)
6467 {
6468 return null;
6469 }
6470
6471 b = baseDNs.get(entryDN);
6472 }
6473
6474 return b;
6475 }
6476
6477
6478 /**
6479 * Obtains a copy of the server's base DN registry. The copy can be used
6480 * to test registration/deregistration of base DNs but cannot be used to
6481 * modify the backends. To modify the server's live base DN to backend
6482 * mappings use {@link #registerBaseDN(DN, Backend, boolean)} and
6483 * {@link #deregisterBaseDN(DN)}.
6484 *
6485 * @return copy of the base DN regsitry
6486 */
6487 public static BaseDnRegistry copyBaseDnRegistry()
6488 {
6489 return directoryServer.baseDnRegistry.copy();
6490 }
6491
6492
6493 /**
6494 * Registers the provided base DN with the server.
6495 *
6496 * @param baseDN The base DN to register with the server. It must not be
6497 * {@code null}.
6498 * @param backend The backend responsible for the provided base DN. It
6499 * must not be {@code null}.
6500 * @param isPrivate Indicates whether the base DN should be considered a
6501 * private base DN. If the provided base DN is a naming
6502 * context, then this controls whether it is public or
6503 * private.
6504 *
6505 * @throws DirectoryException If a problem occurs while attempting to
6506 * register the provided base DN.
6507 */
6508 public static void registerBaseDN(DN baseDN, Backend backend,
6509 boolean isPrivate)
6510 throws DirectoryException
6511 {
6512 ensureNotNull(baseDN, backend);
6513
6514 synchronized (directoryServer)
6515 {
6516 List<Message> warnings =
6517 directoryServer.baseDnRegistry.registerBaseDN(
6518 baseDN, backend, isPrivate);
6519
6520 // Since we've committed the changes we need to log any issues
6521 // that this registration has caused
6522 if (warnings != null) {
6523 for (Message warning : warnings) {
6524 logError(warning);
6525 }
6526 }
6527
6528 // When a new baseDN is registered with the server we have to create
6529 // a new workflow to handle the base DN. We do not need to create
6530 // the workflow in manual mode because in that case the workflows
6531 // are created explicitely.
6532 if (workflowConfigurationModeIsAuto())
6533 {
6534 // Now create a workflow for the registered baseDN and register
6535 // the workflow with the default network group, but don't register
6536 // the workflow if the backend happens to be the configuration
6537 // backend because it's too soon for the config backend.
6538 if (! baseDN.equals(DN.decode("cn=config")))
6539 {
6540 WorkflowImpl workflowImpl = createWorkflow(baseDN, backend);
6541 registerWorkflowWithDefaultNetworkGroup(workflowImpl);
6542 }
6543 }
6544 }
6545 }
6546
6547
6548
6549 /**
6550 * Deregisters the provided base DN with the server.
6551 *
6552 * @param baseDN The base DN to deregister with the server. It must not
6553 * be {@code null}.
6554 *
6555 * @throws DirectoryException If a problem occurs while attempting to
6556 * deregister the provided base DN.
6557 */
6558 public static void deregisterBaseDN(DN baseDN)
6559 throws DirectoryException
6560 {
6561 ensureNotNull(baseDN);
6562
6563 synchronized(directoryServer) {
6564
6565 List<Message> warnings =
6566 directoryServer.baseDnRegistry.deregisterBaseDN(baseDN);
6567
6568 // Since we've committed the changes we need to log any issues
6569 // that this registration has caused
6570 if (warnings != null) {
6571 for (Message error : warnings) {
6572 logError(error);
6573 }
6574 }
6575
6576 // Now we need to deregister the workflow that was associated with
6577 // the base DN but we can do it only when the workflow configuration
6578 // mode is auto, because in manual mode the deregistration is done
6579 // by the workflow config manager.
6580 if (workflowConfigurationModeIsAuto())
6581 {
6582 deregisterWorkflowWithDefaultNetworkGroup(baseDN);
6583 }
6584 }
6585 }
6586
6587
6588
6589 /**
6590 * Retrieves the set of public naming contexts defined in the Directory
6591 * Server, mapped from the naming context DN to the corresponding backend.
6592 *
6593 * @return The set of public naming contexts defined in the Directory Server.
6594 */
6595 public static Map<DN,Backend> getPublicNamingContexts()
6596 {
6597 return directoryServer.baseDnRegistry.getPublicNamingContextsMap();
6598 }
6599
6600
6601
6602 /**
6603 * Retrieves the set of private naming contexts defined in the Directory
6604 * Server, mapped from the naming context DN to the corresponding backend.
6605 *
6606 * @return The set of private naming contexts defined in the Directory
6607 * Server.
6608 */
6609 public static Map<DN,Backend> getPrivateNamingContexts()
6610 {
6611 return directoryServer.baseDnRegistry.getPrivateNamingContextsMap();
6612 }
6613
6614
6615
6616 /**
6617 * Indicates whether the specified DN is one of the Directory Server naming
6618 * contexts.
6619 *
6620 * @param dn The DN for which to make the determination.
6621 *
6622 * @return {@code true} if the specified DN is a naming context for the
6623 * Directory Server, or {@code false} if it is not.
6624 */
6625 public static boolean isNamingContext(DN dn)
6626 {
6627 return directoryServer.baseDnRegistry.containsNamingContext(dn);
6628 }
6629
6630
6631
6632 /**
6633 * Retrieves the root DSE entry for the Directory Server.
6634 *
6635 * @return The root DSE entry for the Directory Server.
6636 */
6637 public static Entry getRootDSE()
6638 {
6639 return directoryServer.rootDSEBackend.getRootDSE();
6640 }
6641
6642
6643
6644 /**
6645 * Retrieves the root DSE backend for the Directory Server.
6646 *
6647 * @return The root DSE backend for the Directory Server.
6648 */
6649 public static RootDSEBackend getRootDSEBackend()
6650 {
6651 return directoryServer.rootDSEBackend;
6652 }
6653
6654
6655
6656 /**
6657 * Retrieves the DN of the entry containing the server schema definitions.
6658 *
6659 * @return The DN of the entry containing the server schema definitions, or
6660 * <CODE>null</CODE> if none has been defined (e.g., if no schema
6661 * backend has been configured).
6662 */
6663 public static DN getSchemaDN()
6664 {
6665 return directoryServer.schemaDN;
6666 }
6667
6668
6669
6670 /**
6671 * Specifies the DN of the entry containing the server schema definitions.
6672 *
6673 * @param schemaDN The DN of the entry containing the server schema
6674 * definitions.
6675 */
6676 public static void setSchemaDN(DN schemaDN)
6677 {
6678 directoryServer.schemaDN = schemaDN;
6679 }
6680
6681
6682
6683 /**
6684 * Retrieves the entry with the requested DN. It will first determine which
6685 * backend should be used for this DN and will then use that backend to
6686 * retrieve the entry. The caller must already hold the appropriate lock on
6687 * the specified entry.
6688 *
6689 * @param entryDN The DN of the entry to retrieve.
6690 *
6691 * @return The requested entry, or <CODE>null</CODE> if it does not exist.
6692 *
6693 * @throws DirectoryException If a problem occurs while attempting to
6694 * retrieve the entry.
6695 */
6696 public static Entry getEntry(DN entryDN)
6697 throws DirectoryException
6698 {
6699 // If the entry is the root DSE, then get and return that.
6700 if (entryDN.isNullDN())
6701 {
6702 return directoryServer.rootDSEBackend.getRootDSE();
6703 }
6704
6705 // Figure out which backend should be used for the entry. If it isn't
6706 // appropriate for any backend, then return null.
6707 Backend backend = getBackend(entryDN);
6708 if (backend == null)
6709 {
6710 return null;
6711 }
6712
6713 // Retrieve the requested entry from the backend.
6714 return backend.getEntry(entryDN);
6715 }
6716
6717
6718
6719 /**
6720 * Indicates whether the specified entry exists in the Directory Server. The
6721 * caller is not required to hold any locks when invoking this method.
6722 *
6723 * @param entryDN The DN of the entry for which to make the determination.
6724 *
6725 * @return <CODE>true</CODE> if the specified entry exists in one of the
6726 * backends, or <CODE>false</CODE> if it does not.
6727 *
6728 * @throws DirectoryException If a problem occurs while attempting to
6729 * make the determination.
6730 */
6731 public static boolean entryExists(DN entryDN)
6732 throws DirectoryException
6733 {
6734 // If the entry is the root DSE, then it will always exist.
6735 if (entryDN.isNullDN())
6736 {
6737 return true;
6738 }
6739
6740 // Figure out which backend should be used for the entry. If it isn't
6741 // appropriate for any backend, then return false.
6742 Backend backend = getBackend(entryDN);
6743 if (backend == null)
6744 {
6745 return false;
6746 }
6747
6748 // Ask the appropriate backend if the entry exists.
6749 return backend.entryExists(entryDN);
6750 }
6751
6752
6753
6754 /**
6755 * Retrieves the set of supported controls registered with the Directory
6756 * Server.
6757 *
6758 * @return The set of supported controls registered with the Directory
6759 * Server.
6760 */
6761 public static TreeSet<String> getSupportedControls()
6762 {
6763 return directoryServer.supportedControls;
6764 }
6765
6766
6767
6768 /**
6769 * Indicates whether the specified OID is registered with the Directory Server
6770 * as a supported control.
6771 *
6772 * @param controlOID The OID of the control for which to make the
6773 * determination.
6774 *
6775 * @return <CODE>true</CODE> if the specified OID is registered with the
6776 * server as a supported control, or <CODE>false</CODE> if not.
6777 */
6778 public static boolean isSupportedControl(String controlOID)
6779 {
6780 return directoryServer.supportedControls.contains(controlOID);
6781 }
6782
6783
6784
6785 /**
6786 * Registers the provided OID as a supported control for the Directory Server.
6787 * This will have no effect if the specified control OID is already present in
6788 * the list of supported controls.
6789 *
6790 * @param controlOID The OID of the control to register as a supported
6791 * control.
6792 */
6793 public static void registerSupportedControl(String controlOID)
6794 {
6795 synchronized (directoryServer.supportedControls)
6796 {
6797 directoryServer.supportedControls.add(controlOID);
6798 }
6799 }
6800
6801
6802
6803 /**
6804 * Deregisters the provided OID as a supported control for the Directory
6805 * Server. This will have no effect if the specified control OID is not
6806 * present in the list of supported controls.
6807 *
6808 * @param controlOID The OID of the control to deregister as a supported
6809 * control.
6810 */
6811 public static void deregisterSupportedControl(String controlOID)
6812 {
6813 synchronized (directoryServer.supportedControls)
6814 {
6815 directoryServer.supportedControls.remove(controlOID);
6816 }
6817 }
6818
6819
6820
6821 /**
6822 * Retrieves the set of supported features registered with the Directory
6823 * Server.
6824 *
6825 * @return The set of supported features registered with the Directory
6826 * Server.
6827 */
6828 public static TreeSet<String> getSupportedFeatures()
6829 {
6830 return directoryServer.supportedFeatures;
6831 }
6832
6833
6834
6835 /**
6836 * Indicates whether the specified OID is registered with the Directory Server
6837 * as a supported feature.
6838 *
6839 * @param featureOID The OID of the feature for which to make the
6840 * determination.
6841 *
6842 * @return <CODE>true</CODE> if the specified OID is registered with the
6843 * server as a supported feature, or <CODE>false</CODE> if not.
6844 */
6845 public static boolean isSupportedFeature(String featureOID)
6846 {
6847 return directoryServer.supportedFeatures.contains(featureOID);
6848 }
6849
6850
6851
6852 /**
6853 * Registers the provided OID as a supported feature for the Directory Server.
6854 * This will have no effect if the specified feature OID is already present in
6855 * the list of supported features.
6856 *
6857 * @param featureOID The OID of the feature to register as a supported
6858 * feature.
6859 */
6860 public static void registerSupportedFeature(String featureOID)
6861 {
6862 synchronized (directoryServer.supportedFeatures)
6863 {
6864 directoryServer.supportedFeatures.add(featureOID);
6865 }
6866 }
6867
6868
6869
6870 /**
6871 * Deregisters the provided OID as a supported feature for the Directory
6872 * Server. This will have no effect if the specified feature OID is not
6873 * present in the list of supported features.
6874 *
6875 * @param featureOID The OID of the feature to deregister as a supported
6876 * feature.
6877 */
6878 public static void deregisterSupportedFeature(String featureOID)
6879 {
6880 synchronized (directoryServer.supportedFeatures)
6881 {
6882 directoryServer.supportedFeatures.remove(featureOID);
6883 }
6884 }
6885
6886
6887
6888 /**
6889 * Retrieves the set of extended operations that may be processed by the
6890 * Directory Server.
6891 *
6892 * @return The set of extended operations that may be processed by the
6893 * Directory Server.
6894 */
6895 public static ConcurrentHashMap<String,ExtendedOperationHandler>
6896 getSupportedExtensions()
6897 {
6898 return directoryServer.extendedOperationHandlers;
6899 }
6900
6901
6902
6903 /**
6904 * Retrieves the handler for the extended operation for the provided OID.
6905 *
6906 * @param oid The OID of the extended operation to retrieve.
6907 *
6908 * @return The handler for the specified extended operation, or
6909 * <CODE>null</CODE> if there is none.
6910 */
6911 public static ExtendedOperationHandler getExtendedOperationHandler(String oid)
6912 {
6913 return directoryServer.extendedOperationHandlers.get(oid);
6914 }
6915
6916
6917
6918 /**
6919 * Registers the provided extended operation handler with the Directory
6920 * Server.
6921 *
6922 * @param oid The OID for the extended operation to register.
6923 * @param handler The extended operation handler to register with the
6924 * Directory Server.
6925 */
6926 public static void registerSupportedExtension(String oid,
6927 ExtendedOperationHandler handler)
6928 {
6929 directoryServer.extendedOperationHandlers.put(toLowerCase(oid), handler);
6930 }
6931
6932
6933
6934 /**
6935 * Deregisters the provided extended operation handler with the Directory
6936 * Server.
6937 *
6938 * @param oid The OID for the extended operation to deregister.
6939 */
6940 public static void deregisterSupportedExtension(String oid)
6941 {
6942 directoryServer.extendedOperationHandlers.remove(toLowerCase(oid));
6943 }
6944
6945
6946
6947 /**
6948 * Retrieves the set of SASL mechanisms that are supported by the Directory
6949 * Server.
6950 *
6951 * @return The set of SASL mechanisms that are supported by the Directory
6952 * Server.
6953 */
6954 public static ConcurrentHashMap<String,SASLMechanismHandler>
6955 getSupportedSASLMechanisms()
6956 {
6957 return directoryServer.saslMechanismHandlers;
6958 }
6959
6960
6961
6962 /**
6963 * Retrieves the handler for the specified SASL mechanism.
6964 *
6965 * @param name The name of the SASL mechanism to retrieve.
6966 *
6967 * @return The handler for the specified SASL mechanism, or <CODE>null</CODE>
6968 * if there is none.
6969 */
6970 public static SASLMechanismHandler getSASLMechanismHandler(String name)
6971 {
6972 return directoryServer.saslMechanismHandlers.get(name);
6973 }
6974
6975
6976
6977 /**
6978 * Registers the provided SASL mechanism handler with the Directory Server.
6979 *
6980 * @param name The name of the SASL mechanism to be registered.
6981 * @param handler The SASL mechanism handler to register with the Directory
6982 * Server.
6983 */
6984 public static void registerSASLMechanismHandler(String name,
6985 SASLMechanismHandler handler)
6986 {
6987 // FIXME -- Should we force this name to be lowercase? If so, then will
6988 // that cause the lower name to be used in the root DSE?
6989 directoryServer.saslMechanismHandlers.put(name, handler);
6990 }
6991
6992
6993
6994 /**
6995 * Deregisters the provided SASL mechanism handler with the Directory Server.
6996 *
6997 * @param name The name of the SASL mechanism to be deregistered.
6998 */
6999 public static void deregisterSASLMechanismHandler(String name)
7000 {
7001 // FIXME -- Should we force this name to be lowercase?
7002 directoryServer.saslMechanismHandlers.remove(name);
7003 }
7004
7005
7006
7007 /**
7008 * Retrieves the supported LDAP versions for the Directory Server.
7009 *
7010 * @return The supported LDAP versions for the Directory Server.
7011 */
7012 public static Set<Integer> getSupportedLDAPVersions()
7013 {
7014 return directoryServer.supportedLDAPVersions.keySet();
7015 }
7016
7017
7018
7019 /**
7020 * Registers the provided LDAP protocol version as supported within the
7021 * Directory Server.
7022 *
7023 * @param supportedLDAPVersion The LDAP protocol version to register as
7024 * supported.
7025 * @param connectionHandler The connection handler that supports the
7026 * provided LDAP version. Note that multiple
7027 * connection handlers can provide support for
7028 * the same LDAP versions.
7029 */
7030 public static synchronized void registerSupportedLDAPVersion(
7031 int supportedLDAPVersion,
7032 ConnectionHandler connectionHandler)
7033 {
7034 List<ConnectionHandler> handlers =
7035 directoryServer.supportedLDAPVersions.get(supportedLDAPVersion);
7036 if (handlers == null)
7037 {
7038 handlers = new LinkedList<ConnectionHandler>();
7039 handlers.add(connectionHandler);
7040 directoryServer.supportedLDAPVersions.put(supportedLDAPVersion, handlers);
7041 }
7042 else
7043 {
7044 if (! handlers.contains(connectionHandler))
7045 {
7046 handlers.add(connectionHandler);
7047 }
7048 }
7049 }
7050
7051
7052
7053 /**
7054 * Deregisters the provided LDAP protocol version as supported within the
7055 * Directory Server.
7056 *
7057 * @param supportedLDAPVersion The LDAP protocol version to deregister.
7058 * @param connectionHandler The connection handler that no longer
7059 * supports the provided LDAP version.
7060 */
7061 public static synchronized void deregisterSupportedLDAPVersion(
7062 int supportedLDAPVersion,
7063 ConnectionHandler connectionHandler)
7064 {
7065 List<ConnectionHandler> handlers =
7066 directoryServer.supportedLDAPVersions.get(supportedLDAPVersion);
7067 if (handlers != null)
7068 {
7069 handlers.remove(connectionHandler);
7070 if (handlers.isEmpty())
7071 {
7072 directoryServer.supportedLDAPVersions.remove(supportedLDAPVersion);
7073 }
7074 }
7075 }
7076
7077
7078
7079
7080 /**
7081 * Retrieves the set of identity mappers defined in the Directory Server
7082 * configuration, as a mapping between the DN of the configuration entry and
7083 * the identity mapper.
7084 *
7085 * @return The set of identity mappers defined in the Directory Server
7086 * configuration.
7087 */
7088 public static ConcurrentHashMap<DN,IdentityMapper> getIdentityMappers()
7089 {
7090 return directoryServer.identityMappers;
7091 }
7092
7093
7094
7095 /**
7096 * Retrieves the Directory Server identity mapper whose configuration resides
7097 * in the specified configuration entry.
7098 *
7099 * @param configEntryDN The DN of the configuration entry for the identity
7100 * mapper to retrieve.
7101 *
7102 * @return The requested identity mapper, or <CODE>null</CODE> if the
7103 * provided entry DN is not associated with an active identity
7104 * mapper.
7105 */
7106 public static IdentityMapper getIdentityMapper(DN configEntryDN)
7107 {
7108 return directoryServer.identityMappers.get(configEntryDN);
7109 }
7110
7111
7112
7113 /**
7114 * Registers the provided identity mapper for use with the Directory Server.
7115 *
7116 * @param configEntryDN The DN of the configuration entry in which the
7117 * identity mapper definition resides.
7118 * @param identityMapper The identity mapper to be registered.
7119 */
7120 public static void registerIdentityMapper(DN configEntryDN,
7121 IdentityMapper identityMapper)
7122 {
7123 directoryServer.identityMappers.put(configEntryDN, identityMapper);
7124 }
7125
7126
7127
7128 /**
7129 * Deregisters the provided identity mapper for use with the Directory Server.
7130 *
7131 * @param configEntryDN The DN of the configuration entry in which the
7132 * identity mapper definition resides.
7133 */
7134 public static void deregisterIdentityMapper(DN configEntryDN)
7135 {
7136 directoryServer.identityMappers.remove(configEntryDN);
7137 }
7138
7139
7140
7141 /**
7142 * Retrieves the DN of the configuration entry for the identity mapper that
7143 * should be used in conjunction with proxied authorization V2 controls.
7144 *
7145 * @return The DN of the configuration entry for the identity mapper that
7146 * should be used in conjunction with proxied authorization V2
7147 * controls, or <CODE>null</CODE> if none is defined.
7148 */
7149 public static DN getProxiedAuthorizationIdentityMapperDN()
7150 {
7151 return directoryServer.proxiedAuthorizationIdentityMapperDN;
7152 }
7153
7154
7155
7156 /**
7157 * Specifies the DN of the configuration entry for the identity mapper that
7158 * should be used in conjunction with proxied authorization V2 controls.
7159 *
7160 * @param proxiedAuthorizationIdentityMapperDN The DN of the configuration
7161 * entry for the identity mapper
7162 * that should be used in
7163 * conjunction with proxied
7164 * authorization V2 controls.
7165 */
7166 public static void setProxiedAuthorizationIdentityMapperDN(
7167 DN proxiedAuthorizationIdentityMapperDN)
7168 {
7169 directoryServer.proxiedAuthorizationIdentityMapperDN =
7170 proxiedAuthorizationIdentityMapperDN;
7171 }
7172
7173
7174
7175 /**
7176 * Retrieves the identity mapper that should be used to resolve authorization
7177 * IDs contained in proxied authorization V2 controls.
7178 *
7179 * @return The identity mapper that should be used to resolve authorization
7180 * IDs contained in proxied authorization V2 controls, or
7181 * <CODE>null</CODE> if none is defined.
7182 */
7183 public static IdentityMapper getProxiedAuthorizationIdentityMapper()
7184 {
7185 if (directoryServer.proxiedAuthorizationIdentityMapperDN == null)
7186 {
7187 return null;
7188 }
7189
7190 return directoryServer.identityMappers.get(
7191 directoryServer.proxiedAuthorizationIdentityMapperDN);
7192 }
7193
7194
7195
7196 /**
7197 * Retrieves the set of connection handlers configured in the Directory
7198 * Server. The returned list must not be altered.
7199 *
7200 * @return The set of connection handlers configured in the Directory Server.
7201 */
7202 public static CopyOnWriteArrayList<ConnectionHandler> getConnectionHandlers()
7203 {
7204 return directoryServer.connectionHandlers;
7205 }
7206
7207
7208
7209 /**
7210 * Registers the provided connection handler with the Directory Server.
7211 *
7212 * @param handler The connection handler to register with the Directory
7213 * Server.
7214 */
7215 public static void registerConnectionHandler(
7216 ConnectionHandler<? extends ConnectionHandlerCfg>
7217 handler)
7218 {
7219 synchronized (directoryServer.connectionHandlers)
7220 {
7221 directoryServer.connectionHandlers.add(handler);
7222
7223 ConnectionHandlerMonitor monitor = new ConnectionHandlerMonitor(handler);
7224 monitor.initializeMonitorProvider(null);
7225 handler.setConnectionHandlerMonitor(monitor);
7226 registerMonitorProvider(monitor);
7227 }
7228 }
7229
7230
7231
7232 /**
7233 * Deregisters the provided connection handler with the Directory Server.
7234 *
7235 * @param handler The connection handler to deregister with the Directory
7236 * Server.
7237 */
7238 public static void deregisterConnectionHandler(ConnectionHandler handler)
7239 {
7240 synchronized (directoryServer.connectionHandlers)
7241 {
7242 directoryServer.connectionHandlers.remove(handler);
7243
7244 ConnectionHandlerMonitor monitor = handler.getConnectionHandlerMonitor();
7245 if (monitor != null)
7246 {
7247 String instanceName = toLowerCase(monitor.getMonitorInstanceName());
7248 deregisterMonitorProvider(instanceName);
7249 monitor.finalizeMonitorProvider();
7250 handler.setConnectionHandlerMonitor(null);
7251 }
7252 }
7253 }
7254
7255
7256
7257 /**
7258 * Starts the connection handlers defined in the Directory Server
7259 * Configuration.
7260 *
7261 * @throws ConfigException If there are more than one connection handlers
7262 * using the same host port or no connection handler
7263 * are enabled or we could not bind to any of the
7264 * listeners.
7265 */
7266 private void startConnectionHandlers() throws ConfigException
7267 {
7268 LinkedHashSet<HostPort> usedListeners = new LinkedHashSet<HostPort>();
7269 LinkedHashSet<Message> errorMessages = new LinkedHashSet<Message>();
7270 // Check that the port specified in the connection handlers is
7271 // available.
7272 for (ConnectionHandler<?> c : connectionHandlers)
7273 {
7274 for (HostPort listener : c.getListeners())
7275 {
7276 if (usedListeners.contains(listener))
7277 {
7278 // The port was already specified: this is a configuration error,
7279 // log a message.
7280 Message message = ERR_HOST_PORT_ALREADY_SPECIFIED.get(
7281 c.getConnectionHandlerName(), listener.toString());
7282 logError(message);
7283 errorMessages.add(message);
7284
7285 }
7286 else
7287 {
7288 usedListeners.add(listener);
7289 }
7290 }
7291 }
7292
7293 if (errorMessages.size() > 0)
7294 {
7295 throw new ConfigException(ERR_ERROR_STARTING_CONNECTION_HANDLERS.get());
7296 }
7297
7298
7299 // If there are no connection handlers log a message.
7300 if (connectionHandlers.isEmpty())
7301 {
7302 Message message = ERR_NOT_AVAILABLE_CONNECTION_HANDLERS.get();
7303 logError(message);
7304 throw new ConfigException(ERR_ERROR_STARTING_CONNECTION_HANDLERS.get());
7305 }
7306
7307 // At this point, we should be ready to go. Start all the connection
7308 // handlers.
7309 for (ConnectionHandler c : connectionHandlers)
7310 {
7311 c.start();
7312 }
7313 }
7314
7315 /**
7316 * Retrieves a reference to the Directory Server work queue.
7317 *
7318 * @return A reference to the Directory Server work queue.
7319 */
7320 public static WorkQueue getWorkQueue()
7321 {
7322 return directoryServer.workQueue;
7323 }
7324
7325
7326
7327 /**
7328 * Adds the provided operation to the work queue so that it will be processed
7329 * by one of the worker threads.
7330 *
7331 * @param operation The operation to be added to the work queue.
7332 *
7333 * @throws DirectoryException If a problem prevents the operation from being
7334 * added to the queue (e.g., the queue is full).
7335 */
7336 public static void enqueueRequest(AbstractOperation operation)
7337 throws DirectoryException
7338 {
7339 // See if a bind is already in progress on the associated connection. If so
7340 // then reject the operation.
7341 ClientConnection clientConnection = operation.getClientConnection();
7342 if (clientConnection.bindInProgress() &&
7343 (operation.getOperationType() != OperationType.BIND))
7344 {
7345 Message message = ERR_ENQUEUE_BIND_IN_PROGRESS.get();
7346 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
7347 }
7348
7349
7350 //Reject or accept the unauthenticated requests based on the configuration
7351 // settings.
7352 if ((directoryServer.rejectUnauthenticatedRequests ||
7353 directoryServer.lockdownMode) &&
7354 !clientConnection.getAuthenticationInfo().isAuthenticated())
7355 {
7356 switch(operation.getOperationType())
7357 {
7358 case ADD:
7359 case COMPARE:
7360 case DELETE:
7361 case SEARCH:
7362 case MODIFY:
7363 case MODIFY_DN:
7364 if (directoryServer.lockdownMode)
7365 {
7366 Message message = NOTE_REJECT_OPERATION_IN_LOCKDOWN_MODE.get();
7367 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
7368 message);
7369 }
7370 else
7371 {
7372 Message message = ERR_REJECT_UNAUTHENTICATED_OPERATION.get();
7373 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
7374 message);
7375 }
7376
7377 case EXTENDED:
7378 ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation;
7379 String requestOID = extOp.getRequestOID();
7380 if (!((requestOID != null) &&
7381 requestOID.equals(OID_START_TLS_REQUEST)))
7382 {
7383 if (directoryServer.lockdownMode)
7384 {
7385 Message message = NOTE_REJECT_OPERATION_IN_LOCKDOWN_MODE.get();
7386 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
7387 message);
7388 }
7389 else
7390 {
7391 Message message = ERR_REJECT_UNAUTHENTICATED_OPERATION.get();
7392 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
7393 message);
7394 }
7395 }
7396 break;
7397
7398 }
7399
7400 }
7401
7402
7403 // If the associated user is required to change their password before
7404 // continuing, then make sure the associated operation is one that could
7405 // result in the password being changed. If not, then reject it.
7406 if (clientConnection.mustChangePassword())
7407 {
7408 switch (operation.getOperationType())
7409 {
7410 case ADD:
7411 case COMPARE:
7412 case DELETE:
7413 case MODIFY_DN:
7414 case SEARCH:
7415 // See if the request included the password policy request control.
7416 // If it did, then add a corresponding response control.
7417 for (Control c : operation.getRequestControls())
7418 {
7419 if (c.getOID().equals(OID_PASSWORD_POLICY_CONTROL))
7420 {
7421 operation.addResponseControl(new PasswordPolicyResponseControl(
7422 null, 0, PasswordPolicyErrorType.CHANGE_AFTER_RESET));
7423 break;
7424 }
7425 }
7426
7427 Message message = ERR_ENQUEUE_MUST_CHANGE_PASSWORD.get();
7428 throw new DirectoryException(
7429 ResultCode.CONSTRAINT_VIOLATION, message);
7430
7431 case EXTENDED:
7432 // We will only allow the password modify and StartTLS extended
7433 // operations.
7434 ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation;
7435 String requestOID = extOp.getRequestOID();
7436 if ((requestOID == null) ||
7437 ((! requestOID.equals(OID_PASSWORD_MODIFY_REQUEST)) &&
7438 (! requestOID.equals(OID_START_TLS_REQUEST))))
7439 {
7440 // See if the request included the password policy request control.
7441 // If it did, then add a corresponding response control.
7442 for (Control c : operation.getRequestControls())
7443 {
7444 if (c.getOID().equals(OID_PASSWORD_POLICY_CONTROL))
7445 {
7446 operation.addResponseControl(new PasswordPolicyResponseControl(
7447 null, 0, PasswordPolicyErrorType.CHANGE_AFTER_RESET));
7448 break;
7449 }
7450 }
7451
7452 message = ERR_ENQUEUE_MUST_CHANGE_PASSWORD.get();
7453 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
7454 message);
7455 }
7456
7457 break;
7458
7459 // Bind, unbind, and abandon will always be allowed.
7460
7461 // Modify may or may not be allowed, but we'll leave that
7462 // determination up to the modify operation itself.
7463 }
7464 }
7465
7466
7467
7468 directoryServer.workQueue.submitOperation(operation);
7469 }
7470
7471
7472
7473 /**
7474 * Retrieves the set of change notification listeners registered with the
7475 * Directory Server.
7476 *
7477 * @return The set of change notification listeners registered with the
7478 * Directory Server.
7479 */
7480 public static CopyOnWriteArrayList<ChangeNotificationListener>
7481 getChangeNotificationListeners()
7482 {
7483 return directoryServer.changeNotificationListeners;
7484 }
7485
7486
7487
7488 /**
7489 * Registers the provided change notification listener with the Directory
7490 * Server so that it will be notified of any add, delete, modify, or modify DN
7491 * operations that are performed.
7492 *
7493 * @param changeListener The change notification listener to register with
7494 * the Directory Server.
7495 */
7496 public static void registerChangeNotificationListener(
7497 ChangeNotificationListener changeListener)
7498 {
7499 directoryServer.changeNotificationListeners.add(changeListener);
7500 }
7501
7502
7503
7504 /**
7505 * Deregisters the provided change notification listener with the Directory
7506 * Server so that it will no longer be notified of any add, delete, modify, or
7507 * modify DN operations that are performed.
7508 *
7509 * @param changeListener The change notification listener to deregister with
7510 * the Directory Server.
7511 */
7512 public static void deregisterChangeNotificationListener(
7513 ChangeNotificationListener changeListener)
7514 {
7515 directoryServer.changeNotificationListeners.remove(changeListener);
7516 }
7517
7518
7519
7520 /**
7521 * Retrieves the set of persistent searches registered with the Directory
7522 * Server.
7523 *
7524 * @return The set of persistent searches registered with the Directory
7525 * Server.
7526 */
7527 public static CopyOnWriteArrayList<PersistentSearch> getPersistentSearches()
7528 {
7529 return directoryServer.persistentSearches;
7530 }
7531
7532
7533
7534 /**
7535 * Registers the provided persistent search operation with the Directory
7536 * Server so that it will be notified of any add, delete, modify, or modify DN
7537 * operations that are performed.
7538 *
7539 * @param persistentSearch The persistent search operation to register with
7540 * the Directory Server.
7541 */
7542 public static void registerPersistentSearch(PersistentSearch persistentSearch)
7543 {
7544 directoryServer.persistentSearches.add(persistentSearch);
7545 persistentSearch.getSearchOperation().getClientConnection().
7546 registerPersistentSearch(persistentSearch);
7547 }
7548
7549
7550
7551 /**
7552 * Deregisters the provided persistent search operation with the Directory
7553 * Server so that it will no longer be notified of any add, delete, modify, or
7554 * modify DN operations that are performed.
7555 *
7556 * @param persistentSearch The persistent search operation to deregister
7557 * with the Directory Server.
7558 */
7559 public static void deregisterPersistentSearch(PersistentSearch
7560 persistentSearch)
7561 {
7562 directoryServer.persistentSearches.remove(persistentSearch);
7563 persistentSearch.getSearchOperation().getClientConnection().
7564 deregisterPersistentSearch(persistentSearch);
7565 }
7566
7567
7568
7569
7570 /**
7571 * Retrieves the set of synchronization providers that have been registered
7572 * with the Directory Server.
7573 *
7574 * @return The set of synchronization providers that have been registered
7575 * with the Directory Server.
7576 */
7577 public static
7578 CopyOnWriteArrayList<SynchronizationProvider<SynchronizationProviderCfg>>
7579 getSynchronizationProviders()
7580 {
7581 return directoryServer.synchronizationProviders;
7582 }
7583
7584
7585
7586 /**
7587 * Registers the provided synchronization provider with the Directory Server.
7588 *
7589 * @param provider The synchronization provider to register.
7590 */
7591 public static void registerSynchronizationProvider(
7592 SynchronizationProvider<SynchronizationProviderCfg> provider)
7593 {
7594 directoryServer.synchronizationProviders.add(provider);
7595
7596 provider.completeSynchronizationProvider();
7597 }
7598
7599
7600
7601 /**
7602 * Deregisters the provided synchronization provider with the Directory
7603 * Server.
7604 *
7605 * @param provider The synchronization provider to deregister.
7606 */
7607 public static void deregisterSynchronizationProvider(SynchronizationProvider
7608 provider)
7609 {
7610 directoryServer.synchronizationProviders.remove(provider);
7611 }
7612
7613
7614
7615 /**
7616 * Retrieves a set containing the names of the allowed tasks that may be
7617 * invoked in the server.
7618 *
7619 * @return A set containing the names of the allowed tasks that may be
7620 * invoked in the server.
7621 */
7622 public static Set<String> getAllowedTasks()
7623 {
7624 return directoryServer.allowedTasks;
7625 }
7626
7627
7628
7629 /**
7630 * Specifies the set of allowed tasks that may be invoked in the server.
7631 *
7632 * @param allowedTasks A set containing the names of the allowed tasks that
7633 * may be invoked in the server.
7634 */
7635 public static void setAllowedTasks(Set<String> allowedTasks)
7636 {
7637 directoryServer.allowedTasks = allowedTasks;
7638 }
7639
7640
7641
7642 /**
7643 * Retrieves the set of privileges that have been disabled.
7644 *
7645 * @return The set of privileges that have been disabled.
7646 */
7647 public static Set<Privilege> getDisabledPrivileges()
7648 {
7649 return directoryServer.disabledPrivileges;
7650 }
7651
7652
7653
7654 /**
7655 * Indicates whether the specified privilege is disabled.
7656 *
7657 * @param privilege The privilege for which to make the determination.
7658 *
7659 * @return {@code true} if the specified privilege is disabled, or
7660 * {@code false} if not.
7661 */
7662 public static boolean isDisabled(Privilege privilege)
7663 {
7664 return directoryServer.disabledPrivileges.contains(privilege);
7665 }
7666
7667
7668
7669 /**
7670 * Specifies the set of privileges that should be disabled in the server.
7671 *
7672 * @param disabledPrivileges The set of privileges that should be disabled
7673 * in the server.
7674 */
7675 public static void setDisabledPrivileges(Set<Privilege> disabledPrivileges)
7676 {
7677 directoryServer.disabledPrivileges = disabledPrivileges;
7678 }
7679
7680
7681
7682 /**
7683 * Indicates whether responses to failed bind operations should include a
7684 * message explaining the reason for the failure.
7685 *
7686 * @return {@code true} if bind responses should include error messages, or
7687 * {@code false} if not.
7688 */
7689 public static boolean returnBindErrorMessages()
7690 {
7691 return directoryServer.returnBindErrorMessages;
7692 }
7693
7694
7695
7696 /**
7697 * Specifies whether responses to failed bind operations should include a
7698 * message explaining the reason for the failure.
7699 *
7700 * @param returnBindErrorMessages Specifies whether responses to failed bind
7701 * operations should include a message
7702 * explaining the reason for the failure.
7703 */
7704 public static void setReturnBindErrorMessages(boolean returnBindErrorMessages)
7705 {
7706 directoryServer.returnBindErrorMessages = returnBindErrorMessages;
7707 }
7708
7709
7710
7711 /**
7712 * Retrieves the maximum length of time in milliseconds that client
7713 * connections should be allowed to remain idle without being disconnected.
7714 *
7715 * @return The maximum length of time in milliseconds that client connections
7716 * should be allowed to remain idle without being disconnected.
7717 */
7718 public static long getIdleTimeLimit()
7719 {
7720 return directoryServer.idleTimeLimit;
7721 }
7722
7723
7724
7725 /**
7726 * Specifies the maximum length of time in milliseconds that client
7727 * connections should be allowed to remain idle without being disconnected.
7728 *
7729 * @param idleTimeLimit The maximum length of time in milliseconds that
7730 * client connections should be allowed to remain idle
7731 * without being disconnected.
7732 */
7733 public static void setIdleTimeLimit(long idleTimeLimit)
7734 {
7735 directoryServer.idleTimeLimit = idleTimeLimit;
7736 }
7737
7738
7739
7740 /**
7741 * Indicates whether the Directory Server should save a copy of its
7742 * configuration whenever it is started successfully.
7743 *
7744 * @return {@code true} if the server should save a copy of its configuration
7745 * whenever it is started successfully, or {@code false} if not.
7746 */
7747 public static boolean saveConfigOnSuccessfulStartup()
7748 {
7749 return directoryServer.saveConfigOnSuccessfulStartup;
7750 }
7751
7752
7753
7754 /**
7755 * Specifies whether the Directory Server should save a copy of its
7756 * configuration whenever it is started successfully.
7757 *
7758 * @param saveConfigOnSuccessfulStartup Specifies whether the server should
7759 * save a copy of its configuration
7760 * whenever it is started successfully.
7761 */
7762 public static void setSaveConfigOnSuccessfulStartup(
7763 boolean saveConfigOnSuccessfulStartup)
7764 {
7765 directoryServer.saveConfigOnSuccessfulStartup =
7766 saveConfigOnSuccessfulStartup;
7767 }
7768
7769
7770
7771 /**
7772 * Registers the provided backup task listener with the Directory Server.
7773 *
7774 * @param listener The backup task listener to register with the Directory
7775 * Server.
7776 */
7777 public static void registerBackupTaskListener(BackupTaskListener listener)
7778 {
7779 directoryServer.backupTaskListeners.addIfAbsent(listener);
7780 }
7781
7782
7783
7784 /**
7785 * Deregisters the provided backup task listener with the Directory Server.
7786 *
7787 * @param listener The backup task listener to deregister with the Directory
7788 * Server.
7789 */
7790 public static void deregisterBackupTaskListener(BackupTaskListener listener)
7791 {
7792 directoryServer.backupTaskListeners.remove(listener);
7793 }
7794
7795
7796
7797 /**
7798 * Notifies the registered backup task listeners that the server will be
7799 * beginning a backup task with the provided information.
7800 *
7801 * @param backend The backend in which the backup is to be performed.
7802 * @param config The configuration for the backup to be performed.
7803 */
7804 public static void notifyBackupBeginning(Backend backend, BackupConfig config)
7805 {
7806 for (BackupTaskListener listener : directoryServer.backupTaskListeners)
7807 {
7808 try
7809 {
7810 listener.processBackupBegin(backend, config);
7811 }
7812 catch (Exception e)
7813 {
7814 if (debugEnabled())
7815 {
7816 TRACER.debugCaught(DebugLogLevel.ERROR, e);
7817 }
7818 }
7819 }
7820 }
7821
7822
7823
7824 /**
7825 * Notifies the registered backup task listeners that the server has completed
7826 * processing on a backup task with the provided information.
7827 *
7828 * @param backend The backend in which the backup was performed.
7829 * @param config The configuration for the backup that was performed.
7830 * @param successful Indicates whether the backup completed successfully.
7831 */
7832 public static void notifyBackupEnded(Backend backend, BackupConfig config,
7833 boolean successful)
7834 {
7835 for (BackupTaskListener listener : directoryServer.backupTaskListeners)
7836 {
7837 try
7838 {
7839 listener.processBackupEnd(backend, config, successful);
7840 }
7841 catch (Exception e)
7842 {
7843 if (debugEnabled())
7844 {
7845 TRACER.debugCaught(DebugLogLevel.ERROR, e);
7846 }
7847 }
7848 }
7849 }
7850
7851
7852
7853 /**
7854 * Registers the provided restore task listener with the Directory Server.
7855 *
7856 * @param listener The restore task listener to register with the Directory
7857 * Server.
7858 */
7859 public static void registerRestoreTaskListener(RestoreTaskListener listener)
7860 {
7861 directoryServer.restoreTaskListeners.addIfAbsent(listener);
7862 }
7863
7864
7865
7866 /**
7867 * Deregisters the provided restore task listener with the Directory Server.
7868 *
7869 * @param listener The restore task listener to deregister with the
7870 * Directory Server.
7871 */
7872 public static void deregisterRestoreTaskListener(RestoreTaskListener listener)
7873 {
7874 directoryServer.restoreTaskListeners.remove(listener);
7875 }
7876
7877
7878
7879 /**
7880 * Notifies the registered restore task listeners that the server will be
7881 * beginning a restore task with the provided information.
7882 *
7883 * @param backend The backend in which the restore is to be performed.
7884 * @param config The configuration for the restore to be performed.
7885 */
7886 public static void notifyRestoreBeginning(Backend backend,
7887 RestoreConfig config)
7888 {
7889 for (RestoreTaskListener listener : directoryServer.restoreTaskListeners)
7890 {
7891 try
7892 {
7893 listener.processRestoreBegin(backend, config);
7894 }
7895 catch (Exception e)
7896 {
7897 if (debugEnabled())
7898 {
7899 TRACER.debugCaught(DebugLogLevel.ERROR, e);
7900 }
7901 }
7902 }
7903 }
7904
7905
7906
7907 /**
7908 * Notifies the registered restore task listeners that the server has
7909 * completed processing on a restore task with the provided information.
7910 *
7911 * @param backend The backend in which the restore was performed.
7912 * @param config The configuration for the restore that was performed.
7913 * @param successful Indicates whether the restore completed successfully.
7914 */
7915 public static void notifyRestoreEnded(Backend backend, RestoreConfig config,
7916 boolean successful)
7917 {
7918 for (RestoreTaskListener listener : directoryServer.restoreTaskListeners)
7919 {
7920 try
7921 {
7922 listener.processRestoreEnd(backend, config, successful);
7923 }
7924 catch (Exception e)
7925 {
7926 if (debugEnabled())
7927 {
7928 TRACER.debugCaught(DebugLogLevel.ERROR, e);
7929 }
7930 }
7931 }
7932 }
7933
7934
7935
7936 /**
7937 * Registers the provided LDIF export task listener with the Directory Server.
7938 *
7939 * @param listener The export task listener to register with the Directory
7940 * Server.
7941 */
7942 public static void registerExportTaskListener(ExportTaskListener listener)
7943 {
7944 directoryServer.exportTaskListeners.addIfAbsent(listener);
7945 }
7946
7947
7948
7949 /**
7950 * Deregisters the provided LDIF export task listener with the Directory
7951 * Server.
7952 *
7953 * @param listener The export task listener to deregister with the Directory
7954 * Server.
7955 */
7956 public static void deregisterExportTaskListener(ExportTaskListener listener)
7957 {
7958 directoryServer.exportTaskListeners.remove(listener);
7959 }
7960
7961
7962
7963 /**
7964 * Notifies the registered LDIF export task listeners that the server will be
7965 * beginning an export task with the provided information.
7966 *
7967 * @param backend The backend in which the export is to be performed.
7968 * @param config The configuration for the export to be performed.
7969 */
7970 public static void notifyExportBeginning(Backend backend,
7971 LDIFExportConfig config)
7972 {
7973 for (ExportTaskListener listener : directoryServer.exportTaskListeners)
7974 {
7975 try
7976 {
7977 listener.processExportBegin(backend, config);
7978 }
7979 catch (Exception e)
7980 {
7981 if (debugEnabled())
7982 {
7983 TRACER.debugCaught(DebugLogLevel.ERROR, e);
7984 }
7985 }
7986 }
7987 }
7988
7989
7990
7991 /**
7992 * Notifies the registered LDIF export task listeners that the server has
7993 * completed processing on an export task with the provided information.
7994 *
7995 * @param backend The backend in which the export was performed.
7996 * @param config The configuration for the export that was performed.
7997 * @param successful Indicates whether the export completed successfully.
7998 */
7999 public static void notifyExportEnded(Backend backend, LDIFExportConfig config,
8000 boolean successful)
8001 {
8002 for (ExportTaskListener listener : directoryServer.exportTaskListeners)
8003 {
8004 try
8005 {
8006 listener.processExportEnd(backend, config, successful);
8007 }
8008 catch (Exception e)
8009 {
8010 if (debugEnabled())
8011 {
8012 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8013 }
8014 }
8015 }
8016 }
8017
8018
8019
8020 /**
8021 * Registers the provided LDIF import task listener with the Directory Server.
8022 *
8023 * @param listener The import task listener to register with the Directory
8024 * Server.
8025 */
8026 public static void registerImportTaskListener(ImportTaskListener listener)
8027 {
8028 directoryServer.importTaskListeners.addIfAbsent(listener);
8029 }
8030
8031
8032
8033 /**
8034 * Deregisters the provided LDIF import task listener with the Directory
8035 * Server.
8036 *
8037 * @param listener The import task listener to deregister with the Directory
8038 * Server.
8039 */
8040 public static void deregisterImportTaskListener(ImportTaskListener listener)
8041 {
8042 directoryServer.importTaskListeners.remove(listener);
8043 }
8044
8045
8046
8047 /**
8048 * Notifies the registered LDIF import task listeners that the server will be
8049 * beginning an import task with the provided information.
8050 *
8051 * @param backend The backend in which the import is to be performed.
8052 * @param config The configuration for the import to be performed.
8053 */
8054 public static void notifyImportBeginning(Backend backend,
8055 LDIFImportConfig config)
8056 {
8057 for (ImportTaskListener listener : directoryServer.importTaskListeners)
8058 {
8059 try
8060 {
8061 listener.processImportBegin(backend, config);
8062 }
8063 catch (Exception e)
8064 {
8065 if (debugEnabled())
8066 {
8067 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8068 }
8069 }
8070 }
8071 }
8072
8073
8074
8075 /**
8076 * Notifies the registered LDIF import task listeners that the server has
8077 * completed processing on an import task with the provided information.
8078 *
8079 * @param backend The backend in which the import was performed.
8080 * @param config The configuration for the import that was performed.
8081 * @param successful Indicates whether the import completed successfully.
8082 */
8083 public static void notifyImportEnded(Backend backend, LDIFImportConfig config,
8084 boolean successful)
8085 {
8086 for (ImportTaskListener listener : directoryServer.importTaskListeners)
8087 {
8088 try
8089 {
8090 listener.processImportEnd(backend, config, successful);
8091 }
8092 catch (Exception e)
8093 {
8094 if (debugEnabled())
8095 {
8096 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8097 }
8098 }
8099 }
8100 }
8101
8102
8103
8104 /**
8105 * Registers the provided shutdown listener with the Directory Server so that
8106 * it will be notified when the server shuts down.
8107 *
8108 * @param listener The shutdown listener to register with the Directory
8109 * Server.
8110 */
8111 public static void registerShutdownListener(ServerShutdownListener listener)
8112 {
8113 directoryServer.shutdownListeners.add(listener);
8114 }
8115
8116
8117
8118 /**
8119 * Deregisters the provided shutdown listener with the Directory Server.
8120 *
8121 * @param listener The shutdown listener to deregister with the Directory
8122 * Server.
8123 */
8124 public static void deregisterShutdownListener(ServerShutdownListener listener)
8125 {
8126 directoryServer.shutdownListeners.remove(listener);
8127 }
8128
8129
8130 /**
8131 * Initiates the Directory Server shutdown process. Note that once this has
8132 * started, it should not be interrupted.
8133 *
8134 * @param className The fully-qualified name of the Java class that
8135 * initiated the shutdown.
8136 * @param reason The human-readable reason that the directory server is
8137 * shutting down.
8138 */
8139 public static void shutDown(String className, Message reason)
8140 {
8141 synchronized (directoryServer)
8142 {
8143 if (directoryServer.shuttingDown)
8144 {
8145 // We already know that the server is shutting down, so we don't need to
8146 // do anything.
8147 return;
8148 }
8149
8150 directoryServer.shuttingDown = true;
8151 }
8152
8153 ConfigEntry rootConfigEntry = null;
8154 try {
8155 rootConfigEntry = directoryServer.configHandler.getConfigRootEntry();
8156 } catch (Exception e) {
8157
8158 }
8159
8160 // Send an alert notification that the server is shutting down.
8161 Message message = NOTE_SERVER_SHUTDOWN.get(className, reason);
8162 sendAlertNotification(directoryServer, ALERT_TYPE_SERVER_SHUTDOWN,
8163 message);
8164
8165
8166 // Create a shutdown monitor that will watch the rest of the shutdown
8167 // process to ensure that everything goes smoothly.
8168 ServerShutdownMonitor shutdownMonitor = new ServerShutdownMonitor();
8169 shutdownMonitor.start();
8170
8171
8172 // Shut down the connection handlers.
8173 for (ConnectionHandler handler : directoryServer.connectionHandlers)
8174 {
8175 try
8176 {
8177
8178 handler.finalizeConnectionHandler(
8179 INFO_CONNHANDLER_CLOSED_BY_SHUTDOWN.get(), true);
8180 }
8181 catch (Exception e)
8182 {
8183 if (debugEnabled())
8184 {
8185 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8186 }
8187 }
8188 }
8189 directoryServer.connectionHandlers.clear();
8190
8191
8192
8193 // Call the shutdown plugins, and then finalize all the plugins defined in
8194 // the server.
8195 if (directoryServer.pluginConfigManager != null)
8196 {
8197 directoryServer.pluginConfigManager.invokeShutdownPlugins(reason);
8198 directoryServer.pluginConfigManager.finalizePlugins();
8199 }
8200
8201
8202 // shutdown the Synchronization Providers
8203 for (SynchronizationProvider provider :
8204 directoryServer.synchronizationProviders)
8205 {
8206 provider.finalizeSynchronizationProvider();
8207 }
8208
8209 // Deregister the shutdown hook.
8210 if (directoryServer.shutdownHook != null)
8211 {
8212 try
8213 {
8214 Runtime.getRuntime().removeShutdownHook(directoryServer.shutdownHook);
8215 }
8216 catch (Exception e) {}
8217 }
8218
8219
8220 // Stop the work queue.
8221 if (directoryServer.workQueue != null)
8222 {
8223 directoryServer.workQueue.finalizeWorkQueue(reason);
8224 }
8225
8226
8227 // Notify all the shutdown listeners.
8228 for (ServerShutdownListener shutdownListener :
8229 directoryServer.shutdownListeners)
8230 {
8231 try
8232 {
8233 shutdownListener.processServerShutdown(reason);
8234 }
8235 catch (Exception e)
8236 {
8237 if (debugEnabled())
8238 {
8239 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8240 }
8241 }
8242 }
8243
8244
8245 // Shut down all of the alert handlers.
8246 for (AlertHandler alertHandler : directoryServer.alertHandlers)
8247 {
8248 alertHandler.finalizeAlertHandler();
8249 }
8250
8251
8252 // Deregister all of the JMX MBeans.
8253 if (directoryServer.mBeanServer != null)
8254 {
8255 Set mBeanSet = directoryServer.mBeanServer.queryMBeans(null, null);
8256 for (Object o : mBeanSet)
8257 {
8258 if (o instanceof DirectoryServerMBean)
8259 {
8260 try
8261 {
8262 DirectoryServerMBean mBean = (DirectoryServerMBean) o;
8263 directoryServer.mBeanServer.unregisterMBean(mBean.getObjectName());
8264 }
8265 catch (Exception e)
8266 {
8267 if (debugEnabled())
8268 {
8269 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8270 }
8271 }
8272 }
8273 }
8274 }
8275
8276
8277 // Finalize all of the SASL mechanism handlers.
8278 for (SASLMechanismHandler handler :
8279 directoryServer.saslMechanismHandlers.values())
8280 {
8281 try
8282 {
8283 handler.finalizeSASLMechanismHandler();
8284 }
8285 catch (Exception e)
8286 {
8287 if (debugEnabled())
8288 {
8289 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8290 }
8291 }
8292 }
8293
8294
8295 // Finalize all of the extended operation handlers.
8296 for (ExtendedOperationHandler handler :
8297 directoryServer.extendedOperationHandlers.values())
8298 {
8299 try
8300 {
8301 handler.finalizeExtendedOperationHandler();
8302 }
8303 catch (Exception e)
8304 {
8305 if (debugEnabled())
8306 {
8307 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8308 }
8309 }
8310 }
8311
8312
8313 // Finalize the password policy map.
8314 for (DN configEntryDN : directoryServer.passwordPolicies.keySet())
8315 {
8316 DirectoryServer.deregisterPasswordPolicy(configEntryDN);
8317 }
8318
8319 // Finalize the access control handler
8320 AccessControlHandler accessControlHandler =
8321 AccessControlConfigManager.getInstance().getAccessControlHandler();
8322 if (accessControlHandler != null)
8323 {
8324 accessControlHandler.finalizeAccessControlHandler();
8325 }
8326
8327 // Perform any necessary cleanup work for the group manager.
8328 if (directoryServer.groupManager != null)
8329 {
8330 directoryServer.groupManager.finalizeGroupManager();
8331 }
8332
8333
8334 // Shut down all the other components that may need special handling.
8335 // NYI
8336
8337
8338 // Shut down the monitor providers.
8339 for (MonitorProvider monitor : directoryServer.monitorProviders.values())
8340 {
8341 try
8342 {
8343 monitor.finalizeMonitorProvider();
8344 }
8345 catch (Exception e)
8346 {
8347 if (debugEnabled())
8348 {
8349 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8350 }
8351 }
8352 }
8353
8354
8355 // Shut down the backends.
8356 for (Backend backend : directoryServer.backends.values())
8357 {
8358 try
8359 {
8360 // Deregister all the local backend workflow elements that have been
8361 // registered with the server.
8362 LocalBackendWorkflowElement.removeAll();
8363
8364 for (BackendInitializationListener listener :
8365 directoryServer.backendInitializationListeners)
8366 {
8367 listener.performBackendFinalizationProcessing(backend);
8368 }
8369
8370 backend.finalizeBackend();
8371
8372 // Remove the shared lock for this backend.
8373 try
8374 {
8375 String lockFile = LockFileManager.getBackendLockFileName(backend);
8376 StringBuilder failureReason = new StringBuilder();
8377 if (! LockFileManager.releaseLock(lockFile, failureReason))
8378 {
8379 message = WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK.
8380 get(backend.getBackendID(), String.valueOf(failureReason));
8381 logError(message);
8382 // FIXME -- Do we need to send an admin alert?
8383 }
8384
8385 serverLocked = false;
8386 }
8387 catch (Exception e2)
8388 {
8389 if (debugEnabled())
8390 {
8391 TRACER.debugCaught(DebugLogLevel.ERROR, e2);
8392 }
8393
8394 message = WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK.
8395 get(backend.getBackendID(), stackTraceToSingleLineString(e2));
8396 logError(message);
8397 // FIXME -- Do we need to send an admin alert?
8398 }
8399 }
8400 catch (Exception e)
8401 {
8402 if (debugEnabled())
8403 {
8404 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8405 }
8406 }
8407 }
8408
8409 // Finalize the entry cache.
8410 EntryCache ec = DirectoryServer.getEntryCache();
8411 if (ec != null)
8412 {
8413 ec.finalizeEntryCache();
8414 }
8415
8416 // Release the exclusive lock for the Directory Server process.
8417 String lockFile = LockFileManager.getServerLockFileName();
8418 try
8419 {
8420 StringBuilder failureReason = new StringBuilder();
8421 if (! LockFileManager.releaseLock(lockFile, failureReason))
8422 {
8423 message = WARN_CANNOT_RELEASE_EXCLUSIVE_SERVER_LOCK.get(
8424 lockFile, String.valueOf(failureReason));
8425 logError(message);
8426 }
8427 }
8428 catch (Exception e)
8429 {
8430 if (debugEnabled())
8431 {
8432 TRACER.debugCaught(DebugLogLevel.ERROR, e);
8433 }
8434
8435 message = WARN_CANNOT_RELEASE_EXCLUSIVE_SERVER_LOCK.get(
8436 lockFile, stackTraceToSingleLineString(e));
8437 logError(message);
8438 }
8439
8440 // Deregister all workflows.
8441 WorkflowImpl.deregisterAllOnShutdown();
8442
8443 // Deregister all network group configuration.
8444 NetworkGroup.deregisterAllOnShutdown();
8445
8446 // Force a new InternalClientConnection to be created on restart.
8447 InternalConnectionHandler.clearRootClientConnectionAtShutdown();
8448
8449 // Log a final message indicating that the server is stopped (which should
8450 // be true for all practical purposes), and then shut down all the error
8451 // loggers.
8452 logError(NOTE_SERVER_STOPPED.get());
8453
8454 removeAllAccessLogPublishers();
8455 removeAllErrorLogPublishers();
8456 removeAllDebugLogPublishers();
8457
8458 // Just in case there's something that isn't shut down properly, wait for
8459 // the monitor to give the OK to stop.
8460 shutdownMonitor.waitForMonitor();
8461
8462
8463 // At this point, the server is no longer running. We should destroy the
8464 // handle to the previous instance, but we will want to get a new instance
8465 // in case the server is to be started again later in the same JVM. Before
8466 // doing that, destroy the previous instance.
8467 DirectoryEnvironmentConfig envConfig = directoryServer.environmentConfig;
8468 directoryServer.destroy();
8469 directoryServer = getNewInstance(envConfig);
8470 }
8471
8472
8473
8474 /**
8475 * Destroy key structures in the current Directory Server instance in a manner
8476 * that can help detect any inappropriate cached references to server
8477 * components.
8478 */
8479 private void destroy()
8480 {
8481 checkSchema = true;
8482 isBootstrapped = false;
8483 isClientBootstrapped = false;
8484 isRunning = false;
8485 lockdownMode = true;
8486 rejectUnauthenticatedRequests = true;
8487 shuttingDown = true;
8488
8489 configClass = null;
8490 configFile = null;
8491 configHandler = null;
8492 coreConfigManager = null;
8493 compressedSchema = null;
8494 cryptoManager = null;
8495 defaultBinarySyntax = null;
8496 defaultBooleanSyntax = null;
8497 defaultDNSyntax = null;
8498 defaultIntegerSyntax = null;
8499 defaultStringSyntax = null;
8500 defaultSyntax = null;
8501 entryCache = null;
8502 environmentConfig = null;
8503 objectClassAttributeType = null;
8504 schemaDN = null;
8505 shutdownHook = null;
8506 workQueue = null;
8507
8508 if (baseDnRegistry != null)
8509 {
8510 baseDnRegistry.clear();
8511 baseDnRegistry = null;
8512 }
8513
8514 if (backends != null)
8515 {
8516 backends.clear();
8517 backends = null;
8518 }
8519
8520 if (schema != null)
8521 {
8522 schema.destroy();
8523 schema = null;
8524 }
8525 }
8526
8527
8528
8529 /**
8530 * Causes the Directory Server to perform an in-core restart. This will
8531 * cause virtually all components of the Directory Server to shut down, and
8532 * once that has completed it will be restarted.
8533 *
8534 * @param className The fully-qualified name of the Java class that
8535 * initiated the shutdown.
8536 * @param reason The human-readable reason that the directory server is
8537 * shutting down.
8538 */
8539 public static void restart(String className, Message reason)
8540 {
8541 restart(className, reason, directoryServer.environmentConfig);
8542 }
8543
8544
8545
8546 /**
8547 * Causes the Directory Server to perform an in-core restart. This will
8548 * cause virtually all components of the Directory Server to shut down, and
8549 * once that has completed it will be restarted.
8550 *
8551 * @param className The fully-qualified name of the Java class that
8552 * initiated the shutdown.
8553 * @param reason The human-readable reason that the directory server is
8554 * shutting down.
8555 * @param config The environment configuration to use for the server.
8556 */
8557 public static void restart(String className, Message reason,
8558 DirectoryEnvironmentConfig config)
8559 {
8560 try
8561 {
8562 shutDown(className, reason);
8563 reinitialize(config);
8564 directoryServer.startServer();
8565 }
8566 catch (Exception e)
8567 {
8568 System.err.println("ERROR: Unable to perform an in-core restart:");
8569 e.printStackTrace();
8570 System.err.println("Halting the JVM so that it must be manually " +
8571 "restarted.");
8572
8573 Runtime.getRuntime().halt(1);
8574 }
8575 }
8576
8577
8578
8579 /**
8580 * Reinitializes the server following a shutdown, preparing it for a call to
8581 * {@code startServer}.
8582 *
8583 * @return The new Directory Server instance created during the
8584 * reinitialization process.
8585 *
8586 * @throws InitializationException If a problem occurs while trying to
8587 * initialize the config handler or
8588 * bootstrap that server.
8589 */
8590 public static DirectoryServer reinitialize()
8591 throws InitializationException
8592 {
8593 return reinitialize(directoryServer.environmentConfig);
8594 }
8595
8596
8597
8598 /**
8599 * Reinitializes the server following a shutdown, preparing it for a call to
8600 * {@code startServer}.
8601 *
8602 * @param config The environment configuration for the Directory Server.
8603 *
8604 * @return The new Directory Server instance created during the
8605 * reinitialization process.
8606 *
8607 * @throws InitializationException If a problem occurs while trying to
8608 * initialize the config handler or
8609 * bootstrap that server.
8610 */
8611 public static DirectoryServer reinitialize(DirectoryEnvironmentConfig config)
8612 throws InitializationException
8613 {
8614 getNewInstance(config);
8615 LockManager.reinitializeLockTable();
8616 directoryServer.bootstrapServer();
8617 directoryServer.initializeConfiguration();
8618 return directoryServer;
8619 }
8620
8621
8622
8623 /**
8624 * Retrieves the maximum number of concurrent client connections that may be
8625 * established.
8626 *
8627 * @return The maximum number of concurrent client connections that may be
8628 * established, or -1 if there is no limit.
8629 */
8630 public static long getMaxAllowedConnections()
8631 {
8632 return directoryServer.maxAllowedConnections;
8633 }
8634
8635
8636
8637 /**
8638 * Specifies the maximum number of concurrent client connections that may be
8639 * established. A value that is less than or equal to zero will indicate that
8640 * no limit should be enforced.
8641 *
8642 * @param maxAllowedConnections The maximum number of concurrent client
8643 * connections that may be established.
8644 */
8645 public static void setMaxAllowedConnections(long maxAllowedConnections)
8646 {
8647 if (maxAllowedConnections > 0)
8648 {
8649 directoryServer.maxAllowedConnections = maxAllowedConnections;
8650 }
8651 else
8652 {
8653 directoryServer.maxAllowedConnections = -1;
8654 }
8655 }
8656
8657
8658
8659 /**
8660 * Indicates that a new connection has been accepted and increments the
8661 * associated counters.
8662 *
8663 * @param clientConnection The client connection that has been established.
8664 *
8665 * @return The connection ID that should be used for this connection, or -1
8666 * if the connection has been rejected for some reason (e.g., the
8667 * maximum numberof concurrent connections have already been
8668 * established).
8669 */
8670 public static long newConnectionAccepted(ClientConnection clientConnection)
8671 {
8672 synchronized (directoryServer.establishedConnections)
8673 {
8674 if (directoryServer.lockdownMode)
8675 {
8676 InetAddress remoteAddress = clientConnection.getRemoteAddress();
8677 if ((remoteAddress != null) && (! remoteAddress.isLoopbackAddress()))
8678 {
8679 return -1;
8680 }
8681 }
8682
8683 if ((directoryServer.maxAllowedConnections > 0) &&
8684 (directoryServer.currentConnections >=
8685 directoryServer.maxAllowedConnections))
8686 {
8687 return -1;
8688 }
8689
8690 directoryServer.establishedConnections.add(clientConnection);
8691 directoryServer.currentConnections++;
8692
8693 if (directoryServer.currentConnections > directoryServer.maxConnections)
8694 {
8695 directoryServer.maxConnections = directoryServer.currentConnections;
8696 }
8697
8698 return directoryServer.totalConnections++;
8699 }
8700 }
8701
8702
8703
8704 /**
8705 * Indicates that the specified client connection has been closed.
8706 *
8707 * @param clientConnection The client connection that has been closed.
8708 */
8709 public static void connectionClosed(ClientConnection clientConnection)
8710 {
8711 synchronized (directoryServer.establishedConnections)
8712 {
8713 directoryServer.establishedConnections.remove(clientConnection);
8714 directoryServer.currentConnections--;
8715 }
8716 }
8717
8718
8719
8720 /**
8721 * Retrieves the number of client connections that are currently established.
8722 *
8723 * @return The number of client connections that are currently established.
8724 */
8725 public static long getCurrentConnections()
8726 {
8727 return directoryServer.currentConnections;
8728 }
8729
8730
8731
8732 /**
8733 * Retrieves the maximum number of client connections that have been
8734 * established concurrently.
8735 *
8736 * @return The maximum number of client connections that have been
8737 * established concurrently.
8738 */
8739 public static long getMaxConnections()
8740 {
8741 return directoryServer.maxConnections;
8742 }
8743
8744
8745
8746 /**
8747 * Retrieves the total number of client connections that have been established
8748 * since the Directory Server started.
8749 *
8750 * @return The total number of client connections that have been established
8751 * since the Directory Server started.
8752 */
8753 public static long getTotalConnections()
8754 {
8755 return directoryServer.totalConnections;
8756 }
8757
8758
8759
8760 /**
8761 * Retrieves the full version string for the Directory Server.
8762 *
8763 * @return The full version string for the Directory Server.
8764 */
8765 public static String getVersionString()
8766 {
8767 return FULL_VERSION_STRING;
8768 }
8769
8770 /**
8771 * Prints out the version string for the Directory Server.
8772 *
8773 *
8774 * @param outputStream The output stream to which the version information
8775 * should be written.
8776 *
8777 * @throws IOException If a problem occurs while attempting to write the
8778 * version information to the provided output stream.
8779 */
8780 public static void printVersion(OutputStream outputStream)
8781 throws IOException
8782 {
8783 outputStream.write(getBytes(PRINTABLE_VERSION_STRING));
8784 return;
8785 }
8786
8787
8788 /**
8789 * Retrieves the default maximum number of entries that should be returned for
8790 * a search.
8791 *
8792 * @return The default maximum number of entries that should be returned for
8793 * a search.
8794 */
8795 public static int getSizeLimit()
8796 {
8797 return directoryServer.sizeLimit;
8798 }
8799
8800
8801
8802 /**
8803 * Specifies the default maximum number of entries that should be returned for
8804 * a search.
8805 *
8806 * @param sizeLimit The default maximum number of entries that should be
8807 * returned for a search.
8808 */
8809 public static void setSizeLimit(int sizeLimit)
8810 {
8811 directoryServer.sizeLimit = sizeLimit;
8812 }
8813
8814
8815
8816 /**
8817 * Retrieves the default maximum number of entries that should checked for
8818 * matches during a search.
8819 *
8820 * @return The default maximum number of entries that should checked for
8821 * matches during a search.
8822 */
8823 public static int getLookthroughLimit()
8824 {
8825 return directoryServer.lookthroughLimit;
8826 }
8827
8828
8829
8830 /**
8831 * Specifies the default maximum number of entries that should be checked for
8832 * matches during a search.
8833 *
8834 * @param lookthroughLimit The default maximum number of entries that should
8835 * be check for matches during a search.
8836 */
8837 public static void setLookthroughLimit(int lookthroughLimit)
8838 {
8839 directoryServer.lookthroughLimit = lookthroughLimit;
8840 }
8841
8842
8843
8844 /**
8845 * Retrieves the default maximum length of time in seconds that should be
8846 * allowed when processing a search.
8847 *
8848 * @return The default maximum length of time in seconds that should be
8849 * allowed when processing a search.
8850 */
8851 public static int getTimeLimit()
8852 {
8853 return directoryServer.timeLimit;
8854 }
8855
8856
8857
8858 /**
8859 * Specifies the default maximum length of time in seconds that should be
8860 * allowed when processing a search.
8861 *
8862 * @param timeLimit The default maximum length of time in seconds that
8863 * should be allowed when processing a search.
8864 */
8865 public static void setTimeLimit(int timeLimit)
8866 {
8867 directoryServer.timeLimit = timeLimit;
8868 }
8869
8870
8871
8872 /**
8873 * Specifies whether to collect nanosecond resolution processing times for
8874 * operations.
8875 *
8876 * @param useNanoTime <code>true</code> if nanosecond resolution times
8877 * should be collected or <code>false</code> to
8878 * only collect in millisecond resolution.
8879 */
8880 public static void setUseNanoTime(boolean useNanoTime)
8881 {
8882 directoryServer.useNanoTime = useNanoTime;
8883 }
8884
8885
8886
8887 /**
8888 * Retrieves whether operation processing times should be collected with
8889 * nanosecond resolution.
8890 *
8891 * @return <code>true</code> if nanosecond resolution times are collected
8892 * or <code>false</code> if only millisecond resolution times are
8893 * being collected.
8894 */
8895 public static boolean getUseNanoTime()
8896 {
8897 return directoryServer.useNanoTime;
8898 }
8899
8900
8901
8902 /**
8903 * Retrieves the writability mode for the Directory Server. This will only
8904 * be applicable for user suffixes.
8905 *
8906 * @return The writability mode for the Directory Server.
8907 */
8908 public static WritabilityMode getWritabilityMode()
8909 {
8910 return directoryServer.writabilityMode;
8911 }
8912
8913
8914
8915 /**
8916 * Specifies the writability mode for the Directory Server. This will only
8917 * be applicable for user suffixes.
8918 *
8919 * @param writabilityMode Specifies the writability mode for the Directory
8920 * Server.
8921 */
8922 public static void setWritabilityMode(WritabilityMode writabilityMode)
8923 {
8924 directoryServer.writabilityMode = writabilityMode;
8925 }
8926
8927
8928
8929
8930 /**
8931 * Indicates whether simple bind requests that contain a bind DN will also be
8932 * required to have a password.
8933 *
8934 * @return <CODE>true</CODE> if simple bind requests containing a bind DN
8935 * will be required to have a password, or <CODE>false</CODE> if not
8936 * (and therefore will be treated as anonymous binds).
8937 */
8938 public static boolean bindWithDNRequiresPassword()
8939 {
8940 return directoryServer.bindWithDNRequiresPassword;
8941 }
8942
8943
8944
8945 /**
8946 * Specifies whether simple bind requests that contain a bind DN will also be
8947 * required to have a password.
8948 *
8949 * @param bindWithDNRequiresPassword Indicates whether simple bind requests
8950 * that contain a bind DN will also be
8951 * required to have a password.
8952 */
8953 public static void setBindWithDNRequiresPassword(boolean
8954 bindWithDNRequiresPassword)
8955 {
8956 directoryServer.bindWithDNRequiresPassword = bindWithDNRequiresPassword;
8957 }
8958
8959
8960
8961 /**
8962 * Indicates whether an unauthenticated request should be rejected.
8963 *
8964 * @return <CODE>true</CODE>if an unauthenticated request should be
8965 * rejected, or <CODE>false</CODE>f if not.
8966 */
8967 public static boolean rejectUnauthenticatedRequests()
8968 {
8969 return directoryServer.rejectUnauthenticatedRequests;
8970 }
8971
8972 /**
8973 * Specifies whether an unauthenticated request should be rejected.
8974 *
8975 * @param rejectUnauthenticatedRequests Indicates whether an
8976 * unauthenticated request should
8977 * be rejected.
8978 */
8979 public static void setRejectUnauthenticatedRequests(boolean
8980 rejectUnauthenticatedRequests)
8981 {
8982 directoryServer.rejectUnauthenticatedRequests =
8983 rejectUnauthenticatedRequests;
8984 }
8985
8986
8987
8988 /**
8989 * Indicates whether the Directory Server is currently configured to operate
8990 * in the lockdown mode, in which all non-root requests will be rejected and
8991 * all connection attempts from non-loopback clients will be rejected.
8992 *
8993 * @return {@code true} if the Directory Server is currently configured to
8994 * operate in the lockdown mode, or {@code false} if not.
8995 */
8996 public static boolean lockdownMode()
8997 {
8998 return directoryServer.lockdownMode;
8999 }
9000
9001
9002
9003 /**
9004 * Specifies whether the server should operate in lockdown mode.
9005 *
9006 * @param lockdownMode Indicates whether the Directory Server should operate
9007 * in lockdown mode.
9008 */
9009 public static void setLockdownMode(boolean lockdownMode)
9010 {
9011 directoryServer.lockdownMode = lockdownMode;
9012
9013 if (lockdownMode)
9014 {
9015 Message message = WARN_DIRECTORY_SERVER_ENTERING_LOCKDOWN_MODE.get();
9016 logError(message);
9017
9018 sendAlertNotification(directoryServer, ALERT_TYPE_ENTERING_LOCKDOWN_MODE,
9019 message);
9020 }
9021 else
9022 {
9023 Message message = NOTE_DIRECTORY_SERVER_LEAVING_LOCKDOWN_MODE.get();
9024 logError(message);
9025
9026 sendAlertNotification(directoryServer, ALERT_TYPE_LEAVING_LOCKDOWN_MODE,
9027 message);
9028 }
9029 }
9030
9031
9032
9033 /**
9034 * Retrieves the DN of the configuration entry with which this alert generator
9035 * is associated.
9036 *
9037 * @return The DN of the configuration entry with which this alert generator
9038 * is associated.
9039 */
9040 public DN getComponentEntryDN()
9041 {
9042 try
9043 {
9044 if (configHandler == null)
9045 {
9046 // The config handler hasn't been initialized yet. Just return the DN
9047 // of the root DSE.
9048 return DN.nullDN();
9049 }
9050
9051 return configHandler.getConfigRootEntry().getDN();
9052 }
9053 catch (Exception e)
9054 {
9055 if (debugEnabled())
9056 {
9057 TRACER.debugCaught(DebugLogLevel.ERROR, e);
9058 }
9059
9060 // This could theoretically happen if an alert needs to be sent before the
9061 // configuration is initialized. In that case, just return an empty DN.
9062 return DN.nullDN();
9063 }
9064 }
9065
9066
9067
9068 /**
9069 * Retrieves the fully-qualified name of the Java class for this alert
9070 * generator implementation.
9071 *
9072 * @return The fully-qualified name of the Java class for this alert
9073 * generator implementation.
9074 */
9075 public String getClassName()
9076 {
9077 return CLASS_NAME;
9078 }
9079
9080
9081
9082 /**
9083 * Retrieves information about the set of alerts that this generator may
9084 * produce. The map returned should be between the notification type for a
9085 * particular notification and the human-readable description for that
9086 * notification. This alert generator must not generate any alerts with types
9087 * that are not contained in this list.
9088 *
9089 * @return Information about the set of alerts that this generator may
9090 * produce.
9091 */
9092 public LinkedHashMap<String,String> getAlerts()
9093 {
9094 LinkedHashMap<String,String> alerts = new LinkedHashMap<String,String>();
9095
9096 alerts.put(ALERT_TYPE_SERVER_STARTED, ALERT_DESCRIPTION_SERVER_STARTED);
9097 alerts.put(ALERT_TYPE_SERVER_SHUTDOWN, ALERT_DESCRIPTION_SERVER_SHUTDOWN);
9098 alerts.put(ALERT_TYPE_UNCAUGHT_EXCEPTION,
9099 ALERT_DESCRIPTION_UNCAUGHT_EXCEPTION);
9100 alerts.put(ALERT_TYPE_ENTERING_LOCKDOWN_MODE,
9101 ALERT_DESCRIPTION_ENTERING_LOCKDOWN_MODE);
9102 alerts.put(ALERT_TYPE_LEAVING_LOCKDOWN_MODE,
9103 ALERT_DESCRIPTION_LEAVING_LOCKDOWN_MODE);
9104
9105 return alerts;
9106 }
9107
9108
9109
9110 /**
9111 * Provides a means of handling a case in which a thread is about to die
9112 * because of an unhandled exception. This method does nothing to try to
9113 * prevent the death of that thread, but will at least log it so that it can
9114 * be available for debugging purposes.
9115 *
9116 * @param thread The thread that threw the exception.
9117 * @param exception The exception that was thrown but not properly handled.
9118 */
9119 public void uncaughtException(Thread thread, Throwable exception)
9120 {
9121 if (debugEnabled())
9122 {
9123 TRACER.debugCaught(DebugLogLevel.ERROR, exception);
9124 }
9125
9126 Message message = ERR_UNCAUGHT_THREAD_EXCEPTION.get(
9127 thread.getName(), stackTraceToString(exception));
9128 logError(message);
9129 sendAlertNotification(this, ALERT_TYPE_UNCAUGHT_EXCEPTION, message);
9130 }
9131
9132
9133
9134 /**
9135 * Indicates whether the server is currently in the process of shutting down.
9136 * @return <CODE>true</CODE> if this server is currently in the process of
9137 * shutting down and <CODE>false</CODE> otherwise.
9138 */
9139 public boolean isShuttingDown()
9140 {
9141 return shuttingDown;
9142 }
9143
9144
9145
9146 /**
9147 * Parses the provided command-line arguments and uses that information to
9148 * bootstrap and start the Directory Server.
9149 *
9150 * @param args The command-line arguments provided to this program.
9151 */
9152 public static void main(String[] args)
9153 {
9154 // Define the arguments that may be provided to the server.
9155 BooleanArgument checkStartability = null;
9156 BooleanArgument quietMode = null;
9157 BooleanArgument windowsNetStart = null;
9158 BooleanArgument displayUsage = null;
9159 BooleanArgument fullVersion = null;
9160 BooleanArgument noDetach = null;
9161 BooleanArgument systemInfo = null;
9162 BooleanArgument useLastKnownGoodConfig = null;
9163 StringArgument configClass = null;
9164 StringArgument configFile = null;
9165
9166
9167 // Create the command-line argument parser for use with this program.
9168 Message toolDescription = INFO_DSCORE_TOOL_DESCRIPTION.get();
9169 ArgumentParser argParser =
9170 new ArgumentParser("org.opends.server.core.DirectoryServer",
9171 toolDescription, false);
9172
9173
9174 // Initialize all the command-line argument types and register them with the
9175 // parser.
9176 try
9177 {
9178 configClass = new StringArgument("configclass", 'C', "configClass",
9179 true, false, true,
9180 INFO_CONFIGCLASS_PLACEHOLDER.get(),
9181 ConfigFileHandler.class.getName(), null,
9182 INFO_DSCORE_DESCRIPTION_CONFIG_CLASS
9183 .get());
9184 configClass.setHidden(true);
9185 argParser.addArgument(configClass);
9186
9187
9188 configFile = new StringArgument("configfile", 'f', "configFile",
9189 true, false, true,
9190 INFO_CONFIGFILE_PLACEHOLDER.get(), null,
9191 null,
9192 INFO_DSCORE_DESCRIPTION_CONFIG_FILE
9193 .get());
9194 configFile.setHidden(true);
9195 argParser.addArgument(configFile);
9196
9197
9198 checkStartability = new BooleanArgument("checkstartability", null,
9199 "checkStartability",
9200 INFO_DSCORE_DESCRIPTION_CHECK_STARTABILITY.get());
9201 checkStartability.setHidden(true);
9202 argParser.addArgument(checkStartability);
9203
9204 windowsNetStart = new BooleanArgument("windowsnetstart", null,
9205 "windowsNetStart",
9206 INFO_DSCORE_DESCRIPTION_WINDOWS_NET_START.get());
9207 windowsNetStart.setHidden(true);
9208 argParser.addArgument(windowsNetStart);
9209
9210
9211 fullVersion = new BooleanArgument("fullversion", 'F', "fullVersion",
9212 INFO_DSCORE_DESCRIPTION_FULLVERSION
9213 .get());
9214 fullVersion.setHidden(true);
9215 argParser.addArgument(fullVersion);
9216
9217
9218 systemInfo = new BooleanArgument("systeminfo", 's', "systemInfo",
9219 INFO_DSCORE_DESCRIPTION_SYSINFO.get());
9220 argParser.addArgument(systemInfo);
9221
9222
9223 useLastKnownGoodConfig =
9224 new BooleanArgument("lastknowngoodconfig", 'L',
9225 "useLastKnownGoodConfig",
9226 INFO_DSCORE_DESCRIPTION_LASTKNOWNGOODCFG.get());
9227 argParser.addArgument(useLastKnownGoodConfig);
9228
9229
9230 noDetach = new BooleanArgument("nodetach", 'N', "nodetach",
9231 INFO_DSCORE_DESCRIPTION_NODETACH.get());
9232 argParser.addArgument(noDetach);
9233
9234
9235 quietMode = new BooleanArgument("quiet", 'Q', "quiet",
9236 INFO_DESCRIPTION_QUIET.get());
9237 argParser.addArgument(quietMode);
9238
9239
9240 displayUsage = new BooleanArgument("help", 'H', "help",
9241 INFO_DSCORE_DESCRIPTION_USAGE.get());
9242 argParser.addArgument(displayUsage);
9243 argParser.setUsageArgument(displayUsage);
9244 }
9245 catch (ArgumentException ae)
9246 {
9247 Message message = ERR_DSCORE_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
9248 System.err.println(message);
9249 System.exit(1);
9250 }
9251
9252
9253 // Parse the command-line arguments provided to this program.
9254 try
9255 {
9256 argParser.parseArguments(args);
9257 }
9258 catch (ArgumentException ae)
9259 {
9260 Message message = ERR_DSCORE_ERROR_PARSING_ARGS.get(ae.getMessage());
9261 System.err.println(message);
9262 System.err.println(argParser.getUsage());
9263 System.exit(1);
9264 }
9265
9266
9267 // If we should just display usage information, then print it and exit.
9268 if (checkStartability.isPresent())
9269 {
9270 // This option should only be used if a PID file already exists in the
9271 // server logs directory, and we need to check which of the following
9272 // conditions best describes the current usage:
9273 // - We're trying to start the server, but it's already running. The
9274 // attempt to start the server should fail, and the server process will
9275 // exit with a result code of 98.
9276 // - We're trying to start the server and it's not already running. We
9277 // won't start it in this invocation, but the script used to get to this
9278 // point should go ahead and overwrite the PID file and retry the
9279 // startup process. The server process will exit with a result code of
9280 // 99.
9281 // - We're not trying to start the server, but instead are trying to do
9282 // something else like display the version number. In that case, we
9283 // don't need to write the PID file at all and can just execute the
9284 // intended command. If that command was successful, then we'll have an
9285 // exit code of NOTHING_TO_DO (0). Otherwise, it will have an exit code
9286 // that is something other than NOTHING_TO_DO, SERVER_ALREADY_STARTED,
9287 // START_AS_DETACH, START_AS_NON_DETACH, START_AS_WINDOWS_SERVICE to
9288 // indicate that a problem occurred.
9289 if (argParser.usageOrVersionDisplayed())
9290 {
9291 // We're just trying to display usage, and that's already been done so
9292 // exit with a code of zero.
9293 System.exit(NOTHING_TO_DO);
9294 }
9295 else if (fullVersion.isPresent() || systemInfo.isPresent())
9296 {
9297 // We're not really trying to start, so rebuild the argument list
9298 // without the "--checkStartability" argument and try again. Exit with
9299 // whatever that exits with.
9300 LinkedList<String> newArgList = new LinkedList<String>();
9301 for (String arg : args)
9302 {
9303 if (! arg.equalsIgnoreCase("--checkstartability"))
9304 {
9305 newArgList.add(arg);
9306 }
9307 }
9308 String[] newArgs = new String[newArgList.size()];
9309 newArgList.toArray(newArgs);
9310 main(newArgs);
9311 System.exit(NOTHING_TO_DO);
9312 }
9313 else
9314 {
9315 System.exit(checkStartability(argParser));
9316 }
9317 }
9318 else if (argParser.usageOrVersionDisplayed())
9319 {
9320 System.exit(0);
9321 }
9322 else if (fullVersion.isPresent())
9323 {
9324 printFullVersionInformation();
9325 return;
9326 }
9327 else if (systemInfo.isPresent())
9328 {
9329 RuntimeInformation.printInfo();
9330 return;
9331 }
9332
9333
9334 // At this point, we know that we're going to try to start the server.
9335 // Attempt to grab an exclusive lock for the Directory Server process.
9336 String lockFile = LockFileManager.getServerLockFileName();
9337 try
9338 {
9339 StringBuilder failureReason = new StringBuilder();
9340 if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
9341 {
9342 Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile,
9343 String.valueOf(failureReason));
9344 System.err.println(message);
9345 System.exit(1);
9346 }
9347 }
9348 catch (Exception e)
9349 {
9350 if (debugEnabled())
9351 {
9352 TRACER.debugCaught(DebugLogLevel.ERROR, e);
9353 }
9354
9355 Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile,
9356 stackTraceToSingleLineString(e));
9357 System.err.println(message);
9358 System.exit(1);
9359 }
9360 serverLocked = true;
9361
9362
9363 // Configure the JVM to delete the PID file on exit, if it exists.
9364 boolean pidFileMarkedForDeletion = false;
9365 boolean startingFileMarkedForDeletion = false;
9366 try
9367 {
9368 String pidFilePath;
9369 String startingFilePath;
9370 String serverRoot = System.getenv(ENV_VAR_INSTANCE_ROOT);
9371 if (serverRoot == null)
9372 {
9373 pidFilePath = "logs/server.pid";
9374 startingFilePath = "logs/server.starting";
9375 }
9376 else
9377 {
9378 pidFilePath = serverRoot + File.separator + "logs" +
9379 File.separator + "server.pid";
9380 startingFilePath = serverRoot + File.separator + "logs" +
9381 File.separator + "server.starting";
9382 }
9383
9384 File pidFile = new File(pidFilePath);
9385 if (pidFile.exists())
9386 {
9387 pidFile.deleteOnExit();
9388 pidFileMarkedForDeletion = true;
9389 }
9390
9391 File startingFile = new File(startingFilePath);
9392 if (startingFile.exists())
9393 {
9394 startingFile.deleteOnExit();
9395 startingFileMarkedForDeletion = true;
9396 }
9397 } catch (Exception e) {}
9398
9399
9400 // Redirect standard output and standard error to the server.out file. If
9401 // the server hasn't detached from the terminal, then also continue writing
9402 // to the original standard output and standard error. Also, configure the
9403 // JVM to delete the PID and server.starting files on exit, if they exist.
9404 PrintStream serverOutStream;
9405 try
9406 {
9407 // We need to figure out where to put the file. See if the server root
9408 // is available as an environment variable and if so then use it.
9409 // Otherwise, try to figure it out from the location of the config file.
9410 String serverRoot = System.getenv(ENV_VAR_INSTANCE_ROOT);
9411 if (serverRoot == null)
9412 {
9413 serverRoot = new File(configFile.getValue()).getParentFile().
9414 getParentFile().getAbsolutePath();
9415 }
9416
9417 if (serverRoot == null)
9418 {
9419 System.err.println("WARNING: Unable to determine server root in " +
9420 "order to redirect standard output and standard " +
9421 "error.");
9422 }
9423 else
9424 {
9425 File logDir = new File(serverRoot + File.separator + "logs");
9426 if (logDir.exists())
9427 {
9428 FileOutputStream fos =
9429 new FileOutputStream(new File(logDir, "server.out"), true);
9430 serverOutStream = new PrintStream(fos);
9431
9432 if (noDetach.isPresent())
9433 {
9434 if (! quietMode.isPresent())
9435 {
9436 MultiOutputStream multiStream =
9437 new MultiOutputStream(System.out, serverOutStream);
9438 serverOutStream = new PrintStream(multiStream);
9439 }
9440 }
9441
9442 System.setOut(serverOutStream);
9443 System.setErr(serverOutStream);
9444
9445 if (! pidFileMarkedForDeletion)
9446 {
9447 File f = new File(logDir, "server.pid");
9448 if (f.exists())
9449 {
9450 f.deleteOnExit();
9451 }
9452 }
9453
9454 if (! startingFileMarkedForDeletion)
9455 {
9456 File f = new File(logDir, "server.starting");
9457 if (f.exists())
9458 {
9459 f.deleteOnExit();
9460 }
9461 }
9462 }
9463 else
9464 {
9465 System.err.println("WARNING: Unable to redirect standard output " +
9466 "and standard error because the logs directory " +
9467 logDir.getAbsolutePath() + " does not exist.");
9468 }
9469 }
9470 }
9471 catch (Exception e)
9472 {
9473 System.err.println("WARNING: Unable to redirect standard output and " +
9474 "standard error: " + stackTraceToSingleLineString(e));
9475 }
9476
9477
9478 // Install the default loggers so the startup messages
9479 // will be printed.
9480 TextErrorLogPublisher startupErrorLogPublisher = null;
9481 TextDebugLogPublisher startupDebugLogPublisher = null;
9482
9483 startupErrorLogPublisher =
9484 TextErrorLogPublisher.getStartupTextErrorPublisher(
9485 new TextWriter.STDOUT());
9486 ErrorLogger.addErrorLogPublisher(startupErrorLogPublisher);
9487
9488 startupDebugLogPublisher =
9489 TextDebugLogPublisher.getStartupTextDebugPublisher(
9490 new TextWriter.STDOUT());
9491 DebugLogger.addDebugLogPublisher(startupDebugLogPublisher);
9492
9493
9494 // Create an environment configuration for the server and populate a number
9495 // of appropriate properties.
9496 DirectoryEnvironmentConfig environmentConfig =
9497 new DirectoryEnvironmentConfig();
9498 try
9499 {
9500 environmentConfig.setProperty(PROPERTY_CONFIG_CLASS,
9501 configClass.getValue());
9502 environmentConfig.setProperty(PROPERTY_CONFIG_FILE,
9503 configFile.getValue());
9504 environmentConfig.setProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG,
9505 String.valueOf(useLastKnownGoodConfig.isPresent()));
9506 }
9507 catch (Exception e)
9508 {
9509 // This shouldn't happen. For the methods we are using, the exception is
9510 // just a guard against making changes with the server running.
9511 }
9512
9513
9514 // Bootstrap and start the Directory Server.
9515 DirectoryServer directoryServer = DirectoryServer.getInstance();
9516 try
9517 {
9518 directoryServer.setEnvironmentConfig(environmentConfig);
9519 directoryServer.bootstrapServer();
9520 directoryServer.initializeConfiguration(configClass.getValue(),
9521 configFile.getValue());
9522 }
9523 catch (InitializationException ie)
9524 {
9525 if (debugEnabled())
9526 {
9527 TRACER.debugCaught(DebugLogLevel.ERROR, ie);
9528 }
9529
9530 Message message = ERR_DSCORE_CANNOT_BOOTSTRAP.get(ie.getMessage());
9531 System.err.println(message);
9532 System.exit(1);
9533 }
9534 catch (Exception e)
9535 {
9536 Message message = ERR_DSCORE_CANNOT_BOOTSTRAP.get(
9537 stackTraceToSingleLineString(e));
9538 System.err.println(message);
9539 System.exit(1);
9540 }
9541
9542 try
9543 {
9544 directoryServer.startServer();
9545 }
9546 catch (InitializationException ie)
9547 {
9548 if (debugEnabled())
9549 {
9550 TRACER.debugCaught(DebugLogLevel.ERROR, ie);
9551 }
9552
9553 Message message = ERR_DSCORE_CANNOT_START.get(ie.getMessage());
9554 shutDown(directoryServer.getClass().getName(), message);
9555 }
9556 catch (Exception e)
9557 {
9558 Message message = ERR_DSCORE_CANNOT_START.get(
9559 stackTraceToSingleLineString(e));
9560 shutDown(directoryServer.getClass().getName(), message);
9561 }
9562
9563 ErrorLogger.removeErrorLogPublisher(startupErrorLogPublisher);
9564 DebugLogger.removeDebugLogPublisher(startupDebugLogPublisher);
9565 }
9566
9567 /**
9568 * Construct the DN of a monitor provider entry.
9569 * @param provider The monitor provider for which a DN is desired.
9570 * @return The DN of the monitor provider entry.
9571 */
9572 public static DN getMonitorProviderDN(MonitorProvider provider)
9573 {
9574 String monitorName = provider.getMonitorInstanceName();
9575 AttributeType cnType = getAttributeType(ATTR_COMMON_NAME);
9576 DN monitorRootDN;
9577 try
9578 {
9579 monitorRootDN = DN.decode(DN_MONITOR_ROOT);
9580 }
9581 catch (DirectoryException e)
9582 {
9583 // Cannot reach this point.
9584 throw new RuntimeException();
9585 }
9586
9587 RDN rdn = RDN.create(cnType, new AttributeValue(cnType, monitorName));
9588 return monitorRootDN.concat(rdn);
9589 }
9590
9591
9592
9593 /**
9594 * Gets the class loader to be used with this directory server
9595 * application.
9596 * <p>
9597 * The class loader will automatically load classes from plugins
9598 * where required.
9599 *
9600 * @return Returns the class loader to be used with this directory
9601 * server application.
9602 */
9603 public static ClassLoader getClassLoader()
9604 {
9605 return ClassLoaderProvider.getInstance().getClassLoader();
9606 }
9607
9608
9609
9610 /**
9611 * Loads the named class using this directory server application's
9612 * class loader.
9613 * <p>
9614 * This method provided as a convenience and is equivalent to
9615 * calling:
9616 *
9617 * <pre>
9618 * Class.forName(name, true, DirectoryServer.getClassLoader());
9619 * </pre>
9620 *
9621 * @param name
9622 * The fully qualified name of the desired class.
9623 * @return Returns the class object representing the desired class.
9624 * @throws LinkageError
9625 * If the linkage fails.
9626 * @throws ExceptionInInitializerError
9627 * If the initialization provoked by this method fails.
9628 * @throws ClassNotFoundException
9629 * If the class cannot be located by the specified class
9630 * loader.
9631 * @see Class#forName(String, boolean, ClassLoader)
9632 */
9633 public static Class<?> loadClass(String name) throws LinkageError,
9634 ExceptionInInitializerError, ClassNotFoundException
9635 {
9636 return Class.forName(name, true, DirectoryServer.getClassLoader());
9637 }
9638
9639
9640
9641 /**
9642 * Returns the error code that we return when we are checking the startability
9643 * of the server.
9644 * If there are conflicting arguments (like asking to run the server in non
9645 * detach mode when the server is configured to run as a window service) it
9646 * returns CHECK_ERROR (1).
9647 * @param argParser the ArgumentParser with the arguments already parsed.
9648 * @return the error code that we return when we are checking the startability
9649 * of the server.
9650 */
9651 private static int checkStartability(ArgumentParser argParser)
9652 {
9653 int returnValue;
9654 boolean isServerRunning;
9655
9656 BooleanArgument noDetach =
9657 (BooleanArgument)argParser.getArgumentForLongID("nodetach");
9658 BooleanArgument quietMode =
9659 (BooleanArgument)argParser.getArgumentForLongID("quiet");
9660 BooleanArgument windowsNetStart =
9661 (BooleanArgument)argParser.getArgumentForLongID("windowsnetstart");
9662
9663 boolean noDetachPresent = noDetach.isPresent();
9664 boolean windowsNetStartPresent = windowsNetStart.isPresent();
9665
9666 // We're trying to start the server, so see if it's already running by
9667 // trying to grab an exclusive lock on the server lock file. If it
9668 // succeeds, then the server isn't running and we can try to start.
9669 // Otherwise, the server is running and this attempt should fail.
9670 String lockFile = LockFileManager.getServerLockFileName();
9671 try
9672 {
9673 StringBuilder failureReason = new StringBuilder();
9674 if (LockFileManager.acquireExclusiveLock(lockFile, failureReason))
9675 {
9676 // The server isn't running, so it can be started.
9677 LockFileManager.releaseLock(lockFile, failureReason);
9678 isServerRunning = false;
9679 }
9680 else
9681 {
9682 // The server's already running.
9683 Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile,
9684 String.valueOf(failureReason));
9685 System.err.println(message);
9686 isServerRunning = true;
9687 }
9688 }
9689 catch (Exception e)
9690 {
9691 // We'll treat this as if the server is running because we won't
9692 // be able to start it anyway.
9693 Message message = ERR_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK.get(lockFile,
9694 getExceptionMessage(e));
9695 System.err.println(message);
9696 isServerRunning = true;
9697 }
9698
9699 boolean configuredAsService = isRunningAsWindowsService();
9700
9701 if (isServerRunning)
9702 {
9703 if (configuredAsService && !windowsNetStartPresent)
9704 {
9705 returnValue = START_AS_WINDOWS_SERVICE;
9706 }
9707 else
9708 {
9709 returnValue = SERVER_ALREADY_STARTED;
9710 }
9711 }
9712 else
9713 {
9714 if (configuredAsService)
9715 {
9716 if (noDetachPresent)
9717 {
9718 // Conflicting arguments
9719 returnValue = CHECK_ERROR;
9720 Message message = ERR_DSCORE_ERROR_NODETACH_AND_WINDOW_SERVICE.get();
9721 System.err.println(message);
9722
9723 }
9724 else
9725 {
9726 if (windowsNetStartPresent)
9727 {
9728 // start-ds.bat is being called through net start, so return
9729 // START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE so that the batch
9730 // file actually starts the server.
9731 returnValue = START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE;
9732 }
9733 else
9734 {
9735 returnValue = START_AS_WINDOWS_SERVICE;
9736 }
9737 }
9738 }
9739 else
9740 {
9741 if (noDetachPresent)
9742 {
9743 returnValue = START_AS_NON_DETACH;
9744 }
9745 else if (quietMode.isPresent())
9746 {
9747 returnValue = START_AS_DETACH_QUIET;
9748 }
9749 else
9750 {
9751 returnValue = START_AS_DETACH;
9752 }
9753 }
9754 }
9755 return returnValue;
9756 }
9757
9758 /**
9759 * Returns true if this server is configured to run as a windows service.
9760 * @return <CODE>true</CODE> if this server is configured to run as a windows
9761 * service and <CODE>false</CODE> otherwise.
9762 */
9763 public static boolean isRunningAsWindowsService()
9764 {
9765 boolean isRunningAsWindowsService;
9766 if (SetupUtils.isWindows())
9767 {
9768 isRunningAsWindowsService = ConfigureWindowsService.serviceState(null,
9769 null) == ConfigureWindowsService.SERVICE_STATE_ENABLED;
9770 }
9771 else
9772 {
9773 isRunningAsWindowsService = false;
9774 }
9775 return isRunningAsWindowsService;
9776 }
9777
9778
9779 /**
9780 * Specifies whether the workflows are configured automatically or manually.
9781 * In auto configuration mode one workflow is created for each and every
9782 * base DN in the local backends. In the auto configuration mode the
9783 * workflows are created according to their description in the configuration
9784 * file.
9785 *
9786 * @param workflowConfigurationMode Indicates whether the workflows are
9787 * configured automatically or manually
9788 */
9789 public static void setWorkflowConfigurationMode(
9790 WorkflowConfigurationMode workflowConfigurationMode)
9791 {
9792 directoryServer.workflowConfigurationMode = workflowConfigurationMode;
9793 }
9794
9795
9796 /**
9797 * Indicates whether the workflow configuration mode is 'auto' or not.
9798 *
9799 * @return the workflow configuration mode
9800 */
9801 public static boolean workflowConfigurationModeIsAuto()
9802 {
9803 boolean isAuto =
9804 (directoryServer.workflowConfigurationMode
9805 == WorkflowConfigurationMode.AUTO);
9806 return isAuto;
9807 }
9808
9809
9810
9811 /**
9812 * Retrieves the workflow configuration mode.
9813 *
9814 * @return the workflow configuration mode
9815 */
9816 public static WorkflowConfigurationMode getWorkflowConfigurationMode()
9817 {
9818 return directoryServer.workflowConfigurationMode;
9819 }
9820
9821
9822
9823 /**
9824 * Print messages for start-ds "-F" option (full version information).
9825 */
9826
9827 private static
9828 void printFullVersionInformation() {
9829 /**
9830 * This option is used by the upgrade to identify the server build and it
9831 * can eventually also be used to be sent to the support in case of an
9832 * issue. Since this is not a public interface and since it is better
9833 * to always have it in English for the support team, the message is
9834 * not localized.
9835 */
9836 String separator = ": ";
9837 System.out.println(getVersionString());
9838 System.out.println(SetupUtils.BUILD_ID+separator+BUILD_ID);
9839 System.out.println(SetupUtils.MAJOR_VERSION+separator+MAJOR_VERSION);
9840 System.out.println(SetupUtils.MINOR_VERSION+separator+MINOR_VERSION);
9841 System.out.println(SetupUtils.POINT_VERSION+separator+POINT_VERSION);
9842 System.out.println(SetupUtils.VERSION_QUALIFIER+separator+
9843 VERSION_QUALIFIER);
9844 if (BUILD_NUMBER > 0)
9845 {
9846 System.out.println(SetupUtils.BUILD_NUMBER+separator+
9847 new DecimalFormat("000").format(BUILD_NUMBER));
9848 }
9849 System.out.println(SetupUtils.REVISION_NUMBER+separator+REVISION_NUMBER);
9850 System.out.println(SetupUtils.FIX_IDS+separator+FIX_IDS);
9851 System.out.println(SetupUtils.DEBUG_BUILD+separator+DEBUG_BUILD);
9852 System.out.println(SetupUtils.BUILD_OS+separator+BUILD_OS);
9853 System.out.println(SetupUtils.BUILD_USER+separator+BUILD_USER);
9854 System.out.println(SetupUtils.BUILD_JAVA_VERSION+separator+
9855 BUILD_JAVA_VERSION);
9856 System.out.println(SetupUtils.BUILD_JAVA_VENDOR+separator+
9857 BUILD_JAVA_VENDOR);
9858 System.out.println(SetupUtils.BUILD_JVM_VERSION+separator+
9859 BUILD_JVM_VERSION);
9860 System.out.println(SetupUtils.BUILD_JVM_VENDOR+separator+BUILD_JVM_VENDOR);
9861 System.out.println(SetupUtils.INCOMPATIBILITY_EVENTS+separator+
9862 StaticUtils.listToString(
9863 VersionCompatibilityIssue.getAllEvents(), ","));
9864 }
9865
9866 }
9867