public Enumeration list()

in modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/Resolver.java [562:757]


    public Enumeration<ResourceRecord> list(String name) throws NamingException {
        final int OUT_BUF_SIZE = 512;
        final int IN_BUF_SIZE = 65536;

        Vector<ResourceRecord> answerVect = new Vector<ResourceRecord>();
        Message mesToSend = null;
        Message receivedMes = null;
        Enumeration<ResourceRecord> enum1;
        // String zoneMasterServer = null;
        // Vector authoritativeServerIPs = new Vector();
        HashSet<Object> authoritativeServers = new HashSet<Object>();
        Iterator<Object> authServersIter;
        int qClassArr[] = new int[1];
        byte outBuf[] = new byte[OUT_BUF_SIZE];
        int outLen;
        byte inBuf[] = new byte[IN_BUF_SIZE];
        boolean received = false;
        boolean completeAnswer = false;
        String proto = null;

        ResolverCache cache = ResolverCache.getInstance();
        // SList slist = SList.getInstance();

        if (name == null) {
            // jndi.2E=The name is null
            throw new NullPointerException(Messages.getString("jndi.2E")); //$NON-NLS-1$
        }
        // if given name is SRV style name where domain name is prefixed
        // with _Proto
        if (name.startsWith("_")) { //$NON-NLS-1$
            int n = name.indexOf('.');

            if (n != -1) {
                proto = name.substring(0, n);
                if (name.length() > n) {
                    name = name.substring(n + 1, name.length());
                } else {
                    // nonsense
                    name = "."; //$NON-NLS-1$
                }
            } else {
                // nonsense
                name = "."; //$NON-NLS-1$
            }
        }
        enum1 = lookup(name, new int[] { ProviderConstants.NS_TYPE },
                new int[] { ProviderConstants.ANY_QTYPE });
        mesToSend = createMessageForSending(name, ProviderConstants.AXFR_QTYPE,
                ProviderConstants.ANY_QCLASS);
        outLen = mesToSend.writeBytes(outBuf, 0);
        // determine the list of zone authoritative servers
        while (enum1.hasMoreElements()) {
            ResourceRecord rr = enum1.nextElement();

            if (rr.getRRType() == ProviderConstants.NS_TYPE) {
                authoritativeServers.add(rr.getRData());
                // assertion: all authoritative servers should have the same
                // DNS class
                qClassArr[0] = rr.getRRClass();
            } else if (rr.getRRType() == ProviderConstants.SOA_TYPE) {
                StringTokenizer st = new StringTokenizer(
                        (String) rr.getRData(), " "); //$NON-NLS-1$

                if (st.hasMoreTokens()) {
                    authoritativeServers.add(st.nextToken());
                    qClassArr[0] = rr.getRRClass();
                    break;
                }
            }
        }
        // try to perform a zone transfer
        authServersIter = authoritativeServers.iterator();
        authServersLoop: while (authServersIter.hasNext()) {
            String authServerName = (String) authServersIter.next();
            Enumeration<ResourceRecord> addrEnum = lookup(authServerName,
                    new int[] { ProviderConstants.A_TYPE }, qClassArr);

            while (addrEnum.hasMoreElements()) {
                ResourceRecord curRR = addrEnum.nextElement();
                String ip = (String) curRR.getRData();

                try {
                    // if (LogConst.DEBUG) {
                    // ProviderMgr.logger.fine(
                    // "Initiating zone transfer, IP=" + ip);
                    // }
                    TransportMgr.sendReceiveTCP(ip,
                            ProviderConstants.DEFAULT_DNS_PORT, outBuf, outLen,
                            inBuf, IN_BUF_SIZE, this.initialTimeout
                                    * this.timeoutRetries);
                    received = true;
                } catch (SocketTimeoutException e) {

                    // if (LogConst.DEBUG) {
                    // ProviderMgr.logger.fine("Socket timeout");
                    // }
                } catch (DomainProtocolException e) {
                    // some problem was encountered
                    // ProviderMgr.logger.log(Level.WARNING,
                    // "Connection failure", e);
                }
                if (received) {
                    receivedMes = new Message();
                    try {
                        int rCode;

                        Message.parseMessage(inBuf, 0, receivedMes);
                        rCode = receivedMes.getRCode();
                        switch (rCode) {
                            case ProviderConstants.NO_ERROR:
                                // put all received records into Resolver's
                                // cache
                                for (int k = 0; k < 3; k++) {
                                    switch (k) {
                                        case 0:
                                            enum1 = receivedMes.getAnswerRRs();
                                            break;
                                        case 1:
                                            enum1 = receivedMes
                                                    .getAuthorityRRs();
                                            break;
                                        case 2:
                                            enum1 = receivedMes
                                                    .getAdditionalRRs();
                                            break;
                                    }
                                    while (enum1.hasMoreElements()) {
                                        ResourceRecord rr = enum1.nextElement();

                                        cache.put(rr);
                                        if (k == 0) {
                                            answerVect.addElement(rr);
                                        }
                                    }
                                }
                                completeAnswer = true;
                                break;
                            case ProviderConstants.NAME_ERROR:
                                // jndi.6D=Name {0} was not found
                                throw new NameNotFoundException(Messages
                                        .getString("jndi.6D", name)); //$NON-NLS-1$
                            case ProviderConstants.SERVER_FAILURE:
                            case ProviderConstants.FORMAT_ERROR:
                            case ProviderConstants.NOT_IMPLEMENTED:
                            case ProviderConstants.REFUSED:
                            default:
                        }
                    } catch (DomainProtocolException e) {
                        // ProviderMgr.logger.log(Level.WARNING,
                        // "Error while parsing of DNS message", e);
                    }
                } // if received
                if (completeAnswer) {
                    // if (LogConst.DEBUG) {
                    // ProviderMgr.logger.fine(
                    // "list: Complete answer received");
                    // }
                    break authServersLoop;
                }
            } // address loop
        } // authoritative servers loop

        if (!completeAnswer) {
            // found nothing
            // jndi.6E=Unable to perform zone transfer
            throw new ServiceUnavailableException(Messages.getString("jndi.6E")); //$NON-NLS-1$
        }
        // SRV _Proto prefix support - filter all records that don't have given
        // _Proto field
        if (proto != null) {
            Vector<ResourceRecord> answerVect2 = new Vector<ResourceRecord>();

            for (int i = 0; i < answerVect.size(); i++) {
                ResourceRecord rr = answerVect.elementAt(i);
                StringTokenizer st = new StringTokenizer(rr.getName(), "."); //$NON-NLS-1$
                String token = null;
                boolean valid = false;

                if (st.hasMoreTokens()) {
                    token = st.nextToken();
                    if (token.length() > 0 && token.charAt(0) == '_'
                            && st.hasMoreTokens()) {
                        token = st.nextToken();
                        if (token.equalsIgnoreCase(proto)) {
                            valid = true;
                        }
                    }
                }
                if (valid) {
                    answerVect2.addElement(rr);
                }
            }
            answerVect = answerVect2;
        }
        return answerVect.elements();
    }