in modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/Resolver.java [252:545]
public Enumeration<ResourceRecord> lookup(String name, int[] types,
int[] classes) throws SecurityException, NameNotFoundException,
ServiceUnavailableException, DomainProtocolException {
// Algorithm:
// 1. Set workZone to the parent of qName; clear queriedServers.
// 2. Try to get a complete answer for the workZone from the servers
// currently available in SLIST exclude servers from queriedServers.
// 3. update queriedServers with "visited servers" info.
// 4. If the complete answer was received - return it to the user;exit.
// 5. If the delegation was received:
// a) If we already have this server & zone pair in SLIST - skip it.
// b) If we don't have - put it into SLIST
// c) If we haven't received any new delegations - goto step (7)
// d) If some new delegation has been received:
// 1) from delegations: found the zone with the best matching count
// with qName
// 2) if this matching count is bigger than matching count between
// workZone and qName:
// - set workZone to zone with biggest matching count determined
// at step (5.d.1)
// - goto step (2)
// 3) if it doesn't then goto step 2 with the same workZone
// 6. If ALIAS was received ...
// 7. If no answer has been received:
// a) Check if the workZone is the root zone.
// b) If so - give up; return empty result to the user.
// c) If it isn't, set workZone to parent of workZone. Goto step (2).
// SList slist = SList.getInstance();
ResolverCache cache = ResolverCache.getInstance();
Vector<QuestionRecord> questions = new Vector<QuestionRecord>();
Vector<ResourceRecord> answers = new Vector<ResourceRecord>();
if (name == null) {
// jndi.2E=The name is null
throw new NullPointerException(Messages.getString("jndi.2E")); //$NON-NLS-1$
}
if (types == null) {
// jndi.6B=types is null
throw new NullPointerException(Messages.getString("jndi.6B")); //$NON-NLS-1$
}
if (classes == null) {
// jndi.6C=classes is null
throw new NullPointerException(Messages.getString("jndi.6C")); //$NON-NLS-1$
}
for (int element : classes) {
for (int element0 : types) {
QuestionRecord quest = new QuestionRecord(name, element0,
element);
questions.addElement(quest);
}
}
// iterate over question records
for (int i = 0; i < questions.size(); i++) {
QuestionRecord curQuestion = questions.elementAt(i);
String qName = curQuestion.getQName();
Message mesToSend = null;
Message receivedMes = null;
AnalysisReport report = null;
String workZone;
Hashtable<Server, Object> visitedServers = new Hashtable<Server, Object>();
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine("Current question: " +
// curQuestion.toString());
// }
// look in cache
if (curQuestion.getQType() != ProviderConstants.ANY_QTYPE
&& curQuestion.getQClass() != ProviderConstants.ANY_QCLASS) {
Enumeration<ResourceRecord> recEnum = cache.get(curQuestion);
if (recEnum.hasMoreElements()) {
while (recEnum.hasMoreElements()) {
answers.addElement(recEnum.nextElement());
}
// we don't need to query any servers since the information
// we want has been found in the local cache
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine(
// "Information was gathered from cache");
// }
continue;
}
}
// query remote DNS servers
// determine work zone
if (qName != null && !qName.equals(".")) { //$NON-NLS-1$
workZone = qName;
// support for SRV-style qNames
while (workZone.startsWith("_")) { //$NON-NLS-1$
workZone = ProviderMgr.getParentName(workZone);
}
} else {
workZone = "."; //$NON-NLS-1$
}
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine("Lookup: new workZone is " +
// "\"" + workZone + "\"");
// }
// construct request message
try {
mesToSend = createMessageForSending(qName, curQuestion
.getQType(), curQuestion.getQClass());
// if (LogConst.DEBUG) {
// ProviderMgr.logger.finest("Message to send:\n" +
// mesToSend.toString());
// }
} catch (DomainProtocolException e) {
throw e;
}
while (true) {
boolean noIdea = false;
try {
receivedMes = queryServers(mesToSend, workZone,
visitedServers, false);
if (receivedMes != null) {
report = analyzeAnswer(mesToSend, receivedMes);
if (!report.messageWasTruncated) {
// Put all extra records into the cache for
// future use
for (int k = 0; k < report.extraRecords.size(); k++) {
ResourceRecord rec = report.extraRecords
.elementAt(k);
cache.put(rec);
}
} else {
// Truncated message MUST NOT be cached and later
// used in such a way that the fact that they are
// truncated is lost (RFC 1123 point 6.1.3.2).
}
// examine the report
if (report.completeAnswerWasReceived) {
// complete answer
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine(
// "Lookup: a complete answer was received");
// }
for (int k = 0; k < report.records.size(); k++) {
ResourceRecord rec = report.records
.elementAt(k);
answers.addElement(rec);
// we are sure that the answer section has not
// been truncated so we can put the record
// into the cache
cache.put(rec);
}
// exit the loop
break;
} else if (report.nameError) {
// name error
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine("Lookup: name error");
// }
// jndi.6D=Name {0} was not found
throw new NameNotFoundException(Messages.getString(
"jndi.6D", name)); //$NON-NLS-1$
} else if (report.aliasInfoWasReceived) {
// alias received
// QuestionRecord newQuestion = new
// QuestionRecord();
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine(
// "Lookup: an alias was received");
// }
qName = report.newName;
curQuestion.setQName(qName);
// look in cache
if (curQuestion.getQType() != ProviderConstants.ANY_QTYPE
&& curQuestion.getQClass() != ProviderConstants.ANY_QCLASS) {
Enumeration<ResourceRecord> recEnum = cache
.get(curQuestion);
if (recEnum.hasMoreElements()) {
while (recEnum.hasMoreElements()) {
answers.addElement(recEnum
.nextElement());
}
// We don't need to query any more servers
// since the information we want has been
// found in the local cache.
// Let's switch to next question if any.
break;
}
}
if (qName != null && !qName.equals(".")) //$NON-NLS-1$
{
workZone = qName;
} else {
workZone = "."; //$NON-NLS-1$
}
visitedServers = new Hashtable<Server, Object>();
for (int k = 0; k < report.records.size(); k++) {
answers.addElement(report.records.elementAt(k));
}
// construct a new request message
try {
mesToSend = createMessageForSending(qName,
curQuestion.getQType(), curQuestion
.getQClass());
} catch (DomainProtocolException e) {
throw e;
}
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine("Lookup: new name is " +
// "\"" + qName + "\"");
// ProviderMgr.logger.fine(
// "Lookup: new workZone is " +
// "\"" + workZone + "\"");
// }
} else if (report.delegationArrived) {
// new delegation, probably need to query once again
int k17 = -1;
int matchingCount = ProviderMgr.getMatchingCount(
qName, workZone);
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine(
// "Lookup: delegation arrived");
// }
for (int k = 0; k < report.delegationZones.size(); k++) {
String curZone = report.delegationZones
.elementAt(k);
int tmpMatchingCount = ProviderMgr
.getMatchingCount(qName, curZone);
if (tmpMatchingCount > matchingCount) {
k17 = k;
matchingCount = tmpMatchingCount;
}
}
if (k17 != -1) {
// better delegation was received
workZone = report.delegationZones
.elementAt(k17);
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine(
// "Lookup: better delegation was found");
// }
} else {
// no better delegation
// do nothing, just query the next server of
// the current workZone
}
} else {
noIdea = true;
}
} // end of if report != null block
else {
noIdea = true;
}
if (noIdea) {
// Resolver has no idea how to get info about
// desired host while querying master hosts of the
// current workZone.
// Let's make one step up to the root.
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine("Lookup: no idea");
// }
if (!workZone.equals(".")) { //$NON-NLS-1$
workZone = ProviderMgr.getParentName(workZone);
// if (LogConst.DEBUG) {
// ProviderMgr.logger.fine(
// "Lookup: new work zone is " +
// "\"" + workZone + "\"");
// }
} else {
// give up
break;
// throw new ServiceUnavailableException(
// "Unable to " +
// "contact authoritative server for " +
// qName +
// " and no other results were found");
}
}
} catch (NameNotFoundException e) {
throw e;
} catch (DomainProtocolException e) {
throw e;
}
} // query servers loop
} // questions loop
return answers.elements();
}