/*
 * @(#)DnsRequest.java
 *
 * Copyright (c) 2001-2002 JScape
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JScape. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JScape.
 */
package com.jscape.inet.dns;

import java.io.Serializable;
import java.util.StringTokenizer;


/**
 * Implements the basic functionality of a DNS request.
 * <p/>
 * Example Usage:<P>
 * <pre>
 * // create new instance
 * Dns dns = new Dns();
 *
 * // creates DNS request with nameserver and domain as arguments
 * DnsRequest request = new DnsRequest("ns.myserver.com","myserver.com");
 * // retrieve only MX (mail exchanger) records
 * request.setRecordType(Dns.TYPE_MX);
 *
 * // gets DNS response
 * DnsResponse response = dns.getResponse(request);
 *
 * // print out records for response to console
 *
 * Enumeration e = response.getAnswers();
 * while(e.hasMoreElements()) {
 *   DnsRecord record = (DnsRecord) e.nextElement();
 *   System.out.println(record);
 * }
 * </pre>
 */
public class DnsRequest
        implements Serializable {
    private static int globalId;
    private String nameserver;
    private int recordType = Dns.TYPE_ANY;
    private String domain;
    private int classType = Dns.CLASS_IN;
    private int queryId;
    private int timeout;

    /**
     * Constructs a new <code>DnsRequest</code> instance.
     *
     * @param nameserver the hostname or IP address of the DNS server
     * @param domain     the hostname or IP address to lookup
     */
    public DnsRequest(String nameserver, String domain) {
        this.queryId = (++globalId) % 65536;
        this.nameserver = nameserver;
        setDomain(domain);
    }

    /**
     * Constructs a new <code>DnsRequest</code> instance.
     * The constants for <code>recordType</code> are defind in Dns class.
     *
     * @param nameserver the hostname or IP address of the DNS server
     * @param domain     the hostname or IP address to lookup
     * @param recordType the type of records to retrieve
     *
     * @see Dns
     */
    public DnsRequest(String nameserver, String domain, int recordType) {
        this(nameserver, domain);
        this.recordType = recordType;
    }

    /**
     * Constructs a new <code>DnsRequest</code> instance
     * The constants for <code>recordType</code> and <code>classType</code> are defind in <code>Dns</code> class.
     *
     * @param nameserver the hostname or IP address of the DNS server
     * @param domain     the hostname or IP address to lookup
     * @param recordType the type of records to retrieve
     * @param classType  the class of records to retrieve
     *
     * @see Dns
     */
    public DnsRequest(String nameserver, String domain, int recordType,
                      int classType) {
        this(nameserver, domain, recordType);
        this.classType = classType;
    }

    /**
     * Gets nameserver used to perform this <code>DnsRequest</code>.
     *
     * @return nameserver
     */
    public String getNameserver() {
        return nameserver;
    }

    /**
     * Sets nameserver used to perform this <code>DnsRequest</code>.
     *
     * @param nameserver the nameserver used to perform this <code>DnsRequest</code>
     */
    public void setNameserver(String nameserver) {
        synchronized (this) {
            this.nameserver = nameserver;
        }
    }

    /**
     * Gets record type to retrieve for this <code>DnsRequest</code>.
     *
     * @return record type
     */
    public int getRecordType() {
        return recordType;
    }

    /**
     * Sets record type to retrieve for this <code>DnsRequest</code>.
     *
     * @param recordType the record type to retrieve for this <code>DnsRequest</code>
     */
    public void setRecordType(int recordType) {
        this.recordType = recordType;
    }

    /**
     * Gets class type to retrieve for this <code>DnsRequest</code>.
     *
     * @return class type
     */
    public int getClassType() {
        return classType;
    }

    /**
     * Sets class type to retrieve for this <code>DnsRequest</code>.
     *
     * @param classType the class type to retrieve for this <code>DnsRequest</code>
     */
    public void setClassType(int classType) {
        this.classType = classType;
    }

    /**
     * Gets hostname or IP address to lookup for this <code>DnsRequest</code>.
     *
     * @return domain
     */
    public String getDomain() {
        return domain;
    }

    /**
     * Sets hostname or IP address to lookup for this <code>DnsRequest</code>.
     *
     * @param domain the hostname or IP address to lookup for this <code>DnsRequest</code>
     */
    public void setDomain(String domain) {
        synchronized (this) {
            StringTokenizer str = new StringTokenizer(domain, ".");

            if (str.countTokens() == 4) {
                int[] octets = { 0, 0, 0, 0 };
                int i = 0;
                boolean reverse = true;

                while (str.hasMoreElements()) {
                    String octet = (String) str.nextElement();

                    try {
                        octets[i] = Integer.parseInt(octet);
                    } catch (Exception e) {
                        reverse = false;

                        break;
                    }

                    i++;
                }

                if (reverse) {
                    domain = "";

                    for (i = 3; i >= 0; i--) {
                        domain += octets[i];
                        domain += ".";
                    }

                    domain += "in-addr.arpa";
                }
            }
            this.domain = domain;
        }
    }

    /**
     * Gets query id for this <code>DnsRequest</code>.
     *
     * @return query id
     */
    public int getQueryId() {
        return queryId;
    }

    /**
     * Sets the timeout for opening connection to DNS server.
     *
     * @param timeout the timeout in milliseconds
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * Gets the timeout for opening connection to DNS server.
     *
     * @return timeout in milliseconds
     */
    public int getTimeout() {
        return timeout;
    }
}
