I am currently reviewing Oracle's examples how to manually follow referrals (case throw
) in Java/JNDI returned from a directory server via LDAP. The example source code in question can be downloaded here.
The code in question:
// Set up environment for creating initial context
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:489/o=JNDITutorial");
// Set referral property to throw ReferralException
env.put(Context.REFERRAL, "throw");
try {
// Create initial context
DirContext ctx = new InitialDirContext(env);
// Set controls for performing subtree search
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Do this in a loop because we don't know how
// many referrals there will be
for (boolean moreReferrals = true; moreReferrals;) {
try {
// Perform search
NamingEnumeration answer = ctx.search("", "(objectclass=*)",
ctls);
// Print the answer
while (answer.hasMore()) {
System.out.println(">>>" +
((SearchResult)answer.next()).getName());
}
// search completes with no more referrals
moreReferrals = false;
} catch (ReferralException e) {
if (! followReferral(e.getReferralInfo())) {
moreReferrals = e.skipReferral();
}
// point to the new context
if (moreReferrals) {
ctx = (DirContext) e.getReferralContext();
}
}
}
// Close the context when we're done
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
I consider this code flawed in several ways. The documentation of DirContext
and NamingEmuneration
exibit a close
method wich immediately releases resources. Especially the former holds an open socket to the target server. Not closing it will lead to a socket leakage.
My understanding (flaws) of the code is:
answer
is never closed.DirContext
in not closed in the case of a NamingException
, should be moved to a finally
block.DirContext
created with e.getReferralContext()
overwrite ctx
which means that intermediate referrals as well as the InitialDirContext
are never closed and lead to leak.Are my findings correct?
PS: I have also checked Oracle's internal implemenation in the case that follow
is set and the funny thing is all referral contexts are closed internally.
Disclaimer: I have posted this initially on Code Review but it was closed because it is not my code. I was advised to try on SO.
You need to close the NamingEnumeration, and anything else you get from JNDI that is closeable.