/*
 * @(#)Whois.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.whois;

import com.jscape.inet.util.TimedSocket;

import java.io.*;
import java.net.Socket;


/**
 * Implements the basic functionality of a Whois client.
 * <P>
 * Example Usage:
 * <P>
 * <pre>
 * Whois whois = new Whois();
 *  try
 * {
 *   // attempts to lookup information about domain myserver.com
 *   String results = whois.query("myserver.com");
 *   System.out.println(results);
 * }
 * catch(WhoisException e)
 * {
 *   System.out.println(e);
 * }
 * </pre>
 * </p>
 */
public class Whois
        implements Serializable {

    private int port = 43; // port of whois server
    private int timeout; // timeout used in network connection
    private String hostname = "whois.networksolutions.com"; // hostname of whois server
    private transient Socket socket; // socket for connection to server

    private static final int DEFAULT_PROXY_PORT = 1080;
    private static final String DEFAULT_PROXY_TYPE = "SOCKS5";
    private String proxyHostname = null;
    private int proxyPort = DEFAULT_PROXY_PORT;
    private String proxyUsername = null;
    private String proxyPassword = null;
    private String proxyType = DEFAULT_PROXY_TYPE;

    /**
     * Creates a new Whois instance.
     */
    public Whois() {
        
    }

    /**
     * Creates a new Whois instance with hostname of whois server as argument.
     * Default whois server hostname is whois.networksolutions.com
     *
     * @param hostname the hostname of whois server
     */
    public Whois(String hostname) {
        this();
        this.hostname = hostname;
    }

    /**
     * Sets port of Whois server. Default value is 43.
     *
     * @param port the port of Whois server
     */
    public void setPort(int port) {
        this.port = port;
    }

    /**
     * Gets port of Whois server. Default value is 43.
     *
     * @return port
     */
    public int getPort() {
        return port;
    }

    /**
     * Sets hostname of Whois server. Default value is
     * whois.networksolutions.com
     *
     * @param str the hostname of Whois server
     */
    public void setHostname(String str) {
        synchronized (this) {
            this.hostname = str;
        }
    }

    /**
     * Gets hostname of Whois server. Default value is
     * whois.networksolutions.com
     *
     * @return hostname
     */
    public String getHostname() {
        return hostname;
    }

    /**
     * Sets the timeout for opening a Whois connection. Default of 0ms uses
     * natural timeout of socket.
     *
     * @param timeout in milliseconds
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * Gets the timeout for opening a Whois connection. Default of 0ms uses
     * natural timeout of socket.
     *
     * @return timeout in milliseconds
     */
    public int getTimeout() {
        return timeout;
    }

    /**
     * Sets the username and password to use when for authentication with
     * proxy server.
     * To clear these settings invoke the <code>#clearProxySettings</code> method.
     *
     * @param proxyUsername the proxy username
     * @param proxyPassword the proxy password
     *
     * @see #clearProxySettings
     */
    public void setProxyAuthentication(String proxyUsername,
                                       String proxyPassword) {
        this.proxyUsername = proxyUsername;
        this.proxyPassword = proxyPassword;
    }

    // PROXY CONTROL

    /**
     * Sets the proxy hostname and port for this connection.
     * To clear these settings invoke the <code>#clearProxySettings</code> method.
     *
     * @param proxyHostname the hostname or ip address of the proxy server
     * @param proxyPort     the port of the proxy server
     *
     * @see #clearProxySettings
     */
    public void setProxyHost(String proxyHostname, int proxyPort) {
        this.proxyHostname = proxyHostname;
        this.proxyPort = proxyPort;
    }

    /**
     * Sets the proxy type will be used for this connection.
     *
     * @param proxyType The proxy type. Valid values: HTTP, SOCKS5
     */
    public void setProxyType(String proxyType) {
        this.proxyType = proxyType;
    }

    /**
     * Clears proxy server values.
     */
    public void clearProxySettings() {
        setProxyAuthentication(null, null);
        setProxyHost(null, DEFAULT_PROXY_PORT);
        setProxyType(DEFAULT_PROXY_TYPE);
    }

    /**
     * Connects to Whois server and performs Whois query.
     *
     * @param command the domain or command to query
     *
     * @return results of Whois query
     *
     * @throws WhoisException if a Whois or I/O error occurs
     */
    public String query(String command)
            throws WhoisException {
        String line = null;
        StringBuffer contents = new StringBuffer();

        try {
            synchronized (this) {
                if (this.proxyHostname == null) {
                    socket = TimedSocket.getSocket(hostname, port, timeout);
                } else {
                    socket = TimedSocket.getSocket(hostname, port, timeout,
                                                   this.proxyHostname, this.proxyPort, this.proxyUsername,
                                                   this.proxyPassword, this.proxyType);
                }

                PrintStream ps = new PrintStream(socket.getOutputStream());
                BufferedReader bin = new BufferedReader(new InputStreamReader(
                        socket.getInputStream()));

                ps.print(command + "\r\n");

                while ((line = bin.readLine()) != null) {
                    contents.append(line);
                    contents.append("\r\n");
                }

                socket.close();
            }
        } catch (IOException ioe) {
            throw new WhoisException(ioe.getMessage(), ioe);
        }

        return contents.toString();
    }
}
