Class LdapServerLocator

java.lang.Object
org.exoplatform.services.organization.idm.ldap.LdapServerLocator

public class LdapServerLocator extends Object
Resolves the LDAP/AD provider URL(s) used to open a JNDI LdapContext.

This class is only ever instantiated - and none of the properties below have any effect - when org.picketlink.idm.impl.store.ldap.ExoLDAPIdentityStoreImpl#FAILOVER_ENABLED_PROP (exo.ldap.failover.enabled) is set to true; that master flag defaults to false, leaving the original PicketLink code path untouched.

By default (feature disabled), this simply returns the statically configured providerURL (i.e. the value of exo.ldap.url) untouched, so existing single- or multi-server configurations keep working exactly as before.

When DNS SRV-based discovery is enabled, this class additionally resolves a _service._proto.domain SRV record set (RFC 2782 - e.g. the standard _ldap._tcp.<domain> record advertised by Active Directory domain controllers), orders it by priority and applies a weighted-random ordering within each priority tier, and prepends the resulting URL list to the statically configured one (used as an ultimate fallback).

Because the JNDI LDAP provider (com.sun.jndi.ldap.LdapCtxFactory) natively accepts a space-separated list of URLs in java.naming.provider.url and tries them in order until one connects, returning a multi-URL string from resolveProviderURL() is sufficient to get connection failover "for free". Re-ordering the list (weighted by SRV priority/weight) on every call additionally spreads new connections across the available servers, providing basic load-balancing.

Independently of SRV discovery, a main server plus explicit secondary/backup servers can be configured statically via exo.ldap.url (main) and exo.ldap.failover.urls (secondary, tried in the order given, after the main server and after any SRV-resolved server).

Recognized configuration properties (all optional, all read via PropertyManager):

  • exo.ldap.failover.urls - comma/space-separated list of secondary/backup LDAP server URLs, tried (in order) after the main exo.ldap.url server(s) and after any SRV-resolved server
  • exo.ldap.srv.enabled - enables SRV-based discovery (defaults to false)
  • exo.ldap.srv.domain - the DNS domain to query, e.g. example.com. Mandatory when SRV lookup is enabled
  • exo.ldap.srv.service - the SRV service/proto prefix, defaults to _ldap._tcp (use e.g. _ldap._tcp.dc._msdcs to target Active Directory domain controllers specifically)
  • exo.ldap.srv.scheme - URL scheme used to build server URLs from the resolved host/port, defaults to ldap
  • exo.ldap.srv.refresh.period - how long (ms) a successful resolution is cached before being refreshed, defaults to 300000 (5 min)
  • exo.ldap.srv.timeout - DNS query timeout (ms), defaults to 5000
  • exo.ldap.srv.dns.servers - comma-separated host[:port] list of DNS servers to query; defaults to the JVM/OS-configured resolver when unset
  • Field Details

  • Constructor Details

    • LdapServerLocator

      public LdapServerLocator(String configuredProviderUrl)
  • Method Details

    • resolveProviderURL

      public String resolveProviderURL()
      Returns:
      the provider URL(s) to use for the next LDAP connection attempt, as a space-separated list suitable for java.naming.provider.url
    • isAllLdaps

      public boolean isAllLdaps()
      Returns:
      true if at least one server is configured and every server this locator can ever return uses the ldaps scheme: the SRV-generated scheme (when SRV lookup is enabled) and every statically configured URL (main and secondary). Returns false when nothing is configured at all - there is no server to prove is ldaps, so this fails closed rather than vacuously true. Used to decide whether it is safe to register a TLS-only java.naming.ldap.factory.socket - that JNDI property is not scheme-scoped, so registering it while any configured server is plain ldap:// would force a TLS handshake on a plaintext connection and break it.
    • isSrvLookupEnabled

      public boolean isSrvLookupEnabled()
    • runAsync

      protected void runAsync(Runnable task)
      Runs task in the background. Overridable so tests can substitute a same-thread execution and keep assertions deterministic.
    • lookupSrvRecords

      protected List<SrvRecord> lookupSrvRecords() throws NamingException
      Throws:
      NamingException
    • orderByRfc2782

      protected List<SrvRecord> orderByRfc2782(List<SrvRecord> records)
      Orders SRV records per RFC 2782: ascending by priority, and within a priority tier, a weighted-random order (higher weight = more likely to be picked earlier). Re-evaluated on every call so successive connections are spread across same-priority servers.
    • currentTimeMillis

      protected long currentTimeMillis()