/*
 * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jndi.dns;


import javax.naming.*;


/**
 * The Resolver class performs DNS client operations in support of DnsContext.
 *
 * <p> Every DnsName instance passed to or returned from a method of
 * this class should be fully-qualified and contain a root label (an
 * empty component at position 0).
 *
 * @author Scott Seligman
 */

class Resolver {

    private DnsClient dnsClient;
    private int timeout;                // initial timeout on UDP queries in ms
    private int retries;                // number of UDP retries


    /*
     * Constructs a new Resolver given its servers and timeout parameters.
     * Each server is of the form "server[:port]".
     * IPv6 literal host names include delimiting brackets.
     * There must be at least one server.
     * "timeout" is the initial timeout interval (in ms) for UDP queries,
     * and "retries" gives the number of retries per server.
     */
    Resolver(String[] servers, int timeout, int retries)
            throws NamingException {
        this.timeout = timeout;
        this.retries = retries;
        dnsClient = new DnsClient(servers, timeout, retries);
    }

    public void close() {
        dnsClient.close();
        dnsClient = null;
    }


    /*
     * Queries resource records of a particular class and type for a
     * given domain name.
     * Useful values of rrclass are ResourceRecord.[Q]CLASS_xxx.
     * Useful values of rrtype are ResourceRecord.[Q]TYPE_xxx.
     * If recursion is true, recursion is requested on the query.
     * If auth is true, only authoritative responses are accepted.
     */
    ResourceRecords query(DnsName fqdn, int rrclass, int rrtype,
                          boolean recursion, boolean auth)
            throws NamingException {
        return dnsClient.query(fqdn, rrclass, rrtype, recursion, auth);
    }

    /*
     * Queries all resource records of a zone given its domain name and class.
     * If recursion is true, recursion is requested on the query to find
     * the name server (and also on the zone transfer, but it won't matter).
     */
    ResourceRecords queryZone(DnsName zone, int rrclass, boolean recursion)
            throws NamingException {

        DnsClient cl =
            new DnsClient(findNameServers(zone, recursion), timeout, retries);
        try {
            return cl.queryZone(zone, rrclass, recursion);
        } finally {
            cl.close();
        }
    }

    /*
     * Finds the zone of a given domain name.  The method is to look
     * for the first SOA record on the path from the given domain to
     * the root.  This search may be partially bypassed if the zone's
     * SOA record is received in the authority section of a response.
     * If recursion is true, recursion is requested on any queries.
     */
    DnsName findZoneName(DnsName fqdn, int rrclass, boolean recursion)
            throws NamingException {

        fqdn = (DnsName) fqdn.clone();
        while (fqdn.size() > 1) {       // while below root
            ResourceRecords rrs = null;
            try {
                rrs = query(fqdn, rrclass, ResourceRecord.TYPE_SOA,
                            recursion, false);
            } catch (NameNotFoundException e) {
                throw e;
            } catch (NamingException e) {
                // Ignore error and keep searching up the tree.
            }
            if (rrs != null) {
                if (rrs.answer.size() > 0) {    // found zone's SOA
                    return fqdn;
                }
                // Look for an SOA record giving the zone's top node.
                for (int i = 0; i < rrs.authority.size(); i++) {
                    ResourceRecord rr = (ResourceRecord)
                        rrs.authority.elementAt(i);
                    if (rr.getType() == ResourceRecord.TYPE_SOA) {
                        DnsName zone = rr.getName();
                        if (fqdn.endsWith(zone)) {
                            return zone;
                        }
                    }
                }
            }
            fqdn.remove(fqdn.size() - 1);       // one step rootward
        }
        return fqdn;                    // no SOA found below root, so
                                        // return root
    }

    /*
     * Finds a zone's SOA record.  Returns null if no SOA is found (in
     * which case "zone" is not actually a zone).
     * If recursion is true, recursion is requested on the query.
     */
     ResourceRecord findSoa(DnsName zone, int rrclass, boolean recursion)
            throws NamingException {

        ResourceRecords rrs = query(zone, rrclass, ResourceRecord.TYPE_SOA,
                                    recursion, false);
        for (int i = 0; i < rrs.answer.size(); i++) {
            ResourceRecord rr = (ResourceRecord) rrs.answer.elementAt(i);
            if (rr.getType() == ResourceRecord.TYPE_SOA) {
                return rr;
            }
        }
        return null;
    }

    /*
     * Finds the name servers of a zone.  <tt>zone</tt> is a fully-qualified
     * domain name at the top of a zone.
     * If recursion is true, recursion is requested on the query.
     */
    private String[] findNameServers(DnsName zone, boolean recursion)
            throws NamingException {

        // %%% As an optimization, could look in authority section of
        // findZoneName() response first.
        ResourceRecords rrs =
            query(zone, ResourceRecord.CLASS_INTERNET, ResourceRecord.TYPE_NS,
                  recursion, false);
        String[] ns = new String[rrs.answer.size()];
        for (int i = 0; i < ns.length; i++) {
            ResourceRecord rr = (ResourceRecord)
                rrs.answer.elementAt(i);
            if (rr.getType() != ResourceRecord.TYPE_NS) {
                throw new CommunicationException("Corrupted DNS message");
            }
            ns[i] = (String) rr.getRdata();

            // Server name will be passed to InetAddress.getByName(), which
            // may not be able to handle a trailing dot.
            // assert ns[i].endsWith(".");
            ns[i] = ns[i].substring(0, ns[i].length() - 1);
        }
        return ns;
    }
}
