    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
    018    package org.apache.commons.net.nntp;
    019
    020    import java.io.BufferedReader;
    021    import java.io.BufferedWriter;
    022    import java.io.IOException;
    023    import java.io.InputStreamReader;
    024    import java.io.OutputStreamWriter;
    025
    026    import org.apache.commons.net.MalformedServerReplyException;
    027    import org.apache.commons.net.ProtocolCommandSupport;
    028    import org.apache.commons.net.SocketClient;
    029    import 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
    083    public 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     */