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


import com.jscape.inet.util.TimedSocket;

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


/**
 * Implements the basic functionality of a FINGER client.
 * <p/>
 * Example Usage:
 * <p/>
 * <pre>
 * Finger finger = new Finger();
 * finger.setHostname("myserver.com");
 *
 * try
 * {
 *   // attempts to lookup information about user jsmith on machine myserver.com
 *   String results = finger.query("jsmith");
 *   System.out.println(results);
 * }
 * catch(FingerException e)
 * {
 *   System.out.println(e);
 * }
 * </pre>
 */

public class Finger
        implements Serializable {
    private int port = 79; // port of finger server
    private int timeout; // timeout used in network connection
    private String hostname; // hostname of finger 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;

    /**
     * Constructs new Finger instance.
     */
    public Finger() {
        
    }

    /**
     * Constructs new Finger instance.
     *
     * @param hostname the hostname of FINGER server
     */
    public Finger(String hostname) {
        this();
        this.hostname = hostname;
    }

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

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

    /**
     * Sets hostname of FINGER server.
     *
     * @param hostname the hostname of FINGER server
     */
    public void setHostname(String hostname) {
        synchronized (this) {
            this.hostname = hostname;
        }
    }

    /**
     * Gets hostname of FINGER server.
     *
     * @return the hostname of FINGER server
     */
    public String getHostname() {
        return hostname;
    }

    /**
     * Sets the timeout for opening a FINGER 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 FINGER 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
     */
    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
     */
    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;
    }

    /**
     * Connects to finger server and performs finger query.
     *
     * @param user the user to query
     *
     * @return results of finger query
     *
     * @throws FingerException if a FINGER or I/O error occurs
     */
    public String query(String user)
            throws FingerException {
        String line = null;

        if (user == null) {
            user = "";
        }
        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(user + "\r\n");

                while ((line = bin.readLine()) != null) {
                    contents.append(line);
                    contents.append("\r\n");
                }
                socket.close();
            }
        } catch (IOException ioe) {
            throw new FingerException(ioe.getMessage(), ioe);
        }
        return contents.toString();
    }

} 

