001/*
002 * Copyright 2007-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2007-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2007-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk;
037
038
039
040import com.unboundid.util.Debug;
041import com.unboundid.util.NotExtensible;
042import com.unboundid.util.NotMutable;
043import com.unboundid.util.NotNull;
044import com.unboundid.util.Nullable;
045import com.unboundid.util.ThreadSafety;
046import com.unboundid.util.ThreadSafetyLevel;
047
048
049
050/**
051 * This class provides a data structure for representing the directory server
052 * root DSE.  This entry provides information about the capabilities of the
053 * directory server, server vendor and version information, and published naming
054 * contexts.
055 * <BR><BR>
056 * Note a root DSE object instance represents a read-only version of an entry,
057 * so all read operations allowed for an entry will succeed, but all write
058 * attempts will be rejected.
059 * <BR><BR>
060 * <H2>Example</H2>
061 * The following example demonstrates the process for retrieving the root DSE
062 * of a directory server and using it to determine whether it supports the
063 * {@link com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl}:
064 * <PRE>
065 * RootDSE rootDSE = connection.getRootDSE();
066 * if (rootDSE.supportsControl(
067 *      ServerSideSortRequestControl.SERVER_SIDE_SORT_REQUEST_OID))
068 * {
069 *   // The directory server does support the server-side sort control.
070 * }
071 * else
072 * {
073 *   // The directory server does not support the server-side sort control.
074 * }
075 * </PRE>
076 */
077@NotExtensible()
078@NotMutable()
079@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
080public class RootDSE
081       extends ReadOnlyEntry
082{
083  /**
084   * The name of the attribute that includes a set of URIs (likely in the form
085   * of LDAP URLs) of other servers that may be contacted if the target server
086   * is unavailable, as defined in RFC 4512 section 5.1.
087   */
088  @NotNull public static final String ATTR_ALT_SERVER = "altServer";
089
090
091
092  /**
093   * The name of the attribute that specifies the DN that is the base of the
094   * LDAP changelog data, if available, as defined in draft-good-ldap-changelog.
095   */
096  @NotNull public static final String ATTR_CHANGELOG_DN = "changelog";
097
098
099
100  /**
101   * The name of the attribute that may contain the change number for the first
102   * entry in the LDAP changelog.  This is not defined in any public
103   * specification, but is provided by a number of servers which implement
104   * draft-good-ldap-changelog.
105   */
106  @NotNull public static final String ATTR_FIRST_CHANGE_NUMBER =
107       "firstChangeNumber";
108
109
110
111  /**
112   * The name of the attribute that may contain the change number for the last
113   * entry in the LDAP changelog, if available.  This is not defined in any
114   * public specification, but is provided by a number of servers which
115   * implement draft-good-ldap-changelog.
116   */
117  @NotNull public static final String ATTR_LAST_CHANGE_NUMBER =
118       "lastChangeNumber";
119
120
121
122  /**
123   * The name of the attribute that may contain the change number for the last
124   * entry purged from the LDAP changelog, if available.  This is not defined in
125   * any public specification, but is provided by a number of servers which
126   * implement draft-good-ldap-changelog.
127   */
128  @NotNull public static final String ATTR_LAST_PURGED_CHANGE_NUMBER =
129       "lastPurgedChangeNumber";
130
131
132
133  /**
134   * The name of the attribute that includes the DNs of the public naming
135   * contexts defined in the server, as defined in RFC 4512 section 5.1.
136   */
137  @NotNull public static final String ATTR_NAMING_CONTEXT = "namingContexts";
138
139
140
141  /**
142   * The name of the attribute that specifies the DN of the subschema subentry
143   * that serves the server root DSE, as defined in RFC 4512 section 4.2.
144   */
145  @NotNull public static final String ATTR_SUBSCHEMA_SUBENTRY =
146       "subschemaSubentry";
147
148
149
150  /**
151   * The name of the attribute that includes the names of the supported
152   * authentication password storage schemes, as defined in RFC 3112.
153   */
154  @NotNull public static final String
155       ATTR_SUPPORTED_AUTH_PASSWORD_STORAGE_SCHEME =
156            "supportedAuthPasswordSchemes";
157
158
159
160  /**
161   * The name of the attribute that includes the OIDs of the request controls
162   * supported by the server, as defined in RFC 4512 section 5.1.
163   */
164  @NotNull public static final String ATTR_SUPPORTED_CONTROL =
165       "supportedControl";
166
167
168
169  /**
170   * The name of the attribute that includes the OIDs of the extended operations
171   * supported by the server, as defined in RFC 4512 section 5.1.
172   */
173  @NotNull public static final String ATTR_SUPPORTED_EXTENDED_OPERATION =
174       "supportedExtension";
175
176
177
178  /**
179   * The name of the attribute that includes the OIDs of the features supported
180   * by the server, as defined in RFC 4512 section 5.1.
181   */
182  @NotNull public static final String ATTR_SUPPORTED_FEATURE =
183       "supportedFeatures";
184
185
186
187  /**
188   * The name of the attribute that includes the OIDs of the LDAP protocol
189   * versions supported by the server, as defined in RFC 4512 section 5.1.
190   */
191  @NotNull public static final String ATTR_SUPPORTED_LDAP_VERSION =
192       "supportedLDAPVersion";
193
194
195
196  /**
197   * The name of the attribute that includes the names of the SASL mechanisms
198   * supported by the server, as defined in RFC 4512 section 5.1.
199   */
200  @NotNull public static final String ATTR_SUPPORTED_SASL_MECHANISM =
201       "supportedSASLMechanisms";
202
203
204
205  /**
206   * The name of the attribute that includes the name of the server vendor,
207   * as defined in RFC 3045.
208   */
209  @NotNull public static final String ATTR_VENDOR_NAME = "vendorName";
210
211
212
213  /**
214   * The name of the attribute that includes the server version, as defined in
215   * RFC 3045.
216   */
217  @NotNull public static final String ATTR_VENDOR_VERSION = "vendorVersion";
218
219
220
221  /**
222   * The set of request attributes to use when attempting to retrieve the server
223   * root DSE.  It will attempt to retrieve all operational attributes if the
224   * server supports that capability, but will also attempt to retrieve specific
225   * attributes by name in case it does not.
226   */
227  @NotNull protected static final String[] REQUEST_ATTRS =
228  {
229    "*",
230    "+",
231    ATTR_ALT_SERVER,
232    ATTR_CHANGELOG_DN,
233    ATTR_FIRST_CHANGE_NUMBER,
234    ATTR_LAST_CHANGE_NUMBER,
235    ATTR_LAST_PURGED_CHANGE_NUMBER,
236    ATTR_NAMING_CONTEXT,
237    ATTR_SUBSCHEMA_SUBENTRY,
238    ATTR_SUPPORTED_AUTH_PASSWORD_STORAGE_SCHEME,
239    ATTR_SUPPORTED_CONTROL,
240    ATTR_SUPPORTED_EXTENDED_OPERATION,
241    ATTR_SUPPORTED_FEATURE,
242    ATTR_SUPPORTED_LDAP_VERSION,
243    ATTR_SUPPORTED_SASL_MECHANISM,
244    ATTR_VENDOR_NAME,
245    ATTR_VENDOR_VERSION,
246  };
247
248
249
250  /**
251   * The serial version UID for this serializable class.
252   */
253  private static final long serialVersionUID = -1678182563511570981L;
254
255
256
257  /**
258   * Creates a new root DSE object from the information in the provided entry.
259   *
260   * @param  rootDSEEntry  The entry to use to create this root DSE object.  It
261   *                       must not be {@code null}.
262   */
263  public RootDSE(@NotNull final Entry rootDSEEntry)
264  {
265    super(rootDSEEntry);
266  }
267
268
269
270  /**
271   * Retrieves the directory server root DSE using the provided connection.
272   *
273   * @param  connection  The connection to use to retrieve the server root DSE.
274   *
275   * @return  The directory server root DSE, or {@code null} if it is not
276   *          available (e.g., the client does not have permission to read the
277   *          entry).
278   *
279   * @throws  LDAPException  If a problem occurs while attempting to retrieve
280   *                         the server root DSE.
281   */
282  @Nullable()
283  public static RootDSE getRootDSE(@NotNull final LDAPInterface connection)
284         throws LDAPException
285  {
286    final Entry rootDSEEntry = connection.getEntry("", REQUEST_ATTRS);
287    if (rootDSEEntry == null)
288    {
289      return null;
290    }
291
292    return new RootDSE(rootDSEEntry);
293  }
294
295
296
297  /**
298   * Retrieves a set of URIs for alternate servers that may be contacted if
299   * the current server becomes unavailable.
300   *
301   * @return  A set of URIs for alternate servers that may be contacted if the
302   *          current server becomes available, or {@code null} if the server
303   *          does not publish that information.
304   */
305  @Nullable()
306  public final String[] getAltServerURIs()
307  {
308    return getAttributeValues(ATTR_ALT_SERVER);
309  }
310
311
312
313  /**
314   * Retrieves the DN of the base entry for the directory server changelog
315   * information, if available.
316   *
317   * @return  The DN of the base entry for the directory server changelog
318   *          information, or {@code null} if the server does not publish that
319   *          information or no changelog is available.
320   */
321  @Nullable()
322  public final String getChangelogDN()
323  {
324    return getAttributeValue(ATTR_CHANGELOG_DN);
325  }
326
327
328
329  /**
330   * Retrieves the change number for the first entry contained in the LDAP
331   * changelog, if available.
332   *
333   * @return  The change number for the first entry contained in the LDAP
334   *          changelog, if available.
335   */
336  @Nullable()
337  public final Long getFirstChangeNumber()
338  {
339    return getAttributeValueAsLong(ATTR_FIRST_CHANGE_NUMBER);
340  }
341
342
343
344  /**
345   * Retrieves the change number for the last entry contained in the LDAP
346   * changelog, if available.
347   *
348   * @return  The change number for the last entry contained in the LDAP
349   *          changelog, if available.
350   */
351  @Nullable()
352  public final Long getLastChangeNumber()
353  {
354    return getAttributeValueAsLong(ATTR_LAST_CHANGE_NUMBER);
355  }
356
357
358
359  /**
360   * Retrieves the change number for the last entry purged from the LDAP
361   * changelog, if available.
362   *
363   * @return  The change number for the last entry purged from the LDAP
364   *          changelog, if available.
365   */
366  @Nullable()
367  public final Long getLastPurgedChangeNumber()
368  {
369    return getAttributeValueAsLong(ATTR_LAST_PURGED_CHANGE_NUMBER);
370  }
371
372
373
374  /**
375   * Retrieves the DNs of the naming contexts provided by the directory server.
376   *
377   * @return  The DNs of the naming contexts provided by the directory server,
378   *          or {@code null} if the server does not publish that information.
379   */
380  @Nullable()
381  public final String[] getNamingContextDNs()
382  {
383    return getAttributeValues(ATTR_NAMING_CONTEXT);
384  }
385
386
387
388  /**
389   * Retrieves the DN of the subschema subentry that serves the directory server
390   * root DSE.
391   *
392   * @return  The DN of the subschema subentry that serves the directory server
393   *          root DSE, or {@code null} if the server does not publish that
394   *          information.
395   */
396  @Nullable()
397  public final String getSubschemaSubentryDN()
398  {
399    return getAttributeValue(ATTR_SUBSCHEMA_SUBENTRY);
400  }
401
402
403
404  /**
405   * Retrieves the names of the authentication password storage schemes
406   * supported by the server.
407   *
408   * @return  The names of the authentication password storage schemes supported
409   *          by the server, or {@code null} if the server does not publish
410   *          that information.
411   */
412  @Nullable()
413  public final String[] getSupportedAuthPasswordSchemeNames()
414  {
415    return getAttributeValues(ATTR_SUPPORTED_AUTH_PASSWORD_STORAGE_SCHEME);
416  }
417
418
419
420  /**
421   * Indicates whether the directory server indicates that it supports the
422   * specified authentication password storage scheme.
423   *
424   * @param  scheme  The name of the authentication password storage scheme for
425   *                 which to make the determination.  It must not be
426   *                 {@code null}.
427   *
428   * @return  {@code true} if the directory server indicates that it supports
429   *          the specified authentication password storage scheme, or
430   *          {@code false} if it does not.
431   */
432  public final boolean supportsAuthPasswordScheme(@NotNull final String scheme)
433  {
434    return hasAttributeValue(ATTR_SUPPORTED_AUTH_PASSWORD_STORAGE_SCHEME,
435                             scheme);
436  }
437
438
439
440  /**
441   * Retrieves the OIDs of the supported request controls advertised by the
442   * server root DSE.
443   *
444   * @return  The OIDs of the supported request controls advertised by the
445   *          server root DSE, or {@code null} if the server does not publish
446   *          that information.
447   */
448  @Nullable()
449  public final String[] getSupportedControlOIDs()
450  {
451    return getAttributeValues(ATTR_SUPPORTED_CONTROL);
452  }
453
454
455
456  /**
457   * Indicates whether the directory server indicates that it supports the
458   * request control with the provided OID.
459   *
460   * @param  controlOID  The OID of the control for which to make the
461   *                     determination.  It must not be {@code null}.
462   *
463   * @return  {@code true} if the server indicates that it supports the request
464   *          control with the specified OID, or {@code false} if it does not.
465   */
466  public final boolean supportsControl(@NotNull final String controlOID)
467  {
468    return hasAttributeValue(ATTR_SUPPORTED_CONTROL, controlOID);
469  }
470
471
472
473  /**
474   * Retrieves the OIDs of the supported extended operations advertised by the
475   * server root DSE.
476   *
477   * @return  The OIDs of the supported extended operations advertised by the
478   *          server root DSE, or {@code null} if the server does not publish
479   *          that information.
480   */
481  @Nullable()
482  public final String[] getSupportedExtendedOperationOIDs()
483  {
484    return getAttributeValues(ATTR_SUPPORTED_EXTENDED_OPERATION);
485  }
486
487
488
489  /**
490   * Indicates whether the directory server indicates that it supports the
491   * extended operation with the provided OID.
492   *
493   * @param  extendedOperationOID  The OID of the extended operation for which
494   *                               to make the determination.  It must not be
495   *                               {@code null}.
496   *
497   * @return  {@code true} if the server indicates that it supports the extended
498   *          operation with the specified OID, or {@code false} if it does not.
499   */
500  public final boolean supportsExtendedOperation(
501                            @NotNull final String extendedOperationOID)
502  {
503    return hasAttributeValue(ATTR_SUPPORTED_EXTENDED_OPERATION,
504                             extendedOperationOID);
505  }
506
507
508
509  /**
510   * Retrieves the OIDs of the supported features advertised by the server root
511   * DSE.
512   *
513   * @return  The OIDs of the supported features advertised by the server root
514   *          DSE, or {@code null} if the server does not publish that
515   *          information.
516   */
517  @Nullable()
518  public final String[] getSupportedFeatureOIDs()
519  {
520    return getAttributeValues(ATTR_SUPPORTED_FEATURE);
521  }
522
523
524
525  /**
526   * Indicates whether the directory server indicates that it supports the
527   * extended operation with the provided OID.
528   *
529   * @param  featureOID  The OID of the feature for which to make the
530   *                     determination.  It must not be {@code null}.
531   *
532   * @return  {@code true} if the server indicates that it supports the feature
533   *          with the specified OID, or {@code false} if it does not.
534   */
535  public final boolean supportsFeature(@NotNull final String featureOID)
536  {
537    return hasAttributeValue(ATTR_SUPPORTED_FEATURE, featureOID);
538  }
539
540
541
542  /**
543   * Retrieves the supported LDAP protocol versions advertised by the server
544   * root DSE.
545   *
546   * @return  The supported LDAP protocol versions advertised by the server
547   *          root DSE, or {@code null} if the server does not publish that
548   *          information.
549   */
550  @Nullable()
551  public final int[] getSupportedLDAPVersions()
552  {
553    final String[] versionStrs =
554         getAttributeValues(ATTR_SUPPORTED_LDAP_VERSION);
555    if (versionStrs == null)
556    {
557      return null;
558    }
559
560    final int[] versions = new int[versionStrs.length];
561    for (int i=0; i < versionStrs.length; i++)
562    {
563      try
564      {
565        versions[i] = Integer.parseInt(versionStrs[i]);
566      }
567      catch (final Exception e)
568      {
569        Debug.debugException(e);
570        // We couldn't parse the value as an integer.
571        return null;
572      }
573    }
574
575    return versions;
576  }
577
578
579
580  /**
581   * Indicates whether the directory server indicates that it supports the
582   * provided LDAP protocol version.
583   *
584   * @param  ldapVersion  The LDAP protocol version for which to make the
585   *                      determination.
586   *
587   * @return  {@code true} if the server indicates that it supports the
588   *          specified LDAP protocol version, or {@code false} if it does not.
589   */
590  public final boolean supportsLDAPVersion(final int ldapVersion)
591  {
592    return hasAttributeValue(ATTR_SUPPORTED_LDAP_VERSION,
593                             String.valueOf(ldapVersion));
594  }
595
596
597
598  /**
599   * Retrieves the names of the supported SASL mechanisms advertised by the
600   * server root DSE.
601   *
602   * @return  The names of the supported SASL mechanisms advertised by the
603   *          server root DSE, or {@code null} if the server does not publish
604   *          that information.
605   */
606  @Nullable()
607  public final String[] getSupportedSASLMechanismNames()
608  {
609    return getAttributeValues(ATTR_SUPPORTED_SASL_MECHANISM);
610  }
611
612
613
614  /**
615   * Indicates whether the directory server indicates that it supports the
616   * specified SASL mechanism.
617   *
618   * @param  mechanismName  The name of the SASL mechanism for which to make the
619   *                        determination.  It must not be {@code null}.
620   *
621   * @return  {@code true} if the server indicates that it supports the
622   *          specified SASL mechanism, or {@code false} if it does not.
623   */
624  public final boolean supportsSASLMechanism(
625                            @NotNull final String mechanismName)
626  {
627    return hasAttributeValue(ATTR_SUPPORTED_SASL_MECHANISM, mechanismName);
628  }
629
630
631
632  /**
633   * Retrieves the name of the directory server vendor, if available.
634   *
635   * @return  The name of the directory server vendor, or {@code null} if the
636   *          server does not publish that information.
637   */
638  @Nullable()
639  public final String getVendorName()
640  {
641    return getAttributeValue(ATTR_VENDOR_NAME);
642  }
643
644
645
646  /**
647   * Retrieves the directory server version string, if available.
648   *
649   * @return  The directory server version string, or {@code null} if the server
650   *          does not publish that information.
651   */
652  @Nullable()
653  public final String getVendorVersion()
654  {
655    return getAttributeValue(ATTR_VENDOR_VERSION);
656  }
657}