private void waitForProcess(final RunContentDescriptor descriptor) {
    ProgressManager.getInstance()
        .runProcessWithProgressSynchronously(
            new Runnable() {
              public void run() {
                final Semaphore semaphore = new Semaphore();
                semaphore.down();

                ApplicationManager.getApplication()
                    .executeOnPooledThread(
                        new Runnable() {
                          public void run() {
                            final ProcessHandler processHandler = descriptor.getProcessHandler();
                            try {
                              if (processHandler != null) {
                                processHandler.waitFor();
                              }
                            } finally {
                              semaphore.up();
                            }
                          }
                        });

                final ProgressIndicator progressIndicator =
                    ProgressManager.getInstance().getProgressIndicator();

                if (progressIndicator != null) {
                  progressIndicator.setText(
                      ExecutionBundle.message("waiting.for.vm.detach.progress.text"));
                  ApplicationManager.getApplication()
                      .executeOnPooledThread(
                          new Runnable() {
                            public void run() {
                              while (true) {
                                if (progressIndicator.isCanceled()
                                    || !progressIndicator.isRunning()) {
                                  semaphore.up();
                                  break;
                                }
                                try {
                                  synchronized (this) {
                                    wait(2000L);
                                  }
                                } catch (InterruptedException ignore) {
                                }
                              }
                            }
                          });
                }

                semaphore.waitFor();
              }
            },
            ExecutionBundle.message(
                "terminating.process.progress.title", descriptor.getDisplayName()),
            true,
            myProject);
  }
 private Content createNewContent(
     final ContentManager contentManager,
     final RunContentDescriptor descriptor,
     Executor executor) {
   final String processDisplayName = descriptor.getDisplayName();
   final Content content =
       ContentFactory.SERVICE
           .getInstance()
           .createContent(descriptor.getComponent(), processDisplayName, true);
   content.putUserData(DESCRIPTOR_KEY, descriptor);
   content.putUserData(ToolWindow.SHOW_CONTENT_ICON, Boolean.TRUE);
   contentManager.addContent(content);
   new CloseListener(content, executor);
   return content;
 }
    private boolean closeQuery() {
      final RunContentDescriptor descriptor = getRunContentDescriptorByContent(myContent);

      if (descriptor == null) {
        return true;
      }

      final ProcessHandler processHandler = descriptor.getProcessHandler();
      if (processHandler == null
          || processHandler.isProcessTerminated()
          || processHandler.isProcessTerminating()) {
        return true;
      }
      final boolean destroyProcess;
      if (processHandler.isSilentlyDestroyOnClose()
          || Boolean.TRUE.equals(
              processHandler.getUserData(ProcessHandler.SILENTLY_DESTROY_ON_CLOSE))) {
        destroyProcess = true;
      } else {
        // todo[nik] this is a temporary solution for the following problem: some configurations
        // should not allow user to choose between 'terminating' and 'detaching'
        final boolean useDefault =
            Boolean.TRUE.equals(
                processHandler.getUserData(ALWAYS_USE_DEFAULT_STOPPING_BEHAVIOUR_KEY));
        final TerminateRemoteProcessDialog terminateDialog =
            new TerminateRemoteProcessDialog(
                myProject,
                descriptor.getDisplayName(),
                processHandler.detachIsDefault(),
                useDefault);
        terminateDialog.show();
        if (terminateDialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) return false;
        destroyProcess = terminateDialog.forceTermination();
      }
      if (destroyProcess) {
        processHandler.destroyProcess();
      } else {
        processHandler.detachProcess();
      }
      waitForProcess(descriptor);
      return true;
    }
  public void showRunContent(
      @NotNull final Executor executor, final RunContentDescriptor descriptor) {
    if (ApplicationManager.getApplication().isUnitTestMode()) return;

    final ContentManager contentManager = getContentManagerForRunner(executor);
    RunContentDescriptor oldDescriptor =
        chooseReuseContentForDescriptor(contentManager, descriptor);

    final Content content;

    if (oldDescriptor != null) {
      content = oldDescriptor.getAttachedContent();
      getSyncPublisher().contentRemoved(oldDescriptor, executor);
      oldDescriptor.dispose(); // is of the same category, can be reused
    } else {
      content = createNewContent(contentManager, descriptor, executor);
      final Icon icon = descriptor.getIcon();
      content.setIcon(icon == null ? executor.getToolWindowIcon() : icon);
    }

    content.setComponent(descriptor.getComponent());
    content.putUserData(DESCRIPTOR_KEY, descriptor);
    final ProcessHandler processHandler = descriptor.getProcessHandler();
    if (processHandler != null) {
      final ProcessAdapter processAdapter =
          new ProcessAdapter() {
            public void startNotified(final ProcessEvent event) {
              LaterInvocator.invokeLater(
                  new Runnable() {
                    public void run() {
                      final Icon icon = descriptor.getIcon();
                      content.setIcon(icon == null ? executor.getToolWindowIcon() : icon);
                    }
                  });
            }

            public void processTerminated(final ProcessEvent event) {
              LaterInvocator.invokeLater(
                  new Runnable() {
                    public void run() {
                      final Icon icon = descriptor.getIcon();
                      content.setIcon(
                          icon == null
                              ? executor.getDisabledIcon()
                              : IconLoader.getTransparentIcon(icon));
                    }
                  });
            }
          };
      processHandler.addProcessListener(processAdapter);
      final Disposable disposer = content.getDisposer();
      if (disposer != null) {
        Disposer.register(
            disposer,
            new Disposable() {
              public void dispose() {
                processHandler.removeProcessListener(processAdapter);
              }
            });
      }
    }
    content.setDisplayName(descriptor.getDisplayName());
    descriptor.setAttachedContent(content);
    content.getManager().setSelectedContent(content);

    ApplicationManager.getApplication()
        .invokeLater(
            new Runnable() {
              public void run() {
                ToolWindow window =
                    ToolWindowManager.getInstance(myProject)
                        .getToolWindow(executor.getToolWindowId());
                // let's activate tool window, but don't move focus
                //
                // window.show() isn't valid here, because it will not
                // mark the window as "last activated" windows and thus
                // some action like navigation up/down in stactrace wont
                // work correctly
                window.activate(null, false, false);
              }
            });
  }