JDK-8141148 : LDAP "follow" throws ClassCastException with Java 8
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.naming
  • Affected Version: 8u66
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2015-11-02
  • Updated: 2017-02-02
  • Resolved: 2016-07-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u102Fixed 9 b128Fixed
Description
    
J2SE Version (please include all output from java -version flag):
java version "1.8.0_66-ea"
Java(TM) SE Runtime Environment (build 1.8.0_66-ea-b02)
Java HotSpot(TM) Client VM (build 25.66-b02, mixed mode, sharing)


Does this problem occur on J2SE 7ux, 8ux?  Yes / No (be specific version#)

not work:
* 1.8.0_40
* 1.8.0_66-ea

work with:
* 1.7.0_71

Operating System Configuration Information (be specific):
Only tested on Windows 8, but this should be platform independent.


Bug Description:

If the flag LDAP connection flag javax.naming.Context.REFERRAL is set to
"follow" then the follow unexpected exception occur:

Exception in thread "main" java.lang.ClassCastException:
com.sun.jndi.ldap.LdapSearchEnumeration cannot be cast to
com.sun.jndi.ldap.LdapNamingEnumeration
    at
com.sun.jndi.ldap.LdapNamingEnumeration.getReferredResults(LdapNamingEnumerati
on.java:78)
    at
com.sun.jndi.ldap.LdapNamingEnumeration.getReferredResults(LdapNamingEnumerati
on.java:36)
    at
com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMoreReferrals(AbstractLdapN
amingEnumeration.java:330)
    at
com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMoreImpl(AbstractLdapNaming
Enumeration.java:227)
    at
com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMore(AbstractLdapNamingEnum
eration.java:189)
    at
com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMoreElements(AbstractLdapNa
mingEnumeration.java:117)
    at TestLdap.query(TestLdap.java:43)
    at TestLdap.main(TestLdap.java:19)


Steps to Reproduce (be specific):
Run the follow test program (attached). You need to change the account
setting. With Java 7 it print 2 numbers. With 8 it print only one number
and then it throw a ClassCastException. The first number is without
"follow". The second which is failing is with "follow".


Comments
As a result of https://bugs.openjdk.java.net/browse/JDK-7072353: http://hg.openjdk.java.net/jdk8u/jdk8u-dev/jdk/rev/18329abcdb7c The test attached to the bug fails with the following trace: Exception in thread "main" java.lang.ClassCastException: com.sun.jndi.ldap.LdapSearchEnumeration cannot be cast to com.sun.jndi.ldap.LdapNamingEnumeration at com.sun.jndi.ldap.LdapNamingEnumeration.getReferredResults(LdapNamingEnumeration.java:78) at com.sun.jndi.ldap.LdapNamingEnumeration.getReferredResults(LdapNamingEnumeration.java:36) at com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMoreReferrals(AbstractLdapNamingEnumeration.java:330) at com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMoreImpl(AbstractLdapNamingEnumeration.java:227) at com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMore(AbstractLdapNamingEnumeration.java:189) at com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMoreElements(AbstractLdapNamingEnumeration.java:117) at TestLdap.query(TestLdap.java:43) at TestLdap.main(TestLdap.java:19) Post refactor we have a NamingEnumeration interface which is implemented by an abstract class AbstractLdapNamingEnumeration. 3 implementations, LdapBindingEnumeration, LdapNamingEnumeration & LdapSearchEnumeration extend AbstractLdapNamingEnumeration. Each implementation has its own getReferredResults method which returns an object of the individual implementations type. Unfortunately this falls down (as can be seen in the stack) because an LdapNamingEnumeration.getReferredResults can call refCtx.search, which returns an LdapSearchEnumeration. This leads to a situation where LdapNamingEnumeration needs to cast an LdapSearchEnumeration which results in the exception above.
12-07-2016

Alot of this code was cleaned up in JDK 8 via JDK-7072353 The cast in this method is wrong : LdapNamingEnumeration.java protected LdapNamingEnumeration getReferredResults( LdapReferralContext refCtx) throws NamingException { // repeat the original operation at the new context return (LdapNamingEnumeration)refCtx.list(listArg); } ... since LdapNamingEnumeration no longer implements NamingEnumeration in JDK 8. Looks like some juggling of return parameters is needed. JDK 8 === final class LdapSearchEnumeration extends AbstractLdapNamingEnumeration<SearchResult> === JDK 7 final class LdapSearchEnumeration extends LdapNamingEnumeration { ====================== JDK 8 === final class LdapNamingEnumeration extends AbstractLdapNamingEnumeration<NameClassPair> { === JDK 7 class LdapNamingEnumeration implements NamingEnumeration, ReferralEnumeration {
06-11-2015