    View Javadoc
    1   package org.apache.commons.net.nntp;
    2
    3   /* ====================================================================
    4    * The Apache Software License, Version 1.1
    5    *
    6    * Copyright (c) 2001 The Apache Software Foundation.  All rights
    7    * reserved.
    8    *
    9    * Redistribution and use in source and binary forms, with or without
    10   * modification, are permitted provided that the following conditions
    11   * are met:
    12   *
    13   * 1. Redistributions of source code must retain the above copyright
    14   *    notice, this list of conditions and the following disclaimer.
    15   *
    16   * 2. Redistributions in binary form must reproduce the above copyright
    17   *    notice, this list of conditions and the following disclaimer in
    18   *    the documentation and/or other materials provided with the
    19   *    distribution.
    20   *
    21   * 3. The end-user documentation included with the redistribution,
    22   *    if any, must include the following acknowledgment:
    23   *       "This product includes software developed by the
    24   *        Apache Software Foundation (http://www.apache.org/)."
    25   *    Alternately, this acknowledgment may appear in the software itself,
    26   *    if and wherever such third-party acknowledgments normally appear.
    27   *
    28   * 4. The names "Apache" and "Apache Software Foundation" and
    29   *    "Apache Commons" must not be used to endorse or promote products
    30   *    derived from this software without prior written permission. For
    31   *    written permission, please contact apache@apache.org.
    32   *
    33   * 5. Products derived from this software may not be called "Apache",
    34   *    nor may "Apache" appear in their name, without
    35   *    prior written permission of the Apache Software Foundation.
    36   *
    37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
    41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    48   * SUCH DAMAGE.
    49   * ====================================================================
    50   *
    51   * This software consists of voluntary contributions made by many
    52   * individuals on behalf of the Apache Software Foundation.  For more
    53   * information on the Apache Software Foundation, please see
    54   * <http://www.apache.org/>;.
    55   */
    56
    57  import java.io.BufferedReader;
    58  import java.io.IOException;
    59  import java.io.Reader;
    60  import java.io.StringWriter;
    61  import java.io.Writer;
    62  import java.util.StringTokenizer;
    63  import java.util.Vector;
    64  import org.apache.commons.net.io.DotTerminatedMessageReader;
    65  import org.apache.commons.net.io.DotTerminatedMessageWriter;
    66  import org.apache.commons.net.io.Util;
    67  import org.apache.commons.net.MalformedServerReplyException;
    68
    69  /****
    70   * NNTPClient encapsulates all the functionality necessary to post and
    71   * retrieve articles from an NNTP server.  As with all classes derived
    72   * from <a href="org.apache.commons.net.SocketClient.html"> SocketClient </a>,
    73   * you must first connect to the server with
    74   * <a href="org.apache.commons.net.SocketClient.html#connect"> connect </a>
    75   * before doing anything, and finally
    76   * <a href="org.apache.commons.net.nntp.NNTP.html#disconnect"> disconnect() </a>
    77   * after you're completely finished interacting with the server.
    78   * Remember that the
    79   * <a href="org.apache.commons.net.nntp.NNTP.html#isAllowedToPost">
    80   * isAllowedToPost()</a> method is defined in
    81   * <a href="org.apache.commons.net.nntp.NNTP.html"> NNTP </a>.
    82   * <p>
    83   * You should keep in mind that the NNTP server may choose to prematurely
    84   * close a connection if the client has been idle for longer than a
    85   * given time period or if the server is being shutdown by the operator or
    86   * some other reason.  The NNTP class will detect a
    87   * premature NNTP server connection closing when it receives a
    88   * <a href="org.apache.commons.net.nntp.NNTPReply.html#SERVICE_DISCONTINUED">
    89   * NNTPReply.SERVICE_DISCONTINUED </a> response to a command.
    90   * When that occurs, the NNTP class method encountering that reply will throw
    91   * an <a href="org.apache.commons.net.nntp.NNTPConnectionClosedException.html">
    92   * NNTPConnectionClosedException </a>.
    93   * <code>NNTPConectionClosedException</code>
    94   * is a subclass of <code> IOException </code> and therefore need not be
    95   * caught separately, but if you are going to catch it separately, its
    96   * catch block must appear before the more general <code> IOException </code>
    97   * catch block.  When you encounter an
    98   * <a href="org.apache.commons.net.nntp.NNTPConnectionClosedException.html">
    99   * NNTPConnectionClosedException </a>, you must disconnect the connection with
    100  * <a href="org.apache.commons.net.nntp.NNTP.html#disconnect"> disconnect() </a>
    101  *  to properly clean up the
    102  * system resources used by NNTP.  Before disconnecting, you may check the
    103  * last reply code and text with
    104  * <a href="org.apache.commons.net.nntp.NNTP.html#getReplyCode"> getReplyCode </a> and
    105  * <a href="org.apache.commons.net.nntp.NNTP.html#getReplyString"> getReplyString </a>.
    106  * <p>
    107  * Rather than list it separately for each method, we mention here that
    108  * every method communicating with the server and throwing an IOException
    109  * can also throw a
    110  * <a href="org.apache.commons.net.MalformedServerReplyException.html">
    111  * MalformedServerReplyException </a>, which is a subclass
    112  * of IOException.  A MalformedServerReplyException will be thrown when
    113  * the reply received from the server deviates enough from the protocol
    114  * specification that it cannot be interpreted in a useful manner despite
    115  * attempts to be as lenient as possible.
    116  * <p>
    117  * <p>
    118  * @author Daniel F. Savarese
    119  * @see NNTP
    120  * @see NNTPConnectionClosedException
    121  * @see org.apache.commons.net.MalformedServerReplyException
    122  ***/
    123
    124 public class NNTPClient extends NNTP
    125 {
    126
    127     private void __parseArticlePointer(String reply, ArticlePointer pointer)
    128     throws MalformedServerReplyException
    129     {
    130         StringTokenizer tokenizer;
    131
    132         // Do loop is a kluge to simulate goto
    133         do
    134         {
    135             tokenizer = new StringTokenizer(reply);
    136
    137             if (tokenizer.countTokens() < 3)
    138                 break;
    139
    140             // Skip numeric response value
    141             tokenizer.nextToken();
    142             // Get article number
    143             try
    144             {
    145                 pointer.articleNumber = Integer.parseInt(tokenizer.nextToken());
    146             }
    147             catch (NumberFormatException e)
    148             {
    149                 break;
    150             }
    151
    152             // Get article id
    153             pointer.articleId = tokenizer.nextToken();
    154             return ;
    155         }
    156         while (false);
    157
    158         throw new MalformedServerReplyException(
    159             "Could not parse article pointer.\nServer reply: " + reply);
    160     }
    161
    162
    163     private void __parseGroupReply(String reply, NewsgroupInfo info)
    164     throws MalformedServerReplyException
    165     {
    166         String count, first, last;
    167         StringTokenizer tokenizer;
    168
    169         // Do loop is a kluge to simulate goto
    170         do
    171         {
    172             tokenizer = new StringTokenizer(reply);
    173
    174             if (tokenizer.countTokens() < 5)
    175                 break;
    176
    177             // Skip numeric response value
    178             tokenizer.nextToken();
    179             // Get estimated article count
    180             count = tokenizer.nextToken();
    181             // Get first article number
    182             first = tokenizer.nextToken();
    183             // Get last article number
    184             last = tokenizer.nextToken();
    185             // Get newsgroup name
    186             info._setNewsgroup(tokenizer.nextToken());
    187
    188             try
    189             {
    190                 info._setArticleCount(Integer.parseInt(count));
    191                 info._setFirstArticle(Integer.parseInt(first));
    192                 info._setLastArticle(Integer.parseInt(last));
    193             }
    194             catch (NumberFormatException e)
    195             {
    196                 break;
    197             }
    198
    199             info._setPostingPermission(NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
    200             return ;
    201         }
    202         while (false);
    203
    204         throw new MalformedServerReplyException(
    205             "Could not parse newsgroup info.\nServer reply: " + reply);
    206     }
    207
    208
    209     private NewsgroupInfo __parseNewsgroupListEntry(String entry)
    210     {
    211         NewsgroupInfo result;
    212         StringTokenizer tokenizer;
    213         int lastNum, firstNum;
    214         String last, first, permission;
    215
    216         result = new NewsgroupInfo();
    217         tokenizer = new StringTokenizer(entry);
    218
    219         if (tokenizer.countTokens() < 4)
    220             return null;
    221
    222         result._setNewsgroup(tokenizer.nextToken());
    223         last = tokenizer.nextToken();
    224         first = tokenizer.nextToken();
    225         permission = tokenizer.nextToken();
    226
    227         try
    228         {
    229             lastNum = Integer.parseInt(last);
    230             firstNum = Integer.parseInt(first);
    231             result._setFirstArticle(firstNum);
    232             result._setLastArticle(lastNum);
    233             result._setArticleCount(lastNum - firstNum + 1);
    234         }
    235         catch (NumberFormatException e)
    236         {
    237             return null;
    238         }
    239
    240         switch (permission.charAt(0))
    241         {
    242         case 'y':
    243         case 'Y':
    244             result._setPostingPermission(
    245                 NewsgroupInfo.PERMITTED_POSTING_PERMISSION);
    246             break;
    247         case 'n':
    248         case 'N':
    249             result._setPostingPermission(
    250                 NewsgroupInfo.PROHIBITED_POSTING_PERMISSION);
    251             break;
    252         case 'm':
    253         case 'M':
    254             result._setPostingPermission(
    255                 NewsgroupInfo.MODERATED_POSTING_PERMISSION);
    256             break;
    257         default:
    258             result._setPostingPermission(
    259                 NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
    260             break;
    261         }
    262
    263         return result;
    264     }
    265
    266     private NewsgroupInfo[] __readNewsgroupListing() throws IOException
    267     {
    268         int size;
    269         String line;
    270         Vector list;
    271         BufferedReader reader;
    272         NewsgroupInfo tmp, info[];
    273
    274         reader = new BufferedReader(new DotTerminatedMessageReader(_reader));
    275         // Start of with a big vector because we may be reading a very large
    276         // amount of groups.
    277         list = new Vector(2048);
    278
    279         while ((line = reader.readLine()) != null)
    280         {
    281             tmp = __parseNewsgroupListEntry(line);
    282             if (tmp != null)
    283                 list.addElement(tmp);
    284             else
    285                 throw new MalformedServerReplyException(line);
    286         }
    287
    288         if ((size = list.size()) < 1)
    289             return new NewsgroupInfo[0];
    290
    291         info = new NewsgroupInfo[size];
    292         list.copyInto(info);
    293
    294         return info;
    295     }
    296
    297
    298     private Reader __retrieve(int command,
    299                               String articleId, ArticlePointer pointer)
    300     throws IOException
    301     {
    302         Reader reader;
    303
    304         if (articleId != null)
    305         {
    306             if (!NNTPReply.isPositiveCompletion(sendCommand(command, articleId)))
    307                 return null;
    308         }
    309         else
    310         {
    311             if (!NNTPReply.isPositiveCompletion(sendCommand(command)))
    312                 return null;
    313         }
    314
    315
    316         if (pointer != null)
    317             __parseArticlePointer(getReplyString(), pointer);
    318
    319         reader = new DotTerminatedMessageReader(_reader);
    320         return reader;
    321     }
    322
    323
    324     private Reader __retrieve(int command,
    325                               int articleNumber, ArticlePointer pointer)
    326     throws IOException
    327     {
    328         Reader reader;
    329
    330         if (!NNTPReply.isPositiveCompletion(sendCommand(command,
    331                                             Integer.toString(articleNumber))))
    332             return null;
    333
    334         if (pointer != null)
    335             __parseArticlePointer(getReplyString(), pointer);
    336
    337         reader = new DotTerminatedMessageReader(_reader);
    338         return reader;
    339     }
    340
    341
    342
    343     /****
    344      * Retrieves an article from the NNTP server.  The article is referenced
    345      * by its unique article identifier (including the enclosing < and >).
    346      * The article number and identifier contained in the server reply
    347      * are returned through an ArticlePointer.  The <code> articleId </code>
    348      * field of the ArticlePointer cannot always be trusted because some
    349      * NNTP servers do not correctly follow the RFC 977 reply format.
    350      * <p>
    351      * A DotTerminatedMessageReader is returned from which the article can
    352      * be read.  If the article does not exist, null is returned.
    353      * <p>
    354      * You must not issue any commands to the NNTP server (i.e., call any
    355      * other methods) until you finish reading the message from the returned
    356      * Reader instance.
    357      * The NNTP protocol uses the same stream for issuing commands as it does
    358      * for returning results.  Therefore the returned Reader actually reads
    359      * directly from the NNTP connection.  After the end of message has been
    360      * reached, new commands can be executed and their replies read.  If
    361      * you do not follow these requirements, your program will not work
    362      * properly.
    363      * <p>
    364      * @param articleId  The unique article identifier of the article to
    365      *     retrieve.  If this parameter is null, the currently selected
    366      *     article is retrieved.
    367      * @param pointer    A parameter through which to return the article's
    368      *   number and unique id.  The articleId field cannot always be trusted
    369      *   because of server deviations from RFC 977 reply formats.  You may
    370      *   set this parameter to null if you do not desire to retrieve the
    371      *   returned article information.
    372      * @return A DotTerminatedMessageReader instance from which the article
    373      *         be read.  null if the article does not exist.
    374      * @exception NNTPConnectionClosedException
    375      *      If the NNTP server prematurely closes the connection as a result
    376      *      of the client being idle or some other reason causing the server
    377      *      to send NNTP reply code 400.  This exception may be caught either
    378      *      as an IOException or independently as itself.
    379      * @exception IOException  If an I/O error occurs while either sending a
    380      *      command to the server or receiving a reply from the server.
    381      ***/
    382     public Reader retrieveArticle(String articleId, ArticlePointer pointer)
    383     throws IOException
    384     {
    385         return __retrieve(NNTPCommand.ARTICLE, articleId, pointer);
    386
    387     }
    388
    389     /**** Same as <code> retrieveArticle(articleId, null) </code> ***/
    390     public Reader retrieveArticle(String articleId) throws IOException
    391     {
    392         return retrieveArticle(articleId, null);
    393     }
    394
    395     /**** Same as <code> retrieveArticle(null) </code> ***/
    396     public Reader retrieveArticle() throws IOException
    397     {
    398         return retrieveArticle(null);
    399     }
    400
    401
    402     /****
    403      * Retrieves an article from the currently selected newsgroup.  The
    404      * article is referenced by its article number.
    405      * The article number and identifier contained in the server reply
    406      * are returned through an ArticlePointer.  The <code> articleId </code>
    407      * field of the ArticlePointer cannot always be trusted because some
    408      * NNTP servers do not correctly follow the RFC 977 reply format.
    409      * <p>
    410      * A DotTerminatedMessageReader is returned from which the article can
    411      * be read.  If the article does not exist, null is returned.
    412      * <p>
    413      * You must not issue any commands to the NNTP server (i.e., call any
    414      * other methods) until you finish reading the message from the returned
    415      * Reader instance.
    416      * The NNTP protocol uses the same stream for issuing commands as it does
    417      * for returning results.  Therefore the returned Reader actually reads
    418      * directly from the NNTP connection.  After the end of message has been
    419      * reached, new commands can be executed and their replies read.  If
    420      * you do not follow these requirements, your program will not work
    421      * properly.
    422      * <p>
    423      * @param articleNumber  The number of the the article to
    424      *     retrieve.
    425      * @param pointer    A parameter through which to return the article's
    426      *   number and unique id.  The articleId field cannot always be trusted
    427      *   because of server deviations from RFC 977 reply formats.  You may
    428      *   set this parameter to null if you do not desire to retrieve the
    429      *   returned article information.
    430      * @return A DotTerminatedMessageReader instance from which the article
    431      *         be read.  null if the article does not exist.
    432      * @exception NNTPConnectionClosedException
    433      *      If the NNTP server prematurely closes the connection as a result
    434      *      of the client being idle or some other reason causing the server
    435      *      to send NNTP reply code 400.  This exception may be caught either
    436      *      as an IOException or independently as itself.
    437      * @exception IOException  If an I/O error occurs while either sending a
    438      *      command to the server or receiving a reply from the server.
    439      ***/
    440     public Reader retrieveArticle(int articleNumber, ArticlePointer pointer)
    441     throws IOException
    442     {
    443         return __retrieve(NNTPCommand.ARTICLE, articleNumber, pointer);
    444     }
    445
    446     /**** Same as <code> retrieveArticle(articleNumber, null) </code> ***/
    447     public Reader retrieveArticle(int articleNumber) throws IOException
    448     {
    449         return retrieveArticle(articleNumber, null);
    450     }
    451
    452
    453
    454     /****
    455      * Retrieves an article header from the NNTP server.  The article is
    456      * referenced
    457      * by its unique article identifier (including the enclosing < and >).
    458      * The article number and identifier contained in the server reply
    459      * are returned through an ArticlePointer.  The <code> articleId </code>
    460      * field of the ArticlePointer cannot always be trusted because some
    461      * NNTP servers do not correctly follow the RFC 977 reply format.
    462      * <p>
    463      * A DotTerminatedMessageReader is returned from which the article can
    464      * be read.  If the article does not exist, null is returned.
    465      * <p>
    466      * You must not issue any commands to the NNTP server (i.e., call any
    467      * other methods) until you finish reading the message from the returned
    468      * Reader instance.
    469      * The NNTP protocol uses the same stream for issuing commands as it does
    470      * for returning results.  Therefore the returned Reader actually reads
    471      * directly from the NNTP connection.  After the end of message has been
    472      * reached, new commands can be executed and their replies read.  If
    473      * you do not follow these requirements, your program will not work
    474      * properly.
    475      * <p>
    476      * @param articleId  The unique article identifier of the article whose
    477      *    header is being retrieved.  If this parameter is null, the
    478      *    header of the currently selected article is retrieved.
    479      * @param pointer    A parameter through which to return the article's
    480      *   number and unique id.  The articleId field cannot always be trusted
    481      *   because of server deviations from RFC 977 reply formats.  You may
    482      *   set this parameter to null if you do not desire to retrieve the
    483      *   returned article information.
    484      * @return A DotTerminatedMessageReader instance from which the article
    485      *         header can be read.  null if the article does not exist.
    486      * @exception NNTPConnectionClosedException
    487      *      If the NNTP server prematurely closes the connection as a result
    488      *      of the client being idle or some other reason causing the server
    489      *      to send NNTP reply code 400.  This exception may be caught either
    490      *      as an IOException or independently as itself.
    491      * @exception IOException  If an I/O error occurs while either sending a
    492      *      command to the server or receiving a reply from the server.
    493      ***/
    494     public Reader retrieveArticleHeader(String articleId, ArticlePointer pointer)
    495     throws IOException
    496     {
    497         return __retrieve(NNTPCommand.HEAD, articleId, pointer);
    498
    499     }
    500
    501     /**** Same as <code> retrieveArticleHeader(articleId, null) </code> ***/
    502     public Reader retrieveArticleHeader(String articleId) throws IOException
    503     {
    504         return retrieveArticleHeader(articleId, null);
    505     }
    506
    507     /**** Same as <code> retrieveArticleHeader(null) </code> ***/
    508     public Reader retrieveArticleHeader() throws IOException
    509     {
    510         return retrieveArticleHeader(null);
    511     }
    512
    513
    514     /****
    515      * Retrieves an article header from the currently selected newsgroup.  The
    516      * article is referenced by its article number.
    517      * The article number and identifier contained in the server reply
    518      * are returned through an ArticlePointer.  The <code> articleId </code>
    519      * field of the ArticlePointer cannot always be trusted because some
    520      * NNTP servers do not correctly follow the RFC 977 reply format.
    521      * <p>
    522      * A DotTerminatedMessageReader is returned from which the article can
    523      * be read.  If the article does not exist, null is returned.
    524      * <p>
    525      * You must not issue any commands to the NNTP server (i.e., call any
    526      * other methods) until you finish reading the message from the returned
    527      * Reader instance.
    528      * The NNTP protocol uses the same stream for issuing commands as it does
    529      * for returning results.  Therefore the returned Reader actually reads
    530      * directly from the NNTP connection.  After the end of message has been
    531      * reached, new commands can be executed and their replies read.  If
    532      * you do not follow these requirements, your program will not work
    533      * properly.
    534      * <p>
    535      * @param articleNumber  The number of the the article whose header is
    536      *     being retrieved.
    537      * @param pointer    A parameter through which to return the article's
    538      *   number and unique id.  The articleId field cannot always be trusted
    539      *   because of server deviations from RFC 977 reply formats.  You may
    540      *   set this parameter to null if you do not desire to retrieve the
    541      *   returned article information.
    542      * @return A DotTerminatedMessageReader instance from which the article
    543      *         header can be read.  null if the article does not exist.
    544      * @exception NNTPConnectionClosedException
    545      *      If the NNTP server prematurely closes the connection as a result
    546      *      of the client being idle or some other reason causing the server
    547      *      to send NNTP reply code 400.  This exception may be caught either
    548      *      as an IOException or independently as itself.
    549      * @exception IOException  If an I/O error occurs while either sending a
    550      *      command to the server or receiving a reply from the server.
    551      ***/
    552     public Reader retrieveArticleHeader(int articleNumber,
    553                                         ArticlePointer pointer)
    554     throws IOException
    555     {
    556         return __retrieve(NNTPCommand.HEAD, articleNumber, pointer);
    557     }
    558
    559
    560     /**** Same as <code> retrieveArticleHeader(articleNumber, null) </code> ***/
    561     public Reader retrieveArticleHeader(int articleNumber) throws IOException
    562     {
    563         return retrieveArticleHeader(articleNumber, null);
    564     }
    565
    566
    567
    568     /****
    569      * Retrieves an article body from the NNTP server.  The article is
    570      * referenced
    571      * by its unique article identifier (including the enclosing < and >).
    572      * The article number and identifier contained in the server reply
    573      * are returned through an ArticlePointer.  The <code> articleId </code>
    574      * field of the ArticlePointer cannot always be trusted because some
    575      * NNTP servers do not correctly follow the RFC 977 reply format.
    576      * <p>
    577      * A DotTerminatedMessageReader is returned from which the article can
    578      * be read.  If the article does not exist, null is returned.
    579      * <p>
    580      * You must not issue any commands to the NNTP server (i.e., call any
    581      * other methods) until you finish reading the message from the returned
    582      * Reader instance.
    583      * The NNTP protocol uses the same stream for issuing commands as it does
    584      * for returning results.  Therefore the returned Reader actually reads
    585      * directly from the NNTP connection.  After the end of message has been
    586      * reached, new commands can be executed and their replies read.  If
    587      * you do not follow these requirements, your program will not work
    588      * properly.
    589      * <p>
    590      * @param articleId  The unique article identifier of the article whose
    591      *    body is being retrieved.  If this parameter is null, the
    592      *    body of the currently selected article is retrieved.
    593      * @param pointer    A parameter through which to return the article's
    594      *   number and unique id.  The articleId field cannot always be trusted
    595      *   because of server deviations from RFC 977 reply formats.  You may
    596      *   set this parameter to null if you do not desire to retrieve the
    597      *   returned article information.
    598      * @return A DotTerminatedMessageReader instance from which the article
    599      *         body can be read.  null if the article does not exist.
    600      * @exception NNTPConnectionClosedException
    601      *      If the NNTP server prematurely closes the connection as a result
    602      *      of the client being idle or some other reason causing the server
    603      *      to send NNTP reply code 400.  This exception may be caught either
    604      *      as an IOException or independently as itself.
    605      * @exception IOException  If an I/O error occurs while either sending a
    606      *      command to the server or receiving a reply from the server.
    607      ***/
    608     public Reader retrieveArticleBody(String articleId, ArticlePointer pointer)
    609     throws IOException
    610     {
    611         return __retrieve(NNTPCommand.BODY, articleId, pointer);
    612
    613     }
    614
    615     /**** Same as <code> retrieveArticleBody(articleId, null) </code> ***/
    616     public Reader retrieveArticleBody(String articleId) throws IOException
    617     {
    618         return retrieveArticleBody(articleId, null);
    619     }
    620
    621     /**** Same as <code> retrieveArticleBody(null) </code> ***/
    622     public Reader retrieveArticleBody() throws IOException
    623     {
    624         return retrieveArticleBody(null);
    625     }
    626
    627
    628     /****
    629      * Retrieves an article body from the currently selected newsgroup.  The
    630      * article is referenced by its article number.
    631      * The article number and identifier contained in the server reply
    632      * are returned through an ArticlePointer.  The <code> articleId </code>
    633      * field of the ArticlePointer cannot always be trusted because some
    634      * NNTP servers do not correctly follow the RFC 977 reply format.
    635      * <p>
    636      * A DotTerminatedMessageReader is returned from which the article can
    637      * be read.  If the article does not exist, null is returned.
    638      * <p>
    639      * You must not issue any commands to the NNTP server (i.e., call any
    640      * other methods) until you finish reading the message from the returned
    641      * Reader instance.
    642      * The NNTP protocol uses the same stream for issuing commands as it does
    643      * for returning results.  Therefore the returned Reader actually reads
    644      * directly from the NNTP connection.  After the end of message has been
    645      * reached, new commands can be executed and their replies read.  If
    646      * you do not follow these requirements, your program will not work
    647      * properly.
    648      * <p>
    649      * @param articleNumber  The number of the the article whose body is
    650      *     being retrieved.
    651      * @param pointer    A parameter through which to return the article's
    652      *   number and unique id.  The articleId field cannot always be trusted
    653      *   because of server deviations from RFC 977 reply formats.  You may
    654      *   set this parameter to null if you do not desire to retrieve the
    655      *   returned article information.
    656      * @return A DotTerminatedMessageReader instance from which the article
    657      *         body can be read.  null if the article does not exist.
    658      * @exception NNTPConnectionClosedException
    659      *      If the NNTP server prematurely closes the connection as a result
    660      *      of the client being idle or some other reason causing the server
    661      *      to send NNTP reply code 400.  This exception may be caught either
    662      *      as an IOException or independently as itself.
    663      * @exception IOException  If an I/O error occurs while either sending a
    664      *      command to the server or receiving a reply from the server.
    665      ***/
    666     public Reader retrieveArticleBody(int articleNumber,
    667                                       ArticlePointer pointer)
    668     throws IOException
    669     {
    670         return __retrieve(NNTPCommand.BODY, articleNumber, pointer);
    671     }
    672
    673
    674     /**** Same as <code> retrieveArticleBody(articleNumber, null) </code> ***/
    675     public Reader retrieveArticleBody(int articleNumber) throws IOException
    676     {
    677         return retrieveArticleBody(articleNumber, null);
    678     }
    679
    680
    681     /****
    682      * Select the specified newsgroup to be the target of for future article
    683      * retrieval and posting operations.  Also return the newsgroup
    684      * information contained in the server reply through the info parameter.
    685      * <p>
    686      * @param newsgroup  The newsgroup to select.
    687      * @param info  A parameter through which the newsgroup information of
    688      *      the selected newsgroup contained in the server reply is returned.
    689      *      Set this to null if you do not desire this information.
    690      * @return True if the newsgroup exists and was selected, false otherwise.
    691      * @exception NNTPConnectionClosedException
    692      *      If the NNTP server prematurely closes the connection as a result
    693      *      of the client being idle or some other reason causing the server
    694      *      to send NNTP reply code 400.  This exception may be caught either
    695      *      as an IOException or independently as itself.
    696      * @exception IOException  If an I/O error occurs while either sending a
    697      *      command to the server or receiving a reply from the server.
    698      ***/
    699     public boolean selectNewsgroup(String newsgroup, NewsgroupInfo info)
    700     throws IOException
    701     {
    702         if (!NNTPReply.isPositiveCompletion(group(newsgroup)))
    703             return false;
    704
    705         if (info != null)
    706             __parseGroupReply(getReplyString(), info);
    707
    708         return true;
    709     }
    710
    711     /**** Same as <code> selectNewsgroup(newsgroup, null) </code> ***/
    712     public boolean selectNewsgroup(String newsgroup) throws IOException
    713     {
    714         return selectNewsgroup(newsgroup, null);
    715     }
    716
    717     /****
    718      * List the command help from the server.
    719      * <p>
    720      * @return The sever help information.
    721      * @exception NNTPConnectionClosedException
    722      *      If the NNTP server prematurely closes the connection as a result
    723      *      of the client being idle or some other reason causing the server
    724      *      to send NNTP reply code 400.  This exception may be caught either
    725      *      as an IOException or independently as itself.
    726      * @exception IOException  If an I/O error occurs while either sending a
    727      *      command to the server or receiving a reply from the server.
    728      ***/
    729     public String listHelp() throws IOException
    730     {
    731         StringWriter help;
    732         Reader reader;
    733
    734         if (!NNTPReply.isInformational(help()))
    735             return null;
    736
    737         help = new StringWriter();
    738         reader = new DotTerminatedMessageReader(_reader);
    739         Util.copyReader(reader, help);
    740         reader.close();
    741         help.close();
    742         return help.toString();
    743     }
    744
    745
    746     /****
    747      * Select an article by its unique identifier (including enclosing
    748      * < and >) and return its article number and id through the
    749      * pointer parameter.  This is achieved through the STAT command.
    750      * According to RFC 977, this will NOT set the current article pointer
    751      * on the server.  To do that, you must reference the article by its
    752      * number.
    753      * <p>
    754      * @param articleId  The unique article identifier of the article that
    755      *    is being selectedd.  If this parameter is null, the
    756      *    body of the current article is selected
    757      * @param pointer    A parameter through which to return the article's
    758      *   number and unique id.  The articleId field cannot always be trusted
    759      *   because of server deviations from RFC 977 reply formats.  You may
    760      *   set this parameter to null if you do not desire to retrieve the
    761      *   returned article information.
    762      * @return True if successful, false if not.
    763      * @exception NNTPConnectionClosedException
    764      *      If the NNTP server prematurely closes the connection as a result
    765      *      of the client being idle or some other reason causing the server
    766      *      to send NNTP reply code 400.  This exception may be caught either
    767      *      as an IOException or independently as itself.
    768      * @exception IOException  If an I/O error occurs while either sending a
    769      *      command to the server or receiving a reply from the server.
    770      ***/
    771     public boolean selectArticle(String articleId, ArticlePointer pointer)
    772     throws IOException
    773     {
    774         if (articleId != null)
    775         {
    776             if (!NNTPReply.isPositiveCompletion(stat(articleId)))
    777                 return false;
    778         }
    779         else
    780         {
    781             if (!NNTPReply.isPositiveCompletion(stat()))
    782                 return false;
    783         }
    784
    785         if (pointer != null)
    786             __parseArticlePointer(getReplyString(), pointer);
    787
    788         return true;
    789     }
    790
    791     /***** Same as <code> selectArticle(articleId, null) </code> ***/
    792     public boolean selectArticle(String articleId) throws IOException
    793     {
    794         return selectArticle(articleId, null);
    795     }
    796
    797     /*****
    798      * Same as <code> selectArticle(null, articleId) </code>.  Useful
    799      * for retrieving the current article number.
    800      ***/
    801     public boolean selectArticle(ArticlePointer pointer) throws IOException
    802     {
    803         return selectArticle(null, pointer);
    804     }
    805
    806
    807     /****
    808      * Select an article in the currently selected newsgroup by its number.
    809      * and return its article number and id through the
    810      * pointer parameter.  This is achieved through the STAT command.
    811      * According to RFC 977, this WILL set the current article pointer
    812      * on the server.  Use this command to select an article before retrieving
    813      * it, or to obtain an article's unique identifier given its number.
    814      * <p>
    815      * @param articleNumber The number of the article to select from the
    816      *       currently selected newsgroup.
    817      * @param pointer    A parameter through which to return the article's
    818      *   number and unique id.  Although the articleId field cannot always
    819      *   be trusted because of server deviations from RFC 977 reply formats,
    820      *   we haven't found a server that misformats this information in response
    821      *   to this particular command.  You may set this parameter to null if
    822      *   you do not desire to retrieve the returned article information.
    823      * @return True if successful, false if not.
    824      * @exception NNTPConnectionClosedException
    825      *      If the NNTP server prematurely closes the connection as a result
    826      *      of the client being idle or some other reason causing the server
    827      *      to send NNTP reply code 400.  This exception may be caught either
    828      *      as an IOException or independently as itself.
    829      * @exception IOException  If an I/O error occurs while either sending a
    830      *      command to the server or receiving a reply from the server.
    831      ***/
    832     public boolean selectArticle(int articleNumber, ArticlePointer pointer)
    833     throws IOException
    834     {
    835         if (!NNTPReply.isPositiveCompletion(stat(articleNumber)))
    836             return false;
    837
    838         if (pointer != null)
    839             __parseArticlePointer(getReplyString(), pointer);
    840
    841         return true;
    842     }
    843
    844
    845     /**** Same as <code> selectArticle(articleNumber, null) </code> ***/
    846     public boolean selectArticle(int articleNumber) throws IOException
    847     {
    848         return selectArticle(articleNumber, null);
    849     }
    850
    851
    852     /****
    853      * Select the article preceeding the currently selected article in the
    854      * currently selected newsgroup and return its number and unique id
    855      * through the pointer parameter.  Because of deviating server
    856      * implementations, the articleId information cannot be trusted.  To
    857      * obtain the article identifier, issue a
    858      * <code> selectArticle(pointer.articleNumber, pointer) </code> immediately
    859      * afterward.
    860      * <p>
    861      * @param pointer    A parameter through which to return the article's
    862      *   number and unique id.  The articleId field cannot always be trusted
    863      *   because of server deviations from RFC 977 reply formats.  You may
    864      *   set this parameter to null if you do not desire to retrieve the
    865      *   returned article information.
    866      * @return True if successful, false if not (e.g., there is no previous
    867      *     article).
    868      * @exception NNTPConnectionClosedException
    869      *      If the NNTP server prematurely closes the connection as a result
    870      *      of the client being idle or some other reason causing the server
    871      *      to send NNTP reply code 400.  This exception may be caught either
    872      *      as an IOException or independently as itself.
    873      * @exception IOException  If an I/O error occurs while either sending a
    874      *      command to the server or receiving a reply from the server.
    875      ***/
    876     public boolean selectPreviousArticle(ArticlePointer pointer)
    877     throws IOException
    878     {
    879         if (!NNTPReply.isPositiveCompletion(last()))
    880             return false;
    881
    882         if (pointer != null)
    883             __parseArticlePointer(getReplyString(), pointer);
    884
    885         return true;
    886     }
    887
    888     /**** Same as <code> selectPreviousArticle(null) </code> ***/
    889     public boolean selectPreviousArticle() throws IOException
    890     {
    891         return selectPreviousArticle(null);
    892     }
    893
    894
    895     /****
    896      * Select the article following the currently selected article in the
    897      * currently selected newsgroup and return its number and unique id
    898      * through the pointer parameter.  Because of deviating server
    899      * implementations, the articleId information cannot be trusted.  To
    900      * obtain the article identifier, issue a
    901      * <code> selectArticle(pointer.articleNumber, pointer) </code> immediately
    902      * afterward.
    903      * <p>
    904      * @param pointer    A parameter through which to return the article's
    905      *   number and unique id.  The articleId field cannot always be trusted
    906      *   because of server deviations from RFC 977 reply formats.  You may
    907      *   set this parameter to null if you do not desire to retrieve the
    908      *   returned article information.
    909      * @return True if successful, false if not (e.g., there is no following
    910      *         article).
    911      * @exception NNTPConnectionClosedException
    912      *      If the NNTP server prematurely closes the connection as a result
    913      *      of the client being idle or some other reason causing the server
    914      *      to send NNTP reply code 400.  This exception may be caught either
    915      *      as an IOException or independently as itself.
    916      * @exception IOException  If an I/O error occurs while either sending a
    917      *      command to the server or receiving a reply from the server.
    918      ***/
    919     public boolean selectNextArticle(ArticlePointer pointer) throws IOException
    920     {
    921         if (!NNTPReply.isPositiveCompletion(next()))
    922             return false;
    923
    924         if (pointer != null)
    925             __parseArticlePointer(getReplyString(), pointer);
    926
    927         return true;
    928     }
    929
    930
    931     /**** Same as <code> selectNextArticle(null) </code> ***/
    932     public boolean selectNextArticle() throws IOException
    933     {
    934         return selectNextArticle(null);
    935     }
    936
    937
    938     /****
    939      * List all newsgroups served by the NNTP server.  If no newsgroups
    940      * are served, a zero length array will be returned.  If the command
    941      * fails, null will be returned.
    942      * <p>
    943      * @return An array of NewsgroupInfo instances containing the information
    944      *    for each newsgroup served by the NNTP server.   If no newsgroups
    945      *    are served, a zero length array will be returned.  If the command
    946      *    fails, null will be returned.
    947      * @exception NNTPConnectionClosedException
    948      *      If the NNTP server prematurely closes the connection as a result
    949      *      of the client being idle or some other reason causing the server
    950      *      to send NNTP reply code 400.  This exception may be caught either
    951      *      as an IOException or independently as itself.
    952      * @exception IOException  If an I/O error occurs while either sending a
    953      *      command to the server or receiving a reply from the server.
    954      ***/
    955     public NewsgroupInfo[] listNewsgroups() throws IOException
    956     {
    957         if (!NNTPReply.isPositiveCompletion(list()))
    958             return null;
    959
    960         return __readNewsgroupListing();
    961     }
    962
    963
    964     /****
    965      * List all new newsgroups added to the NNTP server since a particular
    966      * date subject to the conditions of the specified query.  If no new
    967      * newsgroups were added, a zero length array will be returned.  If the
    968      * command fails, null will be returned.
    969      * <p>
    970      * @param query  The query restricting how to search for new newsgroups.
    971      * @return An array of NewsgroupInfo instances containing the information
    972      *    for each new newsgroup added to the NNTP server.   If no newsgroups
    973      *    were added, a zero length array will be returned.  If the command
    974      *    fails, null will be returned.
    975      * @exception NNTPConnectionClosedException
    976      *      If the NNTP server prematurely closes the connection as a result
    977      *      of the client being idle or some other reason causing the server
    978      *      to send NNTP reply code 400.  This exception may be caught either
    979      *      as an IOException or independently as itself.
    980      * @exception IOException  If an I/O error occurs while either sending a
    981      *      command to the server or receiving a reply from the server.
    982      ***/
    983     public NewsgroupInfo[] listNewNewsgroups(NewGroupsOrNewsQuery query)
    984     throws IOException
    985     {
    986         if (!NNTPReply.isPositiveCompletion(newgroups(
    987                                                 query.getDate(), query.getTime(),
    988                                                 query.isGMT(), query.getDistributions())))
    989             return null;
    990
    991         return __readNewsgroupListing();
    992     }
    993
    994
    995     /****
    996      * List all new articles added to the NNTP server since a particular
    997      * date subject to the conditions of the specified query.  If no new
    998      * new news is found, a zero length array will be returned.  If the
    999      * command fails, null will be returned.  You must add at least one
    1000      * newsgroup to the query, else the command will fail.  Each String
    1001      * in the returned array is a unique message identifier including the
    1002      * enclosing < and >.
    1003      * <p>
    1004      * @param query  The query restricting how to search for new news.  You
    1005      *    must add at least one newsgroup to the query.
    1006      * @return An array of String instances containing the unique message
    1007      *    identifiers for each new article added to the NNTP server.  If no
    1008      *    new news is found, a zero length array will be returned.  If the
    1009      *    command fails, null will be returned.
    1010      * @exception NNTPConnectionClosedException
    1011      *      If the NNTP server prematurely closes the connection as a result
    1012      *      of the client being idle or some other reason causing the server
    1013      *      to send NNTP reply code 400.  This exception may be caught either
    1014      *      as an IOException or independently as itself.
    1015      * @exception IOException  If an I/O error occurs while either sending a
    1016      *      command to the server or receiving a reply from the server.
    1017      ***/
    1018     public String[] listNewNews(NewGroupsOrNewsQuery query)
    1019     throws IOException
    1020     {
    1021         int size;
    1022         String line;
    1023         Vector list;
    1024         String[] result;
    1025         BufferedReader reader;
    1026
    1027         if (!NNTPReply.isPositiveCompletion(newnews(
    1028                                                 query.getNewsgroups(), query.getDate(), query.getTime(),
    1029                                                 query.isGMT(), query.getDistributions())))
    1030             return null;
    1031
    1032         list = new Vector();
    1033         reader = new BufferedReader(new DotTerminatedMessageReader(_reader));
    1034
    1035         while ((line = reader.readLine()) != null)
    1036             list.addElement(line);
    1037
    1038         size = list.size();
    1039
    1040         if (size < 1)
    1041             return new String[0];
    1042
    1043         result = new String[size];
    1044         list.copyInto(result);
    1045
    1046         return result;
    1047     }
    1048
    1049     /****
    1050      * There are a few NNTPClient methods that do not complete the
    1051      * entire sequence of NNTP commands to complete a transaction.  These
    1052      * commands require some action by the programmer after the reception
    1053      * of a positive preliminary command.  After the programmer's code
    1054      * completes its actions, it must call this method to receive
    1055      * the completion reply from the server and verify the success of the
    1056      * entire transaction.
    1057      * <p>
    1058      * For example
    1059      * <pre>
    1060      * writer = client.postArticle();
    1061      * if(writer == null) // failure
    1062      *   return false;
    1063      * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
    1064      * header.addNewsgroup("alt.test");
    1065      * writer.write(header.toString());
    1066      * writer.write("This is just a test");
    1067      * writer.close();
    1068      * if(!client.completePendingCommand()) // failure
    1069      *   return false;
    1070      * </pre>
    1071      * <p>
    1072      * @return True if successfully completed, false if not.
    1073      * @exception NNTPConnectionClosedException
    1074      *      If the NNTP server prematurely closes the connection as a result
    1075      *      of the client being idle or some other reason causing the server
    1076      *      to send NNTP reply code 400.  This exception may be caught either
    1077      *      as an IOException or independently as itself.
    1078      * @exception IOException  If an I/O error occurs while either sending a
    1079      *      command to the server or receiving a reply from the server.
    1080      ***/
    1081     public boolean completePendingCommand() throws IOException
    1082     {
    1083         return NNTPReply.isPositiveCompletion(getReply());
    1084     }
    1085
    1086     /****
    1087      * Post an article to the NNTP server.  This method returns a
    1088      * DotTerminatedMessageWriter instance to which the article can be
    1089      * written.  Null is returned if the posting attempt fails.  You
    1090      * should check <a href="org.apache.commons.nntp.NNTP.html#isAllowedToPost">
    1091      * isAllowedToPost() </a> before trying to post.  However, a posting
    1092      * attempt can fail due to malformed headers.
    1093      * <p>
    1094      * You must not issue any commands to the NNTP server (i.e., call any
    1095      * (other methods) until you finish writing to the returned Writer
    1096      * instance and close it.  The NNTP protocol uses the same stream for
    1097      * issuing commands as it does for returning results.  Therefore the
    1098      * returned Writer actually writes directly to the NNTP connection.
    1099      * After you close the writer, you can execute new commands.  If you
    1100      * do not follow these requirements your program will not work properly.
    1101      * <p>
    1102      * Different NNTP servers will require different header formats, but
    1103      * you can use the provided
    1104      * <a href="org.apache.commons.net.nntp.SimpleNNTPHeader.html"> SimpleNNTPHeader </a>
    1105      * class to construct the bare minimum acceptable header for most
    1106      * news readers.  To construct more complicated headers you should
    1107      * refer to RFC 822.  When the Java Mail API is finalized, you will be
    1108      * able to use it to compose fully compliant Internet text messages.
    1109      * The DotTerminatedMessageWriter takes care of doubling line-leading
    1110      * dots and ending the message with a single dot upon closing, so all
    1111      * you have to worry about is writing the header and the message.
    1112      * <p>
    1113      * Upon closing the returned Writer, you need to call
    1114      * <a href="#completePendingCommand"> completePendingCommand() </a>
    1115      * to finalize the posting and verify its success or failure from
    1116      * the server reply.
    1117      * <p>
    1118      * @return A DotTerminatedMessageWriter to which the article (including
    1119      *      header) can be written.  Returns null if the command fails.
    1120      * @exception IOException  If an I/O error occurs while either sending a
    1121      *      command to the server or receiving a reply from the server.
    1122      ***/
    1123     public Writer postArticle() throws IOException
    1124     {
    1125         if (!NNTPReply.isPositiveIntermediate(post()))
    1126             return null;
    1127
    1128         return new DotTerminatedMessageWriter(_writer);
    1129     }
    1130
    1131
    1132     public Writer forwardArticle(String articleId) throws IOException
    1133     {
    1134         if (!NNTPReply.isPositiveIntermediate(ihave(articleId)))
    1135             return null;
    1136
    1137         return new DotTerminatedMessageWriter(_writer);
    1138     }
    1139
    1140
    1141     /****
    1142      * Logs out of the news server gracefully by sending the QUIT command.
    1143      * However, you must still disconnect from the server before you can open
    1144      * a new connection.
    1145      * <p>
    1146      * @return True if successfully completed, false if not.
    1147      * @exception IOException  If an I/O error occurs while either sending a
    1148      *      command to the server or receiving a reply from the server.
    1149      ***/
    1150     public boolean logout() throws IOException
    1151     {
    1152         return NNTPReply.isPositiveCompletion(quit());
    1153     }
    1154
    1155 }

This page was automatically generated by Maven