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