IDEA-246851 - Add action to disable maven wrapper
authorAlexander Bubenchikov <alexander.bubenchikov@jetbrains.com>
Wed, 12 Aug 2020 15:20:23 +0000 (18:20 +0300)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Wed, 12 Aug 2020 15:25:54 +0000 (15:25 +0000)
GitOrigin-RevId: 4ed0094f0d1610e460558f9663b0deb358f79656

plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/MavenSyncConsole.kt
plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/UseWrapperAction.java [new file with mode: 0644]
plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerConnector.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenWrapperSupport.kt
plugins/maven/src/main/resources/META-INF/plugin.xml
plugins/maven/src/main/resources/messages/MavenProjectBundle.properties
plugins/maven/src/main/resources/messages/MavenSyncBundle.properties

index 473e781ef80e12b30d83a22fa3367914b9e75386..034a4b6cd1d64ede510ab1f9fc970e133d240fc8 100644 (file)
@@ -1,21 +1,22 @@
 // Copyright 2000-2019 JetBrains s.r.o. 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.buildtool
 
-import com.intellij.build.BuildContentDescriptor
-import com.intellij.build.BuildProgressListener
-import com.intellij.build.DefaultBuildDescriptor
-import com.intellij.build.FilePosition
+import com.intellij.build.*
 import com.intellij.build.events.EventResult
 import com.intellij.build.events.MessageEvent
 import com.intellij.build.events.MessageEventResult
 import com.intellij.build.events.impl.*
 import com.intellij.build.issue.BuildIssue
 import com.intellij.build.issue.BuildIssueQuickFix
+import com.intellij.build.process.BuildProcessHandler
 import com.intellij.icons.AllIcons
 import com.intellij.openapi.actionSystem.AnAction
 import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.components.ServiceManager
 import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
 import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
+import com.intellij.openapi.progress.EmptyProgressIndicator
+import com.intellij.openapi.progress.ProgressIndicator
 import com.intellij.openapi.project.Project
 import com.intellij.openapi.util.registry.Registry
 import com.intellij.openapi.util.text.StringUtil
@@ -35,6 +36,7 @@ import org.jetbrains.idea.maven.server.MavenServerProgressIndicator
 import org.jetbrains.idea.maven.utils.MavenLog
 import org.jetbrains.idea.maven.utils.MavenUtil
 import java.io.File
