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