View Javadoc

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