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