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