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     */
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     *   // 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)
062    public 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    }