8176067: Proper directory lookup processing

Reviewed-by: weijun
diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/LdapClient.java b/jdk/src/share/classes/com/sun/jndi/ldap/LdapClient.java
index f6b42d3..d3cdbc2 100644
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapClient.java
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapClient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1233,6 +1233,7 @@
     static final int LDAP_REF_FOLLOW = 0x01;            // follow referrals
     static final int LDAP_REF_THROW = 0x02;             // throw referral ex.
     static final int LDAP_REF_IGNORE = 0x03;            // ignore referrals
+    static final int LDAP_REF_FOLLOW_SCHEME = 0x04;     // follow referrals of the same scheme
 
     static final String LDAP_URL = "ldap://";           // LDAPv3
     static final String LDAPS_URL = "ldaps://";         // LDAPv3
diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/LdapCtx.java b/jdk/src/share/classes/com/sun/jndi/ldap/LdapCtx.java
index 79630f5..4a76771 100644
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapCtx.java
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapCtx.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2413,6 +2413,9 @@
         // First determine the referral mode
         if (ref != null) {
             switch (ref) {
+                case "follow-scheme":
+                    handleReferrals = LdapClient.LDAP_REF_FOLLOW_SCHEME;
+                    break;
                 case "follow":
                     handleReferrals = LdapClient.LDAP_REF_FOLLOW;
                     break;
@@ -2975,8 +2978,23 @@
             r = new LdapReferralException(resolvedName, resolvedObj, remainName,
                 msg, envprops, fullDN, handleReferrals, reqCtls);
             // only one set of URLs is present
-            r.setReferralInfo(res.referrals == null ? null :
-                    res.referrals.elementAt(0), false);
+            Vector<String> refs;
+            if (res.referrals == null) {
+                refs = null;
+            } else if (handleReferrals == LdapClient.LDAP_REF_FOLLOW_SCHEME) {
+                refs = new Vector<>();
+                for (String s : res.referrals.elementAt(0)) {
+                    if (s.startsWith("ldap:")) {
+                        refs.add(s);
+                    }
+                }
+                if (refs.isEmpty()) {
+                    refs = null;
+                }
+            } else {
+                refs = res.referrals.elementAt(0);
+            }
+            r.setReferralInfo(refs, false);
 
             if (hopCount > 1) {
                 r.setHopCount(hopCount);
diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/LdapReferralException.java b/jdk/src/share/classes/com/sun/jndi/ldap/LdapReferralException.java
index 1058d9d..0870ab7 100644
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapReferralException.java
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapReferralException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -117,7 +117,8 @@
 
         // If following referral, request controls are passed to referral ctx
         this.reqCtls =
-            (handleReferrals == LdapClient.LDAP_REF_FOLLOW ? reqCtls : null);
+            (handleReferrals == LdapClient.LDAP_REF_FOLLOW ||
+                    handleReferrals == LdapClient.LDAP_REF_FOLLOW_SCHEME ? reqCtls : null);
     }
 
     /**
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java
index 5a24a69..ba3e4d6 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -265,7 +265,7 @@
              */
             Hashtable<?,?> currentEnv = ctx.getEnvironment();
             if (currentEnv.get(Context.REFERRAL) == null) {
-                ctx.addToEnvironment(Context.REFERRAL, "follow");
+                ctx.addToEnvironment(Context.REFERRAL, "follow-scheme");
             }
         } catch (NamingException e) {
             if (debug != null) {