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.ftp.core.control;
22  
23  import goldengate.common.command.exception.CommandAbstractException;
24  import goldengate.common.file.Restart;
25  import goldengate.common.file.filesystembased.FilesystemBasedOptsMLSxImpl;
26  import goldengate.ftp.core.command.AbstractCommand;
27  import goldengate.ftp.core.command.FtpCommandCode;
28  import goldengate.ftp.core.data.FtpTransfer;
29  import goldengate.ftp.core.file.FtpAuth;
30  import goldengate.ftp.core.file.FtpDir;
31  import goldengate.ftp.core.session.FtpSession;
32  
33  import org.jboss.netty.channel.Channel;
34  import org.jboss.netty.channel.ExceptionEvent;
35  
36  /**
37   * This class is to be implemented in order to allow Business actions according
38   * to FTP service
39   *
40   * @author Frederic Bregier
41   *
42   */
43  public abstract class BusinessHandler {
44      /**
45       * NettyHandler that holds this BusinessHandler
46       */
47      private NetworkHandler networkHandler = null;
48  
49      /**
50       * FtpSession
51       */
52      private FtpSession session = null;
53  
54      /**
55       * Constructor with no argument (mandatory)
56       */
57      public BusinessHandler() {
58          // nothing to do
59      }
60  
61      /**
62       * Called when the NetworkHandler is created
63       *
64       * @param networkHandler
65       *            the networkHandler to set
66       */
67      public void setNetworkHandler(NetworkHandler networkHandler) {
68          this.networkHandler = networkHandler;
69          session = this.networkHandler.getFtpSession();
70      }
71  
72      /**
73       * @return the networkHandler
74       */
75      public NetworkHandler getNetworkHandler() {
76          return networkHandler;
77      }
78  
79      // Some helpful functions
80      /**
81       *
82       * @return the ftpSession
83       */
84      public FtpSession getFtpSession() {
85          return session;
86      }
87  
88      /**
89       * Create a new AuthInterface according to business choice
90       *
91       * @return the new FtpAuth
92       */
93      public abstract FtpAuth getBusinessNewAuth();
94  
95      /**
96       * Create a new FtpDir according to business choice
97       *
98       * @return the new FtpDir
99       */
100     public abstract FtpDir getBusinessNewDir();
101 
102     /**
103      * Create a new Restart according to business choice
104      *
105      * @return the new Restart
106      */
107     public abstract Restart getBusinessNewRestart();
108 
109     /**
110      *
111      * @param arg
112      *            the argument from HELP command
113      * @return the string to return to the client for the HELP command
114      */
115     public abstract String getHelpMessage(String arg);
116 
117     /**
118      *
119      * @return the string to return to the client for the FEAT command
120      */
121     public abstract String getFeatMessage();
122 
123     /**
124      *
125      * @return the string to return to the client for the FEAT command without
126      *         surrounding by "Extensions supported:\n" and "\nEnd"
127      */
128     protected String getDefaultFeatMessage() {
129         StringBuilder builder = new StringBuilder();
130         builder.append(FtpCommandCode.MDTM.name());
131         builder.append('\n');
132         builder.append(FtpCommandCode.MLSD.name());
133         builder.append(getFtpSession().getDir().getOptsMLSx().getFeat());
134         builder.append('\n');
135         builder.append(FtpCommandCode.MLST.name());
136         builder.append(getFtpSession().getDir().getOptsMLSx().getFeat());
137         builder.append('\n');
138         builder.append(FtpCommandCode.SIZE.name());
139         builder.append('\n');
140         builder.append(FtpCommandCode.XCUP.name());
141         builder.append('\n');
142         builder.append(FtpCommandCode.XCWD.name());
143         builder.append('\n');
144         builder.append(FtpCommandCode.XMKD.name());
145         builder.append('\n');
146         builder.append(FtpCommandCode.XPWD.name());
147         builder.append('\n');
148         builder.append(FtpCommandCode.XRMD.name());
149         builder.append('\n');
150         builder.append(FtpCommandCode.PASV.name());
151         builder.append('\n');
152         builder.append(FtpCommandCode.ALLO.name());
153         builder.append('\n');
154         builder.append(FtpCommandCode.EPRT.name());
155         builder.append('\n');
156         builder.append(FtpCommandCode.EPSV.name());
157         builder.append('\n');
158         builder.append(FtpCommandCode.XCRC.name());
159         builder.append(" \"filename\"");
160         builder.append('\n');
161         builder.append(FtpCommandCode.XMD5.name());
162         builder.append(" \"filename\"");
163         builder.append('\n');
164         builder.append(FtpCommandCode.XSHA1.name());
165         builder.append(" \"filename\"");
166         builder.append('\n');
167         builder.append(FtpCommandCode.SITE.name());
168         builder.append(' ');
169         builder.append(FtpCommandCode.XCRC.name());
170         // builder.append(" \"filename\"");
171         builder.append('\n');
172         builder.append(FtpCommandCode.SITE.name());
173         builder.append(' ');
174         builder.append(FtpCommandCode.XMD5.name());
175         // builder.append(" \"filename\"");
176         builder.append('\n');
177         builder.append(FtpCommandCode.SITE.name());
178         builder.append(' ');
179         builder.append(FtpCommandCode.XSHA1.name());
180         // builder.append(" \"filename\"");
181         builder.append('\n');
182         builder.append("LAN EN*");
183         builder.append('\n');
184         builder.append(FtpCommandCode.REST.name());
185         builder.append(" STREAM\n");
186         builder.append("UTF8");
187         return builder.toString();
188     }
189 
190     /**
191      * @param args
192      * @return the string to return to the client for the FEAT command
193      * @exception CommandAbstractException
194      */
195     public abstract String getOptsMessage(String[] args)
196             throws CommandAbstractException;
197 
198     /**
199      * Check if a command pass to SITE command is legal
200      * @param session
201      * @param line
202      * @return the AbstractCommand to execute if it is a Specialized Command, else Null
203      */
204     public abstract AbstractCommand getSpecializedSiteCommand(FtpSession session, String line);
205 
206     /**
207      *
208      * @param args
209      * @return the string to return to the client for the FEAT command for the
210      *         MLSx argument
211      */
212     protected String getMLSxOptsMessage(String[] args) {
213         FilesystemBasedOptsMLSxImpl optsMLSx = (FilesystemBasedOptsMLSxImpl) getFtpSession()
214                 .getDir().getOptsMLSx();
215         optsMLSx.setOptsModify((byte) 0);
216         optsMLSx.setOptsPerm((byte) 0);
217         optsMLSx.setOptsSize((byte) 0);
218         optsMLSx.setOptsType((byte) 0);
219         for (int i = 1; i < args.length; i ++) {
220             if (args[i].equalsIgnoreCase("modify")) {
221                 optsMLSx.setOptsModify((byte) 1);
222             } else if (args[i].equalsIgnoreCase("perm")) {
223                 optsMLSx.setOptsModify((byte) 1);
224             } else if (args[i].equalsIgnoreCase("size")) {
225                 optsMLSx.setOptsModify((byte) 1);
226             } else if (args[i].equalsIgnoreCase("type")) {
227                 optsMLSx.setOptsModify((byte) 1);
228             }
229         }
230         return args[0] + " " + FtpCommandCode.OPTS.name() + optsMLSx.getFeat();
231     }
232 
233     /**
234      * Is executed when the channel is closed, just before cleaning and just
235      * after.<br>
236      * <I>Note: In some circumstances, it could be a good idea to call the clean
237      * operation on FtpAuth in order to relax constraints on user
238      * authentication. It will be called however at least when the session will
239      * be clean just after this call.</I>
240      */
241     public abstract void executeChannelClosed();
242 
243     /**
244      * To Clean the session attached objects
245      */
246     protected abstract void cleanSession();
247 
248     /**
249      * Clean the BusinessHandler.
250      *
251      */
252     public void clear() {
253         cleanSession();
254     }
255 
256     /**
257      * Is executed when the channel is connected after the handler is on, before
258      * answering OK or not on connection, except if the global service is going
259      * to shutdown.
260      *
261      * @param channel
262      */
263     public abstract void executeChannelConnected(Channel channel);
264 
265     /**
266      * Run when an exception is get before the channel is closed. This must set
267      * a correct answer.
268      *
269      * @param e
270      */
271     public abstract void exceptionLocalCaught(ExceptionEvent e);
272 
273     /**
274      * This method is called for every received message before the execution of
275      * the command. If an exception is raised, the reply is immediate and no
276      * action taken.
277      *
278      * @exception CommandAbstractException
279      */
280     public abstract void beforeRunCommand() throws CommandAbstractException;
281 
282     /**
283      * This method is called for every received message after the execution of
284      * the command but before the final reply to the client. If an exception is
285      * raised, the reply is immediate. This is the last call before finishing
286      * the command.
287      *
288      * @exception CommandAbstractException
289      */
290     public abstract void afterRunCommandOk() throws CommandAbstractException;
291 
292     /**
293      * Run when a FTP exception is catch (the channel is not necessary closed
294      * after). This must set a correct answer and a correct code of reply. If
295      * the code of reply is 421, then the channel will be closed after this
296      * call. This is the last call before finishing the command.
297      *
298      * @param e
299      */
300     public abstract void afterRunCommandKo(CommandAbstractException e);
301 
302     /**
303      * Run when a transfer is finished (eventually in error) but before answering.
304      * Note that this is called only for a Transfer Request (or LIST) but
305      * called before afterRunCommandXX is called (Ok or Ko).
306      *
307      * @param transfer
308      * @exception CommandAbstractException
309      */
310     public abstract void afterTransferDoneBeforeAnswer(FtpTransfer transfer) throws CommandAbstractException;
311 }