Source code: org/finj/FTPReply.java
1 package org.finj;
2
3 import java.util.Locale;
4 import java.util.MissingResourceException;
5 import java.util.ResourceBundle;
6
7 /**
8 * This class contains constants and methods that
9 * simplify handling and internationalization of
10 * FTP server replies.
11 *
12 * Codes according to RFC959-4.2
13 * <TT>http://www.cis.ohio-state.edu/htbin/rfc/rfc959.html</TT>
14 * (October 1995).
15 *
16 * @author Javier Iglesias -- jiglesias@users.sourceforge.net
17 * @version $Id$
18 */
19 public class FTPReply extends Object {
20
21 // ----- 100 SERIES CODES -----
22 // Requested action is being initiated, expect
23 // another reply before proceeding with a new command
24 /**
25 * Restart marker reply.
26 *
27 * In this case, the text is exact and not
28 * left to the particular implementation; it must read :
29 * <CODE>MARK yyyy = mmmm</CODE>
30 * Where <CODE>yyyy</CODE> is User-process data stream marker,
31 * and <CODE>mmmm</CODE> server's equivalent marker
32 * (note the spaces between markers and '=`).
33 *
34 * @see "RFC959-4:2:'110'"
35 * @since v1.0
36 */
37 public static final int RESTART_MARKER_REPLY_CODE = 110;
38 /**
39 * Service ready in <CODE>nnn</CODE> minutes.
40 *
41 * @see "RFC959-4:2:'120'"
42 * @since v1.0
43 */
44 public static final int WILL_BE_READY_IN_MINUTES_CODE = 120;
45 /**
46 * Data Connection already open; transfer starting.
47 *
48 * @see "RFC959-4:2:'125'"
49 * @since v1.0
50 */
51 public static final int DATA_CONNECTION_ALREADY_OPENED_CODE = 125;
52 /**
53 * File status okay; about to open data connection.
54 *
55 * @see "RFC959-4:2:'150'"
56 * @since v1.0
57 */
58 public static final int DATA_CONNECTION_ABOUT_TO_BE_OPENED_CODE = 150;
59
60 // ----- 200 SERIES CODES -----
61 // Requested action has been successfully completed
62 /**
63 * Command okay.
64 *
65 * @see "RFC959-4:2:'200'"
66 * @since v1.0
67 */
68 public static final int POSITIVE_COMPLETION_REPLY_CODE = 200;
69 /**
70 * Command not implemented, superfluous at this site.
71 *
72 * @see "RFC959-4:2:'202'"
73 * @since v1.0
74 */
75 public static final int SUPERFLOUS_COMMAND_CODE = 202;
76 /**
77 * System status, or system help reply.
78 *
79 * @see "RFC959-4:2:'211'"
80 * @since v1.0
81 */
82 public static final int SYSTEM_STATUS_OR_HELP_REPLY_CODE = 211;
83 /**
84 * Directory status
85 *
86 * @see "RFC959-4:2:'212'"
87 * @since v1.0
88 */
89 public static final int DIRECTORY_STATUS_CODE = 212;
90 /**
91 * File status.
92 *
93 * @see "RFC959-4:2:'213'"
94 * @since v1.0
95 */
96 public static final int FILE_STATUS_CODE = 213;
97 /**
98 * Help message.
99 *
100 * On how to use the server or the meaning of a particular
101 * non-standard command. This reply is useful only to the
102 * human user.
103 *
104 * @see "RFC959-4:2:'214'"
105 * @since v1.0
106 */
107 public static final int HELP_MESSAGE_CODE = 214;
108 /**
109 * <CODE>NAME</CODE> system type.
110 *
111 * Where <CODE>NAME</CODE> is an official system name from
112 * the list in the Assigned Numbers document.
113 *
114 * @see "RFC959-4:2:'215'"
115 * @see "RFC1700"
116 * @since v1.0
117 */
118 public static final int SYSTEM_TYPE_NAME_CODE = 215;
119 /**
120 * Service ready for new user.
121 *
122 * @see "RFC959-4:2:'220'"
123 * @since v1.0
124 */
125 public static final int CONTROL_CONNECTION_OPENED_CODE = 220;
126 /**
127 * Service closing control connection.
128 *
129 * Logged out if appropriate.
130 *
131 * @see "RFC959-4:2:'221'"
132 * @since v1.0
133 */
134 public static final int CONTROL_CONNECTION_CLOSED_CODE = 221;
135 /**
136 * Data connection open; no transfer in progress.
137 *
138 * @see "RFC959-4:2:'225'"
139 * @since v1.0
140 */
141 public static final int DATA_CONNECTION_OPENED_CODE = 225;
142 /**
143 * Closing data connection.
144 *
145 * Requested file action successful (e.g., file transfer or
146 * file abort).
147 *
148 * @see "RFC959-4:2:'226'"
149 * @since v1.0
150 */
151 public static final int DATA_CONNECTION_CLOSED_CODE = 226;
152 /**
153 * Entering Passive Mode (h1,h2,h3,h4,p1,p2).
154 *
155 * @see "RFC959-4:2:'227'"
156 * @since v1.0
157 */
158 public static final int ENTERING_PASSIVE_MODE_CODE = 227;
159 /**
160 * User logged in, proceed.
161 *
162 * @see "RFC959-4:2:'230'"
163 * @since v1.0
164 */
165 public static final int USER_LOGGED_IN_CODE = 230;
166 /**
167 * Requested file action okay, completed.
168 *
169 * @see "RFC959-4:2:'250'"
170 * @since v1.0
171 */
172 public static final int REQUESTED_FILE_ACTION_OK_CODE = 250;
173 /**
174 * "PATHNAME" created.
175 *
176 * @see "RFC959-4:2:'257'"
177 * @since v1.0
178 */
179 public static final int PATHNAME_CREATED_CODE = 257;
180
181 // ----- 300 SERIES CODES -----
182 // Command has been accepted, but requested action
183 // is being held abeyance, pending receipt of
184 // further information
185 /**
186 * User name okay, need password.
187 *
188 * @see "RFC959-4:2;'331'"
189 * @since v1.0
190 */
191 public static final int USERNAME_OK_NEED_PASSWORD_CODE = 331;
192 /**
193 * Need account for login.
194 *
195 * @see "RFC959-4:2:'332'"
196 * @since v1.0
197 */
198 public static final int NEED_ACCOUNT_FOR_LOGIN_CODE = 332;
199 /**
200 * Requested file action pending further information.
201 *
202 * @see "RFC959-4:2:'350'"
203 * @since v1.0
204 */
205 public static final int REQUESTED_FILE_ACTION_PENDING_CODE = 350;
206
207 // ----- 400 SERIES CODES -----
208 // Command was not accepted and the requested action
209 // did NOT take place, but the error condition is
210 // temporary and the action may be requested again
211 /**
212 * Service not available, closing control connection.
213 *
214 * This may be a reply to any command if the service
215 * knows it must shut down.
216 *
217 * @see "RFC959-4:2:'421'"
218 * @since v1.0
219 */
220 public static final int SERVICE_NOT_AVAILABLE_CODE = 421;
221 /**
222 * Can't open data connection.
223 *
224 * @see "RFC959-4:2:'425'"
225 * @since v1.0
226 */
227 public static final int CAN_T_OPEN_DATA_CONNECTION_CODE = 425;
228 /**
229 * Connection closed; transfer aborted.
230 *
231 * @see "RFC959-4:2:'426'"
232 * @since v1.0
233 */
234 public static final int DATA_CONNECTION_ABORTED_CODE = 426;
235 /**
236 * Requested file action not taken.
237 *
238 * File unavailable (e.g., file busy).
239 *
240 * @see "RFC959-4:2:'450'"
241 * @since v1.0
242 */
243 public static final int TRANSIENT_UNAVAILABLE_FILE_CODE = 450;
244 /**
245 * Requested action aborted: local error in processing.
246 *
247 * @see "RFC959-4:2:'451'"
248 * @since v1.0
249 */
250 public static final int TRANSIENT_LOCAL_PROCESSING_ERROR_CODE = 451;
251 /**
252 * Requested action not taken.
253 *
254 * Insufficient storage space in system.
255 *
256 * @see "RFC959-4:2:'452'"
257 * @since v1.0
258 */
259 public static final int TRANSIENT_INSUFFICIENT_STORAGE_SPACE_CODE = 452;
260
261 // ----- 500 SERIES CODES -----
262 // Command was not accepted and the requested action
263 // did NOT take place
264 /**
265 * Syntax error, command unrecognized.
266 *
267 * This may include errors such as command line too long.
268 *
269 * @see "RFC959-4:2:'500'"
270 * @since v1.0
271 */
272 public static final int PERMANENT_NEGATIVE_COMPLETION_REPLY_CODE = 500;
273 /**
274 * Syntax error n parameters or arguments.
275 *
276 * @see "RFC959-4:2:'501'"
277 * @since v1.0
278 */
279 public static final int SYNTAX_ERROR_IN_ARGUMENTS_CODE = 501;
280 /**
281 * Command not implemented.
282 *
283 * @see "RFC959-4:2:'502'"
284 * @since v1.0
285 */
286 public static final int COMMAND_NOT_IMPLEMENTED_CODE = 502;
287 /**
288 * Bad sequence of commands.
289 *
290 * @see "RFC959-4:2:'503'"
291 * @since v1.0
292 */
293 public static final int BAD_COMMAND_SEQUENCE_CODE = 503;
294 /**
295 * Command not implemented for that parameter.
296 *
297 * @see "RFC959-4:2:'504'"
298 * @since v1.0
299 */
300 public static final int COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER_CODE = 504;
301 /**
302 * Not logged in.
303 *
304 * @see "RFC959-4:2:'530'"
305 * @since v1.0
306 */
307 public static final int NOT_LOGGED_IN_CODE = 530;
308 /**
309 * Need account for storing files.
310 *
311 * @see "RFC959-4:2:'532'"
312 * @since v1.0
313 */
314 public static final int NEED_ACCOUNT_FOR_STORING_FILES_CODE = 532;
315 /**
316 * Requested action not taken.
317 *
318 * File unavailable (e.g., file not found, no access).
319 *
320 * @see "RFC959-4:2:'550'"
321 * @since v1.0
322 */
323 public static final int PERMANENTLY_UNAVAILABLE_FILE_CODE = 550;
324 /**
325 * Requested action aborted: page type unknown.
326 *
327 * @see "RFC959-4:2:'551'"
328 * @since v1.0
329 */
330 public static final int PAGE_TYPE_UNKNOWN_CODE = 551;
331 /**
332 * Requested file action aborted.
333 *
334 * Exceed storage allocation (for current directory or dataset).
335 *
336 * @see "RFC959-4:2:'552'"
337 * @since v1.0
338 */
339 public static final int EXCEEDED_STORAGE_ALLOCATION_CODE = 552;
340 /**
341 * Requested action not taken.
342 *
343 * File name not allowed.
344 *
345 * @see "RFC959-4:2:'553'"
346 * @since v1.0
347 */
348 public static final int FINE_NAME_NOT_ALLOWED_CODE = 553;
349
350
351 // Messages are stored in resource files
352 private static final String MESSAGE_BUNDLE_NAME = "org/finj/FTPMessage";
353 private static final String MESSAGE_NAME_PREFIX = "code_";
354 private static final String DEFAULT_MESSAGE_NAME = "code_default";
355 private ResourceBundle resources = null;
356
357 private int code = 0;
358 private String text = null;
359 private boolean multi = false;
360
361 /**
362 * Defeat parameterless constructor.
363 *
364 * @since v1.0
365 */
366 private FTPReply ( ) {;}
367
368 /**
369 * Constructs a new instance of this class
370 * that will use <CODE>Locale.US</CODE> as
371 * default locale.
372 *
373 * @param text original reply message received on the
374 * control connection.
375 * @since v1.0
376 */
377 public FTPReply ( String text ) {
378 this ( text, Locale.US );
379 }
380
381 /**
382 * Constructs a new instance of this class
383 * that will use <CODE>locale</CODE> as
384 * message language. If not available,
385 * messages for default language
386 * (<CODE>Locale.US</CODE>) will be used.
387 *
388 * @param text original reply message received on the
389 * control connection.
390 * @param locale language to use for message.
391 * @since v1.0
392 */
393 public FTPReply ( String text,
394 Locale locale ) throws IllegalArgumentException {
395 this.code = getCodeFromMessage (text);
396 this.multi = (text.charAt (3) == '-');
397 this.text = text.substring (4, text.length ()).trim ();
398 resources = ResourceBundle.getBundle (MESSAGE_BUNDLE_NAME, locale);
399 }
400
401 /**
402 * Returns the FTP code of this reply.
403 *
404 * @return FTP code
405 * @since v1.0
406 */
407 public int getCode ( ) {
408 return code;
409 }
410
411 /**
412 * Returns a localized version of the message corresponding
413 * to the original one's code. This will only work if a
414 * localized version of the messages are provided.
415 *
416 * @return code of the reply sent by FTP server.
417 * @since v1.0
418 */
419 public String getMessage ( ) {
420 return getMessageFromCode (code);
421 }
422
423 /**
424 * Returns the original message received from the FTP server
425 * and passed at construction time.
426 *
427 * @return original message text.
428 * @since v1.0
429 */
430 public String getOriginalMessage ( ) {
431 return text;
432 }
433
434 /**
435 * Returns true if this reply anounces a multi line reply,
436 * e.g., <CODE>STAT</CODE> command.
437 *
438 * @return <CODE>true</CODE> if more lines are coming next
439 * the one used to construct this instance.
440 * @see "RFC959-4:2"
441 * @since v1.0
442 */
443 public boolean isMultiline ( ) {
444 return multi;
445 }
446
447 /**
448 * Returns the message that corresponds to the
449 * <CODE>code</CODE> given as parameter.
450 *
451 * @param code one of the codes defined in this class.
452 * @since v1.0
453 */
454 protected String getMessageFromCode ( int code ) {
455 try {
456 return resources.getString (new StringBuffer (MESSAGE_NAME_PREFIX).append (code).toString ());
457 } catch ( MissingResourceException mre ) {
458 return resources.getString (DEFAULT_MESSAGE_NAME);
459 }
460 }
461
462 /**
463 * Returns the code contained in the
464 * <CODE>reply</CODE> passed as parameter.
465 * This code are in fact the 3 first characters
466 * of the <CODE>reply</CODE>.
467 *
468 * @param reply FTP server reply to interpret.
469 * @exception IllegalArgumentException
470 * when <CODE>reply</CODE>'s 3 first characters
471 * are not a valid three digit number
472 * @since v1.0
473 */
474 public static int getCodeFromMessage ( String reply ) throws IllegalArgumentException {
475 try {
476 return Integer.parseInt (reply.substring (0, 3));
477 } catch ( Exception e ) {
478 throw new IllegalArgumentException (reply.substring (0, 3) + " is obviously not a valid FTP error code !");
479 }
480 }
481 }