* @throws SearchAbandonException if an error occurs.
*/
private void readRemoteEntry(String[] referral)
throws SearchAbandonException {
LDAPConnectionPool connectionPool = controller.getConnectionPool();
LDAPURL url = null;
SearchResult entry = null;
String remoteDn = null;
Exception lastException = null;
Object lastExceptionArg = null;
int i = 0;
while ((i < referral.length) && (entry == null)) {
InitialLdapContext ctx = null;
try {
url = LDAPURL.decode(referral[i], false);
if (url.getHost() == null)
{
// Use the local server connection.
ctx = controller.getUserDataConnection();
url.setHost(ConnectionUtils.getHostName(ctx));
url.setPort(ConnectionUtils.getPort(ctx));
url.setScheme(ConnectionUtils.isSSL(ctx)?"ldaps":"ldap");
}
ctx = connectionPool.getConnection(url);
remoteDn = url.getRawBaseDN();
if ((remoteDn == null) ||
remoteDn.equals("")) {
/* The referral has not a target DN specified: we
have to use the DN of the entry that contains the
referral... */
if (remoteEntry != null) {
remoteDn = remoteEntry.getName();
} else {
remoteDn = localEntry.getName();
}
/* We have to recreate the url including the target DN
we are using */
url = new LDAPURL(url.getScheme(), url.getHost(), url.getPort(),
remoteDn, url.getAttributes(), url.getScope(), url.getRawFilter(),
url.getExtensions());
}
if (useCustomFilter() && url.getScope() == SearchScope.BASE_OBJECT)
{
// Check that the entry verifies the filter
searchForCustomFilter(remoteDn, ctx);
}
int scope = getJNDIScope(url);
String filter = getJNDIFilter(url);
SearchControls ctls = controller.getBasicSearchControls();
ctls.setReturningAttributes(controller.getAttrsForBlackSearch());
ctls.setSearchScope(scope);
ctls.setCountLimit(1);
NamingEnumeration<SearchResult> sr = ctx.search(remoteDn,
filter,
ctls);
try
{
boolean found = false;
while (sr.hasMore())
{
entry = sr.next();
String name;
if (entry.getName().length() == 0)
{
name = remoteDn;
}
else
{
name = unquoteRelativeName(entry.getName())+","+remoteDn;
}
entry.setName(name);
found = true;
}
if (!found)
{
throw new NameNotFoundException();
}
}
catch (SizeLimitExceededException sle)
{
// We are just searching for an entry, but if there is more than one
// this exception will be thrown. We call sr.hasMore after the
// first entry has been retrieved to avoid sending a systematic
// abandon when closing the sr NamingEnumeration.
// See CR 6976906.
}
finally
{
sr.close();
}
throwAbandonIfNeeded(null);
}
catch (InterruptedNamingException x) {
throwAbandonIfNeeded(x);
}
catch (NamingException x) {
lastException = x;
lastExceptionArg = referral[i];
}
catch (DirectoryException de) {
lastException = de;
lastExceptionArg = referral[i];
}
finally {
if (ctx != null) {
connectionPool.releaseConnection(ctx);
}
}
i = i + 1;
}
if (entry == null) {
throw new SearchAbandonException(
State.FAILED, lastException, lastExceptionArg);
}
else
{
if (url.getScope() != SearchScope.BASE_OBJECT)
{
// The URL is to be transformed: the code assumes that the URL points
// to the remote entry.
url = new LDAPURL(url.getScheme(), url.getHost(),
url.getPort(), entry.getName(), url.getAttributes(),
SearchScope.BASE_OBJECT, null, url.getExtensions());
}
checkLoopInReferral(url, referral[i-1]);
remoteUrl = url;
remoteEntry = entry;
}