/** Abort the current transfer */
 private void abortTransfer() {
   // logger.debug("Will abort transfer and write: ", write);
   FtpFile file = null;
   FtpTransfer current = null;
   try {
     current = getExecutingFtpTransfer();
     file = current.getFtpFile();
     file.abortFile();
   } catch (FtpNoTransferException e) {
     logger.warn("Abort problem", e);
   } catch (FtpNoFileException e) {
   } catch (CommandAbstractException e) {
     logger.warn("Abort problem", e);
   }
   if (current != null) {
     current.setStatus(false);
   }
   endDataConnection();
   session.setReplyCode(
       ReplyCode.REPLY_426_CONNECTION_CLOSED_TRANSFER_ABORTED,
       "Transfer aborted for " + (current == null ? "Unknown command" : current.toString()));
   if (current != null) {
     if (!FtpCommandCode.isListLikeCommand(current.getCommand())) {
       try {
         session.getBusinessHandler().afterTransferDoneBeforeAnswer(current);
       } catch (CommandAbstractException e) {
         session.setReplyCode(e);
       }
     }
   }
   finalizeExecution();
 }
 /** Run the command from an executor */
 private void runExecutor() {
   // Unlock Mode Codec
   try {
     session.getDataConn().getDataNetworkHandler().unlockModeCodec();
   } catch (FtpNoConnectionException e) {
     setTransferAbortedFromInternal(false);
     return;
   }
   // Run the command
   if (executorService == null) {
     executorService = Executors.newSingleThreadExecutor();
   }
   endOfCommand = new WaarpFuture(true);
   final ArrayList<Callable<Object>> tasks = new ArrayList<Callable<Object>>(1);
   tasks.add(Executors.callable(new FtpTransferExecutor(session, executingCommand)));
   try {
     executorService.invokeAll(tasks);
   } catch (InterruptedException e1) {
   }
   // XXX TRY FIX TO IMPROVE
   /*
   executorService.execute(new FtpTransferExecutor(session,
   	executingCommand));
   	*/
   try {
     commandFinishing.await();
   } catch (InterruptedException e) {
   }
 }
 /**
  * To enable abort from internal error
  *
  * @param write True means the message is write back to the control command, false it is only
  *     prepared
  */
 public void setTransferAbortedFromInternal(boolean write) {
   // logger.debug("Set transfer aborted internal {}", write);
   abortTransfer();
   if (write) {
     session.getNetworkHandler().writeIntermediateAnswer();
   }
   if (endOfCommand != null) {
     endOfCommand.cancel();
   }
 }
 /**
  * Set the new opened Channel (from channelConnected of {@link DataNetworkHandler})
  *
  * @param channel
  * @param dataNetworkHandler
  */
 public void setOpenedDataChannel(Channel channel, DataNetworkHandler dataNetworkHandler) {
   logger.debug(
       "SetOpenedDataChannel: " + (channel != null ? channel.getRemoteAddress() : "no channel"));
   if (channel != null) {
     session.getDataConn().setDataNetworkHandler(dataNetworkHandler);
     waitForOpenedDataChannel.setChannel(channel);
     waitForOpenedDataChannel.setSuccess();
   } else {
     waitForOpenedDataChannel.cancel();
   }
 }
 /** Finish correctly a transfer */
 private void closeTransfer() {
   // logger.debug("Will close transfer and write: {}", write);
   FtpFile file = null;
   FtpTransfer current = null;
   try {
     current = getExecutingFtpTransfer();
     file = current.getFtpFile();
     file.closeFile();
   } catch (FtpNoTransferException e) {
     logger.warn("Close problem", e);
   } catch (FtpNoFileException e) {
   } catch (CommandAbstractException e) {
     logger.warn("Close problem", e);
   }
   if (current != null) {
     current.setStatus(true);
   }
   if (session.getDataConn().isStreamFile()) {
     endDataConnection();
   }
   session.setReplyCode(
       ReplyCode.REPLY_226_CLOSING_DATA_CONNECTION,
       "Transfer complete for " + (current == null ? "Unknown command" : current.toString()));
   if (current != null) {
     if (!FtpCommandCode.isListLikeCommand(current.getCommand())) {
       try {
         session.getBusinessHandler().afterTransferDoneBeforeAnswer(current);
       } catch (CommandAbstractException e) {
         session.setReplyCode(e);
       }
     } else {
       // Special wait to prevent fast LIST following by STOR or RETR command
       try {
         Thread.sleep(FtpInternalConfiguration.RETRYINMS);
       } catch (InterruptedException e) {
       }
     }
   }
   finalizeExecution();
 }
 /**
  * Wait that the new opened connection is ready (same method in {@link FtpDataAsyncConn} from
  * openConnection)
  *
  * @return the new opened Channel
  * @throws InterruptedException
  */
 public Channel waitForOpenedDataChannel() throws InterruptedException {
   Channel channel = null;
   if (waitForOpenedDataChannel.await(
       session.getConfiguration().TIMEOUTCON + 1000, TimeUnit.MILLISECONDS)) {
     if (waitForOpenedDataChannel.isSuccess()) {
       channel = waitForOpenedDataChannel.getChannel();
     } else {
       logger.warn("data connection is in error");
     }
   } else {
     logger.warn("Timeout occurs during data connection");
   }
   waitForOpenedDataChannel = new WaarpChannelFuture(true);
   return channel;
 }
 /**
  * Wait for the client to be connected (Passive) or Wait for the server to be connected to the
  * client (Active)
  *
  * @return True if the connection is OK
  * @throws Reply425Exception
  */
 public boolean openDataConnection() throws Reply425Exception {
   // Prepare this Data channel to be closed ;-)
   // In fact, prepare the future close op which should occur since it is
   // now opened
   closedDataChannel = new WaarpFuture(true);
   FtpDataAsyncConn dataAsyncConn = session.getDataConn();
   if (!dataAsyncConn.isStreamFile()) {
     // FIXME isConnected or isDNHReady ?
     if (dataAsyncConn.isConnected()) {
       // Already connected
       // logger.debug("Connection already open");
       session.setReplyCode(
           ReplyCode.REPLY_125_DATA_CONNECTION_ALREADY_OPEN,
           dataAsyncConn.getType().name() + " mode data connection already open");
       return true;
     }
   } else {
     // Stream, Data Connection should not be opened
     if (dataAsyncConn.isConnected()) {
       logger.error("Connection already open but should not since in Stream mode");
       setTransferAbortedFromInternal(false);
       throw new Reply425Exception("Connection already open but should not since in Stream mode");
     }
   }
   // Need to open connection
   session.setReplyCode(
       ReplyCode.REPLY_150_FILE_STATUS_OKAY,
       "Opening " + dataAsyncConn.getType().name() + " mode data connection");
   if (dataAsyncConn.isPassiveMode()) {
     if (!dataAsyncConn.isBind()) {
       // No passive connection prepared
       throw new Reply425Exception("No passive data connection prepared");
     }
     // Wait for the connection to be done by the client
     // logger.debug("Passive mode standby");
     try {
       dataChannel = waitForOpenedDataChannel();
       dataAsyncConn.setNewOpenedDataChannel(dataChannel);
     } catch (InterruptedException e) {
       logger.warn("Connection abort in passive mode", e);
       // Cannot open connection
       throw new Reply425Exception("Cannot open passive data connection");
     }
     // logger.debug("Passive mode connected");
   } else {
     // Wait for the server to be connected to the client
     InetAddress inetAddress = dataAsyncConn.getLocalAddress().getAddress();
     InetSocketAddress inetSocketAddress = dataAsyncConn.getRemoteAddress();
     if (session
         .getConfiguration()
         .getFtpInternalConfiguration()
         .hasFtpSession(inetAddress, inetSocketAddress)) {
       throw new Reply425Exception(
           "Cannot open active data connection since remote address is already in use: "
               + inetSocketAddress);
     }
     // logger.debug("Active mode standby");
     ClientBootstrap clientBootstrap =
         session
             .getConfiguration()
             .getFtpInternalConfiguration()
             .getActiveBootstrap(session.isDataSsl());
     session.getConfiguration().setNewFtpSession(inetAddress, inetSocketAddress, session);
     // Set the session for the future dataChannel
     String mylog = session.toString();
     logger.debug(
         "DataConn for: "
             + session.getCurrentCommand().getCommand()
             + " to "
             + inetSocketAddress.toString());
     ChannelFuture future =
         clientBootstrap.connect(inetSocketAddress, dataAsyncConn.getLocalAddress());
     try {
       future.await();
     } catch (InterruptedException e1) {
     }
     if (!future.isSuccess()) {
       logger.warn(
           "Connection abort in active mode from future while session: "
               + session.toString()
               + "\nTrying connect to: "
               + inetSocketAddress.toString()
               + "\nWas: "
               + mylog,
           future.getCause());
       // Cannot open connection
       session.getConfiguration().delFtpSession(inetAddress, inetSocketAddress);
       throw new Reply425Exception("Cannot open active data connection");
     }
     try {
       dataChannel = waitForOpenedDataChannel();
       dataAsyncConn.setNewOpenedDataChannel(dataChannel);
     } catch (InterruptedException e) {
       logger.warn("Connection abort in active mode", e);
       // Cannot open connection
       session.getConfiguration().delFtpSession(inetAddress, inetSocketAddress);
       throw new Reply425Exception("Cannot open active data connection");
     }
     // logger.debug("Active mode connected");
   }
   if (dataChannel == null) {
     // Cannot have a new Data connection since shutdown
     if (!dataAsyncConn.isPassiveMode()) {
       session
           .getConfiguration()
           .getFtpInternalConfiguration()
           .delFtpSession(
               dataAsyncConn.getLocalAddress().getAddress(), dataAsyncConn.getRemoteAddress());
     }
     throw new Reply425Exception("Cannot open data connection, shuting down");
   }
   return true;
 }