    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 */
    017
    018package org.apache.commons.net.nntp;
    019
    020import java.io.BufferedReader;
    021import java.io.BufferedWriter;
    022import java.io.IOException;
    023import java.io.InputStreamReader;
    024import java.io.OutputStreamWriter;
    025
    026import org.apache.commons.net.MalformedServerReplyException;
    027import org.apache.commons.net.ProtocolCommandSupport;
    028import org.apache.commons.net.SocketClient;
    029import org.apache.commons.net.io.CRLFLineReader;
    030
    031/***
    032 * The NNTP class is not meant to be used by itself and is provided
    033 * only so that you may easily implement your own NNTP client if
    034 * you so desire.  If you have no need to perform your own implementation,
    035 * you should use {@link org.apache.commons.net.nntp.NNTPClient}.
    036 * The NNTP class is made public to provide access to various NNTP constants
    037 * and to make it easier for adventurous programmers (or those with special
    038 * needs) to interact with the NNTP protocol and implement their own clients.
    039 * A set of methods with names corresponding to the NNTP command names are
    040 * provided to facilitate this interaction.
    041 * <p>
    042 * You should keep in mind that the NNTP server may choose to prematurely
    043 * close a connection if the client has been idle for longer than a
    044 * given time period or if the server is being shutdown by the operator or
    045 * some other reason.  The NNTP class will detect a
    046 * premature NNTP server connection closing when it receives a
    047 * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
    048 *  response to a command.
    049 * When that occurs, the NNTP class method encountering that reply will throw
    050 * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
    051 * .
    052 * <code>NNTPConectionClosedException</code>
    053 * is a subclass of <code> IOException </code> and therefore need not be
    054 * caught separately, but if you are going to catch it separately, its
    055 * catch block must appear before the more general <code> IOException </code>
    056 * catch block.  When you encounter an
    057 * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
    058 * , you must disconnect the connection with
    059 * {@link #disconnect  disconnect() } to properly clean up the
    060 * system resources used by NNTP.  Before disconnecting, you may check the
    061 * last reply code and text with
    062 * {@link #getReplyCode  getReplyCode } and
    063 * {@link #getReplyString  getReplyString }.
    064 * <p>
    065 * Rather than list it separately for each method, we mention here that
    066 * every method communicating with the server and throwing an IOException
    067 * can also throw a
    068 * {@link org.apache.commons.net.MalformedServerReplyException}
    069 * , which is a subclass
    070 * of IOException.  A MalformedServerReplyException will be thrown when
    071 * the reply received from the server deviates enough from the protocol
    072 * specification that it cannot be interpreted in a useful manner despite
    073 * attempts to be as lenient as possible.
    074 * <p>
    075 * <p>
    076 * @author Rory Winston
    077 * @author Ted Wise
    078 * @see NNTPClient
    079 * @see NNTPConnectionClosedException
    080 * @see org.apache.commons.net.MalformedServerReplyException
    081 ***/
    082
    083public class NNTP extends SocketClient
    084{
    085    /*** The default NNTP port.  Its value is 119 according to RFC 977. ***/
    086    public static final int DEFAULT_PORT = 119;
    087
    088    // We have to ensure that the protocol communication is in ASCII
    089    // but we use ISO-8859-1 just in case 8-bit characters cross
    090    // the wire.
    091    private static final String __DEFAULT_ENCODING = "ISO-8859-1";
    092
    093    boolean _isAllowedToPost;
    094    int _replyCode;
    095    String _replyString;
    096
    097    /**
    098     * Wraps {@link SocketClient#_input_}
    099     * to communicate with server.  Initialized by {@link #_connectAction_}.
    100     * All server reads should be done through this variable.
    101     */
    102    protected BufferedReader _reader_;
    103
    104    /**
    105     * Wraps {@link SocketClient#_output_}
    106     * to communicate with server.  Initialized by {@link #_connectAction_}.
    107     * All server reads should be done through this variable.
    108     */
    109    protected BufferedWriter _writer_;
    110
    111    /**
    112     * A ProtocolCommandSupport object used to manage the registering of
    113     * ProtocolCommandListeners and te firing of ProtocolCommandEvents.
    114     */
    115    protected ProtocolCommandSupport _commandSupport_;
    116
    117    /***
    118     * The default NNTP constructor.  Sets the default port to
    119     * <code>DEFAULT_PORT</code> and initializes internal data structures
    120     * for saving NNTP reply information.
    121     ***/
    122    public NNTP()
    123    {
    124        setDefaultPort(DEFAULT_PORT);
    125        _replyString = null;
    126        _reader_ = null;
    127        _writer_ = null;
    128        _isAllowedToPost = false;
    129        _commandSupport_ = new ProtocolCommandSupport(this);
    130    }
    131
    132    private void __getReply() throws IOException
    133    {
    134        _replyString = _reader_.readLine();
    135
    136        if (_replyString == null) {
    137            throw new NNTPConnectionClosedException(
    138                    "Connection closed without indication.");
    139        }
    140
    141        // In case we run into an anomaly we don't want fatal index exceptions
    142        // to be thrown.
    143        if (_replyString.length() < 3) {
    144            throw new MalformedServerReplyException(
    145                "Truncated server reply: " + _replyString);
    146        }
    147
    148        try
    149        {
    150            _replyCode = Integer.parseInt(_replyString.substring(0, 3));
    151        }
    152        catch (NumberFormatException e)
    153        {
    154            throw new MalformedServerReplyException(
    155                "Could not parse response code.\nServer Reply: " + _replyString);
    156        }
    157
    158        fireReplyReceived(_replyCode, _replyString + SocketClient.NETASCII_EOL);
    159
    160        if (_replyCode == NNTPReply.SERVICE_DISCONTINUED) {
    161            throw new NNTPConnectionClosedException(
    162                "NNTP response 400 received.  Server closed connection.");
    163        }
    164    }
    165
    166    /***
    167     * Initiates control connections and gets initial reply, determining
    168     * if the client is allowed to post to the server.  Initializes
    169     * {@link #_reader_} and {@link #_writer_} to wrap
    170     * {@link SocketClient#_input_} and {@link SocketClient#_output_}.
    171     ***/
    172    @Override
    173    protected void _connectAction_() throws IOException
    174    {
    175        super._connectAction_();
    176        _reader_ =
    177            new CRLFLineReader(new InputStreamReader(_input_,
    178                                                     __DEFAULT_ENCODING));
    179        _writer_ =
    180            new BufferedWriter(new OutputStreamWriter(_output_,
    181                                                      __DEFAULT_ENCODING));
    182        __getReply();
    183
    184        _isAllowedToPost = (_replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED);
    185    }
    186
    187    /***
    188     * Closes the connection to the NNTP server and sets to null
    189     * some internal data so that the memory may be reclaimed by the
    190     * garbage collector.  The reply text and code information from the
    191     * last command is voided so that the memory it used may be reclaimed.
    192     * <p>
    193     * @exception IOException If an error occurs while disconnecting.
    194     ***/
    195    @Override
    196    public void disconnect() throws IOException
    197    {
    198        super.disconnect();
    199        _reader_ = null;
    200        _writer_ = null;
    201        _replyString = null;
    202        _isAllowedToPost = false;
    203    }
    204
    205
    206    /***
    207     * Indicates whether or not the client is allowed to post articles to
    208     * the server it is currently connected to.
    209     * <p>
    210     * @return True if the client can post articles to the server, false
    211     *         otherwise.
    212     ***/
    213    public boolean isAllowedToPost()
    214    {
    215        return _isAllowedToPost;
    216    }
    217
    218
    219    /***
    220     * Sends an NNTP command to the server, waits for a reply and returns the
    221     * numerical response code.  After invocation, for more detailed
    222     * information, the actual reply text can be accessed by calling
    223     * {@link #getReplyString  getReplyString }.
    224     * <p>
    225     * @param command  The text representation of the  NNTP command to send.
    226     * @param args The arguments to the NNTP command.  If this parameter is
    227     *             set to null, then the command is sent with no argument.
    228     * @return The integer value of the NNTP reply code returned by the server
    229     *         in response to the command.
    230     * @exception NNTPConnectionClosedException
    231     *      If the NNTP server prematurely closes the connection as a result
    232     *      of the client being idle or some other reason causing the server
    233     *      to send NNTP reply code 400.  This exception may be caught either
    234     *      as an IOException or independently as itself.
    235     * @exception IOException  If an I/O error occurs while either sending the
    236     *      command or receiving the server reply.
    237     ***/
    238    public int sendCommand(String command, String args) throws IOException
    239    {
    240        StringBuilder __commandBuffer = new StringBuilder();
    241        __commandBuffer.append(command);
    242
    243        if (args != null)
    244        {
    245            __commandBuffer.append(' ');
    246            __commandBuffer.append(args);
    247        }
    248        __commandBuffer.append(SocketClient.NETASCII_EOL);
    249
    250        String message;
    251        _writer_.write(message = __commandBuffer.toString());
    252        _writer_.flush();
    253
    254        fireCommandSent(command, message);
    255
    256        __getReply();
    257        return _replyCode;
    258    }
    259
    260
    261    /***
    262     * Sends an NNTP command to the server, waits for a reply and returns the
    263     * numerical response code.  After invocation, for more detailed
    264     * information, the actual reply text can be accessed by calling
    265     * {@link #getReplyString  getReplyString }.
    266     * <p>
    267     * @param command  The NNTPCommand constant corresponding to the NNTP command
    268     *                 to send.
    269     * @param args The arguments to the NNTP command.  If this parameter is
    270     *             set to null, then the command is sent with no argument.
    271     * @return The integer value of the NNTP reply code returned by the server
    272     *         in response to the command.
    273     *         in response to the command.
    274     * @exception NNTPConnectionClosedException
    275     *      If the NNTP server prematurely closes the connection as a result
    276     *      of the client being idle or some other reason causing the server
    277     *      to send NNTP reply code 400.  This exception may be caught either
    278     *      as an IOException or independently as itself.
    279     * @exception IOException  If an I/O error occurs while either sending the
    280     *      command or receiving the server reply.
    281     ***/
    282    public int sendCommand(int command, String args) throws IOException
    283    {
    284        return sendCommand(NNTPCommand.getCommand(command), args);
    285    }
    286
    287
    288    /***
    289     * Sends an NNTP command with no arguments to the server, waits for a
    290     * reply and returns the numerical response code.  After invocation, for
    291     * more detailed information, the actual reply text can be accessed by
    292     * calling {@link #getReplyString  getReplyString }.
    293     * <p>
    294     * @param command  The text representation of the  NNTP command to send.
    295     * @return The integer value of the NNTP reply code returned by the server
    296     *         in response to the command.
    297     *         in response to the command.
    298     * @exception NNTPConnectionClosedException
    299     *      If the NNTP server prematurely closes the connection as a result
    300     *      of the client being idle or some other reason causing the server
    301     *      to send NNTP reply code 400.  This exception may be caught either
    302     *      as an IOException or independently as itself.
    303     * @exception IOException  If an I/O error occurs while either sending the
    304     *      command or receiving the server reply.
    305     ***/
    306    public int sendCommand(String command) throws IOException
    307    {
    308        return sendCommand(command, null);
    309    }
    310
    311
    312    /***
    313     * Sends an NNTP command with no arguments to the server, waits for a
    314     * reply and returns the numerical response code.  After invocation, for
    315     * more detailed information, the actual reply text can be accessed by
    316     * calling {@link #getReplyString  getReplyString }.
    317     * <p>
    318     * @param command  The NNTPCommand constant corresponding to the NNTP command
    319     *                 to send.
    320     * @return The integer value of the NNTP reply code returned by the server
    321     *         in response to the command.
    322     *         in response to the command.
    323     * @exception NNTPConnectionClosedException
    324     *      If the NNTP server prematurely closes the connection as a result
    325     *      of the client being idle or some other reason causing the server
    326     *      to send NNTP reply code 400.  This exception may be caught either
    327     *      as an IOException or independently as itself.
    328     * @exception IOException  If an I/O error occurs while either sending the
    329     *      command or receiving the server reply.
    330     ***/
    331    public int sendCommand(int command) throws IOException
    332    {
    333        return sendCommand(command, null);
    334    }
    335
    336
    337    /***
    338     * Returns the integer value of the reply code of the last NNTP reply.
    339     * You will usually only use this method after you connect to the
    340     * NNTP server to check that the connection was successful since
    341     * <code> connect </code> is of type void.
    342     * <p>
    343     * @return The integer value of the reply code of the last NNTP reply.
    344     ***/
    345    public int getReplyCode()
    346    {
    347        return _replyCode;
    348    }
    349
    350    /***
    351     * Fetches a reply from the NNTP server and returns the integer reply
    352     * code.  After calling this method, the actual reply text can be accessed
    353     * from {@link #getReplyString  getReplyString }.  Only use this
    354     * method if you are implementing your own NNTP client or if you need to
    355     * fetch a secondary response from the NNTP server.
    356     * <p>
    357     * @return The integer value of the reply code of the fetched NNTP reply.
    358     *         in response to the command.
    359     * @exception NNTPConnectionClosedException
    360     *      If the NNTP server prematurely closes the connection as a result
    361     *      of the client being idle or some other reason causing the server
    362     *      to send NNTP reply code 400.  This exception may be caught either
    363     *      as an IOException or independently as itself.
    364     * @exception IOException  If an I/O error occurs while
    365     *      receiving the server reply.
    366     ***/
    367    public int getReply() throws IOException
    368    {
    369        __getReply();
    370        return _replyCode;
    371    }
    372
    373
    374    /***
    375     * Returns the entire text of the last NNTP server response exactly
    376     * as it was received, not including the end of line marker.
    377     * <p>
    378     * @return The entire text from the last NNTP response as a String.
    379     ***/
    380    public String getReplyString()
    381    {
    382        return _replyString;
    383    }
    384
    385
    386    /***
    387     * A convenience method to send the NNTP ARTICLE command to the server,
    388     * receive the initial reply, and return the reply code.
    389     * <p>
    390     * @param messageId  The message identifier of the requested article,
    391     *                   including the encapsulating &lt and &gt characters.
    392     * @return The reply code received from the server.
    393     * @exception NNTPConnectionClosedException
    394     *      If the NNTP server prematurely closes the connection as a result
    395     *      of the client being idle or some other reason causing the server
    396     *      to send NNTP reply code 400.  This exception may be caught either
    397     *      as an IOException or independently as itself.
    398     * @exception IOException  If an I/O error occurs while either sending the
    399     *      command or receiving the server reply.
    400     ***/
    401    public int article(String messageId) throws IOException
    402    {
    403        return sendCommand(NNTPCommand.ARTICLE, messageId);
    404    }
    405
    406    /***
    407     * A convenience method to send the NNTP ARTICLE command to the server,
    408     * receive the initial reply, and return the reply code.
    409     * <p>
    410     * @param articleNumber The number of the article to request from the
    411     *                      currently selected newsgroup.
    412     * @return The reply code received from the server.
    413     * @exception NNTPConnectionClosedException
    414     *      If the NNTP server prematurely closes the connection as a result
    415     *      of the client being idle or some other reason causing the server
    416     *      to send NNTP reply code 400.  This exception may be caught either
    417     *      as an IOException or independently as itself.
    418     * @exception IOException  If an I/O error occurs while either sending the
    419     *      command or receiving the server reply.
    420     ***/
    421    public int article(long articleNumber) throws IOException
    422    {
    423        return sendCommand(NNTPCommand.ARTICLE, Long.toString(articleNumber));
    424    }
    425
    426    /***
    427     * A convenience method to send the NNTP ARTICLE command to the server,
    428     * receive the initial reply, and return the reply code.
    429     * <p>
    430     * @return The reply code received from the server.
    431     * @exception NNTPConnectionClosedException
    432     *      If the NNTP server prematurely closes the connection as a result
    433     *      of the client being idle or some other reason causing the server
    434     *      to send NNTP reply code 400.  This exception may be caught either
    435     *      as an IOException or independently as itself.
    436     * @exception IOException  If an I/O error occurs while either sending the
    437     *      command or receiving the server reply.
    438     ***/
    439    public int article() throws IOException
    440    {
    441        return sendCommand(NNTPCommand.ARTICLE);
    442    }
    443
    444
    445
    446    /***
    447     * A convenience method to send the NNTP BODY command to the server,
    448     * receive the initial reply, and return the reply code.
    449     * <p>
    450     * @param messageId  The message identifier of the requested article,
    451     *                   including the encapsulating &lt and &gt characters.
    452     * @return The reply code received from the server.
    453     * @exception NNTPConnectionClosedException
    454     *      If the NNTP server prematurely closes the connection as a result
    455     *      of the client being idle or some other reason causing the server
    456     *      to send NNTP reply code 400.  This exception may be caught either
    457     *      as an IOException or independently as itself.
    458     * @exception IOException  If an I/O error occurs while either sending the
    459     *      command or receiving the server reply.
    460     ***/
    461    public int body(String messageId) throws IOException
    462    {
    463        return sendCommand(NNTPCommand.BODY, messageId);
    464    }
    465
    466    /***
    467     * A convenience method to send the NNTP BODY command to the server,
    468     * receive the initial reply, and return the reply code.
    469     * <p>
    470     * @param articleNumber The number of the article to request from the
    471     *                      currently selected newsgroup.
    472     * @return The reply code received from the server.
    473     * @exception NNTPConnectionClosedException
    474     *      If the NNTP server prematurely closes the connection as a result
    475     *      of the client being idle or some other reason causing the server
    476     *      to send NNTP reply code 400.  This exception may be caught either
    477     *      as an IOException or independently as itself.
    478     * @exception IOException  If an I/O error occurs while either sending the
    479     *      command or receiving the server reply.
    480     ***/
    481    public int body(long articleNumber) throws IOException
    482    {
    483        return sendCommand(NNTPCommand.BODY, Long.toString(articleNumber));
    484    }
    485
    486    /***
    487     * A convenience method to send the NNTP BODY command to the server,
    488     * receive the initial reply, and return the reply code.
    489     * <p>
    490     * @return The reply code received from the server.
    491     * @exception NNTPConnectionClosedException
    492     *      If the NNTP server prematurely closes the connection as a result
    493     *      of the client being idle or some other reason causing the server
    494     *      to send NNTP reply code 400.  This exception may be caught either
    495     *      as an IOException or independently as itself.
    496     * @exception IOException  If an I/O error occurs while either sending the
    497     *      command or receiving the server reply.
    498     ***/
    499    public int body() throws IOException
    500    {
    501        return sendCommand(NNTPCommand.BODY);
    502    }
    503
    504
    505
    506    /***
    507     * A convenience method to send the NNTP HEAD command to the server,
    508     * receive the initial reply, and return the reply code.
    509     * <p>
    510     * @param messageId  The message identifier of the requested article,
    511     *                   including the encapsulating &lt and &gt characters.
    512     * @return The reply code received from the server.
    513     * @exception NNTPConnectionClosedException
    514     *      If the NNTP server prematurely closes the connection as a result
    515     *      of the client being idle or some other reason causing the server
    516     *      to send NNTP reply code 400.  This exception may be caught either
    517     *      as an IOException or independently as itself.
    518     * @exception IOException  If an I/O error occurs while either sending the
    519     *      command or receiving the server reply.
    520     ***/
    521    public int head(String messageId) throws IOException
    522    {
    523        return sendCommand(NNTPCommand.HEAD, messageId);
    524    }
    525
    526    /***
    527     * A convenience method to send the NNTP HEAD command to the server,
    528     * receive the initial reply, and return the reply code.
    529     * <p>
    530     * @param articleNumber The number of the article to request from the
    531     *                      currently selected newsgroup.
    532     * @return The reply code received from the server.
    533     * @exception NNTPConnectionClosedException
    534     *      If the NNTP server prematurely closes the connection as a result
    535     *      of the client being idle or some other reason causing the server
    536     *      to send NNTP reply code 400.  This exception may be caught either
    537     *      as an IOException or independently as itself.
    538     * @exception IOException  If an I/O error occurs while either sending the
    539     *      command or receiving the server reply.
    540     ***/
    541    public int head(long articleNumber) throws IOException
    542    {
    543        return sendCommand(NNTPCommand.HEAD, Long.toString(articleNumber));
    544    }
    545
    546    /***
    547     * A convenience method to send the NNTP HEAD command to the server,
    548     * receive the initial reply, and return the reply code.
    549     * <p>
    550     * @return The reply code received from the server.
    551     * @exception NNTPConnectionClosedException
    552     *      If the NNTP server prematurely closes the connection as a result
    553     *      of the client being idle or some other reason causing the server
    554     *      to send NNTP reply code 400.  This exception may be caught either
    555     *      as an IOException or independently as itself.
    556     * @exception IOException  If an I/O error occurs while either sending the
    557     *      command or receiving the server reply.
    558     ***/
    559    public int head() throws IOException
    560    {
    561        return sendCommand(NNTPCommand.HEAD);
    562    }
    563
    564
    565
    566    /***
    567     * A convenience method to send the NNTP STAT command to the server,
    568     * receive the initial reply, and return the reply code.
    569     * <p>
    570     * @param messageId  The message identifier of the requested article,
    571     *                   including the encapsulating &lt and &gt characters.
    572     * @return The reply code received from the server.
    573     * @exception NNTPConnectionClosedException
    574     *      If the NNTP server prematurely closes the connection as a result
    575     *      of the client being idle or some other reason causing the server
    576     *      to send NNTP reply code 400.  This exception may be caught either
    577     *      as an IOException or independently as itself.
    578     * @exception IOException  If an I/O error occurs while either sending the
    579     *      command or receiving the server reply.
    580     ***/
    581    public int stat(String messageId) throws IOException
    582    {
    583        return sendCommand(NNTPCommand.STAT, messageId);
    584    }
    585
    586    /***
    587     * A convenience method to send the NNTP STAT command to the server,
    588     * receive the initial reply, and return the reply code.
    589     * <p>
    590     * @param articleNumber The number of the article to request from the
    591     *                      currently selected newsgroup.
    592     * @return The reply code received from the server.
    593     * @exception NNTPConnectionClosedException
    594     *      If the NNTP server prematurely closes the connection as a result
    595     *      of the client being idle or some other reason causing the server
    596     *      to send NNTP reply code 400.  This exception may be caught either
    597     *      as an IOException or independently as itself.
    598     * @exception IOException  If an I/O error occurs while either sending the
    599     *      command or receiving the server reply.
    600     ***/
    601    public int stat(long articleNumber) throws IOException
    602    {
    603        return sendCommand(NNTPCommand.STAT, Long.toString(articleNumber));
    604    }
    605
    606    /***
    607     * A convenience method to send the NNTP STAT command to the server,
    608     * receive the initial reply, and return the reply code.
    609     * <p>
    610     * @return The reply code received from the server.
    611     * @exception NNTPConnectionClosedException
    612     *      If the NNTP server prematurely closes the connection as a result
    613     *      of the client being idle or some other reason causing the server
    614     *      to send NNTP reply code 400.  This exception may be caught either
    615     *      as an IOException or independently as itself.
    616     * @exception IOException  If an I/O error occurs while either sending the
    617     *      command or receiving the server reply.
    618     ***/
    619    public int stat() throws IOException
    620    {
    621        return sendCommand(NNTPCommand.STAT);
    622    }
    623
    624
    625    /***
    626     * A convenience method to send the NNTP GROUP command to the server,
    627     * receive the reply, and return the reply code.
    628     * <p>
    629     * @param newsgroup  The name of the newsgroup to select.
    630     * @return The reply code received from the server.
    631     * @exception NNTPConnectionClosedException
    632     *      If the NNTP server prematurely closes the connection as a result
    633     *      of the client being idle or some other reason causing the server
    634     *      to send NNTP reply code 400.  This exception may be caught either
    635     *      as an IOException or independently as itself.
    636     * @exception IOException  If an I/O error occurs while either sending the
    637     *      command or receiving the server reply.
    638     ***/
    639    public int group(String newsgroup) throws IOException
    640    {
    641        return sendCommand(NNTPCommand.GROUP, newsgroup);
    642    }
    643
    644
    645    /***
    646     * A convenience method to send the NNTP HELP command to the server,
    647     * receive the reply, and return the reply code.
    648     * <p>
    649     * @return The reply code received from the server.
    650     * @exception NNTPConnectionClosedException
    651     *      If the NNTP server prematurely closes the connection as a result
    652     *      of the client being idle or some other reason causing the server
    653     *      to send NNTP reply code 400.  This exception may be caught either
    654     *      as an IOException or independently as itself.
    655     * @exception IOException  If an I/O error occurs while either sending the
    656     *      command or receiving the server reply.
    657     ***/
    658    public int help() throws IOException
    659    {
    660        return sendCommand(NNTPCommand.HELP);
    661    }
    662
    663
    664    /***
    665     * A convenience method to send the NNTP IHAVE command to the server,
    666     * receive the reply, and return the reply code.
    667     * <p>
    668     * @param messageId  The article identifier,
    669     *                   including the encapsulating &lt and &gt characters.
    670     * @return The reply code received from the server.
    671     * @exception NNTPConnectionClosedException
    672     *      If the NNTP server prematurely closes the connection as a result
    673     *      of the client being idle or some other reason causing the server
    674     *      to send NNTP reply code 400.  This exception may be caught either
    675     *      as an IOException or independently as itself.
    676     * @exception IOException  If an I/O error occurs while either sending the
    677     *      command or receiving the server reply.
    678     ***/
    679    public int ihave(String messageId) throws IOException
    680    {
    681        return sendCommand(NNTPCommand.IHAVE, messageId);
    682    }
    683
    684
    685    /***
    686     * A convenience method to send the NNTP LAST command to the server,
    687     * receive the reply, and return the reply code.
    688     * <p>
    689     * @return The reply code received from the server.
    690     * @exception NNTPConnectionClosedException
    691     *      If the NNTP server prematurely closes the connection as a result
    692     *      of the client being idle or some other reason causing the server
    693     *      to send NNTP reply code 400.  This exception may be caught either
    694     *      as an IOException or independently as itself.
    695     * @exception IOException  If an I/O error occurs while either sending the
    696     *      command or receiving the server reply.
    697     ***/
    698    public int last() throws IOException
    699    {
    700        return sendCommand(NNTPCommand.LAST);
    701    }
    702
    703
    704
    705    /***
    706     * A convenience method to send the NNTP LIST command to the server,
    707     * receive the reply, and return the reply code.
    708     * <p>
    709     * @return The reply code received from the server.
    710     * @exception NNTPConnectionClosedException
    711     *      If the NNTP server prematurely closes the connection as a result
    712     *      of the client being idle or some other reason causing the server
    713     *      to send NNTP reply code 400.  This exception may be caught either
    714     *      as an IOException or independently as itself.
    715     * @exception IOException  If an I/O error occurs while either sending the
    716     *      command or receiving the server reply.
    717     ***/
    718    public int list() throws IOException
    719    {
    720        return sendCommand(NNTPCommand.LIST);
    721    }
    722
    723
    724
    725    /***
    726     * A convenience method to send the NNTP NEXT command to the server,
    727     * receive the reply, and return the reply code.
    728     * <p>
    729     * @return The reply code received from the server.
    730     * @exception NNTPConnectionClosedException
    731     *      If the NNTP server prematurely closes the connection as a result
    732     *      of the client being idle or some other reason causing the server
    733     *      to send NNTP reply code 400.  This exception may be caught either
    734     *      as an IOException or independently as itself.
    735     * @exception IOException  If an I/O error occurs while either sending the
    736     *      command or receiving the server reply.
    737     ***/
    738    public int next() throws IOException
    739    {
    740        return sendCommand(NNTPCommand.NEXT);
    741    }
    742
    743
    744    /***
    745     * A convenience method to send the "NEWGROUPS" command to the server,
    746     * receive the reply, and return the reply code.
    747     * <p>
    748     * @param date The date after which to check for new groups.
    749     *             Date format is YYMMDD
    750     * @param time The time after which to check for new groups.
    751     *             Time format is HHMMSS using a 24-hour clock.
    752     * @param GMT  True if the time is in GMT, false if local server time.
    753     * @param distributions  Comma-separated distribution list to check for
    754     *            new groups. Set to null if no distributions.
    755     * @return The reply code received from the server.
    756     * @exception NNTPConnectionClosedException
    757     *      If the NNTP server prematurely closes the connection as a result
    758     *      of the client being idle or some other reason causing the server
    759     *      to send NNTP reply code 400.  This exception may be caught either
    760     *      as an IOException or independently as itself.
    761     * @exception IOException  If an I/O error occurs while either sending the
    762     *      command or receiving the server reply.
    763     ***/
    764    public int newgroups(String date, String time, boolean GMT,
    765                         String distributions) throws IOException
    766    {
    767        StringBuilder buffer = new StringBuilder();
    768
    769        buffer.append(date);
    770        buffer.append(' ');
    771        buffer.append(time);
    772
    773        if (GMT)
    774        {
    775            buffer.append(' ');
    776            buffer.append("GMT");
    777        }
    778
    779        if (distributions != null)
    780        {
    781            buffer.append(" <");
    782            buffer.append(distributions);
    783            buffer.append('>');
    784        }
    785
    786        return sendCommand(NNTPCommand.NEWGROUPS, buffer.toString());
    787    }
    788
    789
    790    /***
    791     * A convenience method to send the "NEWNEWS" command to the server,
    792     * receive the reply, and return the reply code.
    793     * <p>
    794     * @param newsgroups A comma-separated list of newsgroups to check for new
    795     *             news.
    796     * @param date The date after which to check for new news.
    797     *             Date format is YYMMDD
    798     * @param time The time after which to check for new news.
    799     *             Time format is HHMMSS using a 24-hour clock.
    800     * @param GMT  True if the time is in GMT, false if local server time.
    801     * @param distributions  Comma-separated distribution list to check for
    802     *            new news. Set to null if no distributions.
    803     * @return The reply code received from the server.
    804     * @exception NNTPConnectionClosedException
    805     *      If the NNTP server prematurely closes the connection as a result
    806     *      of the client being idle or some other reason causing the server
    807     *      to send NNTP reply code 400.  This exception may be caught either
    808     *      as an IOException or independently as itself.
    809     * @exception IOException  If an I/O error occurs while either sending the
    810     *      command or receiving the server reply.
    811     ***/
    812    public int newnews(String newsgroups, String date, String time, boolean GMT,
    813                       String distributions) throws IOException
    814    {
    815        StringBuilder buffer = new StringBuilder();
    816
    817        buffer.append(newsgroups);
    818        buffer.append(' ');
    819        buffer.append(date);
    820        buffer.append(' ');
    821        buffer.append(time);
    822
    823        if (GMT)
    824        {
    825            buffer.append(' ');
    826            buffer.append("GMT");
    827        }
    828
    829        if (distributions != null)
    830        {
    831            buffer.append(" <");
    832            buffer.append(distributions);
    833            buffer.append('>');
    834        }
    835
    836        return sendCommand(NNTPCommand.NEWNEWS, buffer.toString());
    837    }
    838
    839
    840
    841    /***
    842     * A convenience method to send the NNTP POST command to the server,
    843     * receive the reply, and return the reply code.
    844     * <p>
    845     * @return The reply code received from the server.
    846     * @exception NNTPConnectionClosedException
    847     *      If the NNTP server prematurely closes the connection as a result
    848     *      of the client being idle or some other reason causing the server
    849     *      to send NNTP reply code 400.  This exception may be caught either
    850     *      as an IOException or independently as itself.
    851     * @exception IOException  If an I/O error occurs while either sending the
    852     *      command or receiving the server reply.
    853     ***/
    854    public int post() throws IOException
    855    {
    856        return sendCommand(NNTPCommand.POST);
    857    }
    858
    859
    860
    861    /***
    862     * A convenience method to send the NNTP QUIT command to the server,
    863     * receive the reply, and return the reply code.
    864     * <p>
    865     * @return The reply code received from the server.
    866     * @exception NNTPConnectionClosedException
    867     *      If the NNTP server prematurely closes the connection as a result
    868     *      of the client being idle or some other reason causing the server
    869     *      to send NNTP reply code 400.  This exception may be caught either
    870     *      as an IOException or independently as itself.
    871     * @exception IOException  If an I/O error occurs while either sending the
    872     *      command or receiving the server reply.
    873     ***/
    874    public int quit() throws IOException
    875    {
    876        return sendCommand(NNTPCommand.QUIT);
    877    }
    878
    879    /***
    880     * A convenience method to send the AUTHINFO USER command to the server,
    881     *  receive the reply, and return the reply code. (See RFC 2980)
    882     * <p>
    883     * @param username A valid username.
    884     * @return The reply code received from the server. The server should
    885     *          return a 381 or 281 for this command.
    886     * @exception NNTPConnectionClosedException
    887     *      If the NNTP server prematurely closes the connection as a result
    888     *      of the client being idle or some other reason causing the server
    889     *      to send NNTP reply code 400.  This exception may be caught either
    890     *      as an IOException or independently as itself.
    891     * @exception IOException  If an I/O error occurs while either sending the
    892     *      command or receiving the server reply.
    893     ***/
    894    public int authinfoUser(String username) throws IOException {
    895        String userParameter = "USER " + username;
    896        return sendCommand(NNTPCommand.AUTHINFO, userParameter);
    897    }
    898
    899    /***
    900     * A convenience method to send the AUTHINFO PASS command to the server,
    901     * receive the reply, and return the reply code.  If this step is
    902     * required, it should immediately follow the AUTHINFO USER command
    903     * (See RFC 2980)
    904     * <p>
    905     * @param password a valid password.
    906     * @return The reply code received from the server. The server should
    907     *         return a 281 or 502 for this command.
    908     * @exception NNTPConnectionClosedException
    909     *      If the NNTP server prematurely closes the connection as a result
    910     *      of the client being idle or some other reason causing the server
    911     *      to send NNTP reply code 400.  This exception may be caught either
    912     *      as an IOException or independently as itself.
    913     * @exception IOException  If an I/O error occurs while either sending the
    914     *      command or receiving the server reply.
    915     ***/
    916    public int authinfoPass(String password) throws IOException {
    917        String passParameter = "PASS " + password;
    918        return sendCommand(NNTPCommand.AUTHINFO, passParameter);
    919    }
    920
    921    /***
    922     * A convenience method to send the NNTP XOVER command to the server,
    923     * receive the reply, and return the reply code.
    924     * <p>
    925     * @param selectedArticles a String representation of the range of
    926     * article headers required. This may be an article number, or a
    927     * range of article numbers in the form "XXXX-YYYY", where XXXX
    928     * and YYYY are valid article numbers in the current group.  It
    929     * also may be of the form "XXX-", meaning "return XXX and all
    930     * following articles" In this revision, the last format is not
    931     * possible (yet).
    932     * @return The reply code received from the server.
    933     * @exception NNTPConnectionClosedException
    934     *      If the NNTP server prematurely closes the connection as a result
    935     *      of the client being idle or some other reason causing the server
    936     *      to send NNTP reply code 400.  This exception may be caught either
    937     *      as an IOException or independently as itself.
    938     * @exception IOException  If an I/O error occurs while either sending the
    939     *      command or receiving the server reply.
    940     ***/
    941    public int xover(String selectedArticles) throws IOException {
    942        return sendCommand(NNTPCommand.XOVER, selectedArticles);
    943    }
    944
    945    /***
    946     * A convenience method to send the NNTP XHDR command to the server,
    947     * receive the reply, and return the reply code.
    948     * <p>
    949     * @param header a String naming a header line (e.g., "subject").  See
    950     * RFC-1036 for a list of valid header lines.
    951     * @param selectedArticles a String representation of the range of
    952     * article headers required. This may be an article number, or a
    953     * range of article numbers in the form "XXXX-YYYY", where XXXX
    954     * and YYYY are valid article numbers in the current group.  It
    955     * also may be of the form "XXX-", meaning "return XXX and all
    956     * following articles" In this revision, the last format is not
    957     * possible (yet).
    958     * @return The reply code received from the server.
    959     * @exception NNTPConnectionClosedException
    960     *      If the NNTP server prematurely closes the connection as a result
    961     *      of the client being idle or some other reason causing the server
    962     *      to send NNTP reply code 400.  This exception may be caught either
    963     *      as an IOException or independently as itself.
    964     * @exception IOException  If an I/O error occurs while either sending the
    965     *      command or receiving the server reply.
    966     ***/
    967    public int xhdr(String header, String selectedArticles) throws IOException {
    968        StringBuilder command = new StringBuilder(header);
    969        command.append(" ");
    970        command.append(selectedArticles);
    971        return sendCommand(NNTPCommand.XHDR, command.toString());
    972    }
    973
    974    /**
    975     * A convenience wrapper for the extended LIST command that takes
    976     * an argument, allowing us to selectively list multiple groups.
    977     * <p>
    978     * @param wildmat A wildmat (pseudo-regex) pattern. See RFC 2980 for
    979     *                details.
    980     * @return the reply code received from the server.
    981     * @throws IOException
    982     */
    983    public int listActive(String wildmat) throws IOException {
    984        StringBuilder command = new StringBuilder("ACTIVE ");
    985        command.append(wildmat);
    986        return sendCommand(NNTPCommand.LIST, command.toString());
    987    }
    988
    989    // DEPRECATED METHODS - for API compatibility only - DO NOT USE
    990
    991    @Deprecated
    992    public int article(int a) throws IOException
    993    {
    994        return article((long) a);
    995    }
    996
    997    @Deprecated
    998    public int body(int a) throws IOException
    999    {
    1000        return body((long) a);
    1001    }
    1002
    1003    @Deprecated
    1004    public int head(int a) throws IOException
    1005    {
    1006        return head((long) a);
    1007    }
    1008
    1009    @Deprecated
    1010    public int stat(int a) throws IOException
    1011    {
    1012        return stat((long) a);
    1013    }
    1014
    1015    /**
    1016     * Provide command support to super-class
    1017     */
    1018    @Override
    1019    protected ProtocolCommandSupport getCommandSupport() {
    1020        return _commandSupport_;
    1021    }
    1022}
    1023
    1024/* Emacs configuration
    1025 * Local variables:        **
    1026 * mode:             java  **
    1027 * c-basic-offset:   4     **
    1028 * indent-tabs-mode: nil   **
    1029 * End:                    **
    1030 */