KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > net > nntp > NNTPClient


1 /*
2  * Copyright 2001-2005 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.net.nntp;
17
18 import java.io.BufferedReader JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.Reader JavaDoc;
21 import java.io.StringWriter JavaDoc;
22 import java.io.Writer JavaDoc;
23 import java.util.StringTokenizer JavaDoc;
24 import java.util.Vector JavaDoc;
25 import org.apache.commons.net.io.DotTerminatedMessageReader;
26 import org.apache.commons.net.io.DotTerminatedMessageWriter;
27 import org.apache.commons.net.io.Util;
28 import org.apache.commons.net.MalformedServerReplyException;
29
30 /***
31  * NNTPClient encapsulates all the functionality necessary to post and
32  * retrieve articles from an NNTP server. As with all classes derived
33  * from {@link org.apache.commons.net.SocketClient},
34  * you must first connect to the server with
35  * {@link org.apache.commons.net.SocketClient#connect connect }
36  * before doing anything, and finally
37  * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() }
38  * after you're completely finished interacting with the server.
39  * Remember that the
40  * {@link org.apache.commons.net.nntp.NNTP#isAllowedToPost isAllowedToPost()}
41  * method is defined in
42  * {@link org.apache.commons.net.nntp.NNTP}.
43  * <p>
44  * You should keep in mind that the NNTP server may choose to prematurely
45  * close a connection if the client has been idle for longer than a
46  * given time period or if the server is being shutdown by the operator or
47  * some other reason. The NNTP class will detect a
48  * premature NNTP server connection closing when it receives a
49  * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
50  * response to a command.
51  * When that occurs, the NNTP class method encountering that reply will throw
52  * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
53  * .
54  * <code>NNTPConectionClosedException</code>
55  * is a subclass of <code> IOException </code> and therefore need not be
56  * caught separately, but if you are going to catch it separately, its
57  * catch block must appear before the more general <code> IOException </code>
58  * catch block. When you encounter an
59  * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
60  * , you must disconnect the connection with
61  * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() }
62  * to properly clean up the
63  * system resources used by NNTP. Before disconnecting, you may check the
64  * last reply code and text with
65  * {@link org.apache.commons.net.nntp.NNTP#getReplyCode getReplyCode } and
66  * {@link org.apache.commons.net.nntp.NNTP#getReplyString getReplyString }.
67  * <p>
68  * Rather than list it separately for each method, we mention here that
69  * every method communicating with the server and throwing an IOException
70  * can also throw a
71  * {@link org.apache.commons.net.MalformedServerReplyException}
72  * , which is a subclass
73  * of IOException. A MalformedServerReplyException will be thrown when
74  * the reply received from the server deviates enough from the protocol
75  * specification that it cannot be interpreted in a useful manner despite
76  * attempts to be as lenient as possible.
77  * <p>
78  * <p>
79  * @author Daniel F. Savarese
80  * @author Rory Winston
81  * @author Ted Wise
82  * @see NNTP
83  * @see NNTPConnectionClosedException
84  * @see org.apache.commons.net.MalformedServerReplyException
85  ***/

