View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, 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 Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.ftp.core.data;
21  
22  import org.waarp.common.command.ReplyCode;
23  import org.waarp.common.logging.WaarpLogger;
24  import org.waarp.common.logging.WaarpLoggerFactory;
25  import org.waarp.ftp.core.command.FtpCommandCode;
26  import org.waarp.ftp.core.exception.FtpNoConnectionException;
27  import org.waarp.ftp.core.exception.FtpNoFileException;
28  import org.waarp.ftp.core.session.FtpSession;
29  
30  import java.util.List;
31  
32  /**
33   * Class that implements the execution of the Transfer itself.
34   */
35  class FtpTransferExecutor implements Runnable {
36    /**
37     * Internal Logger
38     */
39    private static final WaarpLogger logger =
40        WaarpLoggerFactory.getLogger(FtpTransferExecutor.class);
41  
42    /**
43     * Ftp SessionInterface
44     */
45    private final FtpSession session;
46  
47    /**
48     * FtpTransfer
49     */
50    private final FtpTransfer executeTransfer;
51  
52    /**
53     * Create an executor and launch it
54     *
55     * @param session
56     * @param executeTransfer
57     */
58    FtpTransferExecutor(final FtpSession session,
59                        final FtpTransfer executeTransfer) {
60      this.session = session;
61      this.executeTransfer = executeTransfer;
62      if (this.executeTransfer == null) {
63        this.session.getDataConn().getFtpTransferControl().setEndOfTransfer();
64        logger.error("No Execution to do");
65      }
66    }
67  
68    /**
69     * Internal method, should not be called directly
70     */
71    @Override
72    public void run() {
73      if (executeTransfer == null) {
74        session.getDataConn().getFtpTransferControl().setEndOfTransfer();
75        logger.error("No Execution to do");
76        return;
77      }
78      try {
79        runNextCommand();
80      } catch (final InterruptedException e) {//NOSONAR
81        logger.error("Executor Interrupted: {}", e.getMessage(), e);
82      }
83    }
84  
85    /**
86     * Run the next command or wait for the next
87     *
88     * @throws InterruptedException
89     */
90    private void runNextCommand() throws InterruptedException {
91      if (FtpCommandCode.isStoreLikeCommand(executeTransfer.getCommand())) {
92        // The command is implicitly done by receiving message
93        waitForCommand();
94        // Store set end
95        try {
96          session.getDataConn().getFtpTransferControl().setEndOfTransfer();
97        } catch (final NullPointerException e) {
98          // ignore, due probably to an already clean session
99        }
100     } else if (FtpCommandCode.isListLikeCommand(executeTransfer.getCommand())) {
101       // No wait for Command since the answer is already there
102       final List<String> list = executeTransfer.getInfo();
103       final StringBuilder builder = new StringBuilder();
104       for (final String newfileInfo : list) {
105         builder.append(newfileInfo).append(ReplyCode.CRLF);
106       }
107       if (builder.length() == 0) {
108         builder.append(ReplyCode.CRLF);
109       }
110       final String message = builder.toString();
111       boolean status = false;
112       try {
113         status =
114             session.getDataConn().getDataNetworkHandler().writeMessage(message);
115       } catch (final FtpNoConnectionException e) {
116         logger.error("No Connection but should not be!", e);
117       }
118       // Set status for check, no wait for the command
119       executeTransfer.setStatus(status);
120       // must explicitly set the end and no wait
121       session.getDataConn().getFtpTransferControl().setEndOfTransfer();
122     } else if (FtpCommandCode.isRetrLikeCommand(executeTransfer.getCommand())) {
123       // The command must be launched
124       try {
125         executeTransfer.getFtpFile().trueRetrieve();
126       } catch (final FtpNoFileException e) {
127         // an error occurs
128         logger.error(e);
129         session.getDataConn().getFtpTransferControl().setEndOfTransfer();
130       }
131       logger.debug("wait for end of command");
132       waitForCommand();
133       logger.debug("RETR ending");
134       // RETR set end
135       try {
136         session.getDataConn().getFtpTransferControl().setEndOfTransfer();
137       } catch (final NullPointerException e) {
138         // ignore, due probably to an already clean session
139       }
140     } else {
141       // This is an error as unknown transfer command
142       session.getDataConn().getFtpTransferControl().setEndOfTransfer();
143     }
144   }
145 
146   /**
147    * Wait for the command to finish
148    *
149    * @throws InterruptedException
150    */
151   private void waitForCommand() throws InterruptedException {
152     session.getDataConn().getFtpTransferControl().waitForEndOfTransfer();
153   }
154 }