    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.net.finger;
    018
    019import java.io.BufferedReader;
    020import java.io.IOException;
    021import java.io.InputStream;
    022import java.io.InputStreamReader;
    023import java.io.BufferedOutputStream;
    024import java.io.DataOutputStream;
    025
    026import org.apache.commons.net.SocketClient;
    027import org.apache.commons.net.util.Charsets;
    028
    029/***
    030 * The FingerClient class implements the client side of the Internet Finger
    031 * Protocol defined in RFC 1288.  To finger a host you create a
    032 * FingerClient instance, connect to the host, query the host, and finally
    033 * disconnect from the host.  If the finger service you want to query is on
    034 * a non-standard port, connect to the host at that port.
    035 * Here's a sample use:
    036 * <pre>
    037 *    FingerClient finger;
    038 *
    039 *    finger = new FingerClient();
    040 *
    041 *    try {
    042 *      finger.connect("foo.bar.com");
    043 *      System.out.println(finger.query("foobar", false));
    044 *      finger.disconnect();
    045 *    } catch(IOException e) {
    046 *      System.err.println("Error I/O exception: " + e.getMessage());
    047 *      return;
    048 *    }
    049 * </pre>
    050 * <p>
    051 * <p>
    052 ***/
    053
    054public class FingerClient extends SocketClient
    055{
    056    /***
    057     * The default FINGER port.  Set to 79 according to RFC 1288.
    058     ***/
    059    public static final int DEFAULT_PORT = 79;
    060
    061    private static final String __LONG_FLAG = "/W ";
    062
    063    private transient char[] __buffer = new char[1024];
    064
    065    /***
    066     * The default FingerClient constructor.  Initializes the
    067     * default port to <code> DEFAULT_PORT </code>.
    068     ***/
    069    public FingerClient()
    070    {
    071        setDefaultPort(DEFAULT_PORT);
    072    }
    073
    074
    075    /***
    076     * Fingers a user at the connected host and returns the output
    077     * as a String.  You must first connect to a finger server before
    078     * calling this method, and you should disconnect afterward.
    079     * <p>
    080     * @param longOutput Set to true if long output is requested, false if not.
    081     * @param username  The name of the user to finger.
    082     * @return The result of the finger query.
    083     * @exception IOException If an I/O error occurs while reading the socket.
    084     ***/
    085    public String query(boolean longOutput, String username) throws IOException
    086    {
    087        int read;
    088        StringBuilder result = new StringBuilder(__buffer.length);
    089        BufferedReader input;
    090
    091        input =
    092            new BufferedReader(new InputStreamReader(getInputStream(longOutput,
    093                               username), getCharsetName())); // Java 1.6 can use getCharset()
    094
    095        try {
    096            while (true)
    097            {
    098                read = input.read(__buffer, 0, __buffer.length);
    099                if (read <= 0) {
    100                    break;
    101                }
    102                result.append(__buffer, 0, read);
    103            }
    104        } finally {
    105            input.close();
    106        }
    107
    108        return result.toString();
    109    }
    110
    111
    112    /***
    113     * Fingers the connected host and returns the output
    114     * as a String.  You must first connect to a finger server before
    115     * calling this method, and you should disconnect afterward.
    116     * This is equivalent to calling <code> query(longOutput, "") </code>.
    117     * <p>
    118     * @param longOutput Set to true if long output is requested, false if not.
    119     * @return The result of the finger query.
    120     * @exception IOException If an I/O error occurs while reading the socket.
    121     ***/
    122    public String query(boolean longOutput) throws IOException
    123    {
    124        return query(longOutput, "");
    125    }
    126
    127
    128    /***
    129     * Fingers a user and returns the input stream from the network connection
    130     * of the finger query.  You must first connect to a finger server before
    131     * calling this method, and you should disconnect after finishing reading
    132     * the stream.
    133     * <p>
    134     * @param longOutput Set to true if long output is requested, false if not.
    135     * @param username  The name of the user to finger.
    136     * @return The InputStream of the network connection of the finger query.
    137     *         Can be read to obtain finger results.
    138     * @exception IOException If an I/O error during the operation.
    139     ***/
    140    public InputStream getInputStream(boolean longOutput, String username)
    141    throws IOException
    142    {
    143        return getInputStream(longOutput, username, null);
    144    }
    145
    146    /***
    147     * Fingers a user and returns the input stream from the network connection
    148     * of the finger query.  You must first connect to a finger server before
    149     * calling this method, and you should disconnect after finishing reading
    150     * the stream.
    151     * <p>
    152     * @param longOutput Set to true if long output is requested, false if not.
    153     * @param username  The name of the user to finger.
    154     * @param encoding the character encoding that should be used for the query,
    155     *        null for the platform's default encoding
    156     * @return The InputStream of the network connection of the finger query.
    157     *         Can be read to obtain finger results.
    158     * @exception IOException If an I/O error during the operation.
    159     ***/
    160    public InputStream getInputStream(boolean longOutput, String username, String encoding)
    161    throws IOException
    162    {
    163        DataOutputStream output;
    164        StringBuilder buffer = new StringBuilder(64);
    165        if (longOutput) {
    166            buffer.append(__LONG_FLAG);
    167        }
    168        buffer.append(username);
    169        buffer.append(SocketClient.NETASCII_EOL);
    170
    171        // Note: Charsets.toCharset() returns the platform default for null input
    172        byte[] encodedQuery = buffer.toString().getBytes(Charsets.toCharset(encoding).name()); // Java 1.6 can use charset directly
    173
    174        output = new DataOutputStream(new BufferedOutputStream(_output_, 1024));
    175        output.write(encodedQuery, 0, encodedQuery.length);
    176        output.flush();
    177
    178        return _input_;
    179    }
    180
    181
    182    /***
    183     * Fingers the connected host and returns the input stream from
    184     * the network connection of the finger query.  This is equivalent to
    185     * calling getInputStream(longOutput, "").  You must first connect to a
    186     * finger server before calling this method, and you should disconnect
    187     * after finishing reading the stream.
    188     * <p>
    189     * @param longOutput Set to true if long output is requested, false if not.
    190     * @return The InputStream of the network connection of the finger query.
    191     *         Can be read to obtain finger results.
    192     * @exception IOException If an I/O error during the operation.
    193     ***/
    194    public InputStream getInputStream(boolean longOutput) throws IOException
    195    {
    196        return getInputStream(longOutput, "");
    197    }
    198
    199}