// Path: deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/SyncBuildProcessAdapter.java
// public abstract class SyncBuildProcessAdapter extends BuildProcessAdapter {
//   protected final BuildProgressLogger myLogger;
//   private volatile boolean hasFinished;
//   private volatile BuildFinishedStatus statusCode;
//   private volatile boolean isInterrupted;
// 
// 
//   public SyncBuildProcessAdapter(@NotNull final BuildProgressLogger logger) {
//     myLogger = logger;
//     hasFinished = false;
//     statusCode = null;
//   }
// 
// 
//   @Override
//   public void interrupt() {
//     isInterrupted = true;
//   }
// 
//   @Override
//   public boolean isInterrupted() {
//     return isInterrupted;
//   }
// 
//   @Override
//   public boolean isFinished() {
//     return hasFinished;
//   }
// 
//   @NotNull
//   @Override
//   public BuildFinishedStatus waitFor() throws RunBuildException {
//     while (!isInterrupted() && !hasFinished) {
//       try {
//         Thread.sleep(1000);
//       } catch (InterruptedException e) {
//         throw new RunBuildException(e);
//       }
//     }
//     return hasFinished ? statusCode : BuildFinishedStatus.INTERRUPTED;
//   }
// 
//   @Override
//   public void start() throws RunBuildException {
//     try {
//       statusCode = runProcess();
//       hasFinished = true;
//     } catch (UploadInterruptedException e) {
//       hasFinished = false;
//     }
//   }
// 
//   /**
//    * @return true is process finished successfully
//    */
//   protected abstract BuildFinishedStatus runProcess();
// 
//   protected void checkIsInterrupted() throws UploadInterruptedException {
//     if (isInterrupted()) throw new UploadInterruptedException();
//   }
// 
// }
// 
// Path: deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/UploadInterruptedException.java
// public class UploadInterruptedException extends RuntimeException {
// 
// }
// 
// Path: deploy-runner-common/src/main/java/jetbrains/buildServer/deployer/common/FTPRunnerConstants.java
// public class FTPRunnerConstants {
//   public static final String PARAM_AUTH_METHOD = "jetbrains.buildServer.deployer.ftp.authMethod";
//   public static final String PARAM_TRANSFER_MODE = "jetbrains.buildServer.deployer.ftp.transferMethod";
//   public static final String TRANSFER_MODE_AUTO = "AUTO";
//   public static final String TRANSFER_MODE_BINARY = "BINARY";
//   public static final String TRANSFER_MODE_ASCII = "ASCII";
//   public static final String AUTH_METHOD_USER_PWD = "USER_PWD";
//   public static final String AUTH_METHOD_ANONYMOUS = "ANONYMOUS";
//   public static final String PARAM_SSL_MODE = "jetbrains.buildServer.deployer.ftp.securityMode";
//   public static final String DATA_CHANNEL_PROTECTION = "jetbrains.buildServer.deployer.ftp.dataChannelProtection";
//   public static final String PARAM_FTP_MODE = "jetbrains.buildServer.deployer.ftp.ftpMode";
//   public static final String PARAM_FTP_CONNECT_TIMEOUT = "jetbrains.deployer.ftp.connectTimeout";
//   public static final String PARAM_FTP_CONTROL_KEEP_ALIVE_TIMEOUT = "jetbrains.deployer.ftp.controlKeepAliveTimeout.seconds";
// }
// 
// Path: deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/DeployerAgentUtils.java
// public static void logBuildProblem(BuildProgressLogger logger, String message) {
//   logger.logBuildProblem(BuildProblemData
//           .createBuildProblem(String.valueOf(message.hashCode()),
//                   DeployerRunnerConstants.BUILD_PROBLEM_TYPE,
//                   "Deployment problem: " + message));
// }