+import java.io.OutputStream
 import javax.swing.JComponent
 
 class MavenSyncConsole(private val myProject: Project) {
@@ -43,6 +45,7 @@ class MavenSyncConsole(private val myProject: Project) {
   private var mySyncId = ExternalSystemTaskId.create(MavenUtil.SYSTEM_ID, ExternalSystemTaskType.RESOLVE_PROJECT, myProject)
   private var finished = false
   private var started = false
+  private var wrapperProgressIndicator: WrapperProgressIndicator? = null
   private var hasErrors = false
   private var hasUnresolved = false
   private val JAVADOC_AND_SOURCE_CLASSIFIERS = setOf("javadoc", "sources", "test-javadoc", "test-sources")
@@ -71,23 +74,20 @@ class MavenSyncConsole(private val myProject: Project) {
     finished = false
     hasErrors = false
     hasUnresolved = false
-    mySyncId = ExternalSystemTaskId.create(MavenUtil.SYSTEM_ID, ExternalSystemTaskType.RESOLVE_PROJECT, myProject)
-    val descriptor = DefaultBuildDescriptor(mySyncId, SyncBundle.message("maven.sync.title"), myProject.basePath!!,
-                                            System.currentTimeMillis())
+    wrapperProgressIndicator = WrapperProgressIndicator()
     mySyncView = syncView
+    mySyncId = ExternalSystemTaskId.create(MavenUtil.SYSTEM_ID, ExternalSystemTaskType.RESOLVE_PROJECT, myProject)
     val runDescr = BuildContentDescriptor(null, null, object : JComponent() {}, SyncBundle.message("maven.sync.title"))
     runDescr.isActivateToolWindowWhenFailed = true
     runDescr.isActivateToolWindowWhenAdded = false
-    mySyncView.onEvent(mySyncId,
-                       StartBuildEventImpl(descriptor, SyncBundle.message("maven.sync.project.title", myProject.name))
-                         .withContentDescriptorSupplier
-                         {
-                           runDescr
-                         }.withRestartAction(restartAction))
-    debugLog("maven sync: started importing $myProject")
 
-    delayedActions.forEach { it() }
-    delayedActions.clear()
+    val descriptor = DefaultBuildDescriptor(mySyncId, SyncBundle.message("maven.sync.title"), myProject.basePath!!,
+                                            System.currentTimeMillis())
+      .withRestartAction(restartAction)
+      .withContentDescriptor{runDescr}
+
+    mySyncView.onEvent(mySyncId, StartBuildEventImpl(descriptor, SyncBundle.message("maven.sync.project.title", myProject.name)))
+    debugLog("maven sync: started importing $myProject")
   }
 
   @Synchronized
@@ -132,18 +132,46 @@ class MavenSyncConsole(private val myProject: Project) {
   }
 
   @Synchronized
-  fun startWrapperResolving() = delayUntilImportInProcess {
+  fun startWrapperResolving() {
+    if (!started || finished) {
+      startImport(ServiceManager.getService(myProject, SyncViewManager::class.java))
+    }
     startTask(mySyncId, SyncBundle.message("maven.sync.wrapper"))
   }
 
   @Synchronized
-  fun finishWrapperResolving(e: Throwable? = null) = delayUntilImportInProcess {
+  fun finishWrapperResolving(e: Throwable? = null) {
     if (e != null) {
       addWarning(SyncBundle.message("maven.sync.wrapper.failure"), e.localizedMessage)
     }
     completeTask(mySyncId, SyncBundle.message("maven.sync.wrapper"), SuccessResultImpl())
   }
 
+  fun progressIndicatorForWrapper(): ProgressIndicator {
+    return wrapperProgressIndicator ?: EmptyProgressIndicator()
+  }
+
+  inner class WrapperProgressIndicator : EmptyProgressIndicator() {
+    var myFraction: Long = 0
+    override fun setText(text: String) = doIfImportInProcess {
+      addText(SyncBundle.message("maven.sync.wrapper"), text, true)
+    }
+
+    override fun setFraction(fraction: Double) = doIfImportInProcess {
+      val newFraction = (fraction * 100).toLong()
+      if (myFraction == newFraction) return@doIfImportInProcess
+
+      mySyncView.onEvent(mySyncId,
+                         ProgressBuildEventImpl(SyncBundle.message("maven.sync.wrapper"), SyncBundle.message("maven.sync.wrapper"),
+                                                System.currentTimeMillis(),
+                                                SyncBundle.message("maven.sync.wrapper.dowloading"),
+                                                100,
+                                                (fraction * 100).toLong(),
+                                                "%"
+                         ))
+    }
+  }
+
   @Synchronized
   fun notifyReadingProblems(file: VirtualFile) = doIfImportInProcess {
     debugLog("reading problems in $file")
@@ -185,7 +213,7 @@ class MavenSyncConsole(private val myProject: Project) {
                                                       if (hasErrors) FailureResultImpl() else DerivedResultImpl()))
     val generalSettings = MavenWorkspaceSettingsComponent.getInstance(myProject).settings.generalSettings
     if (hasUnresolved && generalSettings.isWorkOffline) {
-      mySyncView.onEvent(mySyncId, BuildIssueEventImpl(mySyncId, object : BuildIssue{
+      mySyncView.onEvent(mySyncId, BuildIssueEventImpl(mySyncId, object : BuildIssue {
         override val title: String = "Dependency Resolution Failed"
         override val description: String = "<a href=\"${OffMavenOfflineModeQuickFix.ID}\">Switch Off Offline Mode</a>\n"
         override val quickFixes: List<BuildIssueQuickFix> = listOf(OffMavenOfflineModeQuickFix())
@@ -327,15 +355,6 @@ class MavenSyncConsole(private val myProject: Project) {
     action.invoke()
   }
 
-  private fun delayUntilImportInProcess(action: () -> Unit) {
-    if (!started || finished) {
-      delayedActions.add(action)
-    }
-    else {
-      action.invoke()
-    }
-  }
-
 
   private inner class ArtifactSyncListenerImpl(val keyPrefix: String) : ArtifactSyncListener {
     override fun downloadStarted(dependency: String) {
index bf6a9a795f9f8d106a3fb5ad1cdd537950fb4bcb..56f3dea8b7e269911a8c25b2a5370817ead6eb88 100644 (file)
@@ -510,12 +510,12 @@ public final class MavenProjectsManager extends MavenSimpleProjectComponent
 
       myWatcher.stop();
 
-      myReadingProcessor.stop();
-      myResolvingProcessor.stop();
-      myPluginsResolvingProcessor.stop();
-      myFoldersResolvingProcessor.stop();
-      myArtifactsDownloadingProcessor.stop();
-      myPostProcessor.stop();
+    myReadingProcessor.stop();
+    myResolvingProcessor.stop();
+    myPluginsResolvingProcessor.stop();
+    myFoldersResolvingProcessor.stop();
+    myArtifactsDownloadingProcessor.stop();
+    myPostProcessor.stop();
       mySaveQueue.flush();
 
       if (isUnitTestMode()) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/UseWrapperAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/UseWrapperAction.java
new file mode 100644 (file)
index 0000000..7305c73
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2000-2020 JetBrains s.r.o. 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.project.actions;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.ToggleAction;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+@ApiStatus.Experimental
+public class UseWrapperAction extends ToggleAction {
+  private final static String DISABLE_MAVEN_WRAPPER = "maven.wrapper.disable";
+
+  @Override
+  public boolean isSelected(@NotNull AnActionEvent e) {
+    return useWrapper();
+  }
+
+  @Override
+  public void setSelected(@NotNull AnActionEvent e, boolean state) {
+    setSelected(state);
+  }
+
+  public static boolean useWrapper() {
+    return !PropertiesComponent.getInstance().getBoolean(DISABLE_MAVEN_WRAPPER);
+  }
+
+  public static void setSelected(boolean state) {
+    PropertiesComponent.getInstance().setValue(DISABLE_MAVEN_WRAPPER, !state);
+  }
+}
index 1a5b54d85e475e69b151cbb9edb57eb149965172..b377bbb9a4419144560bd380ee76a808789167a0 100644 (file)
@@ -2,6 +2,7 @@
 package org.jetbrains.idea.maven.server;
 
 import com.intellij.openapi.Disposable;
+import com.intellij.openapi.progress.EmptyProgressIndicator;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.util.text.StringUtil;
@@ -125,7 +126,7 @@ public class MavenServerConnector implements @NotNull Disposable {
       try {
 
         console.startWrapperResolving();
-        MavenDistribution distribution = new MavenWrapperSupport().downloadAndInstallMaven(distributionUrl);
+        MavenDistribution distribution = new MavenWrapperSupport().downloadAndInstallMaven(distributionUrl, console.progressIndicatorForWrapper());
         console.finishWrapperResolving(null);
         return distribution;
       }
index 0c2f8a725fcca01d99d5584982bf20bf0be3f558..8436249657c286076760fb071a624ce1d869f72b 100644 (file)
@@ -345,6 +345,7 @@ public final class MavenServerManager implements Disposable {
                                              final boolean alwaysOnline,
                                              @Nullable String workingDirectory,
                                              @Nullable String multiModuleProjectDirectory) {
+
     return new MavenEmbedderWrapper(null) {
       @NotNull
       @Override
index c0341849338362eff5f7e3cbbea357c085c4b70a..02c4758e17f1631a31a3f256c4310bbff8094770 100644 (file)
@@ -2,6 +2,7 @@
 package org.jetbrains.idea.maven.server
 
 import com.intellij.openapi.components.*
+import com.intellij.openapi.progress.ProgressIndicator
 import com.intellij.openapi.util.SystemInfo
 import com.intellij.openapi.util.io.FileUtil
 import com.intellij.openapi.util.io.StreamUtil
@@ -52,7 +53,7 @@ class MavenWrapperSupport {
   val DISTS_DIR = "wrapper/dists"
 
   @Throws(IOException::class)
-  fun downloadAndInstallMaven(urlString: String): MavenDistribution {
+  fun downloadAndInstallMaven(urlString: String, indicator: ProgressIndicator?): MavenDistribution {
     val cachedHome = myMapping.myState.mapping.get(urlString)
     if (cachedHome != null) {
       val file = File(cachedHome)
@@ -64,29 +65,29 @@ class MavenWrapperSupport {
       }
     }
 
-
     val zipFile = getZipFile(urlString)
     if (!zipFile.isFile) {
       val partFile = File(zipFile.parentFile, "${zipFile.name}.part-${System.currentTimeMillis()}")
+      indicator?.apply { text = SyncBundle.message("maven.sync.wrapper.dowloading.from", urlString) }
       HttpRequests.request(urlString)
         .forceHttps(true)
         .connectTimeout(30_000)
         .readTimeout(30_000)
-        .saveToFile(partFile, null) //todo: cancel and progress
+        .saveToFile(partFile, indicator)
       FileUtil.rename(partFile, zipFile)
     }
     if (!zipFile.isFile) {
       throw RuntimeException(SyncBundle.message("cannot.download.zip.from", urlString))
     }
-    val home = unpackZipFile(zipFile).canonicalFile
+    val home = unpackZipFile(zipFile, indicator).canonicalFile
     myMapping.myState.mapping[urlString] = home.absolutePath
     return MavenDistribution(home, urlString)
 
   }
 
 
-  private fun unpackZipFile(zipFile: File): File {
-    unzip(zipFile)
+  private fun unpackZipFile(zipFile: File, indicator: ProgressIndicator?): File {
+    unzip(zipFile, indicator)
     val dirs = zipFile.parentFile.listFiles { it -> it.isDirectory }
     if (dirs == null || dirs.size != 1) {
       MavenLog.LOG.warn("Expected exactly 1 top level dir in Maven distribution, found: " + dirs?.asList())
@@ -105,7 +106,8 @@ class MavenWrapperSupport {
     Files.setPosixFilePermissions(mvnExe.toPath(), permissions)
   }
 
-  private fun unzip(zip: File) {
+  private fun unzip(zip: File, indicator: ProgressIndicator?) {
+    indicator?.apply { text = SyncBundle.message("maven.sync.wrapper.unpacking") }
     val unpackDir = zip.parentFile
     val destinationCanonicalPath = unpackDir.canonicalPath
     var errorUnpacking = false
@@ -134,9 +136,11 @@ class MavenWrapperSupport {
 
       }
       errorUnpacking = false
+      indicator?.apply { text = SyncBundle.message("maven.sync.wrapper.unpacked.into", destinationCanonicalPath) }
     }
     finally {
       if (errorUnpacking) {
+        indicator?.apply { text = SyncBundle.message("maven.sync.wrapper.failure") }
         zip.parentFile.listFiles { it -> it.name != zip.name }?.forEach { FileUtil.delete(it) }
       }
     }
index 4815454a1ae985fb21ca6666a811971728151dbb..019ac98da778419b97537bcce869f46a5499a5dc 100644 (file)
             class="org.jetbrains.idea.maven.project.actions.LookForNestedToggleAction">
     </action>
 
+    <action id="Maven.UseWrapperAction"
+            class="org.jetbrains.idea.maven.project.actions.UseWrapperAction">
+    </action>
+
     <action id="Maven.ToggleSkipTests"
             class="org.jetbrains.idea.maven.project.actions.ToggleSkipTestsAction"
             icon="AllIcons.Nodes.ExceptionClass">
index 1eebbd43c1ebccff3d7ff07e646e6396b6aaefde..6cf0ee782fa01704868c37bf57e6e65662f075fc 100644 (file)
@@ -171,6 +171,8 @@ action.Maven.ToggleOffline.text=Toggle Offline Mode
 action.Maven.ToggleOffline.description=Toggle offline mode for Maven builds
 action.Maven.ToggleLookNested.text=Toggle Search For Maven Project Recursively
 action.Maven.ToggleLookNested.description=Toggle Search for project recursively when importing Maven projects
+action.Maven.UseWrapperAction.text=Use maven wrapper detection
+action.Maven.UseWrapperAction.description=If switched off, Maven wrapper configured in .mvn/wrapper will not be used
 action.Maven.ToggleSkipTests.text=Toggle 'Skip Tests' Mode
 action.Maven.ToggleSkipTests.description=Toggle 'Skip tests' mode for Maven builds
 action.Maven.ExpandAll.text=Expand All
index 9e9f7134a82f3b4fa0668f190d9a4b3c67918b35..dd2073e4fec399e4abcbce8ad1a6e6187f8dbf10 100644 (file)
@@ -42,3 +42,7 @@ cannot.resolve.maven.home=Cannot resolve Maven home
 is.not.correct.maven.home.reverting.to.embedded={0}is not correct maven home, reverting to embedded
 cannot.download.zip.from=Cannot download ZIP distribution from {0}. Please check distributionUrl
 zip.is.not.correct=Zip archive at {0} is not correct Maven distribution. Please check distributionUrl
+maven.sync.wrapper.unpacking=Unpacking archive...
+maven.sync.wrapper.unpacked.into=Maven wrapper unpacked into {0}
+maven.sync.wrapper.dowloading.from=Downloading maven wrapper from {0}
+maven.sync.wrapper.dowloading=Downloading maven wrapper