View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package goldengate.common.command;
22  
23  import goldengate.common.exception.InvalidArgumentException;
24  
25  /**
26   * Reply code references by different RFC.
27   *
28   * @author Frederic Bregier
29   *
30   */
31  public enum ReplyCode {
32      /**
33       * unofficial reply code for no value
34       */
35      REPLY_000_SPECIAL_NOSTATUS(0),
36      /**
37       * 110 Restart marker reply. In this case, the text is exact and not left to
38       * the particular implementation), it must read: MARK yyyy (mmmm Where yyyy
39       * is User-process data stream marker, and mmmm server's equivalent marker
40       * (note the spaces between markers and "=").
41       */
42      REPLY_110_RESTART_MARKER_REPLY(110),
43  
44      /**
45       * 120 Service ready in nnn minutes.
46       */
47      REPLY_120_SERVICE_READY_IN_NNN_MINUTES(120),
48  
49      /**
50       * 125 Data connection already open), transfer starting.
51       */
52      REPLY_125_DATA_CONNECTION_ALREADY_OPEN(125),
53  
54      /**
55       * 150 File status okay), about to open data connection.
56       */
57      REPLY_150_FILE_STATUS_OKAY(150),
58  
59      /**
60       * 200 Command okay.
61       */
62      REPLY_200_COMMAND_OKAY(200),
63  
64      /**
65       * 202 Command not implemented, superfluous at this site.
66       */
67      REPLY_202_COMMAND_NOT_IMPLEMENTED(202),
68  
69      /**
70       * 211 System status, or system help reply.
71       */
72      REPLY_211_SYSTEM_STATUS_REPLY(211),
73  
74      /**
75       * 212 Directory status.
76       */
77      REPLY_212_DIRECTORY_STATUS(212),
78  
79      /**
80       * 213 File status.
81       */
82      REPLY_213_FILE_STATUS(213),
83  
84      /**
85       * 214 Help message. On how to use the server or the meaning of a particular
86       * non-standard command. This reply is useful only to the human user.
87       */
88      REPLY_214_HELP_MESSAGE(
89              214,
90              "This FTP server refers to RFC 959, RFC 775, RFC 2389 and RFC 3659"),
91  
92      /**
93       * 215 NAME system type. Where NAME is an official system name from the list
94       * in the Assigned Numbers document.
95       */
96      REPLY_215_NAME_SYSTEM_TYPE(215),
97  
98      /**
99       * 220 Service ready for new user.
100      */
101     REPLY_220_SERVICE_READY(220),
102 
103     /**
104      * Service closing control connection. Logged out if appropriate.
105      */
106     REPLY_221_CLOSING_CONTROL_CONNECTION(221),
107 
108     /**
109      * 225 Data connection open), no transfer in progress.
110      */
111     REPLY_225_DATA_CONNECTION_OPEN_NO_TRANSFER_IN_PROGRESS(225),
112 
113     /**
114      * Closing data connection. Requested file action successful (for example,
115      * file transfer or file abort).
116      */
117     REPLY_226_CLOSING_DATA_CONNECTION(226),
118 
119     /**
120      * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
121      */
122     REPLY_227_ENTERING_PASSIVE_MODE(227),
123 
124     /**
125      * 229 Entering Extended Passive Mode (|n|addr|port|).
126      */
127     REPLY_229_ENTERING_PASSIVE_MODE(229),
128 
129     /**
130      * 230 User logged in, proceed.
131      */
132     REPLY_230_USER_LOGGED_IN(230),
133 
134     /**
135      * 250 Requested file action okay, completed.
136      */
137     REPLY_250_REQUESTED_FILE_ACTION_OKAY(250),
138 
139     /**
140      * 257 "PATHNAME" created.
141      */
142     REPLY_257_PATHNAME_CREATED(257),
143 
144     /**
145      * 331 User name okay, need password.
146      */
147     REPLY_331_USER_NAME_OKAY_NEED_PASSWORD(331),
148 
149     /**
150      * 332 Need account for login.
151      */
152     REPLY_332_NEED_ACCOUNT_FOR_LOGIN(332),
153 
154     /**
155      * 350 Requested file action pending further information.
156      */
157     REPLY_350_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFORMATION(350),
158 
159     /**
160      * 421 Service not available, closing control connection. This may be a
161      * reply to any command if the service knows it must shut down.
162      */
163     REPLY_421_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION(421),
164 
165     /**
166      * 425 Can't open data connection.
167      */
168     REPLY_425_CANT_OPEN_DATA_CONNECTION(425),
169 
170     /**
171      * 426 Connection closed), transfer aborted.
172      */
173     REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED(426),
174 
175     /**
176      * 450 Requested file action not taken. File unavailable (e.g.,
177      * file busy).
178      */
179     REPLY_450_REQUESTED_FILE_ACTION_NOT_TAKEN(450),
180 
181     /**
182      * 451 Requested action aborted: local error in processing.
183      */
184     REPLY_451_REQUESTED_ACTION_ABORTED(451),
185 
186     /**
187      * 452 Requested action not taken. Insufficient storage space in system.
188      */
189     REPLY_452_REQUESTED_ACTION_NOT_TAKEN(452),
190 
191     /**
192      * 500 Syntax error, command unrecognized. This may include errors such as
193      * command line too long.
194      */
195     REPLY_500_SYNTAX_ERROR_COMMAND_UNRECOGNIZED(500),
196 
197     /**
198      * 501 Syntax error in parameters or arguments.
199      */
200     REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS(501),
201 
202     /**
203      * 502 Command not implemented.
204      */
205     REPLY_502_COMMAND_NOT_IMPLEMENTED(502),
206 
207     /**
208      * 503 Bad sequence of commands.
209      */
210     REPLY_503_BAD_SEQUENCE_OF_COMMANDS(503),
211 
212     /**
213      * 504 Command not implemented for that parameter.
214      */
215     REPLY_504_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER(504),
216 
217     /**
218      * 522 Extended Port Failure - unknown network protocol.
219      */
220     REPLY_522_EXTENDED_PORT_FAILURE_UNKNOWN_NETWORK_PROTOCOL(522),
221 
222     /**
223      * 530 Not logged in.
224      */
225     REPLY_530_NOT_LOGGED_IN(530),
226 
227     /**
228      * 532 Need account for storing files.
229      */
230     REPLY_532_NEED_ACCOUNT_FOR_STORING_FILES(532),
231 
232     /**
233      * 550 Requested action not taken. File unavailable (e.g., file not
234      * found, no access).
235      */
236     REPLY_550_REQUESTED_ACTION_NOT_TAKEN(550),
237 
238     /**
239      * 551 Requested action aborted: page type unknown.
240      */
241     REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN(551),
242 
243     /**
244      * 552 Requested file action aborted. Exceeded storage allocation (for
245      * current directory or dataset).
246      */
247     REPLY_552_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE(552),
248 
249     /**
250      * 553 Requested action not taken. File name not allowed.
251      */
252     REPLY_553_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED(553);
253 
254     /**
255      * Numerical code
256      */
257     private int code;
258 
259     /**
260      * Message associated
261      */
262     private String mesg;
263 
264     /**
265      * LF
266      */
267     public static final String LF = "\n";
268 
269     /**
270      * CR NUL
271      */
272     public static final String CRNUL = "\r\0";
273 
274     /**
275      * CR LF<br>
276      * A User Telnet MUST be able to send any of the forms: CR LF, CR NUL, and
277      * LF. A User Telnet on an ASCII host SHOULD have a user-controllable mode
278      * to send either CR LF or CR NUL when the user presses the "end-of-line"
279      * key, and CR LF SHOULD be the default.
280      */
281     public static final String CRLF = "\r\n";
282 
283     /**
284      * Construct a Reply code from specific message
285      *
286      * @param code
287      * @param mesg
288      */
289     private ReplyCode(int code, String mesg) {
290         this.code = code;
291         this.mesg = getFinalMsg(code, mesg);
292     }
293 
294     /**
295      * Return the final message formatted as needed from the code and the
296      * message
297      *
298      * @param code
299      * @param msg
300      * @return the final formatted message
301      */
302     public static String getFinalMsg(int code, String msg) {
303         StringBuilder builder = new StringBuilder();
304         builder.append(code);
305         if (msg.indexOf('\n') == -1) {
306             builder.append(' ');
307             builder.append(msg);
308             builder.append(ReplyCode.CRLF);
309         } else {
310             String[] lines = msg.split("\n");
311             // first line
312             builder.append('-');
313             builder.append(lines[0]);
314             builder.append(ReplyCode.CRLF);
315             // next lines
316             for (int i = 1; i < lines.length - 1; i ++) {
317                 int firstBlank = lines[i].indexOf(' ');
318                 if (firstBlank > 0) {
319                     String firstParam = lines[i].substring(0, firstBlank);
320                     boolean isInt = false;
321                     try {
322                         Integer.parseInt(firstParam);
323                         isInt = true;
324                     } catch (NumberFormatException e) {
325                         // not a number
326                     }
327                     if (isInt) {
328                         builder.append("  ");
329                     }
330                 }
331                 builder.append(lines[i]);
332                 builder.append(ReplyCode.CRLF);
333             }
334             // last line
335             builder.append(code);
336             builder.append(' ');
337             builder.append(lines[lines.length - 1]);
338             builder.append(ReplyCode.CRLF);
339         }
340         return builder.toString();
341     }
342 
343     /**
344      * Construct a Reply Code from its name in Enum structure
345      *
346      * @param code
347      */
348     private ReplyCode(int code) {
349         this.code = code;
350         mesg = name().substring(6).replace('_', ' ') + ReplyCode.CRLF;
351     }
352 
353     /**
354      * @return the code
355      */
356     public int getCode() {
357         return code;
358     }
359 
360     /**
361      * @return the mesg
362      */
363     public String getMesg() {
364         return mesg;
365     }
366     /**
367      * 
368      * @param code
369      * @return the associated ReplyCode from the given numerical code
370      * @throws InvalidArgumentException 
371      */
372     public static ReplyCode getReplyCode(int code) throws InvalidArgumentException {
373         switch (code) {
374             case 0:
375                 return REPLY_000_SPECIAL_NOSTATUS;
376             case 110:
377                 return REPLY_110_RESTART_MARKER_REPLY;
378             case 120:
379                 return REPLY_120_SERVICE_READY_IN_NNN_MINUTES;
380             case 125:
381                 return REPLY_125_DATA_CONNECTION_ALREADY_OPEN;
382             case 150:
383                 return REPLY_150_FILE_STATUS_OKAY;
384             case 200:
385                 return REPLY_200_COMMAND_OKAY;
386             case 202:
387                 return REPLY_202_COMMAND_NOT_IMPLEMENTED;
388             case 211:
389                 return REPLY_211_SYSTEM_STATUS_REPLY;
390             case 212:
391                 return REPLY_212_DIRECTORY_STATUS;
392             case 213:
393                 return REPLY_213_FILE_STATUS;
394             case 214:
395                 return REPLY_214_HELP_MESSAGE;
396             case 215:
397                 return REPLY_215_NAME_SYSTEM_TYPE;
398             case 220:
399                 return REPLY_220_SERVICE_READY;
400             case 221:
401                 return REPLY_221_CLOSING_CONTROL_CONNECTION;
402             case 225:
403                 return REPLY_225_DATA_CONNECTION_OPEN_NO_TRANSFER_IN_PROGRESS;
404             case 226:
405                 return REPLY_226_CLOSING_DATA_CONNECTION;
406             case 227:
407                 return REPLY_227_ENTERING_PASSIVE_MODE;
408             case 229:
409                 return REPLY_229_ENTERING_PASSIVE_MODE;
410             case 230:
411                 return REPLY_230_USER_LOGGED_IN;
412             case 250:
413                 return REPLY_250_REQUESTED_FILE_ACTION_OKAY;
414             case 257:
415                 return REPLY_257_PATHNAME_CREATED;
416             case 331:
417                 return REPLY_331_USER_NAME_OKAY_NEED_PASSWORD;
418             case 332:
419                 return REPLY_332_NEED_ACCOUNT_FOR_LOGIN;
420             case 350:
421                 return REPLY_350_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFORMATION;
422             case 421:
423                 return REPLY_421_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION;
424             case 425:
425                 return REPLY_425_CANT_OPEN_DATA_CONNECTION;
426             case 426:
427                 return REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED;
428             case 450:
429                 return REPLY_450_REQUESTED_FILE_ACTION_NOT_TAKEN;
430             case 451:
431                 return REPLY_451_REQUESTED_ACTION_ABORTED;
432             case 452:
433                 return REPLY_452_REQUESTED_ACTION_NOT_TAKEN;
434             case 500:
435                 return REPLY_500_SYNTAX_ERROR_COMMAND_UNRECOGNIZED;
436             case 501:
437                 return REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS;
438             case 502:
439                 return REPLY_502_COMMAND_NOT_IMPLEMENTED;
440             case 503:
441                 return REPLY_503_BAD_SEQUENCE_OF_COMMANDS;
442             case 504:
443                 return REPLY_504_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER;
444             case 522:
445                 return REPLY_522_EXTENDED_PORT_FAILURE_UNKNOWN_NETWORK_PROTOCOL;
446             case 530:
447                 return REPLY_530_NOT_LOGGED_IN;
448             case 532:
449                 return REPLY_532_NEED_ACCOUNT_FOR_STORING_FILES;
450             case 550:
451                 return REPLY_550_REQUESTED_ACTION_NOT_TAKEN;
452             case 551:
453                 return REPLY_551_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN;
454             case 552:
455                 return REPLY_552_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE;
456             case 553:
457                 return REPLY_553_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED;
458             default:
459                 throw new InvalidArgumentException("Unknown ReplyCode "+code);
460         }
461     }
462 }