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.session;
22  
23  import java.io.File;
24  
25  import goldengate.common.command.CommandInterface;
26  import goldengate.common.command.ReplyCode;
27  import goldengate.common.command.exception.CommandAbstractException;
28  import goldengate.common.command.exception.Reply425Exception;
29  import goldengate.common.file.FileParameterInterface;
30  import goldengate.common.file.Restart;
31  import goldengate.common.file.SessionInterface;
32  import goldengate.ftp.core.command.AbstractCommand;
33  import goldengate.ftp.core.command.internal.ConnectionCommand;
34  import goldengate.ftp.core.config.FtpConfiguration;
35  import goldengate.ftp.core.control.BusinessHandler;
36  import goldengate.ftp.core.control.NetworkHandler;
37  import goldengate.ftp.core.data.FtpDataAsyncConn;
38  import goldengate.ftp.core.file.FtpAuth;
39  import goldengate.ftp.core.file.FtpDir;
40  
41  import org.jboss.netty.channel.Channel;
42  
43  /**
44   * Main class that stores any information that must be accessible from anywhere
45   * during the connection of one user.
46   *
47   * @author Frederic Bregier
48   *
49   */
50  public class FtpSession implements SessionInterface {
51      /**
52       * Business Handler
53       */
54      private final BusinessHandler businessHandler;
55  
56      /**
57       * Associated global configuration
58       */
59      private final FtpConfiguration configuration;
60  
61      /**
62       * Associated Binary connection
63       */
64      private volatile FtpDataAsyncConn dataConn = null;
65  
66      /**
67       * Ftp Authentication
68       */
69      private FtpAuth ftpAuth = null;
70  
71      /**
72       * Ftp DirInterface configuration and access
73       */
74      private FtpDir ftpDir = null;
75  
76      /**
77       * Previous Command
78       */
79      private AbstractCommand previousCommand = null;
80  
81      /**
82       * Current Command
83       */
84      private AbstractCommand currentCommand = null;
85      /**
86       * Is the current command finished
87       */
88      private volatile boolean isCurrentCommandFinished = true;
89      
90      /**
91       * Associated Reply Code
92       */
93      private ReplyCode replyCode = null;
94  
95      /**
96       * Real text for answer
97       */
98      private String answer = null;
99  
100     /**
101      * Current Restart information
102      */
103     private Restart restart = null;
104 
105     /**
106      * Is the control ready to accept command
107      */
108     private volatile boolean isReady = false;
109 
110     /**
111      * Constructor
112      *
113      * @param configuration
114      * @param handler
115      */
116     public FtpSession(FtpConfiguration configuration, BusinessHandler handler) {
117         this.configuration = configuration;
118         businessHandler = handler;
119         isReady = false;
120     }
121 
122     /**
123      * @return the businessHandler
124      */
125     public BusinessHandler getBusinessHandler() {
126         return businessHandler;
127     }
128 
129     /**
130      * Get the configuration
131      *
132      * @return the configuration
133      */
134     public FtpConfiguration getConfiguration() {
135         return configuration;
136     }
137 
138     public FtpDir getDir() {
139         return ftpDir;
140     }
141 
142     /**
143      * @return the Data Connection
144      */
145     public FtpDataAsyncConn getDataConn() {
146         return dataConn;
147     }
148 
149     public FtpAuth getAuth() {
150         return ftpAuth;
151     }
152 
153     public Restart getRestart() {
154         return restart;
155     }
156 
157     /**
158      * This function is called when the Command Channel is connected (from
159      * channelConnected of the NetworkHandler)
160      */
161     public void setControlConnected() {
162         dataConn = new FtpDataAsyncConn(this);
163         // AuthInterface must be done before FtpFile
164         ftpAuth = businessHandler.getBusinessNewAuth();
165         ftpDir = businessHandler.getBusinessNewDir();
166         restart = businessHandler.getBusinessNewRestart();
167     }
168     /**
169      * Special initialization (FtpExec with Https session)
170      * @param auth
171      * @param dir
172      * @param restart
173      */
174     public void setSpecialInit(FtpAuth auth, FtpDir dir, Restart restart) {
175         this.ftpAuth = auth;
176         this.ftpDir = dir;
177         this.restart = restart;
178     }
179     /**
180      * @return the Control channel
181      */
182     public Channel getControlChannel() {
183         return getNetworkHandler().getControlChannel();
184     }
185 
186     /**
187      *
188      * @return The network handler associated with control
189      */
190     public NetworkHandler getNetworkHandler() {
191         if (businessHandler != null) {
192             return businessHandler.getNetworkHandler();
193         }
194         return null;
195     }
196 
197     /**
198      * Set the new current command
199      *
200      * @param command
201      */
202     public void setNextCommand(CommandInterface command) {
203         previousCommand = currentCommand;
204         currentCommand = (AbstractCommand) command;
205         isCurrentCommandFinished = false;
206     }
207 
208     /**
209      * @return the currentCommand
210      */
211     public AbstractCommand getCurrentCommand() {
212         return currentCommand;
213     }
214 
215     /**
216      * @return the previousCommand
217      */
218     public AbstractCommand getPreviousCommand() {
219         return previousCommand;
220     }
221 
222     /**
223      * Set the previous command as the new current command (used after a
224      * incorrect sequence of commands or unknown command)
225      *
226      */
227     public void setPreviousAsCurrentCommand() {
228         currentCommand = previousCommand;
229         isCurrentCommandFinished = true;
230     }
231     /**
232      * 
233      * @return True if the Current Command is already Finished (ready to accept a new one)
234      */
235     public boolean isCurrentCommandFinished() {
236         return isCurrentCommandFinished;
237     }
238     /**
239      * Set the Current Command as finished
240      */
241     public void setCurrentCommandFinished() {
242         this.isCurrentCommandFinished = true;
243     }
244     /**
245      * @return the answer
246      */
247     public String getAnswer() {
248         if (answer == null) {
249             answer = replyCode.getMesg();
250         }
251         return answer;
252     }
253 
254     /**
255      * @param replyCode
256      *            the replyCode to set
257      * @param answer
258      */
259     public void setReplyCode(ReplyCode replyCode, String answer) {
260         this.replyCode = replyCode;
261         if (answer != null) {
262             this.answer = ReplyCode.getFinalMsg(replyCode.getCode(), answer);
263         } else {
264             this.answer = replyCode.getMesg();
265         }
266     }
267 
268     /**
269      * @param exception
270      */
271     public void setReplyCode(CommandAbstractException exception) {
272         this.setReplyCode(exception.code, exception.message);
273     }
274 
275     /**
276      * Set Exit code after an error
277      *
278      * @param answer
279      */
280     public void setExitErrorCode(String answer) {
281         this
282                 .setReplyCode(
283                         ReplyCode.REPLY_421_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION,
284                         answer);
285     }
286 
287     /**
288      * Set Exit normal code
289      *
290      * @param answer
291      */
292     public void setExitNormalCode(String answer) {
293         this.setReplyCode(ReplyCode.REPLY_221_CLOSING_CONTROL_CONNECTION,
294                 answer);
295     }
296 
297     /**
298      * @return the replyCode
299      */
300     public ReplyCode getReplyCode() {
301         return replyCode;
302     }
303 
304     public void clear() {
305         if (dataConn != null) {
306             dataConn.clear();
307         }
308         if (ftpDir != null) {
309             ftpDir.clear();
310         }
311         if (ftpAuth != null) {
312             ftpAuth.clear();
313         }
314         previousCommand = null;
315         replyCode = null;
316         answer = null;
317         isReady = false;
318     }
319 
320     /**
321      * @return True if the Control is ready to accept command
322      */
323     public boolean isReady() {
324         return isReady;
325     }
326 
327     /**
328      * @param isReady
329      *            the isReady to set
330      */
331     public void setReady(boolean isReady) {
332         this.isReady = isReady;
333     }
334 
335     @Override
336     public String toString() {
337         String mesg = "FtpSession: ";
338         if (ftpAuth != null) {
339             mesg += "User: "+ftpAuth.getUser()+"/"+ftpAuth.getAccount()+" ";
340         }
341         if (currentCommand != null) {
342             mesg += "CMD: " + currentCommand.getCommand() + " " +
343                     currentCommand.getArg() + " ";
344         }
345         if (replyCode != null) {
346             mesg += "Reply: " + (answer != null? answer : replyCode.getMesg()) +
347                     " ";
348         }
349         if (dataConn != null) {
350             mesg += dataConn.toString();
351         }
352         if (ftpDir != null) {
353             try {
354                 mesg += " PWD: " + ftpDir.getPwd();
355             } catch (CommandAbstractException e) {
356             }
357         }
358         return mesg + "\n";
359     }
360 
361     public int getBlockSize() {
362         return configuration.BLOCKSIZE;
363     }
364 
365     public FileParameterInterface getFileParameter() {
366         return configuration.getFileParameter();
367     }
368 
369     /**
370     *
371     * @param path
372     * @return the basename from the given path
373     */
374     public static String getBasename(String path) {
375         File file = new File(path);
376         return file.getName();
377     }
378     /**
379      * Reinitialize the authentication to the connection step
380      *
381      */
382     public void reinitFtpAuth() {
383         AbstractCommand connectioncommand = new ConnectionCommand(this);
384         setNextCommand(connectioncommand);
385         getAuth().clear();
386         getDataConn().clear();
387     }
388 
389     /**
390      * Try to open a connection. Do the intermediate reply if any (150) and the
391      * final one (125)
392      *
393      * @throws Reply425Exception
394      *             if the connection cannot be opened
395      */
396     public void openDataConnection() throws Reply425Exception {
397         getDataConn().getFtpTransferControl().openDataConnection();
398         getNetworkHandler().writeIntermediateAnswer();
399     }
400 
401     /* (non-Javadoc)
402      * @see goldengate.common.file.SessionInterface#getUniqueExtension()
403      */
404     @Override
405     public String getUniqueExtension() {
406         return configuration.getUniqueExtension();
407     }
408 }