001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.geronimo.javamail.transport.nntp;
021    
022    import java.io.BufferedReader;
023    import java.io.IOException;
024    import java.util.ArrayList;
025    import java.util.List;
026    
027    import javax.mail.MessagingException;
028    
029    /**
030     * Util class to represent a reply from a NNTP server
031     * 
032     * @version $Rev: 673152 $ $Date: 2008-07-01 13:37:38 -0400 (Tue, 01 Jul 2008) $
033     */
034    public class NNTPReply {
035        // general server responses
036        public static final int CAPABILITY_LIST = 101; 
037        
038        public static final int POSTING_ALLOWED = 200;
039    
040        public static final int NO_POSTING_ALLOWED = 201;
041    
042        public static final int EXTENSIONS_SUPPORTED = 202;
043    
044        public static final int SERVICE_DISCONTINUED = 400;
045    
046        public static final int COMMAND_NOT_RECOGNIZED = 500;
047    
048        public static final int COMMAND_SYNTAX_ERROR = 501;
049    
050        public static final int PERMISSION_DENIED = 502;
051    
052        public static final int PROGRAM_FAULT = 503;
053    
054        // article responses
055        public static final int ARTICLE_FOLLOWS = 220;
056    
057        public static final int HEAD_FOLLOWS = 221;
058    
059        public static final int BODY_FOLLOWS = 222;
060    
061        public static final int REQUEST_TEXT_SEPARATELY = 223;
062    
063        public static final int OVERVIEW_FOLLOWS = 224;
064    
065        public static final int NEW_ARTICLES_FOLLOWS = 230;
066    
067        public static final int NEW_GROUPS_FOLLOWS = 231;
068    
069        public static final int ARTICLE_TRANSFERRED = 235;
070    
071        public static final int NO_NEWSGROUP_SELECTED = 412;
072    
073        public static final int NO_ARTICLE_SELECTED = 420;
074    
075        public static final int NO_ARTICLE_NUMBER = 423;
076    
077        public static final int NO_ARTICLE_FOUND = 430;
078    
079        // group responses
080        public static final int GROUP_SELECTED = 211;
081    
082        public static final int NO_SUCH_NEWSGROUP = 411;
083    
084        // post responses
085        public static final int POSTED_OK = 240;
086    
087        public static final int SEND_ARTICLE = 340;
088    
089        public static final int POSTING_NOT_ALLOWED = 440;
090    
091        public static final int POSTING_FAILED = 441;
092    
093        // quit responses
094        public static final int CLOSING_CONNECTION = 205;
095    
096        // authentication responses
097        public static final int AUTHINFO_ACCEPTED = 250;
098    
099        public static final int AUTHINFO_ACCEPTED_FINAL = 251;
100    
101        public static final int AUTHINFO_CONTINUE = 350;
102    
103        public static final int AUTHINFO_CHALLENGE = 350;
104    
105        public static final int AUTHINFO_SIMPLE_REJECTED = 402;
106    
107        public static final int AUTHENTICATION_ACCEPTED = 281;
108    
109        public static final int MORE_AUTHENTICATION_REQUIRED = 381;
110    
111        public static final int AUTHINFO_REQUIRED = 480;
112    
113        public static final int AUTHINFO_SIMPLE_REQUIRED = 450;
114    
115        public static final int AUTHENTICATION_REJECTED = 482;
116    
117        // list active reponses
118        public static final int LIST_FOLLOWS = 215;
119    
120        // The original reply string
121        private final String reply;
122    
123        // returned message code
124        private final int code;
125    
126        // the returned message text
127        private final String message;
128    
129        // data associated with a long response command.
130        private ArrayList data;
131    
132        NNTPReply(String s) throws MessagingException {
133            // save the reply
134            reply = s;
135    
136            // In a normal response, the first 3 must be the return code. However,
137            // the response back from a QUIT command is frequently a null string.
138            // Therefore, if the result is
139            // too short, just default the code to -1 and use the entire text for
140            // the message.
141            if (s == null || s.length() < 3) {
142                code = -1;
143                message = s;
144                return;
145            }
146    
147            try {
148                code = Integer.parseInt(s.substring(0, 3));
149    
150                // message should be separated by a space OR a continuation
151                // character if this is a
152                // multi-line response.
153                if (s.length() > 4) {
154                    message = s.substring(4);
155                } else {
156                    message = "";
157                }
158            } catch (NumberFormatException e) {
159                throw new MessagingException("error in parsing reply code", e);
160            }
161        }
162    
163        /**
164         * Retrieve data associated with a multi-line reponse from a server stream.
165         * 
166         * @param in
167         *            The reader that's the source of the additional lines.
168         * 
169         * @exception IOException
170         */
171        public void retrieveData(BufferedReader in) throws MessagingException {
172            try {
173                data = new ArrayList();
174    
175                String line = in.readLine();
176                // read until the end of file or until we see the end of data
177                // marker.
178                while (line != null && !line.equals(".")) {
179                    // this line is not the terminator, but it may have been byte
180                    // stuffed. If it starts with
181                    // '.', throw away the leading one.
182                    if (line.startsWith(".")) {
183                        line = line.substring(1);
184                    }
185    
186                    // just add the line to the list
187                    data.add(line);
188                    line = in.readLine();
189                }
190            } catch (IOException e) {
191                throw new MessagingException("Error reading message reply", e);
192            }
193        }
194    
195        /**
196         * Retrieve the long-command data from this response.
197         * 
198         * @return The data list. Returns null if there is no associated data.
199         */
200        public List getData() {
201            return data;
202        }
203    
204        /**
205         * Return the code value associated with the reply.
206         * 
207         * @return The integer code associated with the reply.
208         */
209        public int getCode() {
210            return this.code;
211        }
212    
213        /**
214         * Get the message text associated with the reply.
215         * 
216         * @return The string value of the message from the reply.
217         */
218        public String getMessage() {
219            return this.message;
220        }
221    
222        /**
223         * Retrieve the raw reply string for the reponse.
224         * 
225         * @return The original reply string from the server.
226         */
227        public String getReply() {
228            return reply;
229        }
230    
231        /**
232         * Indicates if reply is an error condition
233         */
234        boolean isError() {
235            // error codes are all above 400
236            return code >= 400;
237        }
238    
239        public String toString() {
240            return "CODE = " + getCode() + " : MSG = " + getMessage();
241        }
242    }