IDEA-207382 - maven sync tool window

GitOrigin-RevId: f23f23648879f04bc45cf4ef9770662e1831db74
This commit is contained in:
Alexander Bubenchikov
2019-04-28 18:24:37 +03:00
committed by intellij-monorepo-bot
parent f73a87c27e
commit a0963c3bf7
18 changed files with 459 additions and 19 deletions
+3
View File
@@ -68,6 +68,9 @@
<orderEntry type="library" name="NanoXML" level="project" />
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
<orderEntry type="library" scope="TEST" name="hamcrest" level="project" />
<orderEntry type="module" module-name="intellij.maven.server.m2.impl" scope="RUNTIME" />
<orderEntry type="module" module-name="intellij.maven.server.m30.impl" scope="RUNTIME" />
<orderEntry type="module" module-name="intellij.maven.server.m36.impl" scope="RUNTIME" />
</component>
<component name="copyright">
<Base>
@@ -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;
@@ -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);
}
}
@@ -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);
@@ -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);
@@ -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);
@@ -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<Any, ArrayList<Failure>>
private lateinit var myStartedSet: HashSet<String>
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<BuildProgressListener>()
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: Failure): ArrayList<Failure> {
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<Failure>? {
return myFailuresMap["Sync"]
}
@TestOnly
fun getErrors(key: String): ArrayList<Failure>? {
return myFailuresMap[key]
}
@TestOnly
fun started(key: String): Boolean{
return myStartedSet.contains(key.trim('.'))
}
companion object {
const val PLUGINS_RESOLVE_PREFIX = "Downloading Maven plugins--"
}
}
@@ -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);
@@ -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) {
}
@@ -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);
@@ -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<List<Module>> scheduleImportAndResolve() {
getSyncConsole().startImport();
AsyncPromise<List<Module>> 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<List<Module>> scheduleResolve() {
@@ -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<MavenProjectReaderResult> 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<MavenProject> mavenProjects = deletedProjects.isEmpty()
? Collections.emptyList()
: new ArrayList<>(deletedProjects);
@@ -1755,7 +1766,7 @@ public class MavenProjectsTree {
}
default void projectResolved(@NotNull Pair<MavenProject, MavenProjectChanges> 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());
}
}
}
@@ -619,6 +619,16 @@ public class MavenServerManager extends RemoteObjectWrapper<MavenServer> 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();
@@ -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<Condition<MavenProgressIndicator>> myCancelConditions = new ArrayList<>();
private final Supplier<MavenSyncConsole> mySyncSupplier;
public MavenProgressIndicator() {
this(new MyEmptyProgressIndicator());
public MavenProgressIndicator(Supplier<MavenSyncConsole> syncSupplier) {
this(new MyEmptyProgressIndicator(), syncSupplier);
}
public MavenProgressIndicator(ProgressIndicator i) {
public MavenProgressIndicator(ProgressIndicator i,
Supplier<MavenSyncConsole> 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;
@@ -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<MavenProjectReaderResult> results) {
Set<MavenId> 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();
}
@@ -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<VirtualFile> files, String... profiles) {
@@ -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;
@@ -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("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<packaging>jar</packaging>" +
"<version>1</version>");
assertNoErrorsInSync();
}
public void testUnresolvedDependency() {
importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<packaging>jar</packaging>" +
"<version>1</version>" +
"<dependencies>" +
"<dependency>" +
"<groupId>unknown</groupId>" +
"<artifactId>unknown</artifactId>" +
"<version>123</version>" +
"</dependency>" +
"</dependencies>" +
"");
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());
}
}