@Override
  public boolean configureTask(
      RunConfiguration runConfiguration, ExternalSystemBeforeRunTask task) {
    ExternalSystemEditTaskDialog dialog =
        new ExternalSystemEditTaskDialog(myProject, task.getTaskExecutionSettings(), mySystemId);
    dialog.setTitle(
        ExternalSystemBundle.message("tasks.select.task.title", mySystemId.getReadableName()));

    if (!dialog.showAndGet()) {
      return false;
    }

    return true;
  }
  @Override
  public String getDescription(ExternalSystemBeforeRunTask task) {
    final String externalProjectPath = task.getTaskExecutionSettings().getExternalProjectPath();

    if (task.getTaskExecutionSettings().getTaskNames().isEmpty()) {
      return ExternalSystemBundle.message("tasks.before.run.empty", mySystemId.getReadableName());
    }

    String desc = StringUtil.join(task.getTaskExecutionSettings().getTaskNames(), " ");
    for (Module module : ModuleManager.getInstance(myProject).getModules()) {
      if (!mySystemId
          .toString()
          .equals(module.getOptionValue(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY))) continue;

      if (StringUtil.equals(
          externalProjectPath,
          module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY))) {
        desc = module.getName() + ": " + desc;
        break;
      }
    }

    return ExternalSystemBundle.message("tasks.before.run", mySystemId.getReadableName(), desc);
  }
  @Override
  public boolean canExecuteTask(
      RunConfiguration configuration, ExternalSystemBeforeRunTask beforeRunTask) {
    final ExternalSystemTaskExecutionSettings executionSettings =
        beforeRunTask.getTaskExecutionSettings();

    final List<ExternalTaskPojo> tasks = ContainerUtilRt.newArrayList();
    for (String taskName : executionSettings.getTaskNames()) {
      tasks.add(new ExternalTaskPojo(taskName, executionSettings.getExternalProjectPath(), null));
    }
    if (tasks.isEmpty()) return true;

    final Pair<ProgramRunner, ExecutionEnvironment> pair =
        ExternalSystemUtil.createRunner(
            executionSettings, DefaultRunExecutor.EXECUTOR_ID, myProject, mySystemId);

    if (pair == null) return false;

    final ProgramRunner runner = pair.first;
    final ExecutionEnvironment environment = pair.second;

    return runner.canRun(DefaultRunExecutor.EXECUTOR_ID, environment.getRunProfile());
  }
  @Override
  public boolean executeTask(
      DataContext context,
      RunConfiguration configuration,
      ExecutionEnvironment env,
      ExternalSystemBeforeRunTask beforeRunTask) {

    final ExternalSystemTaskExecutionSettings executionSettings =
        beforeRunTask.getTaskExecutionSettings();

    final List<ExternalTaskPojo> tasks = ContainerUtilRt.newArrayList();
    for (String taskName : executionSettings.getTaskNames()) {
      tasks.add(new ExternalTaskPojo(taskName, executionSettings.getExternalProjectPath(), null));
    }
    if (tasks.isEmpty()) return true;

    final Pair<ProgramRunner, ExecutionEnvironment> pair =
        ExternalSystemUtil.createRunner(
            executionSettings, DefaultRunExecutor.EXECUTOR_ID, myProject, mySystemId);

    if (pair == null) return false;

    final ProgramRunner runner = pair.first;
    final ExecutionEnvironment environment = pair.second;
    environment.setExecutionId(env.getExecutionId());

    final Semaphore targetDone = new Semaphore();
    final Ref<Boolean> result = new Ref<Boolean>(false);
    final Disposable disposable = Disposer.newDisposable();

    final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
    final String executorId = executor.getId();

    myProject
        .getMessageBus()
        .connect(disposable)
        .subscribe(
            ExecutionManager.EXECUTION_TOPIC,
            new ExecutionAdapter() {
              public void processStartScheduled(
                  final String executorIdLocal, final ExecutionEnvironment environmentLocal) {
                if (executorId.equals(executorIdLocal) && environment.equals(environmentLocal)) {
                  targetDone.down();
                }
              }

              public void processNotStarted(
                  final String executorIdLocal,
                  @NotNull final ExecutionEnvironment environmentLocal) {
                if (executorId.equals(executorIdLocal) && environment.equals(environmentLocal)) {
                  targetDone.up();
                }
              }

              public void processStarted(
                  final String executorIdLocal,
                  @NotNull final ExecutionEnvironment environmentLocal,
                  @NotNull final ProcessHandler handler) {
                if (executorId.equals(executorIdLocal) && environment.equals(environmentLocal)) {
                  handler.addProcessListener(
                      new ProcessAdapter() {
                        public void processTerminated(ProcessEvent event) {
                          result.set(event.getExitCode() == 0);
                          targetDone.up();
                          environmentLocal.getContentToReuse();
                        }
                      });
                }
              }
            });

    try {
      ApplicationManager.getApplication()
          .invokeAndWait(
              new Runnable() {
                @Override
                public void run() {
                  try {
                    runner.execute(environment);
                  } catch (ExecutionException e) {
                    targetDone.up();
                    LOG.error(e);
                  }
                }
              },
              ModalityState.NON_MODAL);
    } catch (Exception e) {
      LOG.error(e);
      Disposer.dispose(disposable);
      return false;
    }

    targetDone.waitFor();
    Disposer.dispose(disposable);

    return result.get();
  }