86
87 public class NNTPClient extends NNTP
88 {
89
90     private void __parseArticlePointer(String JavaDoc reply, ArticlePointer pointer)
91     throws MalformedServerReplyException
92     {
93         StringTokenizer JavaDoc tokenizer;
94
95         // Do loop is a kluge to simulate goto
96
do
97         {
98             tokenizer = new StringTokenizer JavaDoc(reply);
99
100             if (tokenizer.countTokens() < 3)
101                 break;
102
103             // Skip numeric response value
104
tokenizer.nextToken();
105             // Get article number
106
try
107             {
108                 pointer.articleNumber = Integer.parseInt(tokenizer.nextToken());
109             }
110             catch (NumberFormatException JavaDoc e)
111             {
112                 break;
113             }
114
115             // Get article id
116
pointer.articleId = tokenizer.nextToken();
117             return ;
118         }
119         while (false);
120
121         throw new MalformedServerReplyException(
122             "Could not parse article pointer.\nServer reply: " + reply);
123     }
124
125
126     private void __parseGroupReply(String JavaDoc reply, NewsgroupInfo info)
127     throws MalformedServerReplyException
128     {
129         String JavaDoc count, first, last;
130         StringTokenizer JavaDoc tokenizer;
131
132         // Do loop is a kluge to simulate goto
133
do
134         {
135             tokenizer = new StringTokenizer JavaDoc(reply);
136
137             if (tokenizer.countTokens() < 5)
138                 break;
139
140             // Skip numeric response value
141
tokenizer.nextToken();
142             // Get estimated article count
143
count = tokenizer.nextToken();
144             // Get first article number
145
first = tokenizer.nextToken();
146             // Get last article number
147
last = tokenizer.nextToken();
148             // Get newsgroup name
149
info._setNewsgroup(tokenizer.nextToken());
150
151             try
152             {
153                 info._setArticleCount(Integer.parseInt(count));
154                 info._setFirstArticle(Integer.parseInt(first));
155                 info._setLastArticle(Integer.parseInt(last));
156             }
157             catch (NumberFormatException JavaDoc e)
158             {
159                 break;
160             }
161
162             info._setPostingPermission(NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
163             return ;
164         }
165         while (false);
166
167         throw new MalformedServerReplyException(
168             "Could not parse newsgroup info.\nServer reply: " + reply);
169     }
170
171
172     private NewsgroupInfo __parseNewsgroupListEntry(String JavaDoc entry)
173     {
174         NewsgroupInfo result;
175         StringTokenizer JavaDoc tokenizer;
176         int lastNum, firstNum;
177         String JavaDoc last, first, permission;
178
179         result = new NewsgroupInfo();
180         tokenizer = new StringTokenizer JavaDoc(entry);
181
182         if (tokenizer.countTokens() < 4)
183             return null;
184
185         result._setNewsgroup(tokenizer.nextToken());
186         last = tokenizer.nextToken();
187         first = tokenizer.nextToken();
188         permission = tokenizer.nextToken();
189
190         try
191         {
192             lastNum = Integer.parseInt(last);
193             firstNum = Integer.parseInt(first);
194             result._setFirstArticle(firstNum);
195             result._setLastArticle(lastNum);
196
197         if((firstNum == 0) && (lastNum == 0))
198             result._setArticleCount(0);
199         else
200             result._setArticleCount(lastNum - firstNum + 1);
201         }
202         catch (NumberFormatException JavaDoc e)
203         {
204             return null;
205         }
206
207         switch (permission.charAt(0))
208         {
209         case 'y':
210         case 'Y':
211             result._setPostingPermission(
212                 NewsgroupInfo.PERMITTED_POSTING_PERMISSION);
213             break;
214         case 'n':
215         case 'N':
216             result._setPostingPermission(
217                 NewsgroupInfo.PROHIBITED_POSTING_PERMISSION);
218             break;
219         case 'm':
220         case 'M':
221             result._setPostingPermission(
222                 NewsgroupInfo.MODERATED_POSTING_PERMISSION);
223             break;
224         default:
225             result._setPostingPermission(
226                 NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
227             break;
228         }
229
230         return result;
231     }
232
233     private NewsgroupInfo[] __readNewsgroupListing() throws IOException JavaDoc
234     {
235         int size;
236         String JavaDoc line;
237         Vector JavaDoc list;
238         BufferedReader JavaDoc reader;
239         NewsgroupInfo tmp, info[];
240
241         reader = new BufferedReader JavaDoc(new DotTerminatedMessageReader(_reader_));
242         // Start of with a big vector because we may be reading a very large
243
// amount of groups.
244
list = new Vector JavaDoc(2048);
245
246         while ((line = reader.readLine()) != null)
247         {
248             tmp = __parseNewsgroupListEntry(line);
249             if (tmp != null)
250                 list.addElement(tmp);
251             else
252                 throw new MalformedServerReplyException(line);
253         }
254
255         if ((size = list.size()) < 1)
256             return new NewsgroupInfo[0];
257
258         info = new NewsgroupInfo[size];
259         list.copyInto(info);
260
261         return info;
262     }
263
264
265     private Reader JavaDoc __retrieve(int command,
266                               String JavaDoc articleId, ArticlePointer pointer)
267     throws IOException JavaDoc
268     {
269         Reader JavaDoc reader;
270
271         if (articleId != null)
272         {
273             if (!NNTPReply.isPositiveCompletion(sendCommand(command, articleId)))
274                 return null;
275         }
276         else
277         {
278             if (!NNTPReply.isPositiveCompletion(sendCommand(command)))
279                 return null;
280         }
281
282
283         if (pointer != null)
284             __parseArticlePointer(getReplyString(), pointer);
285
286         reader = new DotTerminatedMessageReader(_reader_);
287         return reader;
288     }
289
290
291     private Reader JavaDoc __retrieve(int command,
292                               int articleNumber, ArticlePointer pointer)
293     throws IOException JavaDoc
294     {
295         Reader JavaDoc reader;
296
297         if (!NNTPReply.isPositiveCompletion(sendCommand(command,
298                                             Integer.toString(articleNumber))))
299             return null;
300
301         if (pointer != null)
302             __parseArticlePointer(getReplyString(), pointer);
303
304         reader = new DotTerminatedMessageReader(_reader_);
305         return reader;
306     }
307
308
309
310     /***
311      * Retrieves an article from the NNTP server. The article is referenced
312      * by its unique article identifier (including the enclosing &lt and &gt).
313      * The article number and identifier contained in the server reply
314      * are returned through an ArticlePointer. The <code> articleId </code>
315      * field of the ArticlePointer cannot always be trusted because some
316      * NNTP servers do not correctly follow the RFC 977 reply format.
317      * <p>
318      * A DotTerminatedMessageReader is returned from which the article can
319      * be read. If the article does not exist, null is returned.
320      * <p>
321      * You must not issue any commands to the NNTP server (i.e., call any
322      * other methods) until you finish reading the message from the returned
323      * Reader instance.
324      * The NNTP protocol uses the same stream for issuing commands as it does
325      * for returning results. Therefore the returned Reader actually reads
326      * directly from the NNTP connection. After the end of message has been
327      * reached, new commands can be executed and their replies read. If
328      * you do not follow these requirements, your program will not work
329      * properly.
330      * <p>
331      * @param articleId The unique article identifier of the article to
332      * retrieve. If this parameter is null, the currently selected
333      * article is retrieved.
334      * @param pointer A parameter through which to return the article's
335      * number and unique id. The articleId field cannot always be trusted
336      * because of server deviations from RFC 977 reply formats. You may
337      * set this parameter to null if you do not desire to retrieve the
338      * returned article information.
339      * @return A DotTerminatedMessageReader instance from which the article
340      * be read. null if the article does not exist.
341      * @exception NNTPConnectionClosedException
342      * If the NNTP server prematurely closes the connection as a result
343      * of the client being idle or some other reason causing the server
344      * to send NNTP reply code 400. This exception may be caught either
345      * as an IOException or independently as itself.
346      * @exception IOException If an I/O error occurs while either sending a
347      * command to the server or receiving a reply from the server.
348      ***/

349     public Reader JavaDoc retrieveArticle(String JavaDoc articleId, ArticlePointer pointer)
350     throws IOException JavaDoc
351     {
352         return __retrieve(NNTPCommand.ARTICLE, articleId, pointer);
353
354     }
355
356     /*** Same as <code> retrieveArticle(articleId, null) </code> ***/
357     public Reader JavaDoc retrieveArticle(String JavaDoc articleId) throws IOException JavaDoc
358     {
359         return retrieveArticle(articleId, null);
360     }
361
362     /*** Same as <code> retrieveArticle(null) </code> ***/
363     public Reader JavaDoc retrieveArticle() throws IOException JavaDoc
364     {
365         return retrieveArticle(null);
366     }
367
368
369     /***
370      * Retrieves an article from the currently selected newsgroup. The
371      * article is referenced by its article number.
372      * The article number and identifier contained in the server reply
373      * are returned through an ArticlePointer. The <code> articleId </code>
374      * field of the ArticlePointer cannot always be trusted because some
375      * NNTP servers do not correctly follow the RFC 977 reply format.
376      * <p>
377      * A DotTerminatedMessageReader is returned from which the article can
378      * be read. If the article does not exist, null is returned.
379      * <p>
380      * You must not issue any commands to the NNTP server (i.e., call any
381      * other methods) until you finish reading the message from the returned
382      * Reader instance.
383      * The NNTP protocol uses the same stream for issuing commands as it does
384      * for returning results. Therefore the returned Reader actually reads
385      * directly from the NNTP connection. After the end of message has been
386      * reached, new commands can be executed and their replies read. If
387      * you do not follow these requirements, your program will not work
388      * properly.
389      * <p>
390      * @param articleNumber The number of the the article to
391      * retrieve.
392      * @param pointer A parameter through which to return the article's
393      * number and unique id. The articleId field cannot always be trusted
394      * because of server deviations from RFC 977 reply formats. You may
395      * set this parameter to null if you do not desire to retrieve the
396      * returned article information.
397      * @return A DotTerminatedMessageReader instance from which the article
398      * be read. null if the article does not exist.
399      * @exception NNTPConnectionClosedException
400      * If the NNTP server prematurely closes the connection as a result
401      * of the client being idle or some other reason causing the server
402      * to send NNTP reply code 400. This exception may be caught either
403      * as an IOException or independently as itself.
404      * @exception IOException If an I/O error occurs while either sending a
405      * command to the server or receiving a reply from the server.
406      ***/

407     public Reader JavaDoc retrieveArticle(int articleNumber, ArticlePointer pointer)
408     throws IOException JavaDoc
409     {
410         return __retrieve(NNTPCommand.ARTICLE, articleNumber, pointer);
411     }
412
413     /*** Same as <code> retrieveArticle(articleNumber, null) </code> ***/
414     public Reader JavaDoc retrieveArticle(int articleNumber) throws IOException JavaDoc
415     {
416         return retrieveArticle(articleNumber, null);
417     }
418
419
420
421     /***
422      * Retrieves an article header from the NNTP server. The article is
423      * referenced
424      * by its unique article identifier (including the enclosing &lt and &gt).
425      * The article number and identifier contained in the server reply
426      * are returned through an ArticlePointer. The <code> articleId </code>
427      * field of the ArticlePointer cannot always be trusted because some
428      * NNTP servers do not correctly follow the RFC 977 reply format.
429      * <p>
430      * A DotTerminatedMessageReader is returned from which the article can
431      * be read. If the article does not exist, null is returned.
432      * <p>
433      * You must not issue any commands to the NNTP server (i.e., call any
434      * other methods) until you finish reading the message from the returned
435      * Reader instance.
436      * The NNTP protocol uses the same stream for issuing commands as it does
437      * for returning results. Therefore the returned Reader actually reads
438      * directly from the NNTP connection. After the end of message has been
439      * reached, new commands can be executed and their replies read. If
440      * you do not follow these requirements, your program will not work
441      * properly.
442      * <p>
443      * @param articleId The unique article identifier of the article whose
444      * header is being retrieved. If this parameter is null, the
445      * header of the currently selected article is retrieved.
446      * @param pointer A parameter through which to return the article's
447      * number and unique id. The articleId field cannot always be trusted
448      * because of server deviations from RFC 977 reply formats. You may
449      * set this parameter to null if you do not desire to retrieve the
450      * returned article information.
451      * @return A DotTerminatedMessageReader instance from which the article
452      * header can be read. null if the article does not exist.
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 a
459      * command to the server or receiving a reply from the server.
460      ***/

461     public Reader JavaDoc retrieveArticleHeader(String JavaDoc articleId, ArticlePointer pointer)
462     throws IOException JavaDoc
463     {
464         return __retrieve(NNTPCommand.HEAD, articleId, pointer);
465
466     }
467
468     /*** Same as <code> retrieveArticleHeader(articleId, null) </code> ***/
469     public Reader JavaDoc retrieveArticleHeader(String JavaDoc articleId) throws IOException JavaDoc
470     {
471         return retrieveArticleHeader(articleId, null);
472     }
473
474     /*** Same as <code> retrieveArticleHeader(null) </code> ***/
475     public Reader JavaDoc retrieveArticleHeader() throws IOException JavaDoc
476     {
477         return retrieveArticleHeader(null);
478     }
479
480
481     /***
482      * Retrieves an article header from the currently selected newsgroup. The
483      * article is referenced by its article number.
484      * The article number and identifier contained in the server reply
485      * are returned through an ArticlePointer. The <code> articleId </code>
486      * field of the ArticlePointer cannot always be trusted because some
487      * NNTP servers do not correctly follow the RFC 977 reply format.
488      * <p>
489      * A DotTerminatedMessageReader is returned from which the article can
490      * be read. If the article does not exist, null is returned.
491      * <p>
492      * You must not issue any commands to the NNTP server (i.e., call any
493      * other methods) until you finish reading the message from the returned
494      * Reader instance.
495      * The NNTP protocol uses the same stream for issuing commands as it does
496      * for returning results. Therefore the returned Reader actually reads
497      * directly from the NNTP connection. After the end of message has been
498      * reached, new commands can be executed and their replies read. If
499      * you do not follow these requirements, your program will not work
500      * properly.
501      * <p>
502      * @param articleNumber The number of the the article whose header is
503      * being retrieved.
504      * @param pointer A parameter through which to return the article's
505      * number and unique id. The articleId field cannot always be trusted
506      * because of server deviations from RFC 977 reply formats. You may
507      * set this parameter to null if you do not desire to retrieve the
508      * returned article information.
509      * @return A DotTerminatedMessageReader instance from which the article
510      * header can be read. null if the article does not exist.
511      * @exception NNTPConnectionClosedException
512      * If the NNTP server prematurely closes the connection as a result
513      * of the client being idle or some other reason causing the server
514      * to send NNTP reply code 400. This exception may be caught either
515      * as an IOException or independently as itself.
516      * @exception IOException If an I/O error occurs while either sending a
517      * command to the server or receiving a reply from the server.
518      ***/

519     public Reader JavaDoc retrieveArticleHeader(int articleNumber,
520                                         ArticlePointer pointer)
521     throws IOException JavaDoc
522     {
523         return __retrieve(NNTPCommand.HEAD, articleNumber, pointer);
524     }
525
526
527     /*** Same as <code> retrieveArticleHeader(articleNumber, null) </code> ***/
528     public Reader JavaDoc retrieveArticleHeader(int articleNumber) throws IOException JavaDoc
529     {
530         return retrieveArticleHeader(articleNumber, null);
531     }
532
533
534
535     /***
536      * Retrieves an article body from the NNTP server. The article is
537      * referenced
538      * by its unique article identifier (including the enclosing &lt and &gt).
539      * The article number and identifier contained in the server reply
540      * are returned through an ArticlePointer. The <code> articleId </code>
541      * field of the ArticlePointer cannot always be trusted because some
542      * NNTP servers do not correctly follow the RFC 977 reply format.
543      * <p>
544      * A DotTerminatedMessageReader is returned from which the article can
545      * be read. If the article does not exist, null is returned.
546      * <p>
547      * You must not issue any commands to the NNTP server (i.e., call any
548      * other methods) until you finish reading the message from the returned
549      * Reader instance.
550      * The NNTP protocol uses the same stream for issuing commands as it does
551      * for returning results. Therefore the returned Reader actually reads
552      * directly from the NNTP connection. After the end of message has been
553      * reached, new commands can be executed and their replies read. If
554      * you do not follow these requirements, your program will not work
555      * properly.
556      * <p>
557      * @param articleId The unique article identifier of the article whose
558      * body is being retrieved. If this parameter is null, the
559      * body of the currently selected article is retrieved.
560      * @param pointer A parameter through which to return the article's
561      * number and unique id. The articleId field cannot always be trusted
562      * because of server deviations from RFC 977 reply formats. You may
563      * set this parameter to null if you do not desire to retrieve the
564      * returned article information.
565      * @return A DotTerminatedMessageReader instance from which the article
566      * body can be read. null if the article does not exist.
567      * @exception NNTPConnectionClosedException
568      * If the NNTP server prematurely closes the connection as a result
569      * of the client being idle or some other reason causing the server
570      * to send NNTP reply code 400. This exception may be caught either
571      * as an IOException or independently as itself.
572      * @exception IOException If an I/O error occurs while either sending a
573      * command to the server or receiving a reply from the server.
574      ***/

575     public Reader JavaDoc retrieveArticleBody(String JavaDoc articleId, ArticlePointer pointer)
576     throws IOException JavaDoc
577     {
578         return __retrieve(NNTPCommand.BODY, articleId, pointer);
579
580     }
581
582     /*** Same as <code> retrieveArticleBody(articleId, null) </code> ***/
583     public Reader JavaDoc retrieveArticleBody(String JavaDoc articleId) throws IOException JavaDoc
584     {
585         return retrieveArticleBody(articleId, null);
586     }
587
588     /*** Same as <code> retrieveArticleBody(null) </code> ***/
589     public Reader JavaDoc retrieveArticleBody() throws IOException JavaDoc
590     {
591         return retrieveArticleBody(null);
592     }
593
594
595     /***
596      * Retrieves an article body from the currently selected newsgroup. The
597      * article is referenced by its article number.
598      * The article number and identifier contained in the server reply
599      * are returned through an ArticlePointer. The <code> articleId </code>
600      * field of the ArticlePointer cannot always be trusted because some
601      * NNTP servers do not correctly follow the RFC 977 reply format.
602      * <p>
603      * A DotTerminatedMessageReader is returned from which the article can
604      * be read. If the article does not exist, null is returned.
605      * <p>
606      * You must not issue any commands to the NNTP server (i.e., call any
607      * other methods) until you finish reading the message from the returned
608      * Reader instance.
609      * The NNTP protocol uses the same stream for issuing commands as it does
610      * for returning results. Therefore the returned Reader actually reads
611      * directly from the NNTP connection. After the end of message has been
612      * reached, new commands can be executed and their replies read. If
613      * you do not follow these requirements, your program will not work
614      * properly.
615      * <p>
616      * @param articleNumber The number of the the article whose body is
617      * being retrieved.
618      * @param pointer A parameter through which to return the article's
619      * number and unique id. The articleId field cannot always be trusted
620      * because of server deviations from RFC 977 reply formats. You may
621      * set this parameter to null if you do not desire to retrieve the
622      * returned article information.
623      * @return A DotTerminatedMessageReader instance from which the article
624      * body can be read. null if the article does not exist.
625      * @exception NNTPConnectionClosedException
626      * If the NNTP server prematurely closes the connection as a result
627      * of the client being idle or some other reason causing the server
628      * to send NNTP reply code 400. This exception may be caught either
629      * as an IOException or independently as itself.
630      * @exception IOException If an I/O error occurs while either sending a
631      * command to the server or receiving a reply from the server.
632      ***/

633     public Reader JavaDoc retrieveArticleBody(int articleNumber,
634                                       ArticlePointer pointer)
635     throws IOException JavaDoc
636     {
637         return __retrieve(NNTPCommand.BODY, articleNumber, pointer);
638     }
639
640
641     /*** Same as <code> retrieveArticleBody(articleNumber, null) </code> ***/
642     public Reader JavaDoc retrieveArticleBody(int articleNumber) throws IOException JavaDoc
643     {
644         return retrieveArticleBody(articleNumber, null);
645     }
646
647
648     /***
649      * Select the specified newsgroup to be the target of for future article
650      * retrieval and posting operations. Also return the newsgroup
651      * information contained in the server reply through the info parameter.
652      * <p>
653      * @param newsgroup The newsgroup to select.
654      * @param info A parameter through which the newsgroup information of
655      * the selected newsgroup contained in the server reply is returned.
656      * Set this to null if you do not desire this information.
657      * @return True if the newsgroup exists and was selected, false otherwise.
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 boolean selectNewsgroup(String JavaDoc newsgroup, NewsgroupInfo info)
667     throws IOException JavaDoc
668     {
669         if (!NNTPReply.isPositiveCompletion(group(newsgroup)))
670             return false;
671
672         if (info != null)
673             __parseGroupReply(getReplyString(), info);
674
675         return true;
676     }
677
678     /*** Same as <code> selectNewsgroup(newsgroup, null) </code> ***/
679     public boolean selectNewsgroup(String JavaDoc newsgroup) throws IOException JavaDoc
680     {
681         return selectNewsgroup(newsgroup, null);
682     }
683
684     /***
685      * List the command help from the server.
686      * <p>
687      * @return The sever help information.
688      * @exception NNTPConnectionClosedException
689      * If the NNTP server prematurely closes the connection as a result
690      * of the client being idle or some other reason causing the server
691      * to send NNTP reply code 400. This exception may be caught either
692      * as an IOException or independently as itself.
693      * @exception IOException If an I/O error occurs while either sending a
694      * command to the server or receiving a reply from the server.
695      ***/

696     public String JavaDoc listHelp() throws IOException JavaDoc
697     {
698         StringWriter JavaDoc help;
699         Reader JavaDoc reader;
700
701         if (!NNTPReply.isInformational(help()))
702             return null;
703
704         help = new StringWriter JavaDoc();
705         reader = new DotTerminatedMessageReader(_reader_);
706         Util.copyReader(reader, help);
707         reader.close();
708         help.close();
709         return help.toString();
710     }
711
712
713     /***
714      * Select an article by its unique identifier (including enclosing
715      * &lt and &gt) and return its article number and id through the
716      * pointer parameter. This is achieved through the STAT command.
717      * According to RFC 977, this will NOT set the current article pointer
718      * on the server. To do that, you must reference the article by its
719      * number.
720      * <p>
721      * @param articleId The unique article identifier of the article that
722      * is being selectedd. If this parameter is null, the
723      * body of the current article is selected
724      * @param pointer A parameter through which to return the article's
725      * number and unique id. The articleId field cannot always be trusted
726      * because of server deviations from RFC 977 reply formats. You may
727      * set this parameter to null if you do not desire to retrieve the
728      * returned article information.
729      * @return True if successful, false if not.
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 a
736      * command to the server or receiving a reply from the server.
737      ***/

738     public boolean selectArticle(String JavaDoc articleId, ArticlePointer pointer)
739     throws IOException JavaDoc
740     {
741         if (articleId != null)
742         {
743             if (!NNTPReply.isPositiveCompletion(stat(articleId)))
744                 return false;
745         }
746         else
747         {
748             if (!NNTPReply.isPositiveCompletion(stat()))
749                 return false;
750         }
751
752         if (pointer != null)
753             __parseArticlePointer(getReplyString(), pointer);
754
755         return true;
756     }
757
758     /**** Same as <code> selectArticle(articleId, null) </code> ***/
759     public boolean selectArticle(String JavaDoc articleId) throws IOException JavaDoc
760     {
761         return selectArticle(articleId, null);
762     }
763
764     /****
765      * Same as <code> selectArticle(null, articleId) </code>. Useful
766      * for retrieving the current article number.
767      ***/

768     public boolean selectArticle(ArticlePointer pointer) throws IOException JavaDoc
769     {
770         return selectArticle(null, pointer);
771     }
772
773
774     /***
775      * Select an article in the currently selected newsgroup by its number.
776      * and return its article number and id through the
777      * pointer parameter. This is achieved through the STAT command.
778      * According to RFC 977, this WILL set the current article pointer
779      * on the server. Use this command to select an article before retrieving
780      * it, or to obtain an article's unique identifier given its number.
781      * <p>
782      * @param articleNumber The number of the article to select from the
783      * currently selected newsgroup.
784      * @param pointer A parameter through which to return the article's
785      * number and unique id. Although the articleId field cannot always
786      * be trusted because of server deviations from RFC 977 reply formats,
787      * we haven't found a server that misformats this information in response
788      * to this particular command. You may set this parameter to null if
789      * you do not desire to retrieve the returned article information.
790      * @return True if successful, false if not.
791      * @exception NNTPConnectionClosedException
792      * If the NNTP server prematurely closes the connection as a result
793      * of the client being idle or some other reason causing the server
794      * to send NNTP reply code 400. This exception may be caught either
795      * as an IOException or independently as itself.
796      * @exception IOException If an I/O error occurs while either sending a
797      * command to the server or receiving a reply from the server.
798      ***/

799     public boolean selectArticle(int articleNumber, ArticlePointer pointer)
800     throws IOException JavaDoc
801     {
802         if (!NNTPReply.isPositiveCompletion(stat(articleNumber)))
803             return false;
804
805         if (pointer != null)
806             __parseArticlePointer(getReplyString(), pointer);
807
808         return true;
809     }
810
811
812     /*** Same as <code> selectArticle(articleNumber, null) </code> ***/
813     public boolean selectArticle(int articleNumber) throws IOException JavaDoc
814     {
815         return selectArticle(articleNumber, null);
816     }
817
818
819     /***
820      * Select the article preceeding the currently selected article in the
821      * currently selected newsgroup and return its number and unique id
822      * through the pointer parameter. Because of deviating server
823      * implementations, the articleId information cannot be trusted. To
824      * obtain the article identifier, issue a
825      * <code> selectArticle(pointer.articleNumber, pointer) </code> immediately
826      * afterward.
827      * <p>
828      * @param pointer A parameter through which to return the article's
829      * number and unique id. The articleId field cannot always be trusted
830      * because of server deviations from RFC 977 reply formats. You may
831      * set this parameter to null if you do not desire to retrieve the
832      * returned article information.
833      * @return True if successful, false if not (e.g., there is no previous
834      * article).
835      * @exception NNTPConnectionClosedException
836      * If the NNTP server prematurely closes the connection as a result
837      * of the client being idle or some other reason causing the server
838      * to send NNTP reply code 400. This exception may be caught either
839      * as an IOException or independently as itself.
840      * @exception IOException If an I/O error occurs while either sending a
841      * command to the server or receiving a reply from the server.
842      ***/

843     public boolean selectPreviousArticle(ArticlePointer pointer)
844     throws IOException JavaDoc
845     {
846         if (!NNTPReply.isPositiveCompletion(last()))
847             return false;
848
849         if (pointer != null)
850             __parseArticlePointer(getReplyString(), pointer);
851
852         return true;
853     }
854
855     /*** Same as <code> selectPreviousArticle(null) </code> ***/
856     public boolean selectPreviousArticle() throws IOException JavaDoc
857     {
858         return selectPreviousArticle(null);
859     }
860
861
862     /***
863      * Select the article following the currently selected article in the
864      * currently selected newsgroup and return its number and unique id
865      * through the pointer parameter. Because of deviating server
866      * implementations, the articleId information cannot be trusted. To
867      * obtain the article identifier, issue a
868      * <code> selectArticle(pointer.articleNumber, pointer) </code> immediately
869      * afterward.
870      * <p>
871      * @param pointer A parameter through which to return the article's
872      * number and unique id. The articleId field cannot always be trusted
873      * because of server deviations from RFC 977 reply formats. You may
874      * set this parameter to null if you do not desire to retrieve the
875      * returned article information.
876      * @return True if successful, false if not (e.g., there is no following
877      * article).
878      * @exception NNTPConnectionClosedException
879      * If the NNTP server prematurely closes the connection as a result
880      * of the client being idle or some other reason causing the server
881      * to send NNTP reply code 400. This exception may be caught either
882      * as an IOException or independently as itself.
883      * @exception IOException If an I/O error occurs while either sending a
884      * command to the server or receiving a reply from the server.
885      ***/

886     public boolean selectNextArticle(ArticlePointer pointer) throws IOException JavaDoc
887     {
888         if (!NNTPReply.isPositiveCompletion(next()))
889             return false;
890
891         if (pointer != null)
892             __parseArticlePointer(getReplyString(), pointer);
893
894         return true;
895     }
896
897
898     /*** Same as <code> selectNextArticle(null) </code> ***/
899     public boolean selectNextArticle() throws IOException JavaDoc
900     {
901         return selectNextArticle(null);
902     }
903
904
905     /***
906      * List all newsgroups served by the NNTP server. If no newsgroups
907      * are served, a zero length array will be returned. If the command
908      * fails, null will be returned.
909      * <p>
910      * @return An array of NewsgroupInfo instances containing the information
911      * for each newsgroup served by the NNTP server. If no newsgroups
912      * are served, a zero length array will be returned. If the command
913      * fails, null will be returned.
914      * @exception NNTPConnectionClosedException
915      * If the NNTP server prematurely closes the connection as a result
916      * of the client being idle or some other reason causing the server
917      * to send NNTP reply code 400. This exception may be caught either
918      * as an IOException or independently as itself.
919      * @exception IOException If an I/O error occurs while either sending a
920      * command to the server or receiving a reply from the server.
921      ***/

922     public NewsgroupInfo[] listNewsgroups() throws IOException JavaDoc
923     {
924         if (!NNTPReply.isPositiveCompletion(list()))
925             return null;
926
927         return __readNewsgroupListing();
928     }
929
930     /**
931      * An overloaded listNewsgroups() command that allows us to
932      * specify with a pattern what groups we want to list. Wraps the
933      * LIST ACTIVE command.
934      * <p>
935      * @param wildmat a pseudo-regex pattern (cf. RFC 2980)
936      * @return An array of NewsgroupInfo instances containing the information
937      * for each newsgroup served by the NNTP server corresponding to the
938      * supplied pattern. If no such newsgroups are served, a zero length
939      * array will be returned. If the command fails, null will be returned.
940      * @throws IOException
941      */

942     public NewsgroupInfo[] listNewsgroups(String JavaDoc wildmat) throws IOException JavaDoc
943     {
944         if(!NNTPReply.isPositiveCompletion(listActive(wildmat)))
945             return null;
946         return __readNewsgroupListing();
947     }
948
949
950     /***
951      * List all new newsgroups added to the NNTP server since a particular
952      * date subject to the conditions of the specified query. If no new
953      * newsgroups were added, a zero length array will be returned. If the
954      * command fails, null will be returned.
955      * <p>
956      * @param query The query restricting how to search for new newsgroups.
957      * @return An array of NewsgroupInfo instances containing the information
958      * for each new newsgroup added to the NNTP server. If no newsgroups
959      * were added, a zero length array will be returned. If the command
960      * fails, null will be returned.
961      * @exception NNTPConnectionClosedException
962      * If the NNTP server prematurely closes the connection as a result
963      * of the client being idle or some other reason causing the server
964      * to send NNTP reply code 400. This exception may be caught either
965      * as an IOException or independently as itself.
966      * @exception IOException If an I/O error occurs while either sending a
967      * command to the server or receiving a reply from the server.
968      ***/

969     public NewsgroupInfo[] listNewNewsgroups(NewGroupsOrNewsQuery query)
970     throws IOException JavaDoc
971     {
972         if (!NNTPReply.isPositiveCompletion(newgroups(
973                                                 query.getDate(), query.getTime(),
974                                                 query.isGMT(), query.getDistributions())))
975             return null;
976
977         return __readNewsgroupListing();
978     }
979
980
981     /***
982      * List all new articles added to the NNTP server since a particular
983      * date subject to the conditions of the specified query. If no new
984      * new news is found, a zero length array will be returned. If the
985      * command fails, null will be returned. You must add at least one
986      * newsgroup to the query, else the command will fail. Each String
987      * in the returned array is a unique message identifier including the
988      * enclosing &lt and &gt.
989      * <p>
990      * @param query The query restricting how to search for new news. You
991      * must add at least one newsgroup to the query.
992      * @return An array of String instances containing the unique message
993      * identifiers for each new article added to the NNTP server. If no
994      * new news is found, a zero length array will be returned. If the
995      * command fails, null will be returned.
996      * @exception NNTPConnectionClosedException
997      * If the NNTP server prematurely closes the connection as a result
998      * of the client being idle or some other reason causing the server
999      * to send NNTP reply code 400. This exception may be caught either
1000     * as an IOException or independently as itself.
1001     * @exception IOException If an I/O error occurs while either sending a
1002     * command to the server or receiving a reply from the server.
1003     ***/

1004    public String JavaDoc[] listNewNews(NewGroupsOrNewsQuery query)
1005    throws IOException JavaDoc
1006    {
1007        int size;
1008        String JavaDoc line;
1009        Vector JavaDoc list;
1010        String JavaDoc[] result;
1011        BufferedReader JavaDoc reader;
1012
1013        if (!NNTPReply.isPositiveCompletion(newnews(
1014                                                query.getNewsgroups(), query.getDate(), query.getTime(),
1015                                                query.isGMT(), query.getDistributions())))
1016            return null;
1017
1018        list = new Vector JavaDoc();
1019        reader = new BufferedReader JavaDoc(new DotTerminatedMessageReader(_reader_));
1020
1021        while ((line = reader.readLine()) != null)
1022            list.addElement(line);
1023
1024        size = list.size();
1025
1026        if (size < 1)
1027            return new String JavaDoc[0];
1028
1029        result = new String JavaDoc[size];
1030        list.copyInto(result);
1031
1032        return result;
1033    }
1034
1035    /***
1036     * There are a few NNTPClient methods that do not complete the
1037     * entire sequence of NNTP commands to complete a transaction. These
1038     * commands require some action by the programmer after the reception
1039     * of a positive preliminary command. After the programmer's code
1040     * completes its actions, it must call this method to receive
1041     * the completion reply from the server and verify the success of the
1042     * entire transaction.
1043     * <p>
1044     * For example
1045     * <pre>
1046     * writer = client.postArticle();
1047     * if(writer == null) // failure
1048     * return false;
1049     * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
1050     * header.addNewsgroup("alt.test");
1051     * writer.write(header.toString());
1052     * writer.write("This is just a test");
1053     * writer.close();
1054     * if(!client.completePendingCommand()) // failure
1055     * return false;
1056     * </pre>
1057     * <p>
1058     * @return True if successfully completed, false if not.
1059     * @exception NNTPConnectionClosedException
1060     * If the NNTP server prematurely closes the connection as a result
1061     * of the client being idle or some other reason causing the server
1062     * to send NNTP reply code 400. This exception may be caught either
1063     * as an IOException or independently as itself.
1064     * @exception IOException If an I/O error occurs while either sending a
1065     * command to the server or receiving a reply from the server.
1066     ***/

1067    public boolean completePendingCommand() throws IOException JavaDoc
1068    {
1069        return NNTPReply.isPositiveCompletion(getReply());
1070    }
1071
1072    /***
1073     * Post an article to the NNTP server. This method returns a
1074     * DotTerminatedMessageWriter instance to which the article can be
1075     * written. Null is returned if the posting attempt fails. You
1076     * should check {@link NNTP#isAllowedToPost isAllowedToPost() }
1077     * before trying to post. However, a posting
1078     * attempt can fail due to malformed headers.
1079     * <p>
1080     * You must not issue any commands to the NNTP server (i.e., call any
1081     * (other methods) until you finish writing to the returned Writer
1082     * instance and close it. The NNTP protocol uses the same stream for
1083     * issuing commands as it does for returning results. Therefore the
1084     * returned Writer actually writes directly to the NNTP connection.
1085     * After you close the writer, you can execute new commands. If you
1086     * do not follow these requirements your program will not work properly.
1087     * <p>
1088     * Different NNTP servers will require different header formats, but
1089     * you can use the provided
1090     * {@link org.apache.commons.net.nntp.SimpleNNTPHeader}
1091     * class to construct the bare minimum acceptable header for most
1092     * news readers. To construct more complicated headers you should
1093     * refer to RFC 822. When the Java Mail API is finalized, you will be
1094     * able to use it to compose fully compliant Internet text messages.
1095     * The DotTerminatedMessageWriter takes care of doubling line-leading
1096     * dots and ending the message with a single dot upon closing, so all
1097     * you have to worry about is writing the header and the message.
1098     * <p>
1099     * Upon closing the returned Writer, you need to call
1100     * {@link #completePendingCommand completePendingCommand() }
1101     * to finalize the posting and verify its success or failure from
1102     * the server reply.
1103     * <p>
1104     * @return A DotTerminatedMessageWriter to which the article (including
1105     * header) can be written. Returns null if the command fails.
1106     * @exception IOException If an I/O error occurs while either sending a
1107     * command to the server or receiving a reply from the server.
1108     ***/

1109
1110    public Writer JavaDoc postArticle() throws IOException JavaDoc
1111    {
1112        if (!NNTPReply.isPositiveIntermediate(post()))
1113            return null;
1114
1115        return new DotTerminatedMessageWriter(_writer_);
1116    }
1117
1118
1119    public Writer JavaDoc forwardArticle(String JavaDoc articleId) throws IOException JavaDoc
1120    {
1121        if (!NNTPReply.isPositiveIntermediate(ihave(articleId)))
1122            return null;
1123
1124        return new DotTerminatedMessageWriter(_writer_);
1125    }
1126
1127
1128    /***
1129     * Logs out of the news server gracefully by sending the QUIT command.
1130     * However, you must still disconnect from the server before you can open
1131     * a new connection.
1132     * <p>
1133     * @return True if successfully completed, false if not.
1134     * @exception IOException If an I/O error occurs while either sending a
1135     * command to the server or receiving a reply from the server.
1136     ***/

1137    public boolean logout() throws IOException JavaDoc
1138    {
1139        return NNTPReply.isPositiveCompletion(quit());
1140    }
1141
1142
1143    /**
1144     * Log into a news server by sending the AUTHINFO USER/AUTHINFO
1145     * PASS command sequence. This is usually sent in response to a
1146     * 480 reply code from the NNTP server.
1147     * <p>
1148     * @param username a valid username
1149     * @param password the corresponding password
1150     * @return True for successful login, false for a failure
1151     * @throws IOException
1152     */

1153    public boolean authenticate(String JavaDoc username, String JavaDoc password)
1154        throws IOException JavaDoc
1155    {
1156        int replyCode = authinfoUser(username);
1157
1158        if (replyCode == NNTPReply.MORE_AUTH_INFO_REQUIRED)
1159            {
1160                replyCode = authinfoPass(password);
1161
1162                if (replyCode == NNTPReply.AUTHENTICATION_ACCEPTED)
1163                    {
1164                        _isAllowedToPost = true;
1165                        return true;
1166                    }
1167            }
1168        return false;
1169    }
1170
1171    /***
1172     * Private implementation of XOVER functionality.
1173     *
1174     * See {@link NNTP#xover}
1175     * for legal agument formats. Alternatively, read RFC 2980 :-)
1176     * <p>
1177     * @param articleRange
1178     * @return Returns a DotTerminatedMessageReader if successful, null
1179     * otherwise
1180     * @exception IOException
1181     */

1182    private Reader JavaDoc __retrieveArticleInfo(String JavaDoc articleRange)
1183        throws IOException JavaDoc
1184    {
1185        if (!NNTPReply.isPositiveCompletion(xover(articleRange)))
1186            return null;
1187
1188        return new DotTerminatedMessageReader(_reader_);
1189    }
1190
1191    /**
1192     * Return article headers for a specified post.
1193     * <p>
1194     * @param articleNumber the article to retrieve headers for
1195     * @return a DotTerminatedReader if successful, null otherwise
1196     * @throws IOException
1197     */

1198    public Reader JavaDoc retrieveArticleInfo(int articleNumber) throws IOException JavaDoc
1199    {
1200        return __retrieveArticleInfo(Integer.toString(articleNumber));
1201    }
1202
1203    /**
1204     * Return article headers for all articles between lowArticleNumber
1205     * and highArticleNumber, inclusively.
1206     * <p>
1207     * @param lowArticleNumber
1208     * @param highArticleNumber
1209     * @return a DotTerminatedReader if successful, null otherwise
1210     * @throws IOException
1211     */

1212    public Reader JavaDoc retrieveArticleInfo(int lowArticleNumber,
1213                                      int highArticleNumber)
1214        throws IOException JavaDoc
1215    {
1216        return
1217            __retrieveArticleInfo(new String JavaDoc(lowArticleNumber + "-" +
1218                                             highArticleNumber));
1219    }
1220
1221    /***
1222     * Private implementation of XHDR functionality.
1223     *
1224     * See {@link NNTP#xhdr}
1225     * for legal agument formats. Alternatively, read RFC 1036.
1226     * <p>
1227     * @param header
1228     * @param articleRange
1229     * @return Returns a DotTerminatedMessageReader if successful, null
1230     * otherwise
1231     * @exception IOException
1232     */

1233    private Reader JavaDoc __retrieveHeader(String JavaDoc header, String JavaDoc articleRange)
1234        throws IOException JavaDoc
1235    {
1236        if (!NNTPReply.isPositiveCompletion(xhdr(header, articleRange)))
1237            return null;
1238
1239        return new DotTerminatedMessageReader(_reader_);
1240    }
1241
1242    /**
1243     * Return an article header for a specified post.
1244     * <p>
1245     * @param header the header to retrieve
1246     * @param articleNumber the article to retrieve the header for
1247     * @return a DotTerminatedReader if successful, null otherwise
1248     * @throws IOException
1249     */

1250    public Reader JavaDoc retrieveHeader(String JavaDoc header, int articleNumber)
1251        throws IOException JavaDoc
1252    {
1253        return __retrieveHeader(header, Integer.toString(articleNumber));
1254    }
1255
1256    /**
1257     * Return an article header for all articles between lowArticleNumber
1258     * and highArticleNumber, inclusively.
1259     * <p>
1260     * @param header
1261     * @param lowArticleNumber
1262     * @param highArticleNumber
1263     * @return a DotTerminatedReader if successful, null otherwise
1264     * @throws IOException
1265     */

1266    public Reader JavaDoc retrieveHeader(String JavaDoc header, int lowArticleNumber,
1267                                 int highArticleNumber)
1268        throws IOException JavaDoc
1269    {
1270        return
1271            __retrieveHeader(header,
1272                             new String JavaDoc(lowArticleNumber + "-" +
1273                                        highArticleNumber));
1274    }
1275}
1276
1277
1278/* Emacs configuration
1279 * Local variables: **
1280 * mode: java **
1281 * c-basic-offset: 4 **
1282 * indent-tabs-mode: nil **
1283 * End: **
1284 */

1285
Popular Tags