@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); } }); } }
@Override public void restartRunProfile(@NotNull final ExecutionEnvironment environment) { RunnerAndConfigurationSettings configuration = environment.getRunnerAndConfigurationSettings(); List<RunContentDescriptor> runningIncompatible; if (configuration == null) { runningIncompatible = Collections.emptyList(); } else { runningIncompatible = getIncompatibleRunningDescriptors(configuration); } RunContentDescriptor contentToReuse = environment.getContentToReuse(); final List<RunContentDescriptor> runningOfTheSameType = new SmartList<>(); if (configuration != null && configuration.isSingleton()) { runningOfTheSameType.addAll(getRunningDescriptorsOfTheSameConfigType(configuration)); } else if (isProcessRunning(contentToReuse)) { runningOfTheSameType.add(contentToReuse); } List<RunContentDescriptor> runningToStop = ContainerUtil.concat(runningOfTheSameType, runningIncompatible); if (!runningToStop.isEmpty()) { if (configuration != null) { if (!runningOfTheSameType.isEmpty() && (runningOfTheSameType.size() > 1 || contentToReuse == null || runningOfTheSameType.get(0) != contentToReuse) && !userApprovesStopForSameTypeConfigurations( environment.getProject(), configuration.getName(), runningOfTheSameType.size())) { return; } if (!runningIncompatible.isEmpty() && !userApprovesStopForIncompatibleConfigurations( myProject, configuration.getName(), runningIncompatible)) { return; } } for (RunContentDescriptor descriptor : runningToStop) { stop(descriptor); } } if (myAwaitingRunProfiles.get(environment.getRunProfile()) == environment) { // defense from rerunning exactly the same ExecutionEnvironment return; } myAwaitingRunProfiles.put(environment.getRunProfile(), environment); awaitTermination( new Runnable() { @Override public void run() { if (myAwaitingRunProfiles.get(environment.getRunProfile()) != environment) { // a new rerun has been requested before starting this one, ignore this rerun return; } if ((DumbService.getInstance(myProject).isDumb() && !Registry.is("dumb.aware.run.configurations")) || ExecutorRegistry.getInstance().isStarting(environment)) { awaitTermination(this, 100); return; } for (RunContentDescriptor descriptor : runningOfTheSameType) { ProcessHandler processHandler = descriptor.getProcessHandler(); if (processHandler != null && !processHandler.isProcessTerminated()) { awaitTermination(this, 100); return; } } myAwaitingRunProfiles.remove(environment.getRunProfile()); start(environment); } }, 50); }
public static void executeConfiguration( @NotNull ExecutionEnvironment environment, boolean showSettings, boolean assignNewId) { if (ExecutorRegistry.getInstance().isStarting(environment)) { return; } RunnerAndConfigurationSettings runnerAndConfigurationSettings = environment.getRunnerAndConfigurationSettings(); if (runnerAndConfigurationSettings != null) { if (!ExecutionTargetManager.canRun(environment)) { ExecutionUtil.handleExecutionError( environment, new ExecutionException( StringUtil.escapeXml( "Cannot run '" + environment.getRunProfile().getName() + "' on '" + environment.getExecutionTarget().getDisplayName() + "'"))); return; } if (!RunManagerImpl.canRunConfiguration(environment) || (showSettings && runnerAndConfigurationSettings.isEditBeforeRun())) { if (!RunDialog.editConfiguration(environment, "Edit configuration")) { return; } while (!RunManagerImpl.canRunConfiguration(environment)) { if (Messages.YES == Messages.showYesNoDialog( environment.getProject(), "Configuration is still incorrect. Do you want to edit it again?", "Change Configuration Settings", "Edit", "Continue Anyway", Messages.getErrorIcon())) { if (!RunDialog.editConfiguration(environment, "Edit configuration")) { return; } } else { break; } } } ConfigurationType configurationType = runnerAndConfigurationSettings.getType(); if (configurationType != null) { UsageTrigger.trigger( "execute." + ConvertUsagesUtil.ensureProperKey(configurationType.getId()) + "." + environment.getExecutor().getId()); } } try { if (assignNewId) { environment.assignNewExecutionId(); } environment.getRunner().execute(environment); } catch (ExecutionException e) { String name = runnerAndConfigurationSettings != null ? runnerAndConfigurationSettings.getName() : null; if (name == null) { name = environment.getRunProfile().getName(); } if (name == null && environment.getContentToReuse() != null) { name = environment.getContentToReuse().getDisplayName(); } if (name == null) { name = "<Unknown>"; } ExecutionUtil.handleExecutionError( environment.getProject(), environment.getExecutor().getToolWindowId(), name, e); } }