private ProcessListener getProcessListener(@NotNull final Pair<Target, Parameters> key) {
    return new ProcessListener() {
      @Override
      public void startNotified(@NotNull ProcessEvent event) {
        ProcessHandler processHandler = event.getProcessHandler();
        processHandler.putUserData(ProcessHandler.SILENTLY_DESTROY_ON_CLOSE, Boolean.TRUE);
        Info o;
        synchronized (myProcMap) {
          o = myProcMap.get(key);
          if (o instanceof PendingInfo) {
            myProcMap.put(key, new PendingInfo(((PendingInfo)o).ref, processHandler));
          }
        }
        sendDataAfterStart(processHandler);
      }

      @Override
      public void processTerminated(@NotNull ProcessEvent event) {
        if (dropProcessInfo(key, null, event.getProcessHandler())) {
          fireModificationCountChanged();
        }
        onProcessTerminated(event);
      }

      @Override
      public void processWillTerminate(@NotNull ProcessEvent event, boolean willBeDestroyed) {
        if (dropProcessInfo(key, null, event.getProcessHandler())) {
          fireModificationCountChanged();
        }
        Heartbeat heartbeat = myHeartbeatRef.get();
        if (heartbeat != null) {
          heartbeat.stopBeat();
        }
      }

      @Override
      public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
        String text = StringUtil.notNullize(event.getText());
        logText(key.second, event, outputType);
        RunningInfo result = null;
        PendingInfo info;
        synchronized (myProcMap) {
          Info o = myProcMap.get(key);
          if (o instanceof PendingInfo) {
            info = (PendingInfo)o;
            if (outputType == ProcessOutputTypes.STDOUT) {
              String prefix = "Port/ServicesPort/ID:";
              if (text.startsWith(prefix)) {
                List<String> data = StringUtil.split(text.substring(prefix.length()).trim(), "/");
                int port = Integer.parseInt(data.get(0));
                int servicesPort = Integer.parseInt(data.get(1));
                String id = data.get(2);

                result = new RunningInfo(info.handler, getRemoteHost(), publishPort(port), id, publishPort(servicesPort));
                myProcMap.put(key, result);
                myProcMap.notifyAll();
              }
            }
            else if (outputType == ProcessOutputTypes.STDERR) {
              info.stderr.append(text);
            }
          }
          else {
            info = null;
          }
        }
        if (result != null) {
          synchronized (info.ref) {
            info.ref.set(result);
            info.ref.notifyAll();
          }
          fireModificationCountChanged();
          try {
            Heartbeat heartbeat = new Heartbeat(result.host, result.port, getClientSocketFactory());
            heartbeat.startBeat();
            myHeartbeatRef.set(heartbeat);
          }
          catch (Throwable e) {
            LOG.warn("The cook failed to start due to " + ExceptionUtil.getRootCause(e));
          }
        }
      }
    };
  }
private ProcessListener getProcessListener(@NotNull final Pair<Target, Parameters> key)