@Nullable private static RunContentDescriptor chooseReuseContentForDescriptor( final ContentManager contentManager, final RunContentDescriptor descriptor) { Content content = null; if (descriptor != null) { if (descriptor.isContentReuseProhibited()) { return null; } final Content attachedContent = descriptor.getAttachedContent(); if (attachedContent != null && attachedContent.isValid()) content = attachedContent; } if (content == null) { content = contentManager.getSelectedContent(); if (content != null && content.isPinned()) content = null; } if (content == null || !isTerminated(content)) { return null; } final RunContentDescriptor oldDescriptor = getRunContentDescriptorByContent(content); if (oldDescriptor != null && !oldDescriptor.isContentReuseProhibited()) { return oldDescriptor; } return null; }
private static boolean isTerminated(final Content content) { final RunContentDescriptor descriptor = getRunContentDescriptorByContent(content); if (descriptor == null) { return true; } else { final ProcessHandler processHandler = descriptor.getProcessHandler(); return processHandler == null || processHandler.isProcessTerminated(); } }
public void showRunContent( @NotNull final Executor info, RunContentDescriptor descriptor, RunContentDescriptor contentToReuse) { if (contentToReuse != null) { descriptor.setAttachedContent(contentToReuse.getAttachedContent()); } showRunContent(info, descriptor); }
public void showRunContent( @NotNull final Executor info, RunContentDescriptor descriptor, RunContentDescriptor contentToReuse) { if (contentToReuse != null) { final Content attachedContent = contentToReuse.getAttachedContent(); if (attachedContent.getManager() != null) { descriptor.setAttachedContent(attachedContent); } } showRunContent(info, descriptor); }
@Nullable private RunContentDescriptor getDescriptorBy(ProcessHandler handler, Executor runnerInfo) { ContentManager contentManager = getContentManagerForRunner(runnerInfo); Content[] contents = contentManager.getContents(); for (Content content : contents) { RunContentDescriptor runContentDescriptor = content.getUserData(DESCRIPTOR_KEY); if (runContentDescriptor.getProcessHandler() == handler) { return runContentDescriptor; } } return null; }
public static List<RunContentDescriptor> collectConsolesByDisplayName( final Project project, @NotNull NotNullFunction<String, Boolean> titleMatcher) { List<RunContentDescriptor> result = Lists.newArrayList(); final ExecutionManager executionManager = ExecutionManager.getInstance(project); final RunContentDescriptor[] runContentDescriptors = ((RunContentManagerImpl) executionManager.getContentManager()).getAllDescriptors(); for (RunContentDescriptor runContentDescriptor : runContentDescriptors) { if (titleMatcher.fun(runContentDescriptor.getDisplayName())) { result.add(runContentDescriptor); } } return result; }
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; }
@Override public void processTerminated(ProcessEvent event) { if (myProject.isDisposed()) return; if (!myTerminateNotified.compareAndSet(false, true)) return; ApplicationManager.getApplication() .invokeLater( () -> { RunnerLayoutUi ui = myDescriptor.getRunnerLayoutUi(); if (ui != null && !ui.isDisposed()) { ui.updateActionsNow(); } }, ModalityState.any()); myProject .getMessageBus() .syncPublisher(EXECUTION_TOPIC) .processTerminated(myExecutorId, myEnvironment, myProcessHandler, event.getExitCode()); SaveAndSyncHandler saveAndSyncHandler = SaveAndSyncHandler.getInstance(); if (saveAndSyncHandler != null) { saveAndSyncHandler.scheduleRefresh(); } }
public void restart() { final Project project = PlatformDataKeys.PROJECT.getData( DataManager.getInstance().getDataContext(myDescriptor.getComponent())); if (ExecutorRegistry.getInstance() .isStarting(project, myExecutor.getId(), myRunner.getRunnerId())) { return; } try { final ExecutionEnvironment old = myEnvironment; myRunner.execute( myExecutor, new ExecutionEnvironment( old.getRunProfile(), old.getExecutionTarget(), project, old.getRunnerSettings(), old.getConfigurationSettings(), myDescriptor, old.getRunnerAndConfigurationSettings())); } catch (RunCanceledByUserException ignore) { } catch (ExecutionException e1) { Messages.showErrorDialog( project, e1.getMessage(), ExecutionBundle.message("restart.error.message.title")); } }
boolean isEnabled() { ProcessHandler processHandler = myDescriptor.getProcessHandler(); boolean isTerminating = processHandler != null && processHandler.isProcessTerminating(); boolean isStarting = ExecutorRegistry.getInstance() .isStarting(myEnvironment.getProject(), myExecutor.getId(), myRunner.getRunnerId()); return !isStarting && !isTerminating; }
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); }
public static void restartIfActive(@NotNull RunContentDescriptor descriptor) { ProcessHandler processHandler = descriptor.getProcessHandler(); if (processHandler != null && processHandler.isStartNotified() && !processHandler.isProcessTerminating() && !processHandler.isProcessTerminated()) { restart(descriptor); } }
@NotNull @Override public ProcessHandler[] getRunningProcesses() { if (myContentManager == null) return EMPTY_PROCESS_HANDLERS; List<ProcessHandler> handlers = null; for (RunContentDescriptor descriptor : getContentManager().getAllDescriptors()) { ProcessHandler processHandler = descriptor.getProcessHandler(); if (processHandler != null) { if (handlers == null) { handlers = new SmartList<>(); } handlers.add(processHandler); } } return handlers == null ? EMPTY_PROCESS_HANDLERS : handlers.toArray(new ProcessHandler[handlers.size()]); }
@Override public void restartRunProfile( @NotNull Project project, @NotNull Executor executor, @NotNull ExecutionTarget target, @Nullable RunnerAndConfigurationSettings configuration, @Nullable ProcessHandler processHandler) { ExecutionEnvironmentBuilder builder = createEnvironmentBuilder(project, executor, configuration); if (processHandler != null) { for (RunContentDescriptor descriptor : getContentManager().getAllDescriptors()) { if (descriptor.getProcessHandler() == processHandler) { builder.contentToReuse(descriptor); break; } } } restartRunProfile(builder.target(target).build()); }
private void dispose() { if (myContent == null) return; final Content content = myContent; try { final RunContentDescriptor descriptor = getRunContentDescriptorByContent(content); getSyncPublisher().contentRemoved(descriptor, myExecutor); descriptor.dispose(); } finally { content.getManager().removeContentManagerListener(this); ProjectManager.getInstance().removeProjectManagerListener(this); content .release(); // don't invoke myContent.release() because myContent becomes null after // destroyProcess() myContent = null; } }
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; }
@Nullable private static Content getRunContentByDescriptor( final ContentManager contentManager, final RunContentDescriptor descriptor) { final Content[] contents = contentManager.getContents(); for (final Content content : contents) { if (descriptor.equals(content.getUserData(DESCRIPTOR_KEY))) { return content; } } return null; }
@Override public void update(final AnActionEvent event) { final Presentation presentation = event.getPresentation(); String name = myEnvironment.getRunProfile().getName(); ProcessHandler processHandler = myDescriptor.getProcessHandler(); final boolean isRunning = processHandler != null && !processHandler.isProcessTerminated(); presentation.setText(ExecutionBundle.message("rerun.configuration.action.name", name)); presentation.setIcon(isRunning ? AllIcons.Actions.Restart : myExecutor.getIcon()); presentation.setEnabled(isEnabled()); }
private String constructConsoleTitle(final @NotNull String consoleTitle) { if (shouldAddNumberToTitle()) { List<RunContentDescriptor> consoles = ExecutionHelper.collectConsolesByDisplayName( myProject, new NotNullFunction<String, Boolean>() { @NotNull @Override public Boolean fun(String dom) { return dom.contains(consoleTitle); } }); int max = 0; for (RunContentDescriptor dsc : consoles) { ProcessHandler handler = dsc.getProcessHandler(); if (handler != null && !handler.isProcessTerminated()) { if (max == 0) { max = 1; } try { int num = Integer.parseInt( dsc.getDisplayName() .substring(consoleTitle.length() + 1, dsc.getDisplayName().length() - 1)); if (num > max) { max = num; } } catch (Exception e) { // skip } } } if (max >= 1) { return consoleTitle + "(" + (max + 1) + ")"; } } return consoleTitle; }
private static void stop(@Nullable RunContentDescriptor descriptor) { ProcessHandler processHandler = descriptor != null ? descriptor.getProcessHandler() : null; if (processHandler == null) { return; } if (processHandler instanceof KillableProcess && processHandler.isProcessTerminating()) { ((KillableProcess) processHandler).killProcess(); return; } if (!processHandler.isProcessTerminated()) { if (processHandler.detachIsDefault()) { processHandler.detachProcess(); } else { processHandler.destroyProcess(); } } }
private void clearContent(RunContentDescriptor descriptor) { Content content = getToolWindow().getContentManager().findContent(descriptor.getDisplayName()); assert content != null; getToolWindow().getContentManager().removeContent(content, true); }
public static boolean isProcessRunning(@Nullable RunContentDescriptor descriptor) { ProcessHandler processHandler = descriptor == null ? null : descriptor.getProcessHandler(); return processHandler != null && !processHandler.isProcessTerminated(); }
private static boolean userApprovesStopForIncompatibleConfigurations( Project project, String configName, List<RunContentDescriptor> runningIncompatibleDescriptors) { RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(project); final RunManagerConfig config = runManager.getConfig(); if (!config.isStopIncompatibleRequiresConfirmation()) return true; DialogWrapper.DoNotAskOption option = new DialogWrapper.DoNotAskOption() { @Override public boolean isToBeShown() { return config.isStopIncompatibleRequiresConfirmation(); } @Override public void setToBeShown(boolean value, int exitCode) { config.setStopIncompatibleRequiresConfirmation(value); } @Override public boolean canBeHidden() { return true; } @Override public boolean shouldSaveOptionsOnCancel() { return false; } @NotNull @Override public String getDoNotShowMessage() { return CommonBundle.message("dialog.options.do.not.show"); } }; final StringBuilder names = new StringBuilder(); for (final RunContentDescriptor descriptor : runningIncompatibleDescriptors) { String name = descriptor.getDisplayName(); if (names.length() > 0) { names.append(", "); } names.append( StringUtil.isEmpty(name) ? ExecutionBundle.message("run.configuration.no.name") : String.format("'%s'", name)); } //noinspection DialogTitleCapitalization return Messages.showOkCancelDialog( project, ExecutionBundle.message( "stop.incompatible.confirmation.message", configName, names.toString(), runningIncompatibleDescriptors.size()), ExecutionBundle.message( "incompatible.configuration.is.running.dialog.title", runningIncompatibleDescriptors.size()), ExecutionBundle.message("stop.incompatible.confirmation.button.text"), CommonBundle.message("button.cancel"), Messages.getQuestionIcon(), option) == Messages.OK; }
@Override public void startRunProfile( @NotNull final RunProfileStarter starter, @NotNull final RunProfileState state, @NotNull final ExecutionEnvironment environment) { final Project project = environment.getProject(); RunContentDescriptor reuseContent = getContentManager().getReuseContent(environment); if (reuseContent != null) { reuseContent.setExecutionId(environment.getExecutionId()); environment.setContentToReuse(reuseContent); } final Executor executor = environment.getExecutor(); project .getMessageBus() .syncPublisher(EXECUTION_TOPIC) .processStartScheduled(executor.getId(), environment); Runnable startRunnable; startRunnable = () -> { if (project.isDisposed()) { return; } RunProfile profile = environment.getRunProfile(); boolean started = false; try { project .getMessageBus() .syncPublisher(EXECUTION_TOPIC) .processStarting(executor.getId(), environment); final RunContentDescriptor descriptor = starter.execute(state, environment); if (descriptor != null) { final Trinity<RunContentDescriptor, RunnerAndConfigurationSettings, Executor> trinity = Trinity.create( descriptor, environment.getRunnerAndConfigurationSettings(), executor); myRunningConfigurations.add(trinity); Disposer.register(descriptor, () -> myRunningConfigurations.remove(trinity)); getContentManager() .showRunContent(executor, descriptor, environment.getContentToReuse()); final ProcessHandler processHandler = descriptor.getProcessHandler(); if (processHandler != null) { if (!processHandler.isStartNotified()) { processHandler.startNotify(); } project .getMessageBus() .syncPublisher(EXECUTION_TOPIC) .processStarted(executor.getId(), environment, processHandler); started = true; ProcessExecutionListener listener = new ProcessExecutionListener( project, executor.getId(), environment, processHandler, descriptor); processHandler.addProcessListener(listener); // Since we cannot guarantee that the listener is added before process handled is // start notified, // we have to make sure the process termination events are delivered to the clients. // Here we check the current process state and manually deliver events, while // the ProcessExecutionListener guarantees each such event is only delivered once // either by this code, or by the ProcessHandler. boolean terminating = processHandler.isProcessTerminating(); boolean terminated = processHandler.isProcessTerminated(); if (terminating || terminated) { listener.processWillTerminate( new ProcessEvent(processHandler), false /*doesn't matter*/); if (terminated) { //noinspection ConstantConditions int exitCode = processHandler.getExitCode(); listener.processTerminated(new ProcessEvent(processHandler, exitCode)); } } } environment.setContentToReuse(descriptor); } } catch (ProcessCanceledException e) { LOG.info(e); } catch (ExecutionException e) { ExecutionUtil.handleExecutionError(project, executor.getToolWindowId(), profile, e); LOG.info(e); } finally { if (!started) { project .getMessageBus() .syncPublisher(EXECUTION_TOPIC) .processNotStarted(executor.getId(), environment); } } }; if (ApplicationManager.getApplication().isUnitTestMode() && !myForceCompilationInTests) { startRunnable.run(); } else { compileAndRun( () -> TransactionGuard.submitTransaction(project, startRunnable), environment, state, () -> { if (!project.isDisposed()) { project .getMessageBus() .syncPublisher(EXECUTION_TOPIC) .processNotStarted(executor.getId(), environment); } }); } }
public static void restart(@NotNull RunContentDescriptor descriptor) { restart(descriptor.getComponent()); }
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); } }); }