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