/*
 * Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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;
    }
}
