[maven] IDEA-258757 Cannot start tasks with maven wrapper

- support maven wrapper to goal execution
- downloaded wrapper if needed before goal.
- event log notification for wrapper process downloading

GitOrigin-RevId: 2f9fd6c9c35a5c39ee43eb70ea27427a0c96dab7
This commit is contained in:
grigoriy.myasoedov
2021-09-07 07:05:27 +00:00
committed by intellij-monorepo-bot
parent 78713364aa
commit 689a3b2b34
10 changed files with 179 additions and 22 deletions
@@ -7,7 +7,6 @@ import com.intellij.codeInsight.highlighting.HighlightUsagesHandler
import com.intellij.find.FindManager
import com.intellij.find.FindModel
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.DataProvider
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.colors.EditorColors
import com.intellij.openapi.fileEditor.FileEditorManager
@@ -41,6 +40,7 @@ class OpenFileQuickFix(private val path: Path, private val search: String?) : Bu
}
companion object {
@JvmStatic
fun showFile(project: Project, path: Path, search: String?) {
ApplicationManager.getApplication().invokeLater {
val file = VfsUtil.findFileByIoFile(path.toFile(), false) ?: return@invokeLater
@@ -103,7 +103,8 @@ public final class MavenExternalParameters {
Sdk jdk = getJdk(project, runnerSettings, project != null && MavenRunner.getInstance(project).getState() == runnerSettings);
params.setJdk(jdk);
final String mavenHome = resolveMavenHome(coreSettings, project, runConfiguration);
File mavenWrapperFile = getMavenWrapper(project, parameters.getWorkingDirPath(), coreSettings);
final String mavenHome = resolveMavenHome(coreSettings, project, runConfiguration, mavenWrapperFile);
final String mavenVersion = MavenUtil.getMavenVersion(mavenHome);
if(mavenVersion == null) {
throw new ExecutionException(MavenProjectBundle.message("dialog.message.maven.home.directory.invalid", mavenHome));
@@ -162,6 +163,14 @@ public final class MavenExternalParameters {
return params;
}
@Nullable
private static File getMavenWrapper(@Nullable Project project,
@NotNull String workingDirPath,
@NotNull MavenGeneralSettings coreSettings) {
return (project != null && MavenUtil.isWrapper(coreSettings))
? MavenDistributionsCache.getInstance(project).getMavenDistribution(workingDirPath).getMavenHome() : null;
}
static @Nullable String getRunVmOptions(@Nullable MavenRunnerSettings runnerSettings,
@Nullable Project project,
@NotNull String workingDirPath) {
@@ -438,7 +447,7 @@ public final class MavenExternalParameters {
@NotNull
public static String resolveMavenHome(@NotNull MavenGeneralSettings coreSettings) throws ExecutionException {
return resolveMavenHome(coreSettings, null, null);
return resolveMavenHome(coreSettings, null, null, null);
}
/**
@@ -452,8 +461,9 @@ public final class MavenExternalParameters {
@NlsSafe
public static String resolveMavenHome(@NotNull MavenGeneralSettings coreSettings,
@Nullable Project project,
@Nullable MavenRunConfiguration runConfiguration) throws ExecutionException {
final File file = MavenUtil.resolveMavenHomeDirectory(coreSettings.getMavenHome());
@Nullable MavenRunConfiguration runConfiguration,
@Nullable File mavenWrapperFile) throws ExecutionException {
final File file = mavenWrapperFile != null ? mavenWrapperFile : MavenUtil.resolveMavenHomeDirectory(coreSettings.getMavenHome());
if (file == null) {
throw createExecutionException(RunnerBundle.message("external.maven.home.no.default"),
@@ -19,8 +19,6 @@ import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -218,7 +216,7 @@ public final class MavenRunConfigurationType implements ConfigurationType {
runConfiguration.setBeforeRunTasks(Collections.emptyList());
}
MavenGeneralSettings generalSettingsToRun =
generalSettings != null ? generalSettings : MavenWorkspaceSettingsComponent.getInstance(project).getSettings().generalSettings;
generalSettings != null ? generalSettings : MavenWorkspaceSettingsComponent.getInstance(project).getSettings().getGeneralSettings();
runConfiguration.setRunnerParameters(params);
runConfiguration.setGeneralSettings(generalSettingsToRun);
MavenRunnerSettings runnerSettingsToRun =
@@ -17,6 +17,7 @@ package org.jetbrains.idea.maven.project.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.execution.MavenRunConfigurationType;
@@ -24,7 +25,10 @@ import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.project.MavenWorkspaceSettingsComponent;
import org.jetbrains.idea.maven.server.MavenDistributionsCache;
import org.jetbrains.idea.maven.utils.MavenDataKeys;
import org.jetbrains.idea.maven.utils.MavenUtil;
import org.jetbrains.idea.maven.utils.actions.MavenAction;
import org.jetbrains.idea.maven.utils.actions.MavenActionUtil;
@@ -62,9 +66,23 @@ public class RunBuildAction extends MavenAction {
explicitProfiles.getEnabledProfiles(),
explicitProfiles.getDisabledProfiles());
MavenRunConfigurationType.runConfiguration(project, params, null);
boolean needDownloadWrapper = needDownloadWrapper(project, mavenProject.getDirectory());
if (needDownloadWrapper) {
ApplicationManager.getApplication().executeOnPooledThread(() -> {
MavenDistributionsCache.getInstance(project).checkOrInstallMavenWrapper(mavenProject.getDirectory());
MavenRunConfigurationType.runConfiguration(project, params, null);
});
} else {
MavenRunConfigurationType.runConfiguration(project, params, null);
}
return true;
}
}
private static boolean needDownloadWrapper(@NotNull Project project, @NotNull String workinDir) {
if (MavenUtil.isWrapper(MavenWorkspaceSettingsComponent.getInstance(project).getSettings().getGeneralSettings())) {
MavenDistributionsCache instance = MavenDistributionsCache.getInstance(project);
return instance.getWrapper(workinDir) == null;
}
return false;
}
}
@@ -18,7 +18,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.buildtool.MavenSyncConsole;
import org.jetbrains.idea.maven.execution.MavenExternalParameters;
import org.jetbrains.idea.maven.execution.SyncBundle;
import org.jetbrains.idea.maven.project.MavenProjectBundle;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.project.MavenWorkspaceSettings;
import org.jetbrains.idea.maven.project.MavenWorkspaceSettingsComponent;
@@ -92,6 +91,12 @@ public class MavenDistributionsCache {
return (distributionUrl == null) ? resolveEmbeddedMavenHome() : getMavenWrapper(distributionUrl);
}
public @Nullable MavenDistribution getWrapper(@NotNull String workingDirectory) {
String multiModuleDir = myWorkingDirToMultimoduleMap.computeIfAbsent(workingDirectory, this::resolveMultimoduleDirectory);
String distributionUrl = getWrapperDistributionUrl(multiModuleDir);
return (distributionUrl != null) ? MavenWrapperSupport.getCurrentDistribution(distributionUrl) : null;
}
private static MavenDistribution getMavenWrapper(String distributionUrl) {
MavenDistribution distribution = MavenWrapperSupport.getCurrentDistribution(distributionUrl);
if (distribution == null) {
@@ -105,7 +110,10 @@ public class MavenDistributionsCache {
String multiModuleDir = getMultimoduleDirectory(workingDir);
String distributionUrl = getWrapperDistributionUrl(multiModuleDir);
if (distributionUrl == null) return;
if (distributionUrl == null) {
MavenWrapperEventLogNotification.noDistributionUrlEvent(myProject, multiModuleDir);
return;
}
MavenDistribution distribution = MavenWrapperSupport.getCurrentDistribution(distributionUrl);
if (distribution != null) return;
@@ -114,6 +122,7 @@ public class MavenDistributionsCache {
MavenSyncConsole console = MavenProjectsManager.getInstance(myProject).getSyncConsole();
console.startWrapperResolving();
MavenWrapperEventLogNotification.informationEvent(myProject, SyncBundle.message("maven.wrapper.notification.downloading.start"));
Task.Backgroundable task = getTaskInfo();
BackgroundableProcessIndicator indicator = console.progressIndicatorForWrapper(myProject, task);
try {
@@ -123,10 +132,12 @@ public class MavenDistributionsCache {
}
myMultimoduleDirToWrapperedMavenDistributionsMap.put(multiModuleDir, distribution);
console.finishWrapperResolving(null);
MavenWrapperEventLogNotification.informationEvent(myProject, SyncBundle.message("maven.wrapper.notification.downloading.finish"));
}
catch (Exception e) {
LOG.warn("error install wrapper", e);
console.finishWrapperResolving(e);
MavenWrapperEventLogNotification.errorDownloading(myProject, e.getLocalizedMessage());
MavenWorkspaceSettings settings = MavenWorkspaceSettingsComponent.getInstance(myProject).getSettings();
settings.getGeneralSettings().setMavenHome(MavenServerManager.BUNDLED_MAVEN_3);
} finally {
@@ -136,7 +147,7 @@ public class MavenDistributionsCache {
}
@NotNull
private Task.Backgroundable getTaskInfo() {
private static Task.Backgroundable getTaskInfo() {
return new Task.Backgroundable(null, SyncBundle.message("maven.sync.wrapper.downloading")) {
@Override
public void run(@NotNull ProgressIndicator indicator) { }
@@ -208,7 +219,6 @@ public class MavenDistributionsCache {
private boolean useWrapper() {
MavenWorkspaceSettings settings = MavenWorkspaceSettingsComponent.getInstance(myProject).getSettings();
return MavenServerManager.WRAPPED_MAVEN.equals(settings.getGeneralSettings().getMavenHome()) ||
StringUtil.equals(settings.getGeneralSettings().getMavenHome(), MavenProjectBundle.message("maven.wrapper.version.title"));
return MavenUtil.isWrapper(settings.getGeneralSettings());
}
}
@@ -0,0 +1,99 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.server
import com.intellij.build.issue.quickfix.OpenFileQuickFix.Companion.showFile
import com.intellij.notification.NotificationAction
import com.intellij.notification.NotificationGroup
import com.intellij.notification.NotificationGroupManager
import com.intellij.notification.NotificationType
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.options.ShowSettingsUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.annotations.Nls
import org.jetbrains.idea.maven.execution.SyncBundle.message
import org.jetbrains.idea.maven.project.MavenProjectBundle
import org.jetbrains.idea.maven.server.MavenWrapperSupport.Companion.getWrapperProperties
class MavenWrapperEventLogNotification {
companion object {
@JvmStatic
fun noDistributionUrlEvent(project: Project, multiModuleDir: String) {
val notificationGroup = NotificationGroupManager.getInstance().getNotificationGroup("Maven") ?: return
ApplicationManager.getApplication().invokeLater {
val wrapperPropertyFile = LocalFileSystem.getInstance().findFileByPath(multiModuleDir)?.let { getWrapperProperties(it) }
if (wrapperPropertyFile == null) {
wrapperPropertyFileNotFound(notificationGroup, project)
}
else {
distributionUrlEmpty(notificationGroup, project, wrapperPropertyFile)
}
}
}
@JvmStatic
fun informationEvent(project: Project, @Nls content: String) {
val notificationGroup = NotificationGroupManager.getInstance().getNotificationGroup("Maven") ?: return
ApplicationManager.getApplication().invokeLater {
notificationGroup
.createNotification(
message("maven.wrapper.notification.title"), content, NotificationType.INFORMATION
)
.notify(project)
}
}
@JvmStatic
fun errorDownloading(project: Project, error: String) {
val notificationGroup = NotificationGroupManager.getInstance().getNotificationGroup("Maven") ?: return
ApplicationManager.getApplication().invokeLater {
notificationGroup
.createNotification(
message("maven.wrapper.notification.title"),
message("maven.wrapper.notification.downloading.error.content", error),
NotificationType.ERROR
)
.addAction(NotificationAction.createSimple(message("maven.wrapper.notification.downloading.error.action")) {
ShowSettingsUtil.getInstance().showSettingsDialog(project,
MavenProjectBundle.message("configurable.MavenSettings.display.name"))
})
.notify(project)
}
}
private fun wrapperPropertyFileNotFound(notificationGroup: NotificationGroup,
project: Project) {
notificationGroup
.createNotification(
message("maven.wrapper.notification.title"),
message("maven.wrapper.notification.empty.url.contant.file.not.found"),
NotificationType.WARNING
)
.addAction(NotificationAction.createSimple(message("maven.wrapper.notification.empty.url.action.disable")) {
ShowSettingsUtil.getInstance().showSettingsDialog(project,
MavenProjectBundle.message("configurable.MavenSettings.display.name"))
})
.notify(project)
}
private fun distributionUrlEmpty(notificationGroup: NotificationGroup,
project: Project,
wrapperPropertyFile: VirtualFile) {
notificationGroup
.createNotification(
message("maven.wrapper.notification.title"),
message("maven.wrapper.notification.empty.url.content"),
NotificationType.WARNING
)
.addAction(NotificationAction.createSimple(message("maven.wrapper.notification.empty.url.action.check")) {
showFile(project, wrapperPropertyFile.toNioPath(), null)
})
.addAction(NotificationAction.createSimple(message("maven.wrapper.notification.empty.url.action.disable")) {
ShowSettingsUtil.getInstance().showSettingsDialog(project,
MavenProjectBundle.message("configurable.MavenSettings.display.name"))
})
.notify(project)
}
}
}
@@ -213,7 +213,8 @@ internal class MavenWrapperSupport {
return null
}
private fun getWrapperProperties(baseDir: VirtualFile?) =
@JvmStatic
fun getWrapperProperties(baseDir: VirtualFile?) =
baseDir?.findChild(".mvn")?.findChild("wrapper")?.findChild("maven-wrapper.properties")
}
}
@@ -13,7 +13,9 @@ import org.jetbrains.idea.maven.execution.MavenExternalParameters.resolveMavenHo
import org.jetbrains.idea.maven.execution.MavenRunner
import org.jetbrains.idea.maven.project.MavenImportingSettings
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.idea.maven.server.MavenDistributionsCache
import org.jetbrains.idea.maven.utils.MavenUtil
import java.io.File
class MavenSettingsCollector : ProjectUsagesCollector() {
override fun getGroupId() = "build.maven.state"
@@ -41,7 +43,8 @@ class MavenSettingsCollector : ProjectUsagesCollector() {
@Suppress("DEPRECATION")
usages.add(newMetric("loggingLevel", generalSettings.loggingLevel))
try {
var mavenVersion = MavenUtil.getMavenVersion(resolveMavenHome(generalSettings, project, null))
val mavenWrapperFile = getMavenWrapper(manager, project)
var mavenVersion = MavenUtil.getMavenVersion(resolveMavenHome(generalSettings, project, null, mavenWrapperFile))
mavenVersion = mavenVersion?.let { Version.parseVersion(it)?.toCompactString() } ?: "unknown"
usages.add(newMetric("mavenVersion", mavenVersion))
}
@@ -93,4 +96,10 @@ class MavenSettingsCollector : ProjectUsagesCollector() {
usages.add(newBooleanMetric("hasRunnerMavenProperties", !runnerSettings.mavenProperties.isNullOrEmpty()))
return usages
}
private fun getMavenWrapper(manager: MavenProjectsManager,
project: Project): File? {
return if (manager.rootProjects.size == 1)
MavenDistributionsCache.getInstance(project).getWrapper(manager.rootProjects.first().directory)?.mavenHome else null
}
}
@@ -72,9 +72,7 @@ import org.jetbrains.idea.maven.execution.MavenRunnerSettings;
import org.jetbrains.idea.maven.execution.SyncBundle;
import org.jetbrains.idea.maven.externalSystemIntegration.output.importproject.quickfixes.CleanBrokenArtifactsAndReimportQuickFix;
import org.jetbrains.idea.maven.model.*;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectReaderResult;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.project.*;
import org.jetbrains.idea.maven.server.*;
import org.jetbrains.idea.maven.wizards.MavenProjectBuilder;
import org.xml.sax.Attributes;
@@ -1473,4 +1471,9 @@ public class MavenUtil {
MavenPlugin plugin = mavenProject.findPlugin("org.apache.maven.plugins", "maven-compiler-plugin");
return plugin != null ? plugin.getVersion() : StringUtils.EMPTY;
}
public static boolean isWrapper(@NotNull MavenGeneralSettings settings) {
return MavenServerManager.WRAPPED_MAVEN.equals(settings.getMavenHome()) ||
StringUtil.equals(settings.getMavenHome(), MavenProjectBundle.message("maven.wrapper.version.title"));
}
}
@@ -54,6 +54,15 @@ maven.sync.wrapper.downloading.from=Downloading Maven wrapper from {0}
maven.sync.wrapper.downloading.progress=Downloading Maven wrapper {0}/{1}%
maven.sync.wrapper.downloading=Downloading Maven wrapper
maven.sync.wrapper.downloading.canceled=Downloading Maven wrapper was canceled
maven.wrapper.notification.title=Maven wrapper
maven.wrapper.notification.empty.url.content=DistributionUrl is empty. The Maven bundled version will be used instead.
maven.wrapper.notification.empty.url.action.check=Check your distribution url.
maven.wrapper.notification.empty.url.action.disable=Disable maven wrapper in settings.
maven.wrapper.notification.empty.url.contant.file.not.found=File .mvn/wrapper/maven-wrapper.properties not found. The Maven bundled version will be used instead.
maven.wrapper.notification.downloading.start=Start downloading. Please wait.
maven.wrapper.notification.downloading.finish=Successfully installed.
maven.wrapper.notification.downloading.error.content={0}<br/>The Maven wrapper was disabled. The Maven bundled version will be used instead.
maven.wrapper.notification.downloading.error.action=Enable back Maven wrapper in settings/
build.event.title.error=Error
build.event.title.internal.server.error=Maven Server Error
importing.jdk.changed=JDK for importer was changed