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