001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.net.nntp; 019 020import java.io.BufferedReader; 021import java.io.BufferedWriter; 022import java.io.IOException; 023import java.io.InputStreamReader; 024import java.io.OutputStreamWriter; 025import java.nio.charset.Charset; 026import java.nio.charset.StandardCharsets; 027 028import org.apache.commons.net.MalformedServerReplyException; 029import org.apache.commons.net.ProtocolCommandSupport; 030import org.apache.commons.net.SocketClient; 031import org.apache.commons.net.io.CRLFLineReader; 032 033/** 034 * The NNTP class is not meant to be used by itself and is provided 035 * only so that you may easily implement your own NNTP client if 036 * you so desire. If you have no need to perform your own implementation, 037 * you should use {@link org.apache.commons.net.nntp.NNTPClient}. 038 * The NNTP class is made public to provide access to various NNTP constants 039 * and to make it easier for adventurous programmers (or those with special 040 * needs) to interact with the NNTP protocol and implement their own clients. 041 * A set of methods with names corresponding to the NNTP command names are 042 * provided to facilitate this interaction. 043 * <p> 044 * You should keep in mind that the NNTP server may choose to prematurely 045 * close a connection if the client has been idle for longer than a 046 * given time period or if the server is being shutdown by the operator or 047 * some other reason. The NNTP class will detect a 048 * premature NNTP server connection closing when it receives a 049 * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED } 050 * response to a command. 051 * When that occurs, the NNTP class method encountering that reply will throw 052 * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} 053 * . 054 * <code>NNTPConectionClosedException</code> 055 * is a subclass of <code> IOException </code> and therefore need not be 056 * caught separately, but if you are going to catch it separately, its 057 * catch block must appear before the more general <code> IOException </code> 058 * catch block. When you encounter an 059 * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} 060 * , you must disconnect the connection with 061 * {@link #disconnect disconnect() } to properly clean up the 062 * system resources used by NNTP. Before disconnecting, you may check the 063 * last reply code and text with 064 * {@link #getReplyCode getReplyCode } and 065 * {@link #getReplyString getReplyString }. 066 * <p> 067 * Rather than list it separately for each method, we mention here that 068 * every method communicating with the server and throwing an IOException 069 * can also throw a 070 * {@link org.apache.commons.net.MalformedServerReplyException} 071 * , which is a subclass 072 * of IOException. A MalformedServerReplyException will be thrown when 073 * the reply received from the server deviates enough from the protocol 074 * specification that it cannot be interpreted in a useful manner despite 075 * attempts to be as lenient as possible. 076 * 077 * @see NNTPClient 078 * @see NNTPConnectionClosedException 079 * @see org.apache.commons.net.MalformedServerReplyException 080 */ 081 082public class NNTP extends SocketClient 083{ 084 /** The default NNTP port. Its value is 119 according to RFC 977. */ 085 public static final int DEFAULT_PORT = 119; 086 087 // We have to ensure that the protocol communication is in ASCII 088 // but we use ISO-8859-1 just in case 8-bit characters cross 089 // the wire. 090 private static final Charset DEFAULT_ENCODING = StandardCharsets.ISO_8859_1; 091 092 boolean _isAllowedToPost; 093 private int replyCode; 094 private String replyString; 095 096 /** 097 * Wraps {@link SocketClient#_input_} 098 * to communicate with server. Initialized by {@link #_connectAction_}. 099 * All server reads should be done through this variable. 100 */ 101 protected BufferedReader _reader_; 102 103 /** 104 * Wraps {@link SocketClient#_output_} 105 * to communicate with server. Initialized by {@link #_connectAction_}. 106 * All server reads should be done through this variable. 107 */ 108 protected BufferedWriter _writer_; 109 110 /** 111 * A ProtocolCommandSupport object used to manage the registering of 112 * ProtocolCommandListeners and te firing of ProtocolCommandEvents. 113 */ 114 protected ProtocolCommandSupport _commandSupport_; 115 116 /** 117 * The default NNTP constructor. Sets the default port to 118 * <code>DEFAULT_PORT</code> and initializes internal data structures 119 * for saving NNTP reply information. 120 */ 121 public NNTP() 122 { 123 setDefaultPort(DEFAULT_PORT); 124 replyString = null; 125 _reader_ = null; 126 _writer_ = null; 127 _isAllowedToPost = false; 128 _commandSupport_ = new ProtocolCommandSupport(this); 129 } 130 131 /** 132 * Initiates control connections and gets initial reply, determining 133 * if the client is allowed to post to the server. Initializes 134 * {@link #_reader_} and {@link #_writer_} to wrap 135 * {@link SocketClient#_input_} and {@link SocketClient#_output_}. 136 */ 137 @Override 138 protected void _connectAction_() throws IOException 139 { 140 super._connectAction_(); 141 _reader_ = 142 new CRLFLineReader(new InputStreamReader(_input_, 143 DEFAULT_ENCODING)); 144 _writer_ = 145 new BufferedWriter(new OutputStreamWriter(_output_, 146 DEFAULT_ENCODING)); 147 getReply(); 148 149 _isAllowedToPost = replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED; 150 } 151 152 /** 153 * Closes the connection to the NNTP server and sets to null 154 * some internal data so that the memory may be reclaimed by the 155 * garbage collector. The reply text and code information from the 156 * last command is voided so that the memory it used may be reclaimed. 157 * <p> 158 * @throws IOException If an error occurs while disconnecting. 159 */ 160 @Override 161 public void disconnect() throws IOException 162 { 163 super.disconnect(); 164 _reader_ = null; 165 _writer_ = null; 166 replyString = null; 167 _isAllowedToPost = false; 168 } 169 170 171 /** 172 * Indicates whether or not the client is allowed to post articles to 173 * the server it is currently connected to. 174 * <p> 175 * @return True if the client can post articles to the server, false 176 * otherwise. 177 */ 178 public boolean isAllowedToPost() 179 { 180 return _isAllowedToPost; 181 } 182 183 184 /** 185 * Sends an NNTP command to the server, waits for a reply and returns the 186 * numerical response code. After invocation, for more detailed 187 * information, the actual reply text can be accessed by calling 188 * {@link #getReplyString getReplyString }. 189 * <p> 190 * @param command The text representation of the NNTP command to send. 191 * @param args The arguments to the NNTP command. If this parameter is 192 * set to null, then the command is sent with no argument. 193 * @return The integer value of the NNTP reply code returned by the server 194 * in response to the command. 195 * @throws NNTPConnectionClosedException 196 * If the NNTP server prematurely closes the connection as a result 197 * of the client being idle or some other reason causing the server 198 * to send NNTP reply code 400. This exception may be caught either 199 * as an IOException or independently as itself. 200 * @throws IOException If an I/O error occurs while either sending the 201 * command or receiving the server reply. 202 */ 203 public int sendCommand(final String command, final String args) throws IOException 204 { 205 final StringBuilder __commandBuffer = new StringBuilder(); 206 __commandBuffer.append(command); 207 208 if (args != null) 209 { 210 __commandBuffer.append(' '); 211 __commandBuffer.append(args); 212 } 213 __commandBuffer.append(SocketClient.NETASCII_EOL); 214 215 final String message; 216 _writer_.write(message = __commandBuffer.toString()); 217 _writer_.flush(); 218 219 fireCommandSent(command, message); 220 221 return getReply(); 222 } 223 224 225 /** 226 * Sends an NNTP command to the server, waits for a reply and returns the 227 * numerical response code. After invocation, for more detailed 228 * information, the actual reply text can be accessed by calling 229 * {@link #getReplyString getReplyString }. 230 * <p> 231 * @param command The NNTPCommand constant corresponding to the NNTP command 232 * to send. 233 * @param args The arguments to the NNTP command. If this parameter is 234 * set to null, then the command is sent with no argument. 235 * @return The integer value of the NNTP reply code returned by the server 236 * in response to the command. 237 * in response to the command. 238 * @throws NNTPConnectionClosedException 239 * If the NNTP server prematurely closes the connection as a result 240 * of the client being idle or some other reason causing the server 241 * to send NNTP reply code 400. This exception may be caught either 242 * as an IOException or independently as itself. 243 * @throws IOException If an I/O error occurs while either sending the 244 * command or receiving the server reply. 245 */ 246 public int sendCommand(final int command, final String args) throws IOException 247 { 248 return sendCommand(NNTPCommand.getCommand(command), args); 249 } 250 251 252 /** 253 * Sends an NNTP command with no arguments to the server, waits for a 254 * reply and returns the numerical response code. After invocation, for 255 * more detailed information, the actual reply text can be accessed by 256 * calling {@link #getReplyString getReplyString }. 257 * <p> 258 * @param command The text representation of the NNTP command to send. 259 * @return The integer value of the NNTP reply code returned by the server 260 * in response to the command. 261 * in response to the command. 262 * @throws NNTPConnectionClosedException 263 * If the NNTP server prematurely closes the connection as a result 264 * of the client being idle or some other reason causing the server 265 * to send NNTP reply code 400. This exception may be caught either 266 * as an IOException or independently as itself. 267 * @throws IOException If an I/O error occurs while either sending the 268 * command or receiving the server reply. 269 */ 270 public int sendCommand(final String command) throws IOException 271 { 272 return sendCommand(command, null); 273 } 274 275 276 /** 277 * Sends an NNTP command with no arguments to the server, waits for a 278 * reply and returns the numerical response code. After invocation, for 279 * more detailed information, the actual reply text can be accessed by 280 * calling {@link #getReplyString getReplyString }. 281 * <p> 282 * @param command The NNTPCommand constant corresponding to the NNTP command 283 * to send. 284 * @return The integer value of the NNTP reply code returned by the server 285 * in response to the command. 286 * in response to the command. 287 * @throws NNTPConnectionClosedException 288 * If the NNTP server prematurely closes the connection as a result 289 * of the client being idle or some other reason causing the server 290 * to send NNTP reply code 400. This exception may be caught either 291 * as an IOException or independently as itself. 292 * @throws IOException If an I/O error occurs while either sending the 293 * command or receiving the server reply. 294 */ 295 public int sendCommand(final int command) throws IOException 296 { 297 return sendCommand(command, null); 298 } 299 300 301 /** 302 * Returns the integer value of the reply code of the last NNTP reply. 303 * You will usually only use this method after you connect to the 304 * NNTP server to check that the connection was successful since 305 * <code> connect </code> is of type void. 306 * <p> 307 * @return The integer value of the reply code of the last NNTP reply. 308 */ 309 public int getReplyCode() 310 { 311 return replyCode; 312 } 313 314 /** 315 * Fetches a reply from the NNTP server and returns the integer reply 316 * code. After calling this method, the actual reply text can be accessed 317 * from {@link #getReplyString getReplyString }. Only use this 318 * method if you are implementing your own NNTP client or if you need to 319 * fetch a secondary response from the NNTP server. 320 * <p> 321 * @return The integer value of the reply code of the fetched NNTP reply. 322 * in response to the command. 323 * @throws NNTPConnectionClosedException 324 * If the NNTP server prematurely closes the connection as a result 325 * of the client being idle or some other reason causing the server 326 * to send NNTP reply code 400. This exception may be caught either 327 * as an IOException or independently as itself. 328 * @throws IOException If an I/O error occurs while 329 * receiving the server reply. 330 */ 331 public int getReply() throws IOException 332 { 333 replyString = _reader_.readLine(); 334 335 if (replyString == null) { 336 throw new NNTPConnectionClosedException( 337 "Connection closed without indication."); 338 } 339 340 // In case we run into an anomaly we don't want fatal index exceptions 341 // to be thrown. 342 if (replyString.length() < 3) { 343 throw new MalformedServerReplyException( 344 "Truncated server reply: " + replyString); 345 } 346 347 try 348 { 349 replyCode = Integer.parseInt(replyString.substring(0, 3)); 350 } 351 catch (final NumberFormatException e) 352 { 353 throw new MalformedServerReplyException( 354 "Could not parse response code.\nServer Reply: " + replyString); 355 } 356 357 fireReplyReceived(replyCode, replyString + SocketClient.NETASCII_EOL); 358 359 if (replyCode == NNTPReply.SERVICE_DISCONTINUED) { 360 throw new NNTPConnectionClosedException( 361 "NNTP response 400 received. Server closed connection."); 362 } 363 return replyCode; 364 } 365 366 367 /** 368 * Returns the entire text of the last NNTP server response exactly 369 * as it was received, not including the end of line marker. 370 * <p> 371 * @return The entire text from the last NNTP response as a String. 372 */ 373 public String getReplyString() 374 { 375 return replyString; 376 } 377 378 379 /** 380 * A convenience method to send the NNTP ARTICLE command to the server, 381 * receive the initial reply, and return the reply code. 382 * <p> 383 * @param messageId The message identifier of the requested article, 384 * including the encapsulating < and > characters. 385 * @return The reply code received from the server. 386 * @throws NNTPConnectionClosedException 387 * If the NNTP server prematurely closes the connection as a result 388 * of the client being idle or some other reason causing the server 389 * to send NNTP reply code 400. This exception may be caught either 390 * as an IOException or independently as itself. 391 * @throws IOException If an I/O error occurs while either sending the 392 * command or receiving the server reply. 393 */ 394 public int article(final String messageId) throws IOException 395 { 396 return sendCommand(NNTPCommand.ARTICLE, messageId); 397 } 398 399 /** 400 * A convenience method to send the NNTP ARTICLE command to the server, 401 * receive the initial reply, and return the reply code. 402 * <p> 403 * @param articleNumber The number of the article to request from the 404 * currently selected newsgroup. 405 * @return The reply code received from the server. 406 * @throws NNTPConnectionClosedException 407 * If the NNTP server prematurely closes the connection as a result 408 * of the client being idle or some other reason causing the server 409 * to send NNTP reply code 400. This exception may be caught either 410 * as an IOException or independently as itself. 411 * @throws IOException If an I/O error occurs while either sending the 412 * command or receiving the server reply. 413 */ 414 public int article(final long articleNumber) throws IOException 415 { 416 return sendCommand(NNTPCommand.ARTICLE, Long.toString(articleNumber)); 417 } 418 419 /** 420 * A convenience method to send the NNTP ARTICLE command to the server, 421 * receive the initial reply, and return the reply code. 422 * <p> 423 * @return The reply code received from the server. 424 * @throws NNTPConnectionClosedException 425 * If the NNTP server prematurely closes the connection as a result 426 * of the client being idle or some other reason causing the server 427 * to send NNTP reply code 400. This exception may be caught either 428 * as an IOException or independently as itself. 429 * @throws IOException If an I/O error occurs while either sending the 430 * command or receiving the server reply. 431 */ 432 public int article() throws IOException 433 { 434 return sendCommand(NNTPCommand.ARTICLE); 435 } 436 437 438 439 /** 440 * A convenience method to send the NNTP BODY command to the server, 441 * receive the initial reply, and return the reply code. 442 * <p> 443 * @param messageId The message identifier of the requested article, 444 * including the encapsulating < and > characters. 445 * @return The reply code received from the server. 446 * @throws NNTPConnectionClosedException 447 * If the NNTP server prematurely closes the connection as a result 448 * of the client being idle or some other reason causing the server 449 * to send NNTP reply code 400. This exception may be caught either 450 * as an IOException or independently as itself. 451 * @throws IOException If an I/O error occurs while either sending the 452 * command or receiving the server reply. 453 */ 454 public int body(final String messageId) throws IOException 455 { 456 return sendCommand(NNTPCommand.BODY, messageId); 457 } 458 459 /** 460 * A convenience method to send the NNTP BODY command to the server, 461 * receive the initial reply, and return the reply code. 462 * <p> 463 * @param articleNumber The number of the article to request from the 464 * currently selected newsgroup. 465 * @return The reply code received from the server. 466 * @throws NNTPConnectionClosedException 467 * If the NNTP server prematurely closes the connection as a result 468 * of the client being idle or some other reason causing the server 469 * to send NNTP reply code 400. This exception may be caught either 470 * as an IOException or independently as itself. 471 * @throws IOException If an I/O error occurs while either sending the 472 * command or receiving the server reply. 473 */ 474 public int body(final long articleNumber) throws IOException 475 { 476 return sendCommand(NNTPCommand.BODY, Long.toString(articleNumber)); 477 } 478 479 /** 480 * A convenience method to send the NNTP BODY command to the server, 481 * receive the initial reply, and return the reply code. 482 * <p> 483 * @return The reply code received from the server. 484 * @throws NNTPConnectionClosedException 485 * If the NNTP server prematurely closes the connection as a result 486 * of the client being idle or some other reason causing the server 487 * to send NNTP reply code 400. This exception may be caught either 488 * as an IOException or independently as itself. 489 * @throws IOException If an I/O error occurs while either sending the 490 * command or receiving the server reply. 491 */ 492 public int body() throws IOException 493 { 494 return sendCommand(NNTPCommand.BODY); 495 } 496 497 498 499 /** 500 * A convenience method to send the NNTP HEAD command to the server, 501 * receive the initial reply, and return the reply code. 502 * <p> 503 * @param messageId The message identifier of the requested article, 504 * including the encapsulating < and > characters. 505 * @return The reply code received from the server. 506 * @throws NNTPConnectionClosedException 507 * If the NNTP server prematurely closes the connection as a result 508 * of the client being idle or some other reason causing the server 509 * to send NNTP reply code 400. This exception may be caught either 510 * as an IOException or independently as itself. 511 * @throws IOException If an I/O error occurs while either sending the 512 * command or receiving the server reply. 513 */ 514 public int head(final String messageId) throws IOException 515 { 516 return sendCommand(NNTPCommand.HEAD, messageId); 517 } 518 519 /** 520 * A convenience method to send the NNTP HEAD command to the server, 521 * receive the initial reply, and return the reply code. 522 * <p> 523 * @param articleNumber The number of the article to request from the 524 * currently selected newsgroup. 525 * @return The reply code received from the server. 526 * @throws NNTPConnectionClosedException 527 * If the NNTP server prematurely closes the connection as a result 528 * of the client being idle or some other reason causing the server 529 * to send NNTP reply code 400. This exception may be caught either 530 * as an IOException or independently as itself. 531 * @throws IOException If an I/O error occurs while either sending the 532 * command or receiving the server reply. 533 */ 534 public int head(final long articleNumber) throws IOException 535 { 536 return sendCommand(NNTPCommand.HEAD, Long.toString(articleNumber)); 537 } 538 539 /** 540 * A convenience method to send the NNTP HEAD command to the server, 541 * receive the initial reply, and return the reply code. 542 * <p> 543 * @return The reply code received from the server. 544 * @throws 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 * @throws IOException If an I/O error occurs while either sending the 550 * command or receiving the server reply. 551 */ 552 public int head() throws IOException 553 { 554 return sendCommand(NNTPCommand.HEAD); 555 } 556 557 558 559 /** 560 * A convenience method to send the NNTP STAT command to the server, 561 * receive the initial reply, and return the reply code. 562 * <p> 563 * @param messageId The message identifier of the requested article, 564 * including the encapsulating < and > characters. 565 * @return The reply code received from the server. 566 * @throws NNTPConnectionClosedException 567 * If the NNTP server prematurely closes the connection as a result 568 * of the client being idle or some other reason causing the server 569 * to send NNTP reply code 400. This exception may be caught either 570 * as an IOException or independently as itself. 571 * @throws IOException If an I/O error occurs while either sending the 572 * command or receiving the server reply. 573 */ 574 public int stat(final String messageId) throws IOException 575 { 576 return sendCommand(NNTPCommand.STAT, messageId); 577 } 578 579 /** 580 * A convenience method to send the NNTP STAT command to the server, 581 * receive the initial reply, and return the reply code. 582 * <p> 583 * @param articleNumber The number of the article to request from the 584 * currently selected newsgroup. 585 * @return The reply code received from the server. 586 * @throws NNTPConnectionClosedException 587 * If the NNTP server prematurely closes the connection as a result 588 * of the client being idle or some other reason causing the server 589 * to send NNTP reply code 400. This exception may be caught either 590 * as an IOException or independently as itself. 591 * @throws IOException If an I/O error occurs while either sending the 592 * command or receiving the server reply. 593 */ 594 public int stat(final long articleNumber) throws IOException 595 { 596 return sendCommand(NNTPCommand.STAT, Long.toString(articleNumber)); 597 } 598 599 /** 600 * A convenience method to send the NNTP STAT command to the server, 601 * receive the initial reply, and return the reply code. 602 * <p> 603 * @return The reply code received from the server. 604 * @throws NNTPConnectionClosedException 605 * If the NNTP server prematurely closes the connection as a result 606 * of the client being idle or some other reason causing the server 607 * to send NNTP reply code 400. This exception may be caught either 608 * as an IOException or independently as itself. 609 * @throws IOException If an I/O error occurs while either sending the 610 * command or receiving the server reply. 611 */ 612 public int stat() throws IOException 613 { 614 return sendCommand(NNTPCommand.STAT); 615 } 616 617 618 /** 619 * A convenience method to send the NNTP GROUP command to the server, 620 * receive the reply, and return the reply code. 621 * <p> 622 * @param newsgroup The name of the newsgroup to select. 623 * @return The reply code received from the server. 624 * @throws NNTPConnectionClosedException 625 * If the NNTP server prematurely closes the connection as a result 626 * of the client being idle or some other reason causing the server 627 * to send NNTP reply code 400. This exception may be caught either 628 * as an IOException or independently as itself. 629 * @throws IOException If an I/O error occurs while either sending the 630 * command or receiving the server reply. 631 */ 632 public int group(final String newsgroup) throws IOException 633 { 634 return sendCommand(NNTPCommand.GROUP, newsgroup); 635 } 636 637 638 /** 639 * A convenience method to send the NNTP HELP command to the server, 640 * receive the reply, and return the reply code. 641 * <p> 642 * @return The reply code received from the server. 643 * @throws NNTPConnectionClosedException 644 * If the NNTP server prematurely closes the connection as a result 645 * of the client being idle or some other reason causing the server 646 * to send NNTP reply code 400. This exception may be caught either 647 * as an IOException or independently as itself. 648 * @throws IOException If an I/O error occurs while either sending the 649 * command or receiving the server reply. 650 */ 651 public int help() throws IOException 652 { 653 return sendCommand(NNTPCommand.HELP); 654 } 655 656 657 /** 658 * A convenience method to send the NNTP IHAVE command to the server, 659 * receive the reply, and return the reply code. 660 * <p> 661 * @param messageId The article identifier, 662 * including the encapsulating < and > characters. 663 * @return The reply code received from the server. 664 * @throws NNTPConnectionClosedException 665 * If the NNTP server prematurely closes the connection as a result 666 * of the client being idle or some other reason causing the server 667 * to send NNTP reply code 400. This exception may be caught either 668 * as an IOException or independently as itself. 669 * @throws IOException If an I/O error occurs while either sending the 670 * command or receiving the server reply. 671 */ 672 public int ihave(final String messageId) throws IOException 673 { 674 return sendCommand(NNTPCommand.IHAVE, messageId); 675 } 676 677 678 /** 679 * A convenience method to send the NNTP LAST command to the server, 680 * receive the reply, and return the reply code. 681 * <p> 682 * @return The reply code received from the server. 683 * @throws NNTPConnectionClosedException 684 * If the NNTP server prematurely closes the connection as a result 685 * of the client being idle or some other reason causing the server 686 * to send NNTP reply code 400. This exception may be caught either 687 * as an IOException or independently as itself. 688 * @throws IOException If an I/O error occurs while either sending the 689 * command or receiving the server reply. 690 */ 691 public int last() throws IOException 692 { 693 return sendCommand(NNTPCommand.LAST); 694 } 695 696 697 698 /** 699 * A convenience method to send the NNTP LIST command to the server, 700 * receive the reply, and return the reply code. 701 * <p> 702 * @return The reply code received from the server. 703 * @throws NNTPConnectionClosedException 704 * If the NNTP server prematurely closes the connection as a result 705 * of the client being idle or some other reason causing the server 706 * to send NNTP reply code 400. This exception may be caught either 707 * as an IOException or independently as itself. 708 * @throws IOException If an I/O error occurs while either sending the 709 * command or receiving the server reply. 710 */ 711 public int list() throws IOException 712 { 713 return sendCommand(NNTPCommand.LIST); 714 } 715 716 717 718 /** 719 * A convenience method to send the NNTP NEXT command to the server, 720 * receive the reply, and return the reply code. 721 * <p> 722 * @return The reply code received from the server. 723 * @throws NNTPConnectionClosedException 724 * If the NNTP server prematurely closes the connection as a result 725 * of the client being idle or some other reason causing the server 726 * to send NNTP reply code 400. This exception may be caught either 727 * as an IOException or independently as itself. 728 * @throws IOException If an I/O error occurs while either sending the 729 * command or receiving the server reply. 730 */ 731 public int next() throws IOException 732 { 733 return sendCommand(NNTPCommand.NEXT); 734 } 735 736 737 /** 738 * A convenience method to send the "NEWGROUPS" command to the server, 739 * receive the reply, and return the reply code. 740 * <p> 741 * @param date The date after which to check for new groups. 742 * Date format is YYMMDD 743 * @param time The time after which to check for new groups. 744 * Time format is HHMMSS using a 24-hour clock. 745 * @param GMT True if the time is in GMT, false if local server time. 746 * @param distributions Comma-separated distribution list to check for 747 * new groups. Set to null if no distributions. 748 * @return The reply code received from the server. 749 * @throws NNTPConnectionClosedException 750 * If the NNTP server prematurely closes the connection as a result 751 * of the client being idle or some other reason causing the server 752 * to send NNTP reply code 400. This exception may be caught either 753 * as an IOException or independently as itself. 754 * @throws IOException If an I/O error occurs while either sending the 755 * command or receiving the server reply. 756 */ 757 public int newgroups(final String date, final String time, final boolean GMT, 758 final String distributions) throws IOException 759 { 760 final StringBuilder buffer = new StringBuilder(); 761 762 buffer.append(date); 763 buffer.append(' '); 764 buffer.append(time); 765 766 if (GMT) 767 { 768 buffer.append(' '); 769 buffer.append("GMT"); 770 } 771 772 if (distributions != null) 773 { 774 buffer.append(" <"); 775 buffer.append(distributions); 776 buffer.append('>'); 777 } 778 779 return sendCommand(NNTPCommand.NEWGROUPS, buffer.toString()); 780 } 781 782 783 /** 784 * A convenience method to send the "NEWNEWS" command to the server, 785 * receive the reply, and return the reply code. 786 * <p> 787 * @param newsgroups A comma-separated list of newsgroups to check for new 788 * news. 789 * @param date The date after which to check for new news. 790 * Date format is YYMMDD 791 * @param time The time after which to check for new news. 792 * Time format is HHMMSS using a 24-hour clock. 793 * @param GMT True if the time is in GMT, false if local server time. 794 * @param distributions Comma-separated distribution list to check for 795 * new news. Set to null if no distributions. 796 * @return The reply code received from the server. 797 * @throws NNTPConnectionClosedException 798 * If the NNTP server prematurely closes the connection as a result 799 * of the client being idle or some other reason causing the server 800 * to send NNTP reply code 400. This exception may be caught either 801 * as an IOException or independently as itself. 802 * @throws IOException If an I/O error occurs while either sending the 803 * command or receiving the server reply. 804 */ 805 public int newnews(final String newsgroups, final String date, final String time, final boolean GMT, 806 final String distributions) throws IOException 807 { 808 final StringBuilder buffer = new StringBuilder(); 809 810 buffer.append(newsgroups); 811 buffer.append(' '); 812 buffer.append(date); 813 buffer.append(' '); 814 buffer.append(time); 815 816 if (GMT) 817 { 818 buffer.append(' '); 819 buffer.append("GMT"); 820 } 821 822 if (distributions != null) 823 { 824 buffer.append(" <"); 825 buffer.append(distributions); 826 buffer.append('>'); 827 } 828 829 return sendCommand(NNTPCommand.NEWNEWS, buffer.toString()); 830 } 831 832 833 834 /** 835 * A convenience method to send the NNTP POST command to the server, 836 * receive the reply, and return the reply code. 837 * <p> 838 * @return The reply code received from the server. 839 * @throws NNTPConnectionClosedException 840 * If the NNTP server prematurely closes the connection as a result 841 * of the client being idle or some other reason causing the server 842 * to send NNTP reply code 400. This exception may be caught either 843 * as an IOException or independently as itself. 844 * @throws IOException If an I/O error occurs while either sending the 845 * command or receiving the server reply. 846 */ 847 public int post() throws IOException 848 { 849 return sendCommand(NNTPCommand.POST); 850 } 851 852 853 854 /** 855 * A convenience method to send the NNTP QUIT command to the server, 856 * receive the reply, and return the reply code. 857 * <p> 858 * @return The reply code received from the server. 859 * @throws NNTPConnectionClosedException 860 * If the NNTP server prematurely closes the connection as a result 861 * of the client being idle or some other reason causing the server 862 * to send NNTP reply code 400. This exception may be caught either 863 * as an IOException or independently as itself. 864 * @throws IOException If an I/O error occurs while either sending the 865 * command or receiving the server reply. 866 */ 867 public int quit() throws IOException 868 { 869 return sendCommand(NNTPCommand.QUIT); 870 } 871 872 /** 873 * A convenience method to send the AUTHINFO USER command to the server, 874 * receive the reply, and return the reply code. (See RFC 2980) 875 * <p> 876 * @param username A valid username. 877 * @return The reply code received from the server. The server should 878 * return a 381 or 281 for this command. 879 * @throws NNTPConnectionClosedException 880 * If the NNTP server prematurely closes the connection as a result 881 * of the client being idle or some other reason causing the server 882 * to send NNTP reply code 400. This exception may be caught either 883 * as an IOException or independently as itself. 884 * @throws IOException If an I/O error occurs while either sending the 885 * command or receiving the server reply. 886 */ 887 public int authinfoUser(final String username) throws IOException { 888 final String userParameter = "USER " + username; 889 return sendCommand(NNTPCommand.AUTHINFO, userParameter); 890 } 891 892 /** 893 * A convenience method to send the AUTHINFO PASS command to the server, 894 * receive the reply, and return the reply code. If this step is 895 * required, it should immediately follow the AUTHINFO USER command 896 * (See RFC 2980) 897 * <p> 898 * @param password a valid password. 899 * @return The reply code received from the server. The server should 900 * return a 281 or 502 for this command. 901 * @throws NNTPConnectionClosedException 902 * If the NNTP server prematurely closes the connection as a result 903 * of the client being idle or some other reason causing the server 904 * to send NNTP reply code 400. This exception may be caught either 905 * as an IOException or independently as itself. 906 * @throws IOException If an I/O error occurs while either sending the 907 * command or receiving the server reply. 908 */ 909 public int authinfoPass(final String password) throws IOException { 910 final String passParameter = "PASS " + password; 911 return sendCommand(NNTPCommand.AUTHINFO, passParameter); 912 } 913 914 /** 915 * A convenience method to send the NNTP XOVER command to the server, 916 * receive the reply, and return the reply code. 917 * <p> 918 * @param selectedArticles a String representation of the range of 919 * article headers required. This may be an article number, or a 920 * range of article numbers in the form "XXXX-YYYY", where XXXX 921 * and YYYY are valid article numbers in the current group. It 922 * also may be of the form "XXX-", meaning "return XXX and all 923 * following articles" In this revision, the last format is not 924 * possible (yet). 925 * @return The reply code received from the server. 926 * @throws NNTPConnectionClosedException 927 * If the NNTP server prematurely closes the connection as a result 928 * of the client being idle or some other reason causing the server 929 * to send NNTP reply code 400. This exception may be caught either 930 * as an IOException or independently as itself. 931 * @throws IOException If an I/O error occurs while either sending the 932 * command or receiving the server reply. 933 */ 934 public int xover(final String selectedArticles) throws IOException { 935 return sendCommand(NNTPCommand.XOVER, selectedArticles); 936 } 937 938 /** 939 * A convenience method to send the NNTP XHDR command to the server, 940 * receive the reply, and return the reply code. 941 * <p> 942 * @param header a String naming a header line (e.g., "subject"). See 943 * RFC-1036 for a list of valid header lines. 944 * @param selectedArticles a String representation of the range of 945 * article headers required. This may be an article number, or a 946 * range of article numbers in the form "XXXX-YYYY", where XXXX 947 * and YYYY are valid article numbers in the current group. It 948 * also may be of the form "XXX-", meaning "return XXX and all 949 * following articles" In this revision, the last format is not 950 * possible (yet). 951 * @return The reply code received from the server. 952 * @throws NNTPConnectionClosedException 953 * If the NNTP server prematurely closes the connection as a result 954 * of the client being idle or some other reason causing the server 955 * to send NNTP reply code 400. This exception may be caught either 956 * as an IOException or independently as itself. 957 * @throws IOException If an I/O error occurs while either sending the 958 * command or receiving the server reply. 959 */ 960 public int xhdr(final String header, final String selectedArticles) throws IOException { 961 final StringBuilder command = new StringBuilder(header); 962 command.append(" "); 963 command.append(selectedArticles); 964 return sendCommand(NNTPCommand.XHDR, command.toString()); 965 } 966 967 /** 968 * A convenience wrapper for the extended LIST command that takes 969 * an argument, allowing us to selectively list multiple groups. 970 * <p> 971 * @param wildmat A wildmat (pseudo-regex) pattern. See RFC 2980 for 972 * details. 973 * @return the reply code received from the server. 974 * @throws IOException if the command fails 975 */ 976 public int listActive(final String wildmat) throws IOException { 977 final StringBuilder command = new StringBuilder("ACTIVE "); 978 command.append(wildmat); 979 return sendCommand(NNTPCommand.LIST, command.toString()); 980 } 981 982 // DEPRECATED METHODS - for API compatibility only - DO NOT USE 983 984 /** 985 * @param a article number 986 * @return number 987 * @throws IOException on error 988 * @deprecated - for API compatibility only - DO NOT USE 989 */ 990 @Deprecated 991 public int article(final int a) throws IOException 992 { 993 return article((long) a); 994 } 995 996 /** 997 * @param a article number 998 * @return number 999 * @throws IOException on error 1000 * @deprecated - for API compatibility only - DO NOT USE 1001 */ 1002 @Deprecated 1003 public int body(final int a) throws IOException 1004 { 1005 return body((long) a); 1006 } 1007 1008 /** 1009 * @param a article number 1010 * @return number 1011 * @throws IOException on error 1012 * @deprecated - for API compatibility only - DO NOT USE 1013 */ 1014 @Deprecated 1015 public int head(final int a) throws IOException 1016 { 1017 return head((long) a); 1018 } 1019 1020 /** 1021 * @param a article number 1022 * @return number 1023 * @throws IOException on error 1024 * @deprecated - for API compatibility only - DO NOT USE 1025 */ 1026 @Deprecated 1027 public int stat(final int a) throws IOException 1028 { 1029 return stat((long) a); 1030 } 1031 1032 /** 1033 * Provide command support to super-class 1034 */ 1035 @Override 1036 protected ProtocolCommandSupport getCommandSupport() { 1037 return _commandSupport_; 1038 } 1039}