001    /*
002     * Copyright 2007-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2015 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     */
021    package com.unboundid.ldap.sdk;
022    
023    
024    
025    import com.unboundid.util.NotExtensible;
026    import com.unboundid.util.NotMutable;
027    import com.unboundid.util.ThreadSafety;
028    import com.unboundid.util.ThreadSafetyLevel;
029    
030    import 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)
064    public 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    }