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

This page was automatically generated by Maven