< prev index next >

src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtxFactory.java

Print this page

        

@@ -23,16 +23,15 @@
  * questions.
  */
 
 package com.sun.jndi.ldap;
 
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.Enumeration;
+import java.util.*;
 
 import javax.naming.*;
 import javax.naming.directory.*;
+import javax.naming.spi.ldap.LdapDnsProviderResult;
 import javax.naming.spi.ObjectFactory;
 import javax.naming.spi.InitialContextFactory;
 import javax.naming.ldap.Control;
 
 import com.sun.jndi.url.ldap.ldapURLContextFactory;

@@ -156,67 +155,98 @@
                 "argument must be an LDAP URL String or array of them");
         }
     }
 
     private static DirContext getUsingURL(String url, Hashtable<?,?> env)
-            throws NamingException {
-        DirContext ctx = null;
-        LdapURL ldapUrl = new LdapURL(url);
-        String dn = ldapUrl.getDN();
-        String host = ldapUrl.getHost();
-        int port = ldapUrl.getPort();
-        String[] hostports;
-        String domainName = null;
-
-        // handle a URL with no hostport (ldap:/// or ldaps:///)
-        // locate the LDAP service using the URL's distinguished name
-        if (host == null &&
-            port == -1 &&
-            dn != null &&
-            (domainName = ServiceLocator.mapDnToDomainName(dn)) != null &&
-            (hostports = ServiceLocator.getLdapService(domainName, env))
-                != null) {
-            // Generate new URLs that include the discovered hostports.
-            // Reuse the original URL scheme.
-            String scheme = ldapUrl.getScheme() + "://";
-            String[] newUrls = new String[hostports.length];
-            String query = ldapUrl.getQuery();
-            String urlSuffix = ldapUrl.getPath() + (query != null ? query : "");
-            for (int i = 0; i < hostports.length; i++) {
-                newUrls[i] = scheme + hostports[i] + urlSuffix;
-            }
-            ctx = getUsingURLs(newUrls, env);
-            // Associate the derived domain name with the context
-            ((LdapCtx)ctx).setDomainName(domainName);
+            throws NamingException
+    {
+        try {
+            LdapDnsProviderResult r =
+                LdapDnsProviderService.getInstance().lookupEndpoints(url, env);
+            LdapCtx ctx = null;
+            NamingException lastException = null;
+
+            /*
+             * Prior to this change we had been assuming that the url.getDN()
+             * should be converted to a domain name via
+             * ServiceLocator.mapDnToDomainName(url.getDN())
+             *
+             * However this is incorrect as we can't assume that the supplied
+             * url.getDN() is the same as the dns domain for the directory
+             * server.
+             *
+             * This means that we depend on the dnsProvider to return both
+             * the list of urls of individual hosts from which we attempt to
+             * create an LdapCtx from *AND* the domain name that they serve
+             *
+             * In order to do this the dnsProvider must return an
+             * {@link LdapDnsProviderResult}.
+             *
+             */
+            for (String u : r.getEndpoints()) {
+                try {
+                    ctx = getLdapCtxFromUrl(
+                            r.getDomainName(), new LdapURL(u), env);
+                } catch (NamingException e) {
+                    // try the next element
+                    lastException = e;
+                }
+            }
+
+            if (lastException != null) {
+                throw lastException;
+            }
+
+            if (ctx == null) {
+                // we have resolved them, but they are not valid
+                throw new NamingException("Could not resolve a valid ldap host");
+            }
 
-        } else {
-            ctx = new LdapCtx(dn, host, port, env, ldapUrl.useSsl());
             // Record the URL that created the context
-            ((LdapCtx)ctx).setProviderUrl(url);
+            ctx.setProviderUrl(url);
+            return ctx;
+        } catch (NamingException e) {
+            // getDnsUrls(url, env) may throw a NamingException, which there is
+            // no need to wrap.
+            throw e;
+        } catch (Exception e) {
+            NamingException ex = new NamingException();
+            ex.setRootCause(e);
+            throw ex;
+        }
         }
+
+    private static LdapCtx getLdapCtxFromUrl(String domain,
+                                             LdapURL url,
+                                             Hashtable<?,?> env)
+            throws NamingException
+    {
+        String dn = url.getDN();
+        String host = url.getHost();
+        int port = url.getPort();
+        LdapCtx ctx = new LdapCtx(dn, host, port, env, url.useSsl());
+        ctx.setDomainName(domain);
         return ctx;
     }
 
     /*
      * Try each URL until one of them succeeds.
      * If all URLs fail, throw one of the exceptions arbitrarily.
      * Not pretty, but potentially more informative than returning null.
      */
     private static DirContext getUsingURLs(String[] urls, Hashtable<?,?> env)
-            throws NamingException {
-        NamingException ne = null;
-        DirContext ctx = null;
-        for (int i = 0; i < urls.length; i++) {
+            throws NamingException
+    {
+        NamingException ex = null;
+        for (String u : urls) {
             try {
-                return getUsingURL(urls[i], env);
-            } catch (AuthenticationException e) {
-                throw e;
+                return getUsingURL(u, env);
             } catch (NamingException e) {
-                ne = e;
+                ex = e;
             }
         }
-        throw ne;
+        throw ex;
     }
 
     /**
      * Used by Obj and obj/RemoteToAttrs too so must be public
      */
< prev index next >