mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes
1. Introduced 'gradle task' concept; 2. Introduced 'resolve gradle project' task; 3. Introduced 'resolve gradle project' action; 4. Refactored notifications processing;
This commit is contained in:
@@ -47,6 +47,7 @@ gradle.import.text.error.file.module.test.output.location=Module test output loc
|
||||
gradle.import.text.incomplete.tooling.api=Gradle version contains incomplete tooling API
|
||||
|
||||
gradle.sync.title.tab=project structure changes
|
||||
gradle.sync.progress.text=Refreshing gradle project
|
||||
gradle.sync.change.type.gradle=Gradle local setting
|
||||
gradle.sync.change.type.intellij={0} local setting
|
||||
gradle.sync.change.type.conflict=Settings conflict
|
||||
|
||||
+31
-3
@@ -3,12 +3,18 @@ package org.jetbrains.plugins.gradle.action;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.config.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Forces the 'gradle' plugin to retrieve the most up-to-date info about the
|
||||
@@ -20,6 +26,8 @@ import java.io.File;
|
||||
*/
|
||||
public class GradleRefreshProjectAction extends AnAction implements DumbAware {
|
||||
|
||||
private final AtomicBoolean myInProgress = new AtomicBoolean();
|
||||
|
||||
public GradleRefreshProjectAction() {
|
||||
getTemplatePresentation().setText(GradleBundle.message("gradle.action.refresh.project.text"));
|
||||
getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.refresh.project.description"));
|
||||
@@ -33,12 +41,32 @@ public class GradleRefreshProjectAction extends AnAction implements DumbAware {
|
||||
return;
|
||||
}
|
||||
final String path = GradleSettings.getInstance(project).LINKED_PROJECT_FILE_PATH;
|
||||
e.getPresentation().setVisible(path != null && new File(path).isFile());
|
||||
final boolean visible = path != null && new File(path).isFile();
|
||||
e.getPresentation().setVisible(visible);
|
||||
e.getPresentation().setEnabled(!myInProgress.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
// TODO den implement
|
||||
int i = 1;
|
||||
final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
|
||||
if (project == null) {
|
||||
e.getPresentation().setVisible(false);
|
||||
return;
|
||||
}
|
||||
// Assuming that the linked project is available if this action is called (update() is successful)
|
||||
final String projectPath = GradleSettings.getInstance(project).LINKED_PROJECT_FILE_PATH;
|
||||
myInProgress.set(true);
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, GradleBundle.message("gradle.sync.progress.text")) {
|
||||
@Override
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
try {
|
||||
GradleResolveProjectTask task = new GradleResolveProjectTask(project, projectPath, true);
|
||||
task.execute(indicator);
|
||||
}
|
||||
finally {
|
||||
myInProgress.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+18
-48
@@ -1,7 +1,6 @@
|
||||
package org.jetbrains.plugins.gradle.importing;
|
||||
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
@@ -25,9 +24,7 @@ import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.*;
|
||||
import org.jetbrains.plugins.gradle.notification.*;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
|
||||
@@ -73,21 +70,20 @@ public class GradleModulesImporter {
|
||||
*/
|
||||
@NotNull
|
||||
public Map<GradleModule, Module> importModules(@NotNull final Iterable<GradleModule> modules, @Nullable final Project project,
|
||||
@Nullable final ModifiableModuleModel model, @NotNull String gradleProjectPath,
|
||||
@NotNull GradleProgressNotificationManager progressManager)
|
||||
@Nullable final ModifiableModuleModel model, @NotNull String gradleProjectPath)
|
||||
{
|
||||
if (project == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
removeExistingModulesSettings(modules);
|
||||
if (!project.isInitialized()) {
|
||||
myAlarm.addRequest(new ImportModulesTask(project, modules, gradleProjectPath, progressManager), PROJECT_INITIALISATION_DELAY_MS);
|
||||
myAlarm.addRequest(new ImportModulesTask(project, modules, gradleProjectPath), PROJECT_INITIALISATION_DELAY_MS);
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
if (model == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return importModules(modules, model, project, gradleProjectPath, progressManager);
|
||||
return importModules(modules, model, project, gradleProjectPath);
|
||||
}
|
||||
|
||||
private static void removeExistingModulesSettings(@NotNull Iterable<GradleModule> modules) {
|
||||
@@ -107,8 +103,7 @@ public class GradleModulesImporter {
|
||||
public Map<GradleModule, Module> importModules(@NotNull final Iterable<GradleModule> modules,
|
||||
@NotNull final ModifiableModuleModel model,
|
||||
@NotNull final Project intellijProject,
|
||||
@NotNull final String gradleProjectPath,
|
||||
@NotNull final GradleProgressNotificationManager progressManager)
|
||||
@NotNull final String gradleProjectPath)
|
||||
{
|
||||
final Map<GradleModule, Module> result = new HashMap<GradleModule, Module>();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@@ -123,7 +118,7 @@ public class GradleModulesImporter {
|
||||
result.putAll(moduleMappings);
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(
|
||||
new SetupExternalLibrariesTask(moduleMappings, gradleProjectPath, intellijProject, progressManager),
|
||||
new SetupExternalLibrariesTask(moduleMappings, gradleProjectPath, intellijProject),
|
||||
PROJECT_INITIALISATION_DELAY_MS
|
||||
);
|
||||
}
|
||||
@@ -142,7 +137,7 @@ public class GradleModulesImporter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual implementation of {@link #importModules(Iterable, Project, ModifiableModuleModel, String, GradleProgressNotificationManager)}.
|
||||
* Actual implementation of {@link #importModules(Iterable, Project, ModifiableModuleModel, String)}.
|
||||
* Insists on all arguments to be ready to use.
|
||||
*
|
||||
* @param modules modules to import
|
||||
@@ -291,10 +286,8 @@ public class GradleModulesImporter {
|
||||
*/
|
||||
private static void setupLibraries(@NotNull final Map<GradleModule, Module> moduleMappings,
|
||||
@NotNull final Project intellijProject,
|
||||
@NotNull final String gradleProjectPath,
|
||||
@NotNull final GradleProgressNotificationManager progressManager)
|
||||
@NotNull final String gradleProjectPath)
|
||||
{
|
||||
final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
|
||||
final Ref<GradleProject> gradleProjectRef = new Ref<GradleProject>();
|
||||
|
||||
final Runnable setupExternalDependenciesTask = new Runnable() {
|
||||
@@ -323,28 +316,11 @@ public class GradleModulesImporter {
|
||||
new Task.Backgroundable(intellijProject, GradleBundle.message("gradle.library.resolve.progress.text"), false) {
|
||||
@Override
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
indicator.setIndeterminate(true);
|
||||
GradleTaskNotificationListener progressListener = new GradleTaskNotificationListenerAdapter() {
|
||||
@Override
|
||||
public void onStatusChange(@NotNull GradleTaskNotificationEvent event) {
|
||||
indicator.setText2(event.getDescription());
|
||||
}
|
||||
};
|
||||
GradleTaskId taskId = GradleTaskId.create(GradleTaskType.RESOLVE_PROJECT);
|
||||
progressManager.addNotificationListener(taskId, progressListener);
|
||||
try {
|
||||
GradleProjectResolver resolver = manager.getFacade().getResolver();
|
||||
|
||||
GradleProject projectWithResolvedLibraries = resolver.resolveProjectInfo(taskId, gradleProjectPath, true);
|
||||
gradleProjectRef.set(projectWithResolvedLibraries);
|
||||
ApplicationManager.getApplication().invokeLater(setupExternalDependenciesTask, ModalityState.NON_MODAL);
|
||||
}
|
||||
catch (Exception e) {
|
||||
GradleLog.LOG.warn("Can't resolve external dependencies of the target gradle project (" + gradleProjectPath + ")", e);
|
||||
}
|
||||
finally {
|
||||
progressManager.removeNotificationListener(progressListener);
|
||||
}
|
||||
GradleResolveProjectTask task = new GradleResolveProjectTask(intellijProject, gradleProjectPath, true);
|
||||
task.execute(indicator);
|
||||
GradleProject projectWithResolvedLibraries = task.getProject();
|
||||
gradleProjectRef.set(projectWithResolvedLibraries);
|
||||
ApplicationManager.getApplication().invokeLater(setupExternalDependenciesTask, ModalityState.NON_MODAL);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -497,14 +473,11 @@ public class GradleModulesImporter {
|
||||
private final Project myProject;
|
||||
private final Iterable<GradleModule> myModules;
|
||||
private final String myGradleProjectPath;
|
||||
private final GradleProgressNotificationManager myProgressManger;
|
||||
|
||||
ImportModulesTask(@NotNull Project project, @NotNull Iterable<GradleModule> modules, @NotNull String gradleProjectPath,
|
||||
@NotNull GradleProgressNotificationManager progressManager) {
|
||||
ImportModulesTask(@NotNull Project project, @NotNull Iterable<GradleModule> modules, @NotNull String gradleProjectPath) {
|
||||
myProject = project;
|
||||
myModules = modules;
|
||||
myGradleProjectPath = gradleProjectPath;
|
||||
myProgressManger = progressManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -512,7 +485,7 @@ public class GradleModulesImporter {
|
||||
myAlarm.cancelAllRequests();
|
||||
if (!myProject.isInitialized()) {
|
||||
myAlarm.addRequest(
|
||||
new ImportModulesTask(myProject, myModules, myGradleProjectPath, myProgressManger),
|
||||
new ImportModulesTask(myProject, myModules, myGradleProjectPath),
|
||||
PROJECT_INITIALISATION_DELAY_MS
|
||||
);
|
||||
return;
|
||||
@@ -524,7 +497,7 @@ public class GradleModulesImporter {
|
||||
}
|
||||
}.execute().getResultObject();
|
||||
|
||||
importModules(myModules, model, myProject, myGradleProjectPath, myProgressManger);
|
||||
importModules(myModules, model, myProject, myGradleProjectPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,22 +506,19 @@ public class GradleModulesImporter {
|
||||
private final Map<GradleModule, Module> myModules;
|
||||
private final String myGradleProjectPath;
|
||||
private final Project myIntellijProject;
|
||||
private final GradleProgressNotificationManager myProgressManager;
|
||||
|
||||
SetupExternalLibrariesTask(@NotNull Map<GradleModule, Module> modules,
|
||||
@NotNull String gradleProjectPath,
|
||||
@NotNull Project intellijProject,
|
||||
@NotNull GradleProgressNotificationManager manager)
|
||||
@NotNull Project intellijProject)
|
||||
{
|
||||
myModules = modules;
|
||||
myGradleProjectPath = gradleProjectPath;
|
||||
myIntellijProject = intellijProject;
|
||||
myProgressManager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
setupLibraries(myModules, myIntellijProject, myGradleProjectPath, myProgressManager);
|
||||
setupLibraries(myModules, myIntellijProject, myGradleProjectPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-47
@@ -3,11 +3,9 @@ package org.jetbrains.plugins.gradle.importing;
|
||||
import com.intellij.execution.rmi.RemoteUtil;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.ide.util.projectWizard.WizardContext;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
@@ -28,10 +26,8 @@ import org.jetbrains.plugins.gradle.config.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.model.GradleEntity;
|
||||
import org.jetbrains.plugins.gradle.model.GradleModule;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
import org.jetbrains.plugins.gradle.notification.*;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiException;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
|
||||
import org.jetbrains.plugins.gradle.ui.GradleIcons;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
@@ -54,15 +50,9 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
|
||||
/** @see #setModuleMappings(Map) */
|
||||
private final Map<GradleModule/*origin*/, GradleModule/*adjusted*/> myModuleMappings = new HashMap<GradleModule, GradleModule>();
|
||||
|
||||
private final GradleProgressNotificationManager myProgressManager;
|
||||
|
||||
private GradleProject myGradleProject;
|
||||
private File myProjectFile;
|
||||
|
||||
public GradleProjectImportBuilder(@NotNull GradleProgressNotificationManager progressManager) {
|
||||
myProgressManager = progressManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return GradleBundle.message("gradle.name");
|
||||
@@ -107,7 +97,7 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
|
||||
}
|
||||
GradleModulesImporter importer = new GradleModulesImporter();
|
||||
Map<GradleModule, Module> mappings =
|
||||
importer.importModules(myModuleMappings.values(), project, model, myProjectFile.getAbsolutePath(), myProgressManager);
|
||||
importer.importModules(myModuleMappings.values(), project, model, myProjectFile.getAbsolutePath());
|
||||
return new ArrayList<Module>(mappings.values());
|
||||
}
|
||||
|
||||
@@ -165,48 +155,36 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
|
||||
}
|
||||
final Ref<String> errorReason = new Ref<String>();
|
||||
try {
|
||||
Project project = getProject(wizardContext);
|
||||
final Project project = getProject(wizardContext);
|
||||
ProgressManager.getInstance().run(new Task.Modal(project, GradleBundle.message("gradle.import.progress.text"), true) {
|
||||
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
|
||||
@Override
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
indicator.setIndeterminate(true);
|
||||
GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
|
||||
GradleTaskNotificationListener gradleProgressListener = new GradleTaskNotificationListenerAdapter() {
|
||||
@Override
|
||||
public void onStatusChange(@NotNull GradleTaskNotificationEvent event) {
|
||||
indicator.setText2(event.getDescription());
|
||||
}
|
||||
};
|
||||
GradleTaskId taskId = GradleTaskId.create(GradleTaskType.RESOLVE_PROJECT);
|
||||
myProgressManager.addNotificationListener(taskId, gradleProgressListener);
|
||||
try {
|
||||
GradleProjectResolver resolver = manager.getFacade().getResolver();
|
||||
myGradleProject = resolver.resolveProjectInfo(taskId, myProjectFile.getAbsolutePath(), false);
|
||||
GradleResolveProjectTask task = new GradleResolveProjectTask(project, myProjectFile.getAbsolutePath(), false);
|
||||
task.execute(indicator);
|
||||
myGradleProject = task.getProject();
|
||||
if (myGradleProject != null) {
|
||||
return;
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
// Ignore
|
||||
final Throwable error = task.getError();
|
||||
if (error == null) {
|
||||
return;
|
||||
}
|
||||
catch (Exception e) {
|
||||
Throwable unwrapped = RemoteUtil.unwrap(e);
|
||||
String reason = unwrapped.getLocalizedMessage();
|
||||
if (!StringUtil.isEmpty(reason)) {
|
||||
errorReason.set(reason);
|
||||
}
|
||||
if (unwrapped.getClass() == NoClassDefFoundError.class) {
|
||||
errorReason.set(GradleBundle.message("gradle.import.text.incomplete.tooling.api"));
|
||||
}
|
||||
else if (unwrapped.getClass() == GradleApiException.class) {
|
||||
GradleLog.LOG.warn("Can't resolve gradle project. Reason: gradle api threw an exception:\n"
|
||||
+ ((GradleApiException)unwrapped).getOriginalReason()
|
||||
);
|
||||
}
|
||||
else {
|
||||
GradleLog.LOG.warn("Can't resolve gradle project", e);
|
||||
}
|
||||
Throwable unwrapped = RemoteUtil.unwrap(error);
|
||||
String reason = unwrapped.getLocalizedMessage();
|
||||
if (!StringUtil.isEmpty(reason)) {
|
||||
errorReason.set(reason);
|
||||
}
|
||||
finally {
|
||||
myProgressManager.removeNotificationListener(gradleProgressListener);
|
||||
if (unwrapped.getClass() == NoClassDefFoundError.class) {
|
||||
errorReason.set(GradleBundle.message("gradle.import.text.incomplete.tooling.api"));
|
||||
}
|
||||
else if (unwrapped.getClass() == GradleApiException.class) {
|
||||
GradleLog.LOG.warn("Can't resolve gradle project. Reason: gradle api threw an exception:\n"
|
||||
+ ((GradleApiException)unwrapped).getOriginalReason()
|
||||
);
|
||||
}
|
||||
else {
|
||||
GradleLog.LOG.warn("Can't resolve gradle project", unwrapped);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.plugins.gradle.notification;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
|
||||
+1
@@ -5,6 +5,7 @@ import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import com.intellij.util.containers.ConcurrentHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProgressNotificationManager;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.plugins.gradle.notification;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.plugins.gradle.notification;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
|
||||
/**
|
||||
* Defines contract for callback to listen gradle task notifications.
|
||||
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.plugins.gradle.notification;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package org.jetbrains.plugins.gradle.remote;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Serves as a facade for working with
|
||||
@@ -42,4 +45,23 @@ public interface GradleApiFacade extends Remote {
|
||||
* @throws RemoteException in case of unexpected I/O exception during processing
|
||||
*/
|
||||
void applyProgressManager(@NotNull RemoteGradleProgressNotificationManager progressManager) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Asks remote gradle process to check if a task with the given id is being executed right now.
|
||||
*
|
||||
* @param id target task's id
|
||||
* @return <code>true</code> if a task with the given id is executed at the moment; <code>false</code> otherwise
|
||||
* @throws RemoteException in case of unexpected I/O exception during processing
|
||||
*/
|
||||
boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Allows to ask remote gradle process for the ids of the tasks with the given type being executed now.
|
||||
*
|
||||
* @param type target task type
|
||||
* @return ids of the tasks of the target type being executed at the moment (if any)
|
||||
* @throws RemoteException in case of unexpected I/O exception during processing
|
||||
*/
|
||||
@NotNull
|
||||
Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) throws RemoteException;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.jetbrains.plugins.gradle.remote;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package org.jetbrains.plugins.gradle.remote;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
|
||||
|
||||
import java.rmi.Remote;
|
||||
|
||||
@@ -2,9 +2,12 @@ package org.jetbrains.plugins.gradle.remote;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Generic interface with common functionality for all remote services that work with gradle tooling api.
|
||||
@@ -14,6 +17,26 @@ import java.rmi.RemoteException;
|
||||
*/
|
||||
public interface RemoteGradleService extends Remote {
|
||||
|
||||
/**
|
||||
* Allows to check if current service executes the target task.
|
||||
*
|
||||
* @param id target task's id
|
||||
* @return <code>true</code> if a task with the given id is executed at the moment by the current service;
|
||||
* <code>false</code> otherwise
|
||||
* @throws RemoteException as required by RMI
|
||||
*/
|
||||
boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Allows to ask current service for the ids of the tasks with the given type being executed now.
|
||||
*
|
||||
* @param type target task type
|
||||
* @return ids of the tasks of the target type being executed at the moment by the current service (if any)
|
||||
* @throws RemoteException as required by RMI
|
||||
*/
|
||||
@NotNull
|
||||
Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Provides the service settings to use.
|
||||
*
|
||||
|
||||
+31
-4
@@ -4,19 +4,19 @@ import com.intellij.execution.rmi.RemoteServer;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProgressNotificationManager;
|
||||
import org.jetbrains.plugins.gradle.remote.*;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -35,7 +35,7 @@ public class GradleApiFacadeImpl extends RemoteServer implements GradleApiFacade
|
||||
= new ConcurrentHashMap<Class<?>, RemoteGradleService>();
|
||||
private final AtomicReference<RemoteGradleProcessSettings> mySettings
|
||||
= new AtomicReference<RemoteGradleProcessSettings>();
|
||||
private final AtomicReference<GradleTaskNotificationListener> myNotificationListener
|
||||
private final AtomicReference<GradleTaskNotificationListener> myNotificationListener
|
||||
= new AtomicReference<GradleTaskNotificationListener>();
|
||||
private final AtomicLong myTtlMs
|
||||
= new AtomicLong(DEFAULT_REMOTE_GRADLE_PROCESS_TTL_IN_MS);
|
||||
@@ -130,6 +130,33 @@ public class GradleApiFacadeImpl extends RemoteServer implements GradleApiFacade
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
|
||||
for (RemoteGradleService service : myRemotes.values()) {
|
||||
if (service.isTaskInProgress(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) throws RemoteException {
|
||||
Set<GradleTaskId> result = null;
|
||||
for (RemoteGradleService service : myRemotes.values()) {
|
||||
final Collection<GradleTaskId> tasks = service.getTasksInProgress(type);
|
||||
if (tasks.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (result == null) {
|
||||
result = new HashSet<GradleTaskId>();
|
||||
}
|
||||
result.addAll(tasks);
|
||||
}
|
||||
return result == null ? Collections.<GradleTaskId>emptySet() : result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
|
||||
mySettings.set(settings);
|
||||
|
||||
+27
-11
@@ -5,6 +5,7 @@ import com.intellij.openapi.roots.DependencyScope;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ConcurrentHashSet;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.gradle.tooling.*;
|
||||
import org.gradle.tooling.model.DomainObjectSet;
|
||||
@@ -12,22 +13,21 @@ import org.gradle.tooling.model.idea.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.*;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiException;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleService;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -39,12 +39,14 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
*/
|
||||
public class GradleProjectResolverImpl extends RemoteObject implements GradleProjectResolver, RemoteGradleService {
|
||||
|
||||
private final ThreadLocal<ProjectConnection> myCurrentConnection = new ThreadLocal<ProjectConnection>();
|
||||
private final BlockingQueue<ProjectConnection> myConnections = new LinkedBlockingQueue<ProjectConnection>();
|
||||
private final AtomicReference<RemoteGradleProcessSettings> mySettings = new AtomicReference<RemoteGradleProcessSettings>();
|
||||
private final GradleLibraryNamesMixer myLibraryNamesMixer = new GradleLibraryNamesMixer();
|
||||
private final AtomicReference<GradleTaskNotificationListener> myNotificationListener =
|
||||
new AtomicReference<GradleTaskNotificationListener>();
|
||||
private final ThreadLocal<ProjectConnection> myCurrentConnection = new ThreadLocal<ProjectConnection>();
|
||||
private final BlockingQueue<ProjectConnection> myConnections = new LinkedBlockingQueue<ProjectConnection>();
|
||||
private final AtomicReference<RemoteGradleProcessSettings> mySettings = new AtomicReference<RemoteGradleProcessSettings>();
|
||||
private final GradleLibraryNamesMixer myLibraryNamesMixer = new GradleLibraryNamesMixer();
|
||||
private final ConcurrentHashSet<GradleTaskId> myTasksInProgress = new ConcurrentHashSet<GradleTaskId>();
|
||||
private final AtomicReference<GradleTaskNotificationListener> myNotificationListener
|
||||
= new AtomicReference<GradleTaskNotificationListener>();
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -71,7 +73,21 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isTaskInProgress(@NotNull GradleTaskId id) {
|
||||
return myTasksInProgress.contains(id);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) {
|
||||
if (type != GradleTaskType.RESOLVE_PROJECT || myTasksInProgress.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return new HashSet<GradleTaskId>(myTasksInProgress);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GradleProject doResolveProjectInfo(@NotNull final GradleTaskId id, @NotNull String projectPath, boolean downloadLibraries)
|
||||
throws RemoteException, IllegalArgumentException, IllegalStateException
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class GradleProjectStructureChangesModel extends AbstractProjectComponent
|
||||
* <li>{@link #addListener(GradleProjectStructureChangeListener) Registered listeners} are notified if any new change is detected;</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param gradleProject
|
||||
* @param gradleProject gradle project to sync with
|
||||
*/
|
||||
public void update(@NotNull GradleProject gradleProject) {
|
||||
//TODO den implement
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListenerAdapter;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacade;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Encapsulates particular task performed by the gradle integration.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/24/12 7:03 AM
|
||||
*/
|
||||
public abstract class AbstractGradleTask implements GradleTask {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + AbstractGradleTask.class.getName());
|
||||
|
||||
private final AtomicReference<GradleTaskState> myState = new AtomicReference<GradleTaskState>(GradleTaskState.NOT_STARTED);
|
||||
private final AtomicReference<Throwable> myError = new AtomicReference<Throwable>();
|
||||
|
||||
private final GradleTaskId myId;
|
||||
|
||||
protected AbstractGradleTask(@NotNull GradleTaskType type) {
|
||||
myId = GradleTaskId.create(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GradleTaskId getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GradleTaskState getState() {
|
||||
return myState.get();
|
||||
}
|
||||
|
||||
protected void setState(@NotNull GradleTaskState state) {
|
||||
myState.set(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable getError() {
|
||||
return myError.get();
|
||||
}
|
||||
|
||||
public void refreshState() {
|
||||
if (getState() != GradleTaskState.IN_PROGRESS) {
|
||||
return;
|
||||
}
|
||||
final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
|
||||
try {
|
||||
final GradleApiFacade facade = manager.getFacade();
|
||||
setState(facade.isTaskInProgress(getId()) ? GradleTaskState.IN_PROGRESS : GradleTaskState.FAILED);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
setState(GradleTaskState.FAILED);
|
||||
myError.set(e);
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull final ProgressIndicator indicator) {
|
||||
indicator.setIndeterminate(true);
|
||||
execute(new GradleTaskNotificationListenerAdapter() {
|
||||
@Override
|
||||
public void onStatusChange(@NotNull GradleTaskNotificationEvent event) {
|
||||
indicator.setText2(event.getDescription());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull GradleTaskNotificationListener... listeners) {
|
||||
GradleProgressNotificationManager progressManager = ServiceManager.getService(GradleProgressNotificationManager.class);
|
||||
for (GradleTaskNotificationListener listener : listeners) {
|
||||
progressManager.addNotificationListener(getId(), listener);
|
||||
}
|
||||
try {
|
||||
doExecute();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
setState(GradleTaskState.FAILED);
|
||||
myError.set(e);
|
||||
LOG.warn(e);
|
||||
}
|
||||
finally {
|
||||
for (GradleTaskNotificationListener listener : listeners) {
|
||||
progressManager.addNotificationListener(getId(), listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doExecute() throws Exception;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myId.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AbstractGradleTask task = (AbstractGradleTask)o;
|
||||
return myId.equals(task.myId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: %s", myId, myState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/24/12 7:21 AM
|
||||
*/
|
||||
public class GradleResolveProjectTask extends AbstractGradleTask {
|
||||
|
||||
private final AtomicReference<GradleProject> myGradleProject = new AtomicReference<GradleProject>();
|
||||
|
||||
private final Project myIntellijProject;
|
||||
private final String myProjectPath;
|
||||
private final boolean myResolveLibraries;
|
||||
|
||||
public GradleResolveProjectTask(@Nullable Project project, @NotNull String projectPath, boolean resolveLibraries) {
|
||||
super(GradleTaskType.RESOLVE_PROJECT);
|
||||
myIntellijProject = project;
|
||||
myProjectPath = projectPath;
|
||||
myResolveLibraries = resolveLibraries;
|
||||
}
|
||||
|
||||
protected void doExecute() throws Exception {
|
||||
final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
|
||||
GradleProjectResolver resolver = manager.getFacade().getResolver();
|
||||
setState(GradleTaskState.IN_PROGRESS);
|
||||
final GradleProject project = resolver.resolveProjectInfo(getId(), myProjectPath, myResolveLibraries);
|
||||
myGradleProject.set(project);
|
||||
setState(GradleTaskState.FINISHED);
|
||||
if (myIntellijProject == null) {
|
||||
return;
|
||||
}
|
||||
final GradleProjectStructureChangesModel model = myIntellijProject.getComponent(GradleProjectStructureChangesModel.class);
|
||||
model.update(project);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GradleProject getProject() {
|
||||
return myGradleProject.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/24/12 7:16 AM
|
||||
*/
|
||||
public interface GradleTask {
|
||||
|
||||
@NotNull
|
||||
GradleTaskId getId();
|
||||
|
||||
@NotNull
|
||||
GradleTaskState getState();
|
||||
|
||||
/**
|
||||
* @return error occurred during the task execution (if any)
|
||||
*/
|
||||
@Nullable
|
||||
Throwable getError();
|
||||
|
||||
/**
|
||||
* Executes current task and updates given indicator's {@link ProgressIndicator#setText2(String) status} during that.
|
||||
*
|
||||
* @param indicator target progress indicator
|
||||
*/
|
||||
void execute(@NotNull ProgressIndicator indicator);
|
||||
|
||||
/**
|
||||
* Executes 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 execute(@NotNull GradleTaskNotificationListener ... listeners);
|
||||
|
||||
/**
|
||||
* Forces current task to refresh {@link #getState() its state}.
|
||||
*/
|
||||
void refreshState();
|
||||
}
|
||||
+6
-5
@@ -1,4 +1,4 @@
|
||||
package org.jetbrains.plugins.gradle.notification;
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Represents id of the task enqueued to Gradle API for execution.
|
||||
*
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 11/10/11 9:09 AM
|
||||
*/
|
||||
@@ -15,7 +15,7 @@ public class GradleTaskId implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final AtomicLong COUNTER = new AtomicLong();
|
||||
|
||||
|
||||
private final GradleTaskType myType;
|
||||
private final long myId;
|
||||
|
||||
@@ -26,7 +26,7 @@ public class GradleTaskId implements Serializable {
|
||||
|
||||
/**
|
||||
* Allows to retrieve distinct task id object of the given type.
|
||||
*
|
||||
*
|
||||
* @param type target task type
|
||||
* @return distinct task id object of the given type
|
||||
*/
|
||||
@@ -34,7 +34,8 @@ public class GradleTaskId implements Serializable {
|
||||
public static GradleTaskId create(@NotNull GradleTaskType type) {
|
||||
return new GradleTaskId(type, COUNTER.getAndIncrement());
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public GradleTaskType getType() {
|
||||
return myType;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/24/12 7:08 AM
|
||||
*/
|
||||
public enum GradleTaskState {
|
||||
|
||||
NOT_STARTED, IN_PROGRESS, FINISHED, FAILED
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.jetbrains.plugins.gradle.notification;
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
/**
|
||||
* Enumerates interested types of tasks that may be enqueued to Gradle API.
|
||||
Reference in New Issue
Block a user