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