internal virtual System.Collections.ArrayList chaseReferral(LdapMessageQueue queue, LdapConstraints cons, LdapMessage msg, System.String[] initialReferrals, int hopCount, bool searchReference, System.Collections.ArrayList connectionList)
{
System.Collections.ArrayList connList = connectionList;
LdapConnection rconn = null; // new conn for following referral
ReferralInfo rinfo = null; // referral info
LdapMessage origMsg;
// Get a place to store new connections
if (connList == null)
{
connList = new System.Collections.ArrayList(cons.HopLimit);
}
// Following referrals or search reference
System.String[] refs; // referral list
if (initialReferrals != null)
{
// Search continuation reference from a search request
refs = initialReferrals;
origMsg = msg.RequestingMessage;
}
else
{
// Not a search request
LdapResponse resp = (LdapResponse) queue.getResponse();
if (resp.ResultCode != LdapException.REFERRAL)
{
// Not referral result,throw Exception if nonzero result
resp.chkResultCode();
return connList;
}
// We have a referral response
refs = resp.Referrals;
origMsg = resp.RequestingMessage;
}
LdapUrl refUrl; // referral represented as URL
try
{
// increment hop count, check max hops
if (hopCount++ > cons.HopLimit)
{
throw new LdapLocalException("Max hops exceeded", LdapException.REFERRAL_LIMIT_EXCEEDED);
}
// Get a connection to follow the referral
rinfo = getReferralConnection(refs);
rconn = rinfo.ReferralConnection;
refUrl = rinfo.ReferralUrl;
connList.Add(rconn);
// rebuild msg into new msg changing msgID,dn,scope,filter
LdapMessage newMsg = rebuildRequest(origMsg, refUrl, searchReference);
// Send new message on new connection
try
{
MessageAgent agent;
if (queue is LdapResponseQueue)
{
agent = queue.MessageAgent;
}
else
{
agent = queue.MessageAgent;
}
agent.sendMessage(rconn.Connection, newMsg, defSearchCons.TimeLimit, queue, null);
}
catch (InterThreadException ex)
{
// Error ending request to referred server
LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_SEND, LdapException.CONNECT_ERROR, null, ex);
rex.setReferrals(initialReferrals);
ReferralInfo ref_Renamed = rconn.Connection.ActiveReferral;
rex.FailedReferral = ref_Renamed.ReferralUrl.ToString();
throw rex;
}
if (initialReferrals == null)
{
// For operation results, when all responses are complete,
// the stack unwinds back to the original and returns
// to the application.
// An exception is thrown for an error
connList = chaseReferral(queue, cons, null, null, hopCount, false, connList);
}
else
{
// For search, just return to LdapSearchResults object
return connList;
}
}
catch (System.Exception ex)
{
if (ex is LdapReferralException)
{
throw (LdapReferralException) ex;
}
else
{
// Set referral list and failed referral
LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_ERROR, ex);
rex.setReferrals(refs);
if (rinfo != null)
{
rex.FailedReferral = rinfo.ReferralUrl.ToString();
}
else
{
rex.FailedReferral = refs[refs.Length - 1];
}
throw rex;
}
}
return connList;
}