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