import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.agent.BuildFinishedStatus;
import jetbrains.buildServer.agent.BuildRunnerContext;
import jetbrains.buildServer.agent.impl.artifacts.ArtifactsCollection;
import jetbrains.buildServer.deployer.agent.SyncBuildProcessAdapter;
import jetbrains.buildServer.deployer.agent.UploadInterruptedException;
import jetbrains.buildServer.deployer.common.FTPRunnerConstants;
import jetbrains.buildServer.util.StringUtil;
import jetbrains.buildServer.util.WaitFor;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.commons.net.util.TrustManagerUtils;
import org.jetbrains.annotations.NotNull;
import javax.net.ssl.SSLException;
import java.io.IOException;
import java.net.SocketException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static jetbrains.buildServer.deployer.agent.DeployerAgentUtils.logBuildProblem;
      final String host = targetUrl.getHost();
      final int port = targetUrl.getPort();
      final String encodedPath = targetUrl.getPath();

      final String path;
      if (encodedPath.length() > 0) {
        path = URLDecoder.decode(encodedPath.substring(1), "UTF-8");
      } else {
        path = "";
      }

      final FTPClient client = createClient();
      clientToDisconnect = client;

      if (port > 0) {
        client.connect(host, port);
      } else {
        client.connect(host);
      }

      client.addProtocolCommandListener(new BuildLogCommandListener(myLogger));

      if (myIsActive) {
        client.enterLocalActiveMode();
      } else {
        client.enterLocalPassiveMode();
      }

      final boolean loginSuccessful = client.login(myUsername, myPassword);
      if (!loginSuccessful) {
// Path: deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/SyncBuildProcessAdapter.java
// public abstract class SyncBuildProcessAdapter extends BuildProcessAdapter {
//   protected final BuildProgressLogger myLogger;
//   private volatile boolean hasFinished;
//   private volatile BuildFinishedStatus statusCode;
//   private volatile boolean isInterrupted;
// 
// 
//   public SyncBuildProcessAdapter(@NotNull final BuildProgressLogger logger) {
//     myLogger = logger;
//     hasFinished = false;
//     statusCode = null;
//   }
// 
// 
//   @Override
//   public void interrupt() {
//     isInterrupted = true;
//   }
// 
//   @Override
//   public boolean isInterrupted() {
//     return isInterrupted;
//   }
// 
//   @Override
//   public boolean isFinished() {
//     return hasFinished;
//   }
// 
//   @NotNull
//   @Override
//   public BuildFinishedStatus waitFor() throws RunBuildException {
//     while (!isInterrupted() && !hasFinished) {
//       try {
//         Thread.sleep(1000);
//       } catch (InterruptedException e) {
//         throw new RunBuildException(e);
//       }
//     }
//     return hasFinished ? statusCode : BuildFinishedStatus.INTERRUPTED;
//   }
// 
//   @Override
//   public void start() throws RunBuildException {
//     try {
//       statusCode = runProcess();
//       hasFinished = true;
//     } catch (UploadInterruptedException e) {
//       hasFinished = false;
//     }
//   }
// 
//   /**
//    * @return true is process finished successfully
//    */
//   protected abstract BuildFinishedStatus runProcess();
// 
//   protected void checkIsInterrupted() throws UploadInterruptedException {
//     if (isInterrupted()) throw new UploadInterruptedException();
//   }
// 
// }
// 
// Path: deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/UploadInterruptedException.java
// public class UploadInterruptedException extends RuntimeException {
// 
// }
// 
// Path: deploy-runner-common/src/main/java/jetbrains/buildServer/deployer/common/FTPRunnerConstants.java
// public class FTPRunnerConstants {
//   public static final String PARAM_AUTH_METHOD = "jetbrains.buildServer.deployer.ftp.authMethod";
//   public static final String PARAM_TRANSFER_MODE = "jetbrains.buildServer.deployer.ftp.transferMethod";
//   public static final String TRANSFER_MODE_AUTO = "AUTO";
//   public static final String TRANSFER_MODE_BINARY = "BINARY";
//   public static final String TRANSFER_MODE_ASCII = "ASCII";
//   public static final String AUTH_METHOD_USER_PWD = "USER_PWD";
//   public static final String AUTH_METHOD_ANONYMOUS = "ANONYMOUS";
//   public static final String PARAM_SSL_MODE = "jetbrains.buildServer.deployer.ftp.securityMode";
//   public static final String DATA_CHANNEL_PROTECTION = "jetbrains.buildServer.deployer.ftp.dataChannelProtection";
//   public static final String PARAM_FTP_MODE = "jetbrains.buildServer.deployer.ftp.ftpMode";
//   public static final String PARAM_FTP_CONNECT_TIMEOUT = "jetbrains.deployer.ftp.connectTimeout";
//   public static final String PARAM_FTP_CONTROL_KEEP_ALIVE_TIMEOUT = "jetbrains.deployer.ftp.controlKeepAliveTimeout.seconds";
// }
// 
// Path: deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/DeployerAgentUtils.java
// public static void logBuildProblem(BuildProgressLogger logger, String message) {
//   logger.logBuildProblem(BuildProblemData
//           .createBuildProblem(String.valueOf(message.hashCode()),
//                   DeployerRunnerConstants.BUILD_PROBLEM_TYPE,
//                   "Deployment problem: " + message));
// }


// Path: deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/ftp/FtpBuildProcessAdapter.java
import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.agent.BuildFinishedStatus;
import jetbrains.buildServer.agent.BuildRunnerContext;
import jetbrains.buildServer.agent.impl.artifacts.ArtifactsCollection;
import jetbrains.buildServer.deployer.agent.SyncBuildProcessAdapter;
import jetbrains.buildServer.deployer.agent.UploadInterruptedException;
import jetbrains.buildServer.deployer.common.FTPRunnerConstants;
import jetbrains.buildServer.util.StringUtil;
import jetbrains.buildServer.util.WaitFor;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.commons.net.util.TrustManagerUtils;
import org.jetbrains.annotations.NotNull;
import javax.net.ssl.SSLException;
import java.io.IOException;
import java.net.SocketException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static jetbrains.buildServer.deployer.agent.DeployerAgentUtils.logBuildProblem;

      final String host = targetUrl.getHost();
      final int port = targetUrl.getPort();
      final String encodedPath = targetUrl.getPath();

      final String path;
      if (encodedPath.length() > 0) {
        path = URLDecoder.decode(encodedPath.substring(1), "UTF-8");
      } else {
        path = "";
      }

      final FTPClient client = createClient();
      clientToDisconnect = client;

      if (port > 0) {
        client.connect(host, port);
      } else {
        client.connect(host);
      }

      client.addProtocolCommandListener(new BuildLogCommandListener(myLogger));

      if (myIsActive) {
        client.enterLocalActiveMode();
      } else {
        client.enterLocalPassiveMode();
      }

      final boolean loginSuccessful = client.login(myUsername, myPassword);
      if (!loginSuccessful) {
        logBuildProblem(myLogger, "Failed to login. Reply was: " + client.getReplyString());