< prev index next >

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

Print this page

        

@@ -23,13 +23,18 @@
  * questions.
  */
 
 package com.sun.jndi.ldap;
 
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Vector;
 import java.util.Enumeration;
+import java.util.function.BiFunction;
 
 import javax.naming.*;
 import javax.naming.directory.*;
 import javax.naming.spi.ObjectFactory;
 import javax.naming.spi.InitialContextFactory;

@@ -156,60 +161,85 @@
                 "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);
+            throws NamingException
+    {
+        NamingException ne = new NamingException();
+        DirContext ctx;
+        try {
+            List<String> urls = getDnsUrls(url, env);
+            if (urls.size() == 0) {
+                String factory;
+                if (env.contains(LdapCtx.DNS_PROVIDER)) {
+                    factory = (String) env.get(LdapCtx.DNS_PROVIDER);
+                } else {
+                    factory = "com.sun.jndi.ldap.DefaultDnsProvider";
+                }
+                throw new NamingException(
+                        factory + " was unable to resolve a valid ldap url");
+            }
+
+            for (String u : urls) {
+                LdapURL ldapUrl = new LdapURL(u);
         String dn = ldapUrl.getDN();
         String host = ldapUrl.getHost();
         int port = ldapUrl.getPort();
-        String[] hostports;
-        String domainName = null;
+                ctx = new LdapCtx(dn, host, port, env, ldapUrl.useSsl());
+                // Record the URL that created the context
+                ((LdapCtx) ctx).setProviderUrl(u);
+                return ctx;
+            }
+        } catch (Exception e) {
+            ne.setRootCause(e);
+        }
+        throw ne;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<String> getDnsUrls(String url, Hashtable<?,?> env)
+            throws Exception
+    {
+        BiFunction<String, Hashtable<?,?>, List<String>> dnsProvider = 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;
+        if (env.containsKey(LdapCtx.DNS_PROVIDER)) {
+            PrivilegedAction<ClassLoader> act =
+                    Thread.currentThread()::getContextClassLoader;
+            ClassLoader cl = AccessController.doPrivileged(act);
+            Class<?> cls = Class.forName(
+                    (String) env.get(LdapCtx.DNS_PROVIDER), true, cl);
+            Constructor<?> ctor = cls.getConstructor();
+            dnsProvider =
+                    (BiFunction<String, Hashtable<?,?>, List<String>>) ctor.newInstance();
             }
-            ctx = getUsingURLs(newUrls, env);
-            // Associate the derived domain name with the context
-            ((LdapCtx)ctx).setDomainName(domainName);
 
-        } else {
-            ctx = new LdapCtx(dn, host, port, env, ldapUrl.useSsl());
-            // Record the URL that created the context
-            ((LdapCtx)ctx).setProviderUrl(url);
+        if (dnsProvider == null) {
+            dnsProvider = new DefaultLdapDnsProvider();
         }
-        return ctx;
+
+        return dnsProvider.apply(url, env);
     }
 
     /*
      * 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 ne = new NamingException();
+        DirContext ctx;
+        for (String u : urls) {
             try {
-                return getUsingURL(urls[i], env);
+                ctx = getUsingURL(u, env);
+                LdapURL ldapUrl = new LdapURL(u);
+                // Associate the derived domain name with the context
+                ((LdapCtx) ctx).setDomainName(
+                        ServiceLocator.mapDnToDomainName(ldapUrl.getDN()));
+                return ctx;
             } catch (AuthenticationException e) {
                 throw e;
             } catch (NamingException e) {
                 ne = e;
             }
< prev index next >