%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
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; |
|
19 | import java.io.IOException; |
|
20 | import java.io.Reader; |
|
21 | import java.io.StringWriter; |
|
22 | import java.io.Writer; |
|
23 | import java.util.StringTokenizer; |
|
24 | import java.util.Vector; |
|
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 | 0 | public class NNTPClient extends NNTP |
88 | { |
|
89 | ||
90 | private void __parseArticlePointer(String reply, ArticlePointer pointer) |
|
91 | throws MalformedServerReplyException |
|
92 | { |
|
93 | StringTokenizer tokenizer; |
|
94 | ||
95 | // Do loop is a kluge to simulate goto |
|
96 | do |
|
97 | { |
|
98 | 0 | tokenizer = new StringTokenizer(reply); |
99 | ||
100 | 0 | if (tokenizer.countTokens() < 3) |
101 | 0 | break; |
102 | ||
103 | // Skip numeric response value |
|
104 | 0 | tokenizer.nextToken(); |
105 | // Get article number |
|
106 | try |
|
107 | { |
|
108 | 0 | pointer.articleNumber = Integer.parseInt(tokenizer.nextToken()); |
109 | } |
|
110 | 0 | catch (NumberFormatException e) |
111 | { |
|
112 | 0 | break; |
113 | 0 | } |
114 | ||
115 | // Get article id |
|
116 | 0 | pointer.articleId = tokenizer.nextToken(); |
117 | 0 | return ; |
118 | } |
|
119 | while (false); |
|
120 | ||
121 | 0 | throw new MalformedServerReplyException( |
122 | "Could not parse article pointer.\nServer reply: " + reply); |
|
123 | } |
|
124 | ||
125 | ||
126 | private void __parseGroupReply(String reply, NewsgroupInfo info) |
|
127 | throws MalformedServerReplyException |
|
128 | { |
|
129 | String count, first, last; |
|
130 | StringTokenizer tokenizer; |
|
131 | ||
132 | // Do loop is a kluge to simulate goto |
|
133 | do |
|
134 | { |
|
135 | 0 | tokenizer = new StringTokenizer(reply); |
136 | ||
137 | 0 | if (tokenizer.countTokens() < 5) |
138 | 0 | break; |
139 | ||
140 | // Skip numeric response value |
|
141 | 0 | tokenizer.nextToken(); |
142 | // Get estimated article count |
|
143 | 0 | count = tokenizer.nextToken(); |
144 | // Get first article number |
|
145 | 0 | first = tokenizer.nextToken(); |
146 | // Get last article number |
|
147 | 0 | last = tokenizer.nextToken(); |
148 | // Get newsgroup name |
|
149 | 0 | info._setNewsgroup(tokenizer.nextToken()); |
150 | ||
151 | try |
|
152 | { |
|
153 | 0 | info._setArticleCount(Integer.parseInt(count)); |
154 | 0 | info._setFirstArticle(Integer.parseInt(first)); |
155 | 0 | info._setLastArticle(Integer.parseInt(last)); |
156 | } |
|
157 | 0 | catch (NumberFormatException e) |
158 | { |
|
159 | 0 | break; |
160 | 0 | } |
161 | ||
162 | 0 | info._setPostingPermission(NewsgroupInfo.UNKNOWN_POSTING_PERMISSION); |
163 | 0 | return ; |
164 | } |
|
165 | while (false); |
|
166 | ||
167 | 0 | throw new MalformedServerReplyException( |
168 | "Could not parse newsgroup info.\nServer reply: " + reply); |
|
169 | } |
|
170 | ||
171 | ||
172 | private NewsgroupInfo __parseNewsgroupListEntry(String entry) |
|
173 | { |
|
174 | NewsgroupInfo result; |
|
175 | StringTokenizer tokenizer; |
|
176 | int lastNum, firstNum; |
|
177 | String last, first, permission; |
|
178 | ||
179 | 0 | result = new NewsgroupInfo(); |
180 | 0 | tokenizer = new StringTokenizer(entry); |
181 | ||
182 | 0 | if (tokenizer.countTokens() < 4) |
183 | 0 | return null; |
184 | ||
185 | 0 | result._setNewsgroup(tokenizer.nextToken()); |
186 | 0 | last = tokenizer.nextToken(); |
187 | 0 | first = tokenizer.nextToken(); |
188 | 0 | permission = tokenizer.nextToken(); |
189 | ||
190 | try |
|
191 | { |
|
192 | 0 | lastNum = Integer.parseInt(last); |
193 | 0 | firstNum = Integer.parseInt(first); |
194 | 0 | result._setFirstArticle(firstNum); |
195 | 0 | result._setLastArticle(lastNum); |
196 | ||
197 | 0 | if((firstNum == 0) && (lastNum == 0)) |
198 | 0 | result._setArticleCount(0); |
199 | else |
|
200 | 0 | result._setArticleCount(lastNum - firstNum + 1); |
201 | } |
|
202 | 0 | catch (NumberFormatException e) |
203 | { |
|
204 | 0 | return null; |
205 | 0 | } |
206 | ||
207 | 0 | switch (permission.charAt(0)) |
208 | { |
|
209 | case 'y': |
|
210 | case 'Y': |
|
211 | 0 | result._setPostingPermission( |
212 | NewsgroupInfo.PERMITTED_POSTING_PERMISSION); |
|
213 | 0 | break; |
214 | case 'n': |
|
215 | case 'N': |
|
216 | 0 | result._setPostingPermission( |
217 | NewsgroupInfo.PROHIBITED_POSTING_PERMISSION); |
|
218 | 0 | break; |
219 | case 'm': |
|
220 | case 'M': |
|
221 | 0 | result._setPostingPermission( |
222 | NewsgroupInfo.MODERATED_POSTING_PERMISSION); |
|
223 | 0 | break; |
224 | default: |
|
225 | 0 | result._setPostingPermission( |
226 | NewsgroupInfo.UNKNOWN_POSTING_PERMISSION); |
|
227 | break; |
|
228 | } |
|
229 | ||
230 | 0 | return result; |
231 | } |
|
232 | ||
233 | private NewsgroupInfo[] __readNewsgroupListing() throws IOException |
|
234 | { |
|
235 | int size; |
|
236 | String line; |
|
237 | Vector list; |
|
238 | BufferedReader reader; |
|
239 | NewsgroupInfo tmp, info[]; |
|
240 | ||
241 | 0 | reader = new BufferedReader(class="keyword">new DotTerminatedMessageReader(_reader_)); |
242 | // Start of with a big vector because we may be reading a very large |
|
243 | // amount of groups. |
|
244 | 0 | list = new Vector(2048); |
245 | ||
246 | 0 | while ((line = reader.readLine()) != null) |
247 | { |
|
248 | 0 | tmp = __parseNewsgroupListEntry(line); |
249 | 0 | if (tmp != null) |
250 | 0 | list.addElement(tmp); |
251 | else |
|
252 | 0 | throw new MalformedServerReplyException(line); |
253 | } |
|
254 | ||
255 | 0 | if ((size = list.size()) < 1) |
256 | 0 | return new NewsgroupInfo[0]; |
257 | ||
258 | 0 | info = new NewsgroupInfo[size]; |
259 | 0 | list.copyInto(info); |
260 | ||
261 | 0 | return info; |
262 | } |
|
263 | ||
264 | ||
265 | private Reader __retrieve(int command, |
|
266 | String articleId, ArticlePointer pointer) |
|
267 | throws IOException |
|
268 | { |
|
269 | Reader reader; |
|
270 | ||
271 | 0 | if (articleId != null) |
272 | { |
|
273 | 0 | if (!NNTPReply.isPositiveCompletion(sendCommand(command, articleId))) |
274 | 0 | return null; |
275 | } |
|
276 | else |
|
277 | { |
|
278 | 0 | if (!NNTPReply.isPositiveCompletion(sendCommand(command))) |
279 | 0 | return null; |
280 | } |
|
281 | ||
282 | ||
283 | 0 | if (pointer != null) |
284 | 0 | __parseArticlePointer(getReplyString(), pointer); |
285 | ||
286 | 0 | reader = new DotTerminatedMessageReader(_reader_); |
287 | 0 | return reader; |
288 | } |
|
289 | ||
290 | ||
291 | private Reader __retrieve(int command, |
|
292 | int articleNumber, ArticlePoclass="keyword">inter poclass="keyword">inter) |
|
293 | throws IOException |
|
294 | { |
|
295 | Reader reader; |
|
296 | ||
297 | 0 | if (!NNTPReply.isPositiveCompletion(sendCommand(command, |
298 | Integer.toString(articleNumber)))) |
|
299 | 0 | return null; |
300 | ||
301 | 0 | if (pointer != null) |
302 | 0 | __parseArticlePointer(getReplyString(), pointer); |
303 | ||
304 | 0 | reader = new DotTerminatedMessageReader(_reader_); |
305 | 0 | 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 < and >). |
|
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 retrieveArticle(String articleId, ArticlePointer pointer) |
|
350 | throws IOException |
|
351 | { |
|
352 | 0 | return __retrieve(NNTPCommand.ARTICLE, articleId, pointer); |
353 | ||
354 | } |
|
355 | ||
356 | /*** Same as <code> retrieveArticle(articleId, null) </code> ***/ |
|
357 | public Reader retrieveArticle(String articleId) throws IOException |
|
358 | { |
|
359 | 0 | return retrieveArticle(articleId, null); |
360 | } |
|
361 | ||
362 | /*** Same as <code> retrieveArticle(null) </code> ***/ |
|
363 | public Reader retrieveArticle() throws IOException |
|
364 | { |
|
365 | 0 | 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 retrieveArticle(int articleNumber, ArticlePoclass="keyword">inter poclass="keyword">inter) |
|
408 | throws IOException |
|
409 | { |
|
410 | 0 | return __retrieve(NNTPCommand.ARTICLE, articleNumber, pointer); |
411 | } |
|
412 | ||
413 | /*** Same as <code> retrieveArticle(articleNumber, null) </code> ***/ |
|
414 | public Reader retrieveArticle(int articleNumber) throws IOException |
|
415 | { |
|
416 | 0 | 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 < and >). |
|
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 retrieveArticleHeader(String articleId, ArticlePointer pointer) |
|
462 | throws IOException |
|
463 | { |
|
464 | 0 | return __retrieve(NNTPCommand.HEAD, articleId, pointer); |
465 | ||
466 | } |
|
467 | ||
468 | /*** Same as <code> retrieveArticleHeader(articleId, null) </code> ***/ |
|
469 | public Reader retrieveArticleHeader(String articleId) throws IOException |
|
470 | { |
|
471 | 0 | return retrieveArticleHeader(articleId, null); |
472 | } |
|
473 | ||
474 | /*** Same as <code> retrieveArticleHeader(null) </code> ***/ |
|
475 | public Reader retrieveArticleHeader() throws IOException |
|
476 | { |
|
477 | 0 | 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 retrieveArticleHeader(int articleNumber, |
|
520 | ArticlePointer pointer) |
|
521 | throws IOException |
|
522 | { |
|
523 | 0 | return __retrieve(NNTPCommand.HEAD, articleNumber, pointer); |
524 | } |
|
525 | ||
526 | ||
527 | /*** Same as <code> retrieveArticleHeader(articleNumber, null) </code> ***/ |
|
528 | public Reader retrieveArticleHeader(int articleNumber) throws IOException |
|
529 | { |
|
530 | 0 | 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 < and >). |
|
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 retrieveArticleBody(String articleId, ArticlePointer pointer) |
|
576 | throws IOException |
|
577 | { |
|
578 | 0 | return __retrieve(NNTPCommand.BODY, articleId, pointer); |
579 | ||
580 | } |
|
581 | ||
582 | /*** Same as <code> retrieveArticleBody(articleId, null) </code> ***/ |
|
583 | public Reader retrieveArticleBody(String articleId) throws IOException |
|
584 | { |
|
585 | 0 | return retrieveArticleBody(articleId, null); |
586 | } |
|
587 | ||
588 | /*** Same as <code> retrieveArticleBody(null) </code> ***/ |
|
589 | public Reader retrieveArticleBody() throws IOException |
|
590 | { |
|
591 | 0 | 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 retrieveArticleBody(int articleNumber, |
|
634 | ArticlePointer pointer) |
|
635 | throws IOException |
|
636 | { |
|
637 | 0 | return __retrieve(NNTPCommand.BODY, articleNumber, pointer); |
638 | } |
|
639 | ||
640 | ||
641 | /*** Same as <code> retrieveArticleBody(articleNumber, null) </code> ***/ |
|
642 | public Reader retrieveArticleBody(int articleNumber) throws IOException |
|
643 | { |
|
644 | 0 | 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 newsgroup, NewsgroupInfo info) |
|
667 | throws IOException |
|
668 | { |
|
669 | 0 | if (!NNTPReply.isPositiveCompletion(group(newsgroup))) |
670 | 0 | return false; |
671 | ||
672 | 0 | if (info != null) |
673 | 0 | __parseGroupReply(getReplyString(), info); |
674 | ||
675 | 0 | return true; |
676 | } |
|
677 | ||
678 | /*** Same as <code> selectNewsgroup(newsgroup, null) </code> ***/ |
|
679 | public boolean selectNewsgroup(String newsgroup) throws IOException |
|
680 | { |
|
681 | 0 | 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 listHelp() throws IOException |
|
697 | { |
|
698 | StringWriter help; |
|
699 | Reader reader; |
|
700 | ||
701 | 0 | if (!NNTPReply.isInformational(help())) |
702 | 0 | return null; |
703 | ||
704 | 0 | help = new StringWriter(); |
705 | 0 | reader = new DotTerminatedMessageReader(_reader_); |
706 | 0 | Util.copyReader(reader, help); |
707 | 0 | reader.close(); |
708 | 0 | help.close(); |
709 | 0 | return help.toString(); |
710 | } |
|
711 | ||
712 | ||
713 | /*** |
|
714 | * Select an article by its unique identifier (including enclosing |
|
715 | * < and >) 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 articleId, ArticlePointer pointer) |
|
739 | throws IOException |
|
740 | { |
|
741 | 0 | if (articleId != null) |
742 | { |
|
743 | 0 | if (!NNTPReply.isPositiveCompletion(stat(articleId))) |
744 | 0 | return false; |
745 | } |
|
746 | else |
|
747 | { |
|
748 | 0 | if (!NNTPReply.isPositiveCompletion(stat())) |
749 | 0 | return false; |
750 | } |
|
751 | ||
752 | 0 | if (pointer != null) |
753 | 0 | __parseArticlePointer(getReplyString(), pointer); |
754 | ||
755 | 0 | return true; |
756 | } |
|
757 | ||
758 | /**** Same as <code> selectArticle(articleId, null) </code> ***/ |
|
759 | public boolean selectArticle(String articleId) throws IOException |
|
760 | { |
|
761 | 0 | 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 |
|
769 | { |
|
770 | 0 | 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, ArticlePoclass="keyword">inter poclass="keyword">inter) |
|
800 | throws IOException |
|
801 | { |
|
802 | 0 | if (!NNTPReply.isPositiveCompletion(stat(articleNumber))) |
803 | 0 | return false; |
804 | ||
805 | 0 | if (pointer != null) |
806 | 0 | __parseArticlePointer(getReplyString(), pointer); |
807 | ||
808 | 0 | return true; |
809 | } |
|
810 | ||
811 | ||
812 | /*** Same as <code> selectArticle(articleNumber, null) </code> ***/ |
|
813 | public boolean selectArticle(int articleNumber) throws IOException |
|
814 | { |
|
815 | 0 | 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 |
|
845 | { |
|
846 | 0 | if (!NNTPReply.isPositiveCompletion(last())) |
847 | 0 | return false; |
848 | ||
849 | 0 | if (pointer != null) |
850 | 0 | __parseArticlePointer(getReplyString(), pointer); |
851 | ||
852 | 0 | return true; |
853 | } |
|
854 | ||
855 | /*** Same as <code> selectPreviousArticle(null) </code> ***/ |
|
856 | public boolean selectPreviousArticle() throws IOException |
|
857 | { |
|
858 | 0 | 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 |
|
887 | { |
|
888 | 0 | if (!NNTPReply.isPositiveCompletion(next())) |
889 | 0 | return false; |
890 | ||
891 | 0 | if (pointer != null) |
892 | 0 | __parseArticlePointer(getReplyString(), pointer); |
893 | ||
894 | 0 | return true; |
895 | } |
|
896 | ||
897 | ||
898 | /*** Same as <code> selectNextArticle(null) </code> ***/ |
|
899 | public boolean selectNextArticle() throws IOException |
|
900 | { |
|
901 | 0 | 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 |
|
923 | { |
|
924 | 0 | if (!NNTPReply.isPositiveCompletion(list())) |
925 | 0 | return null; |
926 | ||
927 | 0 | 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 wildmat) throws IOException |
|
943 | { |
|
944 | 0 | if(!NNTPReply.isPositiveCompletion(listActive(wildmat))) |
945 | 0 | return null; |
946 | 0 | 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 |
|
971 | { |
|
972 | 0 | if (!NNTPReply.isPositiveCompletion(newgroups( |
973 | query.getDate(), query.getTime(), |
|
974 | query.isGMT(), query.getDistributions()))) |
|
975 | 0 | return null; |
976 | ||
977 | 0 | 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 < and >. |
|
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[] listNewNews(NewGroupsOrNewsQuery query) |
|
1005 | throws IOException |
|
1006 | { |
|
1007 | int size; |
|
1008 | String line; |
|
1009 | Vector list; |
|
1010 | String[] result; |
|
1011 | BufferedReader reader; |
|
1012 | ||
1013 | 0 | if (!NNTPReply.isPositiveCompletion(newnews( |
1014 | query.getNewsgroups(), query.getDate(), query.getTime(), |
|
1015 | query.isGMT(), query.getDistributions()))) |
|
1016 | 0 | return null; |
1017 | ||
1018 | 0 | list = new Vector(); |
1019 | 0 | reader = new BufferedReader(class="keyword">new DotTerminatedMessageReader(_reader_)); |
1020 | ||
1021 | 0 | while ((line = reader.readLine()) != null) |
1022 | 0 | list.addElement(line); |
1023 | ||
1024 | 0 | size = list.size(); |
1025 | ||
1026 | 0 | if (size < 1) |
1027 | 0 | return new String[0]; |
1028 | ||
1029 | 0 | result = new String[size]; |
1030 | 0 | list.copyInto(result); |
1031 | ||
1032 | 0 | 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 |
|
1068 | { |
|
1069 | 0 | 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 postArticle() throws IOException |
|
1111 | { |
|
1112 | 0 | if (!NNTPReply.isPositiveIntermediate(post())) |
1113 | 0 | return null; |
1114 | ||
1115 | 0 | return new DotTerminatedMessageWriter(_writer_); |
1116 | } |
|
1117 | ||
1118 | ||
1119 | public Writer forwardArticle(String articleId) throws IOException |
|
1120 | { |
|
1121 | 0 | if (!NNTPReply.isPositiveIntermediate(ihave(articleId))) |
1122 | 0 | return null; |
1123 | ||
1124 | 0 | 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 |
|
1138 | { |
|
1139 | 0 | 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 username, String password) |
|
1154 | throws IOException |
|
1155 | { |
|
1156 | 0 | int replyCode = authinfoUser(username); |
1157 | ||
1158 | 0 | if (replyCode == NNTPReply.MORE_AUTH_INFO_REQUIRED) |
1159 | { |
|
1160 | 0 | replyCode = authinfoPass(password); |
1161 | ||
1162 | 0 | if (replyCode == NNTPReply.AUTHENTICATION_ACCEPTED) |
1163 | { |
|
1164 | 0 | _isAllowedToPost = true; |
1165 | 0 | return true; |
1166 | } |
|
1167 | } |
|
1168 | 0 | 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 __retrieveArticleInfo(String articleRange) |
|
1183 | throws IOException |
|
1184 | { |
|
1185 | 0 | if (!NNTPReply.isPositiveCompletion(xover(articleRange))) |
1186 | 0 | return null; |
1187 | ||
1188 | 0 | 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 retrieveArticleInfo(int articleNumber) throws IOException |
|
1199 | { |
|
1200 | 0 | 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 retrieveArticleInfo(int lowArticleNumber, |
|
1213 | int highArticleNumber) |
|
1214 | throws IOException |
|
1215 | { |
|
1216 | 0 | return |
1217 | __retrieveArticleInfo(new String(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 __retrieveHeader(String header, String articleRange) |
|
1234 | throws IOException |
|
1235 | { |
|
1236 | 0 | if (!NNTPReply.isPositiveCompletion(xhdr(header, articleRange))) |
1237 | 0 | return null; |
1238 | ||
1239 | 0 | 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 retrieveHeader(String header, int articleNumber) |
|
1251 | throws IOException |
|
1252 | { |
|
1253 | 0 | 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 retrieveHeader(String header, int lowArticleNumber, |
|
1267 | int highArticleNumber) |
|
1268 | throws IOException |
|
1269 | { |
|
1270 | 0 | return |
1271 | __retrieveHeader(header, |
|
1272 | new String(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 | */ |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |