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 * https://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 only so that you may easily implement your own NNTP client if you so desire. If you have no 035 * need to perform your own implementation, you should use {@link org.apache.commons.net.nntp.NNTPClient}. The NNTP class is made public to provide access to 036 * various NNTP constants and to make it easier for adventurous programmers (or those with special needs) to interact with the NNTP protocol and implement their 037 * own clients. A set of methods with names corresponding to the NNTP command names are provided to facilitate this interaction. 038 * <p> 039 * You should keep in mind that the NNTP server may choose to prematurely close a connection if the client has been idle for longer than a given time period or 040 * if the server is being shutdown by the operator or some other reason. The NNTP class will detect a premature NNTP server connection closing when it receives 041 * a {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED} response to a command. When that occurs, the NNTP class 042 * method encountering that reply will throw an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} . {@code NNTPConectionClosedException} is 043 * a subclass of {@code IOException} and therefore need not be caught separately, but if you are going to catch it separately, its catch block must 044 * appear before the more general {@code IOException} catch block. When you encounter an 045 * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException} , you must disconnect the connection with {@link #disconnect disconnect()} to properly 046 * clean up the system resources used by NNTP. Before disconnecting, you may check the last reply code and text with {@link #getReplyCode getReplyCode} and 047 * {@link #getReplyString getReplyString}. 048 * </p> 049 * <p> 050 * Rather than list it separately for each method, we mention here that every method communicating with the server and throwing an IOException can also throw a 051 * {@link org.apache.commons.net.MalformedServerReplyException} , which is a subclass of IOException. A MalformedServerReplyException will be thrown when the 052 * reply received from the server deviates enough from the protocol specification that it cannot be interpreted in a useful manner despite attempts to be as 053 * lenient as possible. 054 * </p> 055 * 056 * @see NNTPClient 057 * @see NNTPConnectionClosedException 058 * @see org.apache.commons.net.MalformedServerReplyException 059 */ 060 061public class NNTP extends SocketClient { 062 063 /** The default NNTP port. Its value is 119 according to RFC 977. */ 064 public static final int DEFAULT_PORT = 119; 065 066 // We have to ensure that the protocol communication is in ASCII, 067 // but we use ISO-8859-1 just in case 8-bit characters cross 068 // the wire. 069 private static final Charset DEFAULT_ENCODING = StandardCharsets.ISO_8859_1; 070 071 boolean _isAllowedToPost; 072 private int replyCode; 073 private String replyString; 074 075 /** 076 * Wraps {@link SocketClient#_input_} to communicate with server. Initialized by {@link #_connectAction_}. All server reads should be done through this 077 * variable. 078 */ 079 protected BufferedReader _reader_; 080 081 /** 082 * Wraps {@link SocketClient#_output_} to communicate with server. Initialized by {@link #_connectAction_}. All server reads should be done through this 083 * variable. 084 */ 085 protected BufferedWriter _writer_; 086 087 /** 088 * A ProtocolCommandSupport object used to manage the registering of ProtocolCommandListeners and te firing of ProtocolCommandEvents. 089 */ 090 protected ProtocolCommandSupport _commandSupport_; 091 092 /** 093 * The default NNTP constructor. Sets the default port to {@code DEFAULT_PORT} and initializes internal data structures for saving NNTP reply 094 * information. 095 */ 096 public NNTP() { 097 setDefaultPort(DEFAULT_PORT); 098 replyString = null; 099 _reader_ = null; 100 _writer_ = null; 101 _isAllowedToPost = false; 102 _commandSupport_ = new ProtocolCommandSupport(this); 103 } 104 105 /** 106 * Initiates control connections and gets initial reply, determining if the client is allowed to post to the server. Initializes {@link #_reader_} and 107 * {@link #_writer_} to wrap {@link SocketClient#_input_} and {@link SocketClient#_output_}. 108 */ 109 @Override 110 protected void _connectAction_() throws IOException { 111 super._connectAction_(); 112 _reader_ = new CRLFLineReader(new InputStreamReader(_input_, DEFAULT_ENCODING)); 113 _writer_ = new BufferedWriter(new OutputStreamWriter(_output_, DEFAULT_ENCODING)); 114 getReply(); 115 116 _isAllowedToPost = replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED; 117 } 118 119 /** 120 * A convenience method to send the NNTP ARTICLE command to the server, receive the initial reply, and return the reply code. 121 * 122 * @return The reply code received from the server. 123 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 124 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 125 * independently as itself. 126 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 127 */ 128 public int article() throws IOException { 129 return sendCommand(NNTPCommand.ARTICLE); 130 } 131 132 /** 133 * @param a article number 134 * @return number 135 * @throws IOException on error 136 * @deprecated - for API compatibility only - DO NOT USE 137 */ 138 @Deprecated 139 public int article(final int a) throws IOException { 140 return article((long) a); 141 } 142 143 /** 144 * A convenience method to send the NNTP ARTICLE command to the server, receive the initial reply, and return the reply code. 145 * 146 * @param articleNumber The number of the article to request from the currently selected newsgroup. 147 * @return The reply code received from the server. 148 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 149 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 150 * independently as itself. 151 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 152 */ 153 public int article(final long articleNumber) throws IOException { 154 return sendCommand(NNTPCommand.ARTICLE, Long.toString(articleNumber)); 155 } 156 157 /** 158 * A convenience method to send the NNTP ARTICLE command to the server, receive the initial reply, and return the reply code. 159 * 160 * @param messageId The message identifier of the requested article, including the encapsulating < and > characters. 161 * @return The reply code received from the server. 162 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 163 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 164 * independently as itself. 165 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 166 */ 167 public int article(final String messageId) throws IOException { 168 return sendCommand(NNTPCommand.ARTICLE, messageId); 169 } 170 171 /** 172 * A convenience method to send the AUTHINFO PASS command to the server, receive the reply, and return the reply code. If this step is required, it should 173 * immediately follow the AUTHINFO USER command (See RFC 2980) 174 * 175 * @param password a valid password. 176 * @return The reply code received from the server. The server should return a 281 or 502 for this command. 177 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 178 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 179 * independently as itself. 180 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 181 */ 182 public int authinfoPass(final String password) throws IOException { 183 final String passParameter = "PASS " + password; 184 return sendCommand(NNTPCommand.AUTHINFO, passParameter); 185 } 186 187 /** 188 * A convenience method to send the AUTHINFO USER command to the server, receive the reply, and return the reply code. (See RFC 2980) 189 * 190 * @param user A valid user name. 191 * @return The reply code received from the server. The server should return a 381 or 281 for this command. 192 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 193 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 194 * independently as itself. 195 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 196 */ 197 public int authinfoUser(final String user) throws IOException { 198 final String userParameter = "USER " + user; 199 return sendCommand(NNTPCommand.AUTHINFO, userParameter); 200 } 201 202 /** 203 * A convenience method to send the NNTP BODY command to the server, receive the initial reply, and return the reply code. 204 * 205 * @return The reply code received from the server. 206 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 207 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 208 * independently as itself. 209 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 210 */ 211 public int body() throws IOException { 212 return sendCommand(NNTPCommand.BODY); 213 } 214 215 /** 216 * @param a article number 217 * @return number 218 * @throws IOException on error 219 * @deprecated - for API compatibility only - DO NOT USE 220 */ 221 @Deprecated 222 public int body(final int a) throws IOException { 223 return body((long) a); 224 } 225 226 /** 227 * A convenience method to send the NNTP BODY command to the server, receive the initial reply, and return the reply code. 228 * 229 * @param articleNumber The number of the article to request from the currently selected newsgroup. 230 * @return The reply code received from the server. 231 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 232 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 233 * independently as itself. 234 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 235 */ 236 public int body(final long articleNumber) throws IOException { 237 return sendCommand(NNTPCommand.BODY, Long.toString(articleNumber)); 238 } 239 240 /** 241 * A convenience method to send the NNTP BODY command to the server, receive the initial reply, and return the reply code. 242 * 243 * @param messageId The message identifier of the requested article, including the encapsulating < and > characters. 244 * @return The reply code received from the server. 245 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 246 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 247 * independently as itself. 248 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 249 */ 250 public int body(final String messageId) throws IOException { 251 return sendCommand(NNTPCommand.BODY, messageId); 252 } 253 254 /** 255 * Closes the connection to the NNTP server and sets to null some internal data so that the memory may be reclaimed by the garbage collector. The reply text 256 * and code information from the last command is voided so that the memory it used may be reclaimed. 257 * 258 * @throws IOException If an error occurs while disconnecting. 259 */ 260 @Override 261 public void disconnect() throws IOException { 262 super.disconnect(); 263 _reader_ = null; 264 _writer_ = null; 265 replyString = null; 266 _isAllowedToPost = false; 267 } 268 269 /** 270 * Gets the command support. 271 */ 272 @Override 273 protected ProtocolCommandSupport getCommandSupport() { 274 return _commandSupport_; 275 } 276 277 /** 278 * Gets a reply from the NNTP server and returns the integer reply code. After calling this method, the actual reply text can be accessed from 279 * {@link #getReplyString getReplyString}. Only use this method if you are implementing your own NNTP client or if you need to fetch a secondary response 280 * from the NNTP server. 281 * 282 * @return The integer value of the reply code of the fetched NNTP reply. in response to the command. 283 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 284 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 285 * independently as itself. 286 * @throws IOException If an I/O error occurs while receiving the server reply. 287 */ 288 public int getReply() throws IOException { 289 replyString = _reader_.readLine(); 290 291 if (replyString == null) { 292 throw new NNTPConnectionClosedException("Connection closed without indication."); 293 } 294 295 // In case we run into an anomaly we don't want fatal index exceptions 296 // to be thrown. 297 if (replyString.length() < 3) { 298 throw new MalformedServerReplyException("Truncated server reply: " + replyString); 299 } 300 301 try { 302 replyCode = Integer.parseInt(replyString.substring(0, 3)); 303 } catch (final NumberFormatException e) { 304 throw new MalformedServerReplyException("Could not parse response code.\nServer Reply: " + replyString); 305 } 306 307 fireReplyReceived(replyCode, replyString + NETASCII_EOL); 308 309 if (replyCode == NNTPReply.SERVICE_DISCONTINUED) { 310 throw new NNTPConnectionClosedException("NNTP response 400 received. Server closed connection."); 311 } 312 return replyCode; 313 } 314 315 /** 316 * Gets the integer value of the reply code of the last NNTP reply. You will usually only use this method after you connect to the NNTP server to check 317 * that the connection was successful since {@code connect} is of type void. 318 * 319 * @return The integer value of the reply code of the last NNTP reply. 320 */ 321 public int getReplyCode() { 322 return replyCode; 323 } 324 325 /** 326 * Gets the entire text of the last NNTP server response exactly as it was received, not including the end of line marker. 327 * 328 * @return The entire text from the last NNTP response as a String. 329 */ 330 public String getReplyString() { 331 return replyString; 332 } 333 334 /** 335 * A convenience method to send the NNTP GROUP command to the server, receive the reply, and return the reply code. 336 * 337 * @param newsgroup The name of the newsgroup to select. 338 * @return The reply code received from the server. 339 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 340 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 341 * independently as itself. 342 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 343 */ 344 public int group(final String newsgroup) throws IOException { 345 return sendCommand(NNTPCommand.GROUP, newsgroup); 346 } 347 348 /** 349 * A convenience method to send the NNTP HEAD command to the server, receive the initial reply, and return the reply code. 350 * 351 * @return The reply code received from the server. 352 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 353 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 354 * independently as itself. 355 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 356 */ 357 public int head() throws IOException { 358 return sendCommand(NNTPCommand.HEAD); 359 } 360 361 /** 362 * @param a article number 363 * @return number 364 * @throws IOException on error 365 * @deprecated - for API compatibility only - DO NOT USE 366 */ 367 @Deprecated 368 public int head(final int a) throws IOException { 369 return head((long) a); 370 } 371 372 /** 373 * A convenience method to send the NNTP HEAD command to the server, receive the initial reply, and return the reply code. 374 * 375 * @param articleNumber The number of the article to request from the currently selected newsgroup. 376 * @return The reply code received from the server. 377 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 378 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 379 * independently as itself. 380 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 381 */ 382 public int head(final long articleNumber) throws IOException { 383 return sendCommand(NNTPCommand.HEAD, Long.toString(articleNumber)); 384 } 385 386 /** 387 * A convenience method to send the NNTP HEAD command to the server, receive the initial reply, and return the reply code. 388 * 389 * @param messageId The message identifier of the requested article, including the encapsulating < and > characters. 390 * @return The reply code received from the server. 391 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 392 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 393 * independently as itself. 394 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 395 */ 396 public int head(final String messageId) throws IOException { 397 return sendCommand(NNTPCommand.HEAD, messageId); 398 } 399 400 /** 401 * A convenience method to send the NNTP HELP command to the server, receive the reply, and return the reply code. 402 * 403 * @return The reply code received from the server. 404 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 405 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 406 * independently as itself. 407 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 408 */ 409 public int help() throws IOException { 410 return sendCommand(NNTPCommand.HELP); 411 } 412 413 /** 414 * A convenience method to send the NNTP IHAVE command to the server, receive the reply, and return the reply code. 415 * 416 * @param messageId The article identifier, including the encapsulating < and > characters. 417 * @return The reply code received from the server. 418 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 419 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 420 * independently as itself. 421 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 422 */ 423 public int ihave(final String messageId) throws IOException { 424 return sendCommand(NNTPCommand.IHAVE, messageId); 425 } 426 427 /** 428 * Indicates whether or not the client is allowed to post articles to the server it is currently connected to. 429 * 430 * @return True if the client can post articles to the server, false otherwise. 431 */ 432 public boolean isAllowedToPost() { 433 return _isAllowedToPost; 434 } 435 436 /** 437 * A convenience method to send the NNTP LAST command to the server, receive the reply, and return the reply code. 438 * 439 * @return The reply code received from the server. 440 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 441 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 442 * independently as itself. 443 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 444 */ 445 public int last() throws IOException { 446 return sendCommand(NNTPCommand.LAST); 447 } 448 449 /** 450 * A convenience method to send the NNTP LIST command to the server, receive the reply, and return the reply code. 451 * 452 * @return The reply code received from the server. 453 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 454 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 455 * independently as itself. 456 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 457 */ 458 public int list() throws IOException { 459 return sendCommand(NNTPCommand.LIST); 460 } 461 462 /** 463 * A convenience wrapper for the extended LIST command that takes an argument, allowing us to selectively list multiple groups. 464 * 465 * @param wildmat A wildmat (pseudo-regex) pattern. See RFC 2980 for details. 466 * @return the reply code received from the server. 467 * @throws IOException if the command fails 468 */ 469 public int listActive(final String wildmat) throws IOException { 470 final StringBuilder command = new StringBuilder("ACTIVE "); 471 command.append(wildmat); 472 return sendCommand(NNTPCommand.LIST, command.toString()); 473 } 474 475 /** 476 * A convenience method to send the "NEWGROUPS" command to the server, receive the reply, and return the reply code. 477 * 478 * @param date The date after which to check for new groups. Date format is YYMMDD 479 * @param time The time after which to check for new groups. Time format is HHMMSS using a 24-hour clock. 480 * @param GMT True if the time is in GMT, false if local server time. 481 * @param distributions Comma-separated distribution list to check for new groups. Set to null if no distributions. 482 * @return The reply code received from the server. 483 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 484 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 485 * independently as itself. 486 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 487 */ 488 public int newgroups(final String date, final String time, final boolean GMT, final String distributions) throws IOException { 489 final StringBuilder buffer = new StringBuilder(); 490 491 buffer.append(date); 492 buffer.append(' '); 493 buffer.append(time); 494 495 if (GMT) { 496 buffer.append(' '); 497 buffer.append("GMT"); 498 } 499 500 if (distributions != null) { 501 buffer.append(" <"); 502 buffer.append(distributions); 503 buffer.append('>'); 504 } 505 506 return sendCommand(NNTPCommand.NEWGROUPS, buffer.toString()); 507 } 508 509 /** 510 * A convenience method to send the "NEWNEWS" command to the server, receive the reply, and return the reply code. 511 * 512 * @param newsgroups A comma-separated list of newsgroups to check for new news. 513 * @param date The date after which to check for new news. Date format is YYMMDD 514 * @param time The time after which to check for new news. Time format is HHMMSS using a 24-hour clock. 515 * @param GMT True if the time is in GMT, false if local server time. 516 * @param distributions Comma-separated distribution list to check for new news. Set to null if no distributions. 517 * @return The reply code received from the server. 518 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 519 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 520 * independently as itself. 521 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 522 */ 523 public int newnews(final String newsgroups, final String date, final String time, final boolean GMT, final String distributions) throws IOException { 524 final StringBuilder buffer = new StringBuilder(); 525 526 buffer.append(newsgroups); 527 buffer.append(' '); 528 buffer.append(date); 529 buffer.append(' '); 530 buffer.append(time); 531 532 if (GMT) { 533 buffer.append(' '); 534 buffer.append("GMT"); 535 } 536 537 if (distributions != null) { 538 buffer.append(" <"); 539 buffer.append(distributions); 540 buffer.append('>'); 541 } 542 543 return sendCommand(NNTPCommand.NEWNEWS, buffer.toString()); 544 } 545 546 /** 547 * A convenience method to send the NNTP NEXT command to the server, receive the reply, and return the reply code. 548 * 549 * @return The reply code received from the server. 550 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 551 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 552 * independently as itself. 553 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 554 */ 555 public int next() throws IOException { 556 return sendCommand(NNTPCommand.NEXT); 557 } 558 559 /** 560 * A convenience method to send the NNTP POST command to the server, receive the reply, and return the reply code. 561 * 562 * @return The reply code received from the server. 563 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 564 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 565 * independently as itself. 566 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 567 */ 568 public int post() throws IOException { 569 return sendCommand(NNTPCommand.POST); 570 } 571 572 /** 573 * A convenience method to send the NNTP QUIT command to the server, receive the reply, and return the reply code. 574 * 575 * @return The reply code received from the server. 576 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 577 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 578 * independently as itself. 579 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 580 */ 581 public int quit() throws IOException { 582 return sendCommand(NNTPCommand.QUIT); 583 } 584 585 /** 586 * Sends an NNTP command with no arguments to the server, waits for a reply and returns the numerical response code. After invocation, for more detailed 587 * information, the actual reply text can be accessed by calling {@link #getReplyString getReplyString}. 588 * 589 * @param command The NNTPCommand constant corresponding to the NNTP command to send. 590 * @return The integer value of the NNTP reply code returned by the server in response to the command. in response to the command. 591 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 592 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 593 * independently as itself. 594 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 595 */ 596 public int sendCommand(final int command) throws IOException { 597 return sendCommand(command, null); 598 } 599 600 /** 601 * Sends an NNTP command to the server, waits for a reply and returns the numerical response code. After invocation, for more detailed information, the 602 * actual reply text can be accessed by calling {@link #getReplyString getReplyString}. 603 * 604 * @param command The NNTPCommand constant corresponding to the NNTP command to send. 605 * @param args The arguments to the NNTP command. If this parameter is set to null, then the command is sent with no argument. 606 * @return The integer value of the NNTP reply code returned by the server in response to the command. in response to the command. 607 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 608 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 609 * independently as itself. 610 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 611 */ 612 public int sendCommand(final int command, final String args) throws IOException { 613 return sendCommand(NNTPCommand.getCommand(command), args); 614 } 615 616 /** 617 * Sends an NNTP command with no arguments to the server, waits for a reply and returns the numerical response code. After invocation, for more detailed 618 * information, the actual reply text can be accessed by calling {@link #getReplyString getReplyString}. 619 * 620 * @param command The text representation of the NNTP command to send. 621 * @return The integer value of the NNTP reply code returned by the server in response to the command. in response to the command. 622 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 623 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 624 * independently as itself. 625 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 626 */ 627 public int sendCommand(final String command) throws IOException { 628 return sendCommand(command, null); 629 } 630 631 /** 632 * Sends an NNTP command to the server, waits for a reply and returns the numerical response code. After invocation, for more detailed information, the 633 * actual reply text can be accessed by calling {@link #getReplyString getReplyString}. 634 * 635 * @param command The text representation of the NNTP command to send. 636 * @param args The arguments to the NNTP command. If this parameter is set to null, then the command is sent with no argument. 637 * @return The integer value of the NNTP reply code returned by the server in response to the command. 638 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 639 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 640 * independently as itself. 641 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 642 */ 643 public int sendCommand(final String command, final String args) throws IOException { 644 final StringBuilder builder = new StringBuilder(command); 645 if (args != null) { 646 builder.append(' '); 647 builder.append(args); 648 } 649 builder.append(NETASCII_EOL); 650 final String message; 651 _writer_.write(message = builder.toString()); 652 _writer_.flush(); 653 fireCommandSent(command, message); 654 return getReply(); 655 } 656 657 /** 658 * A convenience method to send the NNTP STAT command to the server, receive the initial reply, and return the reply code. 659 * 660 * @return The reply code received from the server. 661 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 662 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 663 * independently as itself. 664 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 665 */ 666 public int stat() throws IOException { 667 return sendCommand(NNTPCommand.STAT); 668 } 669 670 /** 671 * @param a article number 672 * @return number 673 * @throws IOException on error 674 * @deprecated - for API compatibility only - DO NOT USE 675 */ 676 @Deprecated 677 public int stat(final int a) throws IOException { 678 return stat((long) a); 679 } 680 681 /** 682 * A convenience method to send the NNTP STAT command to the server, receive the initial reply, and return the reply code. 683 * 684 * @param articleNumber The number of the article to request from the currently selected newsgroup. 685 * @return The reply code received from the server. 686 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 687 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 688 * independently as itself. 689 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 690 */ 691 public int stat(final long articleNumber) throws IOException { 692 return sendCommand(NNTPCommand.STAT, Long.toString(articleNumber)); 693 } 694 695 /** 696 * A convenience method to send the NNTP STAT command to the server, receive the initial reply, and return the reply code. 697 * 698 * @param messageId The message identifier of the requested article, including the encapsulating < and > characters. 699 * @return The reply code received from the server. 700 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 701 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 702 * independently as itself. 703 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 704 */ 705 public int stat(final String messageId) throws IOException { 706 return sendCommand(NNTPCommand.STAT, messageId); 707 } 708 709 /** 710 * A convenience method to send the NNTP XHDR command to the server, receive the reply, and return the reply code. 711 * 712 * @param header a String naming a header line (e.g., "subject"). See RFC-1036 for a list of valid header lines. 713 * @param selectedArticles a String representation of the range of article headers required. This may be an article number, or a range of article numbers in 714 * the form "XXXX-YYYY", where XXXX and YYYY are valid article numbers in the current group. It also may be of the form "XXX-", 715 * meaning "return XXX and all following articles" In this revision, the last format is not possible (yet). 716 * @return The reply code received from the server. 717 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 718 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 719 * independently as itself. 720 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 721 */ 722 public int xhdr(final String header, final String selectedArticles) throws IOException { 723 final StringBuilder command = new StringBuilder(header); 724 command.append(" "); 725 command.append(selectedArticles); 726 return sendCommand(NNTPCommand.XHDR, command.toString()); 727 } 728 729 /** 730 * A convenience method to send the NNTP XOVER command to the server, receive the reply, and return the reply code. 731 * 732 * @param selectedArticles a String representation of the range of article headers required. This may be an article number, or a range of article numbers in 733 * the form "XXXX-YYYY", where XXXX and YYYY are valid article numbers in the current group. It also may be of the form "XXX-", 734 * meaning "return XXX and all following articles" In this revision, the last format is not possible (yet). 735 * @return The reply code received from the server. 736 * @throws NNTPConnectionClosedException If the NNTP server prematurely closes the connection as a result of the client being idle or some other reason 737 * causing the server to send NNTP reply code 400. This exception may be caught either as an IOException or 738 * independently as itself. 739 * @throws IOException If an I/O error occurs while either sending the command or receiving the server reply. 740 */ 741 public int xover(final String selectedArticles) throws IOException { 742 return sendCommand(NNTPCommand.XOVER, selectedArticles); 743 } 744}