001    /*
002     * Copyright 2007-2013 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2013 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.NotMutable;
026    import com.unboundid.util.ThreadSafety;
027    import com.unboundid.util.ThreadSafetyLevel;
028    
029    import 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     *     System.out.println("The directory server supports the use of the " +
053     *                        "server-side sort request control.");
054     *   }
055     *   else
056     *   {
057     *     System.out.println("The directory server does not support the use of " +
058     *                        "the server-side sort request control.");
059     *   }
060     * </PRE>
061     */
062    @NotMutable()
063    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
064    public final 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      private 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 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 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 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 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 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 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 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 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 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 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 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 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 boolean supportsExtendedOperation(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 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 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 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            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 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 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 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 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 String getVendorVersion()
615      {
616        return getAttributeValue(ATTR_VENDOR_VERSION);
617      }
618    }