From 14cc2d580da7c840a25032d0ede1dd93857b0681 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Mon, 7 Oct 2013 17:16:33 +0400 Subject: [PATCH] IDEA-114534 Gradle: cancelation of gradle tasks for "out-of-process" mode --- .../model/task/ExternalSystemTask.java | 15 +++++++ .../model/task/ExternalSystemTaskState.java | 2 +- .../model/task/ExternalSystemTaskType.java | 2 +- .../task/ExternalSystemTaskManager.java | 4 ++ .../AbstractExternalSystemFacadeImpl.java | 11 ++++- .../service/RemoteExternalSystemFacade.java | 10 +++-- .../RemoteExternalSystemFacadeImpl.java | 7 +++ .../ExternalSystemRunConfiguration.java | 36 +++++++++++++-- .../internal/AbstractExternalSystemTask.java | 44 +++++++++++++++++++ .../ExternalSystemExecuteTaskTask.java | 14 ++++++ .../ExternalSystemResolveProjectTask.java | 14 ++++++ .../internal/ExternalSystemTaskAware.java | 11 +++++ .../RemoteExternalSystemProjectResolver.java | 6 ++- ...moteExternalSystemProjectResolverImpl.java | 7 +++ .../RemoteExternalSystemTaskManager.java | 7 +++ .../RemoteExternalSystemTaskManagerImpl.java | 8 +++- .../wrapper/ExternalSystemFacadeWrapper.java | 9 +++- .../ExternalSystemProjectResolverWrapper.java | 16 ++++++- .../ExternalSystemTaskManagerWrapper.java | 13 ++++++ .../plugins/gradle/GradleManager.java | 6 ++- ...butionWithSourcesNotificationProvider.java | 4 +- .../service/task/GradleTaskManager.java | 15 ++++++- .../plugins/gradle/util/GradleUtil.java | 11 +++-- 23 files changed, 246 insertions(+), 26 deletions(-) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTask.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTask.java index 4c93222793fc..2329fd38e67d 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTask.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTask.java @@ -37,6 +37,21 @@ public interface ExternalSystemTask { */ void execute(@NotNull ExternalSystemTaskNotificationListener... listeners); + /** + * Cancels current task and updates given indicator's {@link ProgressIndicator#setText2(String) status} during that. + * + * @param indicator target progress indicator + * @param listeners callbacks to be notified on task execution update + */ + void cancel(@NotNull ProgressIndicator indicator, @NotNull ExternalSystemTaskNotificationListener... listeners); + + /** + * Cancels current task at the calling thread, i.e. the call to this method blocks. + * + * @param listeners callbacks to be notified about the task execution update + */ + void cancel(@NotNull ExternalSystemTaskNotificationListener... listeners); + /** * Forces current task to refresh {@link #getState() its state}. */ diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskState.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskState.java index 315a7a6fecf6..2df96affc604 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskState.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskState.java @@ -21,5 +21,5 @@ package com.intellij.openapi.externalSystem.model.task; */ public enum ExternalSystemTaskState { - NOT_STARTED, IN_PROGRESS, FINISHED, FAILED + NOT_STARTED, IN_PROGRESS, FINISHED, FAILED, CANCELING, CANCELED } diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskType.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskType.java index 490e8a5dfe76..81ce2f65a230 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskType.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/task/ExternalSystemTaskType.java @@ -1,7 +1,7 @@ package com.intellij.openapi.externalSystem.model.task; /** - * Enumerates interested types of tasks that may be enqueued to Gradle API. + * Enumerates interested types of tasks that may be enqueued to external systems API. * * @author Denis Zhdanov * @since 11/10/11 9:07 AM diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/task/ExternalSystemTaskManager.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/task/ExternalSystemTaskManager.java index 4629e383795c..df27cdb7a382 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/task/ExternalSystemTaskManager.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/task/ExternalSystemTaskManager.java @@ -40,4 +40,8 @@ public interface ExternalSystemTaskManager> getTasksInProgress() throws RemoteException { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemFacadeImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemFacadeImpl.java index 16d181ea7bc3..625c83c2a0d9 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemFacadeImpl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemFacadeImpl.java @@ -18,6 +18,8 @@ package com.intellij.openapi.externalSystem.service; import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings; import com.intellij.openapi.externalSystem.service.project.ExternalSystemProjectResolver; import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager; +import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; +import com.intellij.openapi.util.registry.Registry; import com.intellij.util.Alarm; import org.jetbrains.annotations.NotNull; @@ -82,6 +84,11 @@ public class RemoteExternalSystemFacadeImpl tasks = ContainerUtilRt.newArrayList(); for (String taskName : mySettings.getTaskNames()) { tasks.add(new ExternalTaskPojo(taskName, mySettings.getExternalProjectPath(), null)); @@ -156,6 +157,10 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase { tasks, mySettings.getVmOptions(), debuggerSetup); + + final MyProcessHandler processHandler = new MyProcessHandler(task); + console.attachToProcess(processHandler); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { @Override public void run() { @@ -190,14 +195,37 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase { return new DefaultExecutionResult(console, processHandler); } } - + private static class MyProcessHandler extends ProcessHandler { + private final ExternalSystemExecuteTaskTask myTask; + + public MyProcessHandler(ExternalSystemExecuteTaskTask task) { + myTask = task; + } + @Override protected void destroyProcessImpl() { } @Override protected void detachProcessImpl() { + myTask.cancel(new ExternalSystemTaskNotificationListenerAdapter() { + + private boolean myResetGreeting = true; + + @Override + public void onTaskOutput(@NotNull ExternalSystemTaskId id, @NotNull String text, boolean stdOut) { + if (myResetGreeting) { + notifyTextAvailable("\r", ProcessOutputTypes.SYSTEM); + myResetGreeting = false; + } + notifyTextAvailable(text, stdOut ? ProcessOutputTypes.STDOUT : ProcessOutputTypes.STDERR); + } + + @Override + public void onEnd(@NotNull ExternalSystemTaskId id) { + } + }); notifyProcessDetached(); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/AbstractExternalSystemTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/AbstractExternalSystemTask.java index e7367232bfce..562cf4d8e6bb 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/AbstractExternalSystemTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/AbstractExternalSystemTask.java @@ -143,6 +143,50 @@ public abstract class AbstractExternalSystemTask implements ExternalSystemTask { protected abstract void doExecute() throws Exception; + @Override + public void cancel(@NotNull final ProgressIndicator indicator, @NotNull ExternalSystemTaskNotificationListener... listeners) { + indicator.setIndeterminate(true); + ExternalSystemTaskNotificationListenerAdapter adapter = new ExternalSystemTaskNotificationListenerAdapter() { + @Override + public void onStatusChange(@NotNull ExternalSystemTaskNotificationEvent event) { + indicator.setText(wrapProgressText(event.getDescription())); + } + }; + final ExternalSystemTaskNotificationListener[] ls; + if (listeners.length > 0) { + ls = ArrayUtil.append(listeners, adapter); + } + else { + ls = new ExternalSystemTaskNotificationListener[] { adapter }; + } + + cancel(ls); + } + + @Override + public void cancel(@NotNull ExternalSystemTaskNotificationListener... listeners) { + ExternalSystemProgressNotificationManager progressManager = ServiceManager.getService(ExternalSystemProgressNotificationManager.class); + for (ExternalSystemTaskNotificationListener listener : listeners) { + progressManager.addNotificationListener(getId(), listener); + } + try { + doCancel(); + } + catch (Throwable e) { + setState(ExternalSystemTaskState.FAILED); + myError.set(e); + LOG.warn(e); + } + finally { + for (ExternalSystemTaskNotificationListener listener : listeners) { + progressManager.removeNotificationListener(listener); + } + } + } + + protected abstract void doCancel() throws Exception; + + @NotNull protected String wrapProgressText(@NotNull String text) { return ExternalSystemBundle.message("progress.update.text", getExternalSystemId(), text); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java index 50f882159eeb..8b5cb63beb04 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java @@ -106,4 +106,18 @@ public class ExternalSystemExecuteTaskTask extends AbstractExternalSystemTask { setState(ExternalSystemTaskState.FINISHED); } } + + @Override + protected void doCancel() throws Exception { + final ExternalSystemFacadeManager manager = ServiceManager.getService(ExternalSystemFacadeManager.class); + RemoteExternalSystemFacade facade = manager.getFacade(getIdeProject(), getExternalProjectPath(), getExternalSystemId()); + RemoteExternalSystemTaskManager taskManager = facade.getTaskManager(); + setState(ExternalSystemTaskState.CANCELING); + try { + taskManager.cancelTask(getId()); + } + finally { + setState(ExternalSystemTaskState.CANCELED); + } + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java index 9f7f08da0bbb..fe0d5466dfa2 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java @@ -62,6 +62,20 @@ public class ExternalSystemResolveProjectTask extends AbstractExternalSystemTask } } + protected void doCancel() throws Exception { + final ExternalSystemFacadeManager manager = ServiceManager.getService(ExternalSystemFacadeManager.class); + Project ideProject = getIdeProject(); + RemoteExternalSystemProjectResolver resolver = manager.getFacade(ideProject, myProjectPath, getExternalSystemId()).getResolver(); + + setState(ExternalSystemTaskState.CANCELING); + try { + resolver.cancelTask(getId()); + } + finally { + setState(ExternalSystemTaskState.CANCELED); + } + } + @Nullable public DataNode getExternalProject() { return myExternalProject.get(); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemTaskAware.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemTaskAware.java index 73947b4f82d1..7ecc0c6028f9 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemTaskAware.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemTaskAware.java @@ -26,6 +26,17 @@ public interface ExternalSystemTaskAware { */ boolean isTaskInProgress(@NotNull ExternalSystemTaskId id) throws RemoteException; + /** + * Allows to cancel the target task by the current service. + * + * + * @param id target task's id + * @return true if a task was successfully canceled; + * false otherwise + * @throws RemoteException as required by RMI + */ + void cancelTask(@NotNull ExternalSystemTaskId id) throws RemoteException; + /** * Allows to ask current service for all tasks being executed at the moment. * diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolver.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolver.java index 558fa5efed1c..2e5ce6469684 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolver.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolver.java @@ -20,9 +20,9 @@ import com.intellij.openapi.externalSystem.model.ExternalSystemException; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId; +import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType; import com.intellij.openapi.externalSystem.service.RemoteExternalSystemService; -import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,6 +64,10 @@ public interface RemoteExternalSystemProjectResolver> getTasksInProgress() throws RemoteException { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolverImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolverImpl.java index ef892d295274..2bc337199d88 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolverImpl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/RemoteExternalSystemProjectResolverImpl.java @@ -42,4 +42,11 @@ public class RemoteExternalSystemProjectResolverImpl> getTasksInProgress() throws RemoteException { return myDelegate.getTasksInProgress(); } + + @Override + public void cancelTask(@NotNull ExternalSystemTaskId id) throws RemoteException { + myDelegate.cancelTask(id); + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemProjectResolverWrapper.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemProjectResolverWrapper.java index d9bb08cd9ecb..47a7a138ac9a 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemProjectResolverWrapper.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemProjectResolverWrapper.java @@ -3,11 +3,11 @@ package com.intellij.openapi.externalSystem.service.remote.wrapper; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.ExternalSystemException; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId; import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings; +import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId; +import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; import com.intellij.openapi.externalSystem.service.remote.RemoteExternalSystemProgressNotificationManager; import com.intellij.openapi.externalSystem.service.remote.RemoteExternalSystemProjectResolver; -import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,4 +52,16 @@ public class ExternalSystemProjectResolverWrapper