diff --git a/plugins/maven/intellij.maven.iml b/plugins/maven/intellij.maven.iml
index d06b2bf492e0..ed23a2c5c07c 100644
--- a/plugins/maven/intellij.maven.iml
+++ b/plugins/maven/intellij.maven.iml
@@ -68,6 +68,9 @@
+
+
+
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicator.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicator.java
index a455759a3050..6fe31f32d1cb 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicator.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicator.java
@@ -19,8 +19,12 @@ import java.rmi.Remote;
import java.rmi.RemoteException;
public interface MavenServerProgressIndicator extends Remote {
+ String DEPENDENCIES_RESOLVE_PREFIX = "Resolving Maven dependencies--";
+ String PLUGINS_RESOLVE_PREFIX = "Downloading Maven plugins--";
void setText(String text) throws RemoteException;
void setText2(String text) throws RemoteException;
+ void startTask(String text) throws RemoteException;
+ void completeTask(String text, String errorMessage) throws RemoteException;
boolean isCanceled() throws RemoteException;
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicatorWrapper.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicatorWrapper.java
index ba026247a29a..c385bf6b65c2 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicatorWrapper.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerProgressIndicatorWrapper.java
@@ -78,4 +78,14 @@ public class MavenServerProgressIndicatorWrapper implements MavenServerProgressI
public void setFraction(double fraction) throws RemoteException {
myDelegate.setFraction(fraction);
}
+
+ @Override
+ public void startTask(String text) throws RemoteException {
+ myDelegate.startTask(text);
+ }
+
+ @Override
+ public void completeTask(String text, String errorMessage) throws RemoteException {
+ myDelegate.completeTask(text, errorMessage);
+ }
}
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java
index afc78cebf0af..b01be54a3410 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java
@@ -24,6 +24,8 @@ import org.eclipse.aether.transfer.TransferResource;
import java.io.File;
import java.rmi.RemoteException;
+import static org.jetbrains.idea.maven.server.MavenServerProgressIndicator.DEPENDENCIES_RESOLVE_PREFIX;
+
public class TransferListenerAdapter implements TransferListener {
protected final MavenServerProgressIndicator myIndicator;
@@ -51,6 +53,13 @@ public class TransferListenerAdapter implements TransferListener {
public void transferInitiated(TransferEvent event) {
checkCanceled();
+ try {
+ myIndicator.startTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event));
+ }
+ catch (RemoteException e) {
+ throw new RuntimeRemoteException(e);
+ }
+
try {
myIndicator.setIndeterminate(true);
myIndicator.setText2(formatResourceName(event));
@@ -100,6 +109,7 @@ public class TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Checksum failed: " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), "Checksum failed");
}
catch (RemoteException e) {
throw new RuntimeRemoteException(e);
@@ -111,6 +121,7 @@ public class TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Finished (" + StringUtilRt.formatFileSize(event.getTransferredBytes()) + ") " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), null);
Maven3ServerGlobals.getDownloadListener().artifactDownloaded(event.getResource().getFile(), event.getResource().getResourceName());
}
@@ -124,6 +135,7 @@ public class TransferListenerAdapter implements TransferListener {
try {
if (myIndicator.isCanceled()) {
myIndicator.setText2("Canceling...");
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), "Cancelled");
return; // Don't throw exception here.
}
}
@@ -134,6 +146,12 @@ public class TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Failed to download " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ String message = "Failed to download";
+ if(event.getException()!=null) {
+ message += ": " + event.getException().getMessage();
+ }
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), message);
+
}
catch (RemoteException e) {
throw new RuntimeRemoteException(e);
diff --git a/plugins/maven/maven30-server-impl/src/org/jetbrains/idea/maven/server/Maven30TransferListenerAdapter.java b/plugins/maven/maven30-server-impl/src/org/jetbrains/idea/maven/server/Maven30TransferListenerAdapter.java
index d1652c6d8d4c..b1bf2e9f7844 100644
--- a/plugins/maven/maven30-server-impl/src/org/jetbrains/idea/maven/server/Maven30TransferListenerAdapter.java
+++ b/plugins/maven/maven30-server-impl/src/org/jetbrains/idea/maven/server/Maven30TransferListenerAdapter.java
@@ -24,6 +24,8 @@ import org.sonatype.aether.transfer.TransferResource;
import java.io.File;
import java.rmi.RemoteException;
+import static org.jetbrains.idea.maven.server.MavenServerProgressIndicator.DEPENDENCIES_RESOLVE_PREFIX;
+
/**
* @author Sergey Evdokimov
*/
@@ -54,6 +56,13 @@ public class Maven30TransferListenerAdapter implements TransferListener {
public void transferInitiated(TransferEvent event) {
checkCanceled();
+ try {
+ myIndicator.startTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event));
+ }
+ catch (RemoteException e) {
+ throw new RuntimeRemoteException(e);
+ }
+
try {
myIndicator.setIndeterminate(true);
myIndicator.setText2(formatResourceName(event));
@@ -103,6 +112,7 @@ public class Maven30TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Checksum failed: " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), "Checksum failed");
}
catch (RemoteException e) {
throw new RuntimeRemoteException(e);
@@ -114,6 +124,9 @@ public class Maven30TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Finished (" + StringUtilRt.formatFileSize(event.getTransferredBytes()) + ") " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), null);
+
+ Maven3ServerGlobals.getDownloadListener().artifactDownloaded(event.getResource().getFile(), event.getResource().getResourceName());
}
catch (RemoteException e) {
throw new RuntimeRemoteException(e);
@@ -125,6 +138,7 @@ public class Maven30TransferListenerAdapter implements TransferListener {
try {
if (myIndicator.isCanceled()) {
myIndicator.setText2("Canceling...");
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), "Cancelled");
return; // Don't throw exception here.
}
}
@@ -135,6 +149,12 @@ public class Maven30TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Failed to download " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ String message = "Failed to download";
+ if(event.getException()!=null) {
+ message += ": " + event.getException().getMessage();
+ }
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), message);
+
}
catch (RemoteException e) {
throw new RuntimeRemoteException(e);
diff --git a/plugins/maven/maven36-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java b/plugins/maven/maven36-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java
index afc78cebf0af..b01be54a3410 100644
--- a/plugins/maven/maven36-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java
+++ b/plugins/maven/maven36-server-impl/src/org/jetbrains/idea/maven/server/TransferListenerAdapter.java
@@ -24,6 +24,8 @@ import org.eclipse.aether.transfer.TransferResource;
import java.io.File;
import java.rmi.RemoteException;
+import static org.jetbrains.idea.maven.server.MavenServerProgressIndicator.DEPENDENCIES_RESOLVE_PREFIX;
+
public class TransferListenerAdapter implements TransferListener {
protected final MavenServerProgressIndicator myIndicator;
@@ -51,6 +53,13 @@ public class TransferListenerAdapter implements TransferListener {
public void transferInitiated(TransferEvent event) {
checkCanceled();
+ try {
+ myIndicator.startTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event));
+ }
+ catch (RemoteException e) {
+ throw new RuntimeRemoteException(e);
+ }
+
try {
myIndicator.setIndeterminate(true);
myIndicator.setText2(formatResourceName(event));
@@ -100,6 +109,7 @@ public class TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Checksum failed: " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), "Checksum failed");
}
catch (RemoteException e) {
throw new RuntimeRemoteException(e);
@@ -111,6 +121,7 @@ public class TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Finished (" + StringUtilRt.formatFileSize(event.getTransferredBytes()) + ") " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), null);
Maven3ServerGlobals.getDownloadListener().artifactDownloaded(event.getResource().getFile(), event.getResource().getResourceName());
}
@@ -124,6 +135,7 @@ public class TransferListenerAdapter implements TransferListener {
try {
if (myIndicator.isCanceled()) {
myIndicator.setText2("Canceling...");
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), "Cancelled");
return; // Don't throw exception here.
}
}
@@ -134,6 +146,12 @@ public class TransferListenerAdapter implements TransferListener {
try {
myIndicator.setText2("Failed to download " + formatResourceName(event));
myIndicator.setIndeterminate(true);
+ String message = "Failed to download";
+ if(event.getException()!=null) {
+ message += ": " + event.getException().getMessage();
+ }
+ myIndicator.completeTask(DEPENDENCIES_RESOLVE_PREFIX + formatResourceName(event), message);
+
}
catch (RemoteException e) {
throw new RuntimeRemoteException(e);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/MavenSyncConsole.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/MavenSyncConsole.kt
new file mode 100644
index 000000000000..3ce91c5a5b65
--- /dev/null
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/MavenSyncConsole.kt
@@ -0,0 +1,206 @@
+// 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.BuildProgressListener
+import com.intellij.build.DefaultBuildDescriptor
+import com.intellij.build.SyncViewManager
+import com.intellij.build.events.EventResult
+import com.intellij.build.events.Failure
+import com.intellij.build.events.impl.*
+import com.intellij.openapi.application.ApplicationManager
+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.project.Project
+import com.intellij.openapi.util.Ref
+import com.intellij.openapi.util.text.StringUtil
+import org.jetbrains.annotations.TestOnly
+import org.jetbrains.idea.maven.utils.MavenUtil
+
+
+class MavenSyncConsole(private val myProject: Project) {
+ private lateinit var mySyncView: BuildProgressListener
+ private lateinit var myTaskId: ExternalSystemTaskId
+ private var finished = false
+ private var started = false
+
+ private lateinit var myFailuresMap: LinkedHashMap>
+ private lateinit var myStartedSet: HashSet
+ private var tasksRunning: Int = 0
+
+
+ @Synchronized
+ fun startImport() {
+ if(started){
+ return
+ }
+ finished = false
+ started = true
+ myStartedSet = HashSet()
+ myFailuresMap = LinkedHashMap()
+ tasksRunning = 0
+
+
+ myTaskId = ExternalSystemTaskId.create(MavenUtil.SYSTEM_ID, ExternalSystemTaskType.RESOLVE_PROJECT, myProject)
+ val descriptor = DefaultBuildDescriptor(myTaskId, "Sync", myProject.basePath!!, System.currentTimeMillis())
+ val result = Ref()
+ ApplicationManager.getApplication().invokeAndWait { result.set(ServiceManager.getService(myProject, SyncViewManager::class.java)) }
+ mySyncView = result.get()
+ mySyncView.onEvent(StartBuildEventImpl(descriptor, "Sync ${myProject.name}"))
+ debugLog("maven sync: started importing $myProject")
+ }
+
+
+ @Synchronized
+ fun addText(text: String) {
+ addText(text, true)
+ }
+
+ @Synchronized
+ fun addText(text: String, stdout: Boolean) {
+ if(!started) return
+ if (StringUtil.isEmpty(text) || finished) {
+ return
+ }
+ //println("Maven sync: print $text into $parentId")
+ mySyncView.onEvent(OutputBuildEventImpl(myTaskId, "$text\n", stdout))
+ }
+
+
+ @Synchronized
+ fun finishImport() {
+ debugLog("Maven sync: finishImport")
+ finished = true
+ tryFinish()
+ }
+
+ @Synchronized
+ fun startTask(taskName: String) {
+ debugLog("Maven sync: start $taskName $tasksRunning")
+ if (finished||!started) {
+ return
+ }
+ tasksRunning += 1
+ val title = getTitle(taskName)
+ val parentId = extractParent(taskName)
+ myStartedSet.add(taskName.trim('.'))
+ mySyncView.onEvent(StartEventImpl(title, parentId, System.currentTimeMillis(), title))
+ }
+
+
+ @Synchronized
+ fun completeTask(taskName: String) {
+ debugLog("Maven sync: complete $taskName $tasksRunning")
+ if(!started || !myStartedSet.contains(taskName.trim('.'))) return
+
+ val title = getTitle(taskName)
+ val parentId = extractParent(taskName)
+ val result = eventResult(title)
+ mySyncView.onEvent(FinishEventImpl(title, parentId, System.currentTimeMillis(), title, result))
+ tasksRunning -= 1
+ tryFinish()
+ }
+
+
+ @Synchronized
+ fun completeTask(taskName: String, e: Throwable) {
+ debugLog("Maven sync: complete $taskName $tasksRunning with $e")
+ if(!started || !myStartedSet.contains(taskName.trim('.'))) return
+ val title = getTitle(taskName)
+ val parentId = extractParent(taskName)
+ updateErrorStackAbove(e, taskName)
+ mySyncView.onEvent(FinishEventImpl(title, parentId, System.currentTimeMillis(), title, FailureResultImpl(e)))
+ tasksRunning -= 1
+ tryFinish()
+ }
+
+ @Synchronized
+ fun addRootError(e: Throwable) {
+ if(!started) return
+ addRootError(e.message?:"", e)
+ }
+ @Synchronized
+ fun addRootError(message: String, e: Throwable) {
+ addText(message, false)
+ myFailuresMap.compute("Sync") { _, list -> add(list, FailureImpl(message, e)) }
+
+ }
+
+ private fun updateErrorStackAbove(e: Throwable, taskName: String) {
+ taskName.splitToSequence("/").forEach {
+ myFailuresMap.compute(it) { _, list -> add(list, FailureImpl(e.message, e)) }
+ }
+ myFailuresMap.compute("Sync") { _, list -> add(list, FailureImpl(e.message, e)) }
+ }
+
+ private fun add(list: ArrayList?, failure: Failure): ArrayList {
+ if (list == null) {
+ return arrayListOf(failure)
+ }
+ else {
+ list.add(failure)
+ return list
+ }
+ }
+
+ private fun tryFinish() {
+ if (!finished || tasksRunning > 0) {
+ return
+ }
+ val result = eventResult("Sync")
+ mySyncView
+ .onEvent(FinishBuildEventImpl(myTaskId, null, System.currentTimeMillis(), "Sync Complete", result))
+ started = false
+ }
+
+
+ private fun eventResult(title: String): EventResult {
+ val failures = myFailuresMap[title]
+ val result = if (failures != null) FailureResultImpl(failures) else SuccessResultImpl(false)
+ return result
+ }
+
+ private fun extractParent(taskName: String): Any {
+ val parent = taskName.split("--").map { it.trimEnd('.') }.dropLast(1).joinToString("/")
+ return if (parent.isBlank()) myTaskId else parent
+ }
+
+ private fun getTitle(taskName: String): String {
+ return taskName.split("--").last().trimEnd('.')
+ }
+
+ private fun debugLog(text: String) {
+ println(text)
+ }
+
+ @TestOnly
+ fun isFinished(): Boolean {
+ return finished
+ }
+
+ @TestOnly
+ fun runningProcesses() : Int{
+ return tasksRunning
+ }
+
+ @TestOnly
+ fun getErrors(): ArrayList? {
+ return myFailuresMap["Sync"]
+ }
+
+ @TestOnly
+ fun getErrors(key: String): ArrayList? {
+ return myFailuresMap[key]
+ }
+
+ @TestOnly
+ fun started(key: String): Boolean{
+ return myStartedSet.contains(key.trim('.'))
+ }
+
+ companion object {
+ const val PLUGINS_RESOLVE_PREFIX = "Downloading Maven plugins--"
+ }
+
+
+}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
index 31caba992a39..0600195763c3 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
@@ -59,6 +59,7 @@ import org.jetbrains.idea.maven.project.MavenGeneralSettings;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.server.MavenServerUtil;
+import org.jetbrains.idea.maven.utils.MavenLog;
import org.jetbrains.idea.maven.utils.MavenSettings;
import org.jetbrains.idea.maven.utils.MavenUtil;
@@ -126,6 +127,9 @@ public class MavenExternalParameters {
final String mavenHome = resolveMavenHome(coreSettings, project, runConfiguration);
final String mavenVersion = MavenUtil.getMavenVersion(mavenHome);
+ if(mavenVersion == null) {
+ throw new ExecutionException("Cannot run maven: Maven home " + mavenHome + " looks incorrect");
+ }
String sdkConfigLocation = "Settings | Build, Execution, Deployment | Build Tools | Maven | Runner | JRE";
verifyMavenSdkRequirements(jdk, mavenVersion, sdkConfigLocation);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java
index b8acf438e710..3424ca9a1076 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java
@@ -167,9 +167,7 @@ public class MavenIndicesManager implements Disposable {
MavenIndices indicesObjectCache = getIndicesObject();
try {
- MavenIndex localIndex = indicesObjectCache.add(LOCAL_REPOSITORY_ID, localRepository.getPath(), MavenIndex.Kind.LOCAL);
- scheduleUpdate(project, Collections.singletonList(localIndex));
- return localIndex;
+ return indicesObjectCache.add(LOCAL_REPOSITORY_ID, localRepository.getPath(), MavenIndex.Kind.LOCAL);
}
catch (MavenIndexException e) {
MavenLog.LOG.warn(e);
@@ -236,7 +234,7 @@ public class MavenIndicesManager implements Disposable {
public void run(@NotNull ProgressIndicator indicator) {
try {
indicator.setIndeterminate(false);
- doUpdateIndices(projectOrNull, toSchedule, fullUpdate, new MavenProgressIndicator(indicator));
+ doUpdateIndices(projectOrNull, toSchedule, fullUpdate, new MavenProgressIndicator(indicator,null));
}
catch (MavenProcessCanceledException ignore) {
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
index dfb1cfc86b39..ad4e0dd041d5 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
@@ -694,6 +694,7 @@ public class MavenProject {
Collections.singleton(getFile()),
getActivatedProfilesIds(),
locator);
+ MavenUtil.notifySyncForUnresolved(project, results);
final MavenProjectReaderResult result = results.iterator().next();
MavenProjectChanges changes = set(result, generalSettings, false, result.readingProblems.isEmpty(), false);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
index 11b393ba0850..9090cdab7b20 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
@@ -46,6 +46,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.concurrency.AsyncPromise;
import org.jetbrains.concurrency.Promise;
+import org.jetbrains.idea.maven.buildtool.MavenSyncConsole;
import org.jetbrains.idea.maven.importing.MavenFoldersImporter;
import org.jetbrains.idea.maven.importing.MavenPomPathModuleService;
import org.jetbrains.idea.maven.importing.MavenProjectImporter;
@@ -106,6 +107,7 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
private MavenWorkspaceSettings myWorkspaceSettings;
+ private MavenSyncConsole mySyncConsole;
private final MavenMergingUpdateQueue mySaveQueue;
private static final int SAVE_DELAY = 1000;
@@ -284,6 +286,13 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
}
}
+ public synchronized MavenSyncConsole getSyncConsole() {
+ if (mySyncConsole == null) {
+ mySyncConsole = new MavenSyncConsole(myProject);
+ }
+ return mySyncConsole;
+ }
+
private void initProjectsTree(boolean tryToLoadExisting) {
if (tryToLoadExisting) {
Path file = getProjectsTreeFile();
@@ -359,7 +368,7 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
new MavenProjectsManagerWatcher(myProject, this, myProjectsTree, getGeneralSettings(), myReadingProcessor, myEmbeddersManager);
myImportingQueue = new MavenMergingUpdateQueue(getComponentName() + ": Importing queue", IMPORT_DELAY, !isUnitTestMode(), myProject);
- myImportingQueue.setPassThrough(false);
+ myImportingQueue.setPassThrough(ApplicationManager.getApplication().isUnitTestMode());
myImportingQueue.makeUserAware(myProject);
myImportingQueue.makeDumbAware(myProject);
@@ -833,9 +842,12 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
* if project is closed)
*/
public Promise> scheduleImportAndResolve() {
+ getSyncConsole().startImport();
AsyncPromise> promise = scheduleResolve();// scheduleImport will be called after the scheduleResolve process has finished
fireImportAndResolveScheduled();
- return promise;
+ return promise
+ .onError(t -> getSyncConsole().addRootError(t))
+ .onProcessed(modules -> getSyncConsole().finishImport());
}
private AsyncPromise> scheduleResolve() {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
index 2046e14eb85f..7dcfe45a7bb4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
@@ -47,6 +47,7 @@ import org.jdom.output.XMLOutputter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.idea.maven.buildtool.MavenSyncConsole;
import org.jetbrains.idea.maven.dom.references.MavenFilteredPropertyPsiReferenceProvider;
import org.jetbrains.idea.maven.execution.RunnerBundle;
import org.jetbrains.idea.maven.importing.MavenImporter;
@@ -66,6 +67,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
+
public class MavenProjectsTree {
private static final Logger LOG = Logger.getInstance(MavenProjectsTree.class);
@@ -535,7 +537,6 @@ public class MavenProjectsTree {
return;
}
updateStack.push(mavenProject);
-
process.setText(ProjectBundle.message("maven.reading.pom", mavenProject.getPath()));
process.setText2("");
@@ -1281,6 +1282,7 @@ public class MavenProjectsTree {
if (FileUtil.pathsEqual(mavenProject.getDirectory(), cause.getDirectory())) {
showNotificationInvalidConfig(project, mavenProject, cause.getMessage());
mavenProject.setConfigFileError(cause.getMessage());
+ MavenProjectsManager.getInstance(myProject).getSyncConsole().addRootError(RunnerBundle.message("maven.invalid.config.file", cause.getMessage()), cause);
}
}
}
@@ -1354,6 +1356,7 @@ public class MavenProjectsTree {
Collection results = new MavenProjectReader(project).resolveProject(
generalSettings, embedder, files, explicitProfiles, myProjectLocator);
+ MavenUtil.notifySyncForUnresolved(project, results);
for (MavenProjectReaderResult result : results) {
MavenProject mavenProjectCandidate = null;
for (MavenProject mavenProject : mavenProjects) {
@@ -1404,6 +1407,11 @@ public class MavenProjectsTree {
filesToRefresh.add(pluginDir); // Refresh both *.pom and *.jar files.
}
}
+ if(artifacts.isEmpty()) {
+ process.startTask(MavenSyncConsole.PLUGINS_RESOLVE_PREFIX + each.getMavenId());
+ process.completeTask(MavenSyncConsole.PLUGINS_RESOLVE_PREFIX + each.getMavenId(), "Cannot Resolve plugin");
+ }
+
}
mavenProject.resetCache();
@@ -1605,7 +1613,10 @@ public class MavenProjectsTree {
}
public void fireUpdatedIfNecessary() {
- if (updatedProjectsWithChanges.isEmpty() && deletedProjects.isEmpty()) return;
+ if (updatedProjectsWithChanges.isEmpty() && deletedProjects.isEmpty()) {
+ //MavenProjectsManager.getInstance(myProject).getSyncConsole().finishImport();
+ return;
+ }
List mavenProjects = deletedProjects.isEmpty()
? Collections.emptyList()
: new ArrayList<>(deletedProjects);
@@ -1755,7 +1766,7 @@ public class MavenProjectsTree {
}
default void projectResolved(@NotNull Pair projectWithChanges,
- @Nullable NativeMavenProjectHolder nativeMavenProject) {
+ @Nullable NativeMavenProjectHolder nativeMavenProject) {
}
default void pluginsResolved(@NotNull MavenProject project) {
@@ -1778,8 +1789,8 @@ public class MavenProjectsTree {
@Override
public boolean equals(MavenCoordinate o1, MavenCoordinate o2) {
return Comparing.equal(o1.getArtifactId(), o2.getArtifactId())
- && Comparing.equal(o1.getVersion(), o2.getVersion())
- && Comparing.equal(o1.getGroupId(), o2.getGroupId());
+ && Comparing.equal(o1.getVersion(), o2.getVersion())
+ && Comparing.equal(o1.getGroupId(), o2.getGroupId());
}
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
index 78ad8212e692..66352292f802 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
@@ -619,6 +619,16 @@ public class MavenServerManager extends RemoteObjectWrapper impleme
myProcess.setText2(text);
}
+ @Override
+ public void startTask(String text) throws RemoteException {
+ myProcess.startTask(text);
+ }
+
+ @Override
+ public void completeTask(String text, String errorMessage) throws RemoteException {
+ myProcess.completeTask(text, errorMessage);
+ }
+
@Override
public boolean isCanceled() {
return myProcess.isCanceled();
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenProgressIndicator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenProgressIndicator.java
index 9fa525bb9d85..00fcd2d6b9c4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenProgressIndicator.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenProgressIndicator.java
@@ -15,27 +15,39 @@
*/
package org.jetbrains.idea.maven.utils;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.TaskInfo;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.buildtool.MavenSyncConsole;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Supplier;
public class MavenProgressIndicator {
private ProgressIndicator myIndicator;
private final List> myCancelConditions = new ArrayList<>();
+ private final Supplier mySyncSupplier;
- public MavenProgressIndicator() {
- this(new MyEmptyProgressIndicator());
+ public MavenProgressIndicator(Supplier syncSupplier) {
+ this(new MyEmptyProgressIndicator(), syncSupplier);
}
- public MavenProgressIndicator(ProgressIndicator i) {
+ public MavenProgressIndicator(ProgressIndicator i,
+ Supplier syncSupplier) {
+
myIndicator = i;
+ mySyncSupplier = syncSupplier;
}
public synchronized void setIndicator(ProgressIndicator i) {
+ //setIndicatorStatus(i);
i.setText(myIndicator.getText());
i.setText2(myIndicator.getText2());
if (!i.isIndeterminate()) {
@@ -51,10 +63,17 @@ public class MavenProgressIndicator {
public synchronized void setText(String text) {
myIndicator.setText(text);
+ if (mySyncSupplier != null) {
+ mySyncSupplier.get().addText(text);
+ }
+
}
public synchronized void setText2(String text) {
myIndicator.setText2(text);
+ if (mySyncSupplier != null) {
+ mySyncSupplier.get().addText(text);
+ }
}
public synchronized void setFraction(double fraction) {
@@ -102,6 +121,23 @@ public class MavenProgressIndicator {
if (isCanceled()) throw new ProcessCanceledException();
}
+ public void startTask(String text) {
+ if (mySyncSupplier != null) {
+ mySyncSupplier.get().startTask(text);
+ }
+ }
+
+ public void completeTask(String text, String message) {
+ if (mySyncSupplier != null) {
+ if (message == null) {
+ mySyncSupplier.get().completeTask(text);
+ }
+ else {
+ mySyncSupplier.get().completeTask(text, new RuntimeException(message));
+ }
+ }
+ }
+
private static class MyEmptyProgressIndicator extends EmptyProgressIndicator {
private String myText;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java
index 4e0a50ab3e79..7b7cb7374c93 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java
@@ -52,11 +52,14 @@ import icons.MavenIcons;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.buildtool.MavenSyncConsole;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
+import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenConstants;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.model.MavenPlugin;
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.server.MavenServerManager;
import org.jetbrains.idea.maven.server.MavenServerUtil;
@@ -84,6 +87,7 @@ import static com.intellij.openapi.util.io.JarUtil.getJarAttribute;
import static com.intellij.openapi.util.io.JarUtil.loadProperties;
import static com.intellij.openapi.util.text.StringUtil.*;
import static com.intellij.util.xml.NanoXmlBuilder.stop;
+import static org.jetbrains.idea.maven.server.MavenServerProgressIndicator.DEPENDENCIES_RESOLVE_PREFIX;
public class MavenUtil {
@ApiStatus.Experimental
@@ -414,7 +418,8 @@ public class MavenUtil {
return true;
}
- public static void run(Project project, String title, final MavenTask task) throws MavenProcessCanceledException {
+ public static void run(Project project, String title, final MavenTask task)
+ throws MavenProcessCanceledException {
final Exception[] canceledEx = new Exception[1];
final RuntimeException[] runtimeEx = new RuntimeException[1];
final Error[] errorEx = new Error[1];
@@ -423,7 +428,7 @@ public class MavenUtil {
@Override
public void run(@NotNull ProgressIndicator i) {
try {
- task.run(new MavenProgressIndicator(i));
+ task.run(new MavenProgressIndicator(i, null));
}
catch (MavenProcessCanceledException | ProcessCanceledException e) {
canceledEx[0] = e;
@@ -447,15 +452,20 @@ public class MavenUtil {
final String title,
final boolean cancellable,
final MavenTask task) {
- final MavenProgressIndicator indicator = new MavenProgressIndicator();
+ MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
+
+ final MavenProgressIndicator indicator = new MavenProgressIndicator(manager::getSyncConsole);
Runnable runnable = () -> {
if (project.isDisposed()) return;
try {
+ manager.getSyncConsole().startTask(title);
task.run(indicator);
+ manager.getSyncConsole().completeTask(title);
}
- catch (MavenProcessCanceledException | ProcessCanceledException ignore) {
+ catch (MavenProcessCanceledException | ProcessCanceledException e) {
+ manager.getSyncConsole().completeTask(title, e);
indicator.cancel();
}
};
@@ -637,6 +647,7 @@ public class MavenUtil {
}
}
}
+ MavenLog.LOG.warn("Cannot resolve maven version for " + mavenHome);
return null;
}
@@ -792,6 +803,29 @@ public class MavenUtil {
return res;
}
+ public static void notifySyncForUnresolved(@NotNull Project project, @NotNull Collection results) {
+ Set unresolvedIds = new HashSet<>();
+ for (MavenProjectReaderResult result : results) {
+ if (result.mavenModel.getDependencies() != null) {
+ for (MavenArtifact artifact : result.mavenModel.getDependencies()) {
+ if (!artifact.isResolved()) {
+ unresolvedIds.add(artifact.getMavenId());
+ }
+ }
+ }
+ }
+
+ if (unresolvedIds.isEmpty()) {
+ return;
+ }
+
+ MavenSyncConsole syncConsole = MavenProjectsManager.getInstance(project).getSyncConsole();
+ for (MavenId id : unresolvedIds) {
+ syncConsole.startTask(DEPENDENCIES_RESOLVE_PREFIX + id.getKey());
+ syncConsole.completeTask(DEPENDENCIES_RESOLVE_PREFIX + id.getKey(), new RuntimeException(id + " not resolved"));
+ }
+ }
+
public interface MavenTaskHandler {
void waitFor();
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
index 4febe8b40216..5ad40739114f 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
@@ -28,6 +28,7 @@ import com.intellij.util.ui.UIUtil;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.concurrency.AsyncPromise;
+import org.jetbrains.idea.maven.buildtool.MavenSyncConsole;
import org.jetbrains.idea.maven.execution.*;
import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
@@ -396,6 +397,11 @@ public abstract class MavenImportingTestCase extends MavenTestCase {
assertFalse("Failed to import Maven project: " + each.getProblems(), each.hasReadingProblems());
}
}
+
+ MavenSyncConsole syncConsole = myProjectsManager.getSyncConsole();
+ assertEquals(0, syncConsole.runningProcesses());
+ assertTrue(syncConsole.isFinished());
+
}
protected void readProjects(List files, String... profiles) {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
index 737b78d3e642..44474bb1220f 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
@@ -48,7 +48,7 @@ public abstract class MavenTestCase extends UsefulTestCase {
protected static final MavenConsole NULL_MAVEN_CONSOLE = new NullMavenConsole();
// should not be static
protected static MavenProgressIndicator EMPTY_MAVEN_PROCESS =
- new MavenProgressIndicator(new EmptyProgressIndicator(ModalityState.NON_MODAL));
+ new MavenProgressIndicator(new EmptyProgressIndicator(ModalityState.NON_MODAL), null);
private File ourTempDir;
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenSyncTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenSyncTest.java
new file mode 100644
index 000000000000..2e7cc4fcdac7
--- /dev/null
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenSyncTest.java
@@ -0,0 +1,49 @@
+// 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.importing;
+
+import org.jetbrains.idea.maven.MavenImportingTestCase;
+
+public class MavenSyncTest extends MavenImportingTestCase {
+ public static final String PLUGINS_RESOLVE_PREFIX = "Downloading Maven plugins--";
+
+ public void testSync() {
+ importProject("test" +
+ "project" +
+ "jar" +
+ "1");
+
+ assertNoErrorsInSync();
+ }
+
+ public void testUnresolvedDependency() {
+ importProject("test" +
+ "project" +
+ "jar" +
+ "1" +
+ "" +
+ "" +
+ "unknown" +
+ "unknown" +
+ "123" +
+ "" +
+ "" +
+ "");
+
+ assertEventRegistered("Resolving Maven dependencies");
+ assertError("unknown:unknown:123 not resolved");
+
+ }
+
+ private void assertError(String message) {
+ assertTrue("Should have error " + message, myProjectsManager.getSyncConsole().getErrors().stream().anyMatch(e -> message.equals(e.getMessage())));
+ }
+
+ private void assertEventRegistered(String step) {
+ assertTrue("Should have step " + step, myProjectsManager.getSyncConsole().started(step));
+ }
+
+ private void assertNoErrorsInSync() {
+ assertNullOrEmpty(myProjectsManager.getSyncConsole().getErrors());
+ }
+}
+