public Enumeration lookup()

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();
    }