@Override
  @NotNull
  public TaskResult execute(@NotNull TaskContext context) throws TaskException {
    BuildLogger logger = getBuildLogger(context);
    final ErrorMemorisingInterceptor errorLines = new ErrorMemorisingInterceptor();
    logger.getInterceptorStack().add(errorLines);
    Map<String, String> combinedMap = Maps.newHashMap();
    combinedMap.putAll(context.getConfigurationMap());
    combinedMap.putAll(context.getBuildContext().getBuildDefinition().getCustomConfiguration());
    IvyBuildContext buildContext = new IvyBuildContext(combinedMap);
    File rootDirectory = context.getRootDirectory();
    long serverId = buildContext.getArtifactoryServerId();
    try {
      ivyDependenciesDir = extractIvyDependencies(serverId, rootDirectory, buildContext);
      log.info(logger.addBuildLogEntry("Ivy dependency directory found at: " + ivyDependenciesDir));
    } catch (IOException ioe) {
      ivyDependenciesDir = null;
      logger.addBuildLogEntry(
          new ErrorLogEntry(
              "Error occurred while preparing Artifactory Ivy Runner dependencies. Build Info support is "
                  + "disabled: "
                  + ioe.getMessage()));
      log.error(
          "Error occurred while preparing Artifactory Ivy Runner dependencies. "
              + "Build Info support is disabled.",
          ioe);
    }
    if (ivyDependenciesDir == null) {
      String message = "Ivy dependency directory not found.";
      logger.addErrorLogEntry(message);
      log.error(message);
    }
    String executable = getExecutable(buildContext);
    if (StringUtils.isBlank(executable)) {
      log.error(logger.addErrorLogEntry("Cannot find ivy executable"));
      return TaskResultBuilder.create(context).failed().build();
    }
    Map<String, String> globalEnv = environmentVariableAccessor.getEnvironment();
    Map<String, String> environment = Maps.newHashMap(globalEnv);
    if (StringUtils.isNotBlank(ivyDependenciesDir)) {
      ArtifactoryBuildInfoPropertyHelper propertyHelper = new IvyPropertyHelper();
      propertyHelper.init(context.getBuildContext());
      buildInfoPropertiesFile =
          propertyHelper.createFileAndGetPath(
              buildContext,
              context.getBuildLogger(),
              environmentVariableAccessor.getEnvironment(context),
              globalEnv);
      if (StringUtils.isNotBlank(buildInfoPropertiesFile)) {
        activateBuildInfoRecording = true;
        environment.put(BuildInfoConfigProperties.PROP_PROPS_FILE, buildInfoPropertiesFile);
      }
    }
    List<String> command = Lists.newArrayList(executable);
    if (activateBuildInfoRecording) {
      command.add("-lib");
      command.add(Commandline.quoteArgument(ivyDependenciesDir));
      command.add("-listener");
      command.add(
          Commandline.quoteArgument("org.jfrog.build.extractor.listener.ArtifactoryBuildListener"));
    }
    String buildFile = buildContext.getBuildFile();
    if (StringUtils.isNotBlank(buildFile)) {
      command.addAll(Arrays.asList("-f", buildFile));
    }
    String targets = buildContext.getTargets();
    if (StringUtils.isNotBlank(targets)) {
      String[] targetTokens = StringUtils.split(targets, ' ');
      command.addAll(Arrays.asList(targetTokens));
    }

    String antOpts = buildContext.getAntOpts();
    if (StringUtils.isNotBlank(antOpts)) {
      environment.put("ANT_OPTS", antOpts);
    }
    if (StringUtils.isNotBlank(buildContext.getEnvironmentVariables())) {
      environment.putAll(
          environmentVariableAccessor.splitEnvironmentAssignments(
              buildContext.getEnvironmentVariables(), false));
    }
    String subDirectory = buildContext.getWorkingSubDirectory();
    if (StringUtils.isNotBlank(subDirectory)) {
      rootDirectory = new File(rootDirectory, subDirectory);
    }
    ExternalProcessBuilder processBuilder =
        new ExternalProcessBuilder()
            .workingDirectory(rootDirectory)
            .command(command)
            .env(environment);
    try {
      return TaskResultBuilder.create(context)
          .checkReturnCode(processService.executeProcess(context, processBuilder))
          .build();
    } finally {
      context.getBuildContext().getBuildResult().addBuildErrors(errorLines.getErrorStringList());
    }
  }