From 4825ffe8e203912a70be37aa85c2f64bbfdc3bdb Mon Sep 17 00:00:00 2001 From: Alexander Bubenchikov Date: Mon, 8 Jan 2024 12:03:18 +0100 Subject: [PATCH] [maven] [IDEA-340163] maven indices refactored step 1. Separated classes by responsibility, cleaned lifetime index flow. Lucene is not used in GAV anymore GitOrigin-RevId: de82eeb4691b70e71c7e2326b25d4e905afef61e --- .../maven/ImportMavenRepositoriesTask.java | 14 +- .../idea/maven/model/MavenRepositoryInfo.java | 17 + .../MavenArtifactCoordinatesConverter.java | 17 +- .../maven/indices/IndexUpdatingState.java | 6 + .../maven/indices/MavenArchetypeManager.java | 20 +- .../idea/maven/indices/MavenGAVIndex.java | 23 +- .../idea/maven/indices/MavenIndex.java | 14 +- .../idea/maven/indices/MavenIndexHolder.java | 18 +- .../idea/maven/indices/MavenIndexImpl.java | 13 +- .../indices/MavenIndexUpdateManager.java | 168 -------- .../idea/maven/indices/MavenIndexUtils.java | 35 +- .../idea/maven/indices/MavenIndices.java | 55 +-- .../maven/indices/MavenIndicesManager.java | 390 ------------------ .../idea/maven/indices/MavenIndicesManager.kt | 356 ++++++++++++++++ .../maven/indices/MavenLocalGavIndexImpl.kt | 101 +++-- .../MavenRepositoriesConfigurable.form | 2 +- .../MavenRepositoriesConfigurable.java | 101 ++--- .../maven/indices/MavenRepositoryIndex.java | 18 + .../idea/maven/indices/MavenSearchIndex.java | 13 +- .../indices/MavenSystemIndicesManager.kt | 194 ++++++--- .../maven/indices/MavenUpdatableIndex.java | 12 - .../idea/maven/indices/MavenUpdatableIndex.kt | 14 + .../navigator/actions/IndexUpdateAction.kt | 2 +- .../IndexBasedCompletionProvider.kt | 16 +- .../MavenCompletionProviderFactory.java | 17 +- .../maven/project/MavenProjectsManager.java | 5 +- .../maven/server/MavenIndexerWrapper.java | 2 +- .../statistics/MavenIndexUsageCollector.kt | 19 +- ...enDependencyCompletionAndResolutionTest.kt | 1 + .../dom/MavenDependencySmartCompletionTest.kt | 53 +-- .../maven/dom/MavenDomWithIndicesTestCase.kt | 34 +- .../indices/MavenIndicesManagerTest.java | 44 +- .../idea/maven/indices/MavenIndicesTest.java | 24 +- .../indices/MavenIndicesTestFixture.java | 11 +- .../indices/MavenMultiProjectImportTest.kt | 6 +- .../idea/maven/indices/MavenSearcherTest.kt | 8 +- .../maven/testFramework/MavenDomTestCase.kt | 3 +- .../reposearch/DependencySearchService.kt | 3 + 38 files changed, 864 insertions(+), 985 deletions(-) create mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndexUpdatingState.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUpdateManager.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java create mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.kt create mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoryIndex.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.java create mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.kt diff --git a/plugins/gradle-maven/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java b/plugins/gradle-maven/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java index 2eb4acfa5f2a..797aba681df7 100644 --- a/plugins/gradle-maven/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java +++ b/plugins/gradle-maven/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java @@ -19,7 +19,6 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.indices.MavenIndicesManager; -import org.jetbrains.idea.maven.indices.MavenSearchIndex; import org.jetbrains.idea.maven.model.MavenRemoteRepository; import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -34,7 +33,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals import java.net.URI; import java.net.URISyntaxException; import java.util.*; -import java.util.stream.Collectors; /** * @author Vladislav.Soroka @@ -104,17 +102,7 @@ final class ImportMavenRepositoriesTask { // register imported maven repository URLs but do not force to download the index // the index can be downloaded and/or updated later using Maven Configuration UI (Settings -> Build, Execution, Deployment -> Build tools -> Maven -> Repositories) MavenRepositoriesHolder.getInstance(myProject).update(mavenRemoteRepositories); - MavenIndicesManager.getInstance(myProject).scheduleUpdateIndicesList(indexes -> { - if (myProject.isDisposed()) return; - - List repositoriesWithEmptyIndex = indexes.stream() - .filter(index -> index.getUpdateTimestamp() == -1 && - index.getFailureMessage() == null && - MavenRepositoriesHolder.getInstance(myProject).contains(index.getRepositoryPathOrUrl())) - .map(MavenSearchIndex::getRepositoryPathOrUrl) - .collect(Collectors.toList()); - MavenRepositoriesHolder.getInstance(myProject).updateNotIndexedUrls(repositoriesWithEmptyIndex); - }); + MavenIndicesManager.getInstance(myProject).scheduleUpdateIndicesList(); } @NotNull diff --git a/plugins/maven-server-api/src/main/java/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java b/plugins/maven-server-api/src/main/java/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java index b4b2d5051a00..4e59f533df65 100644 --- a/plugins/maven-server-api/src/main/java/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java +++ b/plugins/maven-server-api/src/main/java/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.maven.model; import java.io.Serializable; +import java.util.Objects; public class MavenRepositoryInfo implements Serializable { private final String myId; @@ -60,4 +61,20 @@ public class MavenRepositoryInfo implements Serializable { return builder.toString(); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MavenRepositoryInfo info = (MavenRepositoryInfo)o; + return Objects.equals(myId, info.myId) && + Objects.equals(myName, info.myName) && + Objects.equals(myUrl, info.myUrl) && + myKind == info.myKind; + } + + @Override + public int hashCode() { + return Objects.hash(myId, myName, myUrl, myKind); + } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java index 66a944b07fa9..cbf185b0c065 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java @@ -26,11 +26,12 @@ import org.jetbrains.idea.maven.dom.DependencyConflictId; import org.jetbrains.idea.maven.dom.MavenDomBundle; import org.jetbrains.idea.maven.dom.MavenDomProjectProcessorUtils; import org.jetbrains.idea.maven.dom.model.*; -import org.jetbrains.idea.maven.indices.MavenIndex; +import org.jetbrains.idea.maven.indices.MavenIndexUtils; import org.jetbrains.idea.maven.indices.MavenIndicesManager; import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.model.MavenPlugin; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenArtifactUtil; @@ -42,6 +43,7 @@ import java.io.File; import java.nio.file.Path; import java.util.Collection; import java.util.HashSet; +import java.util.Objects; import java.util.Set; public abstract class MavenArtifactCoordinatesConverter extends ResolvingConverter implements MavenDomSoftAwareConverter { @@ -56,11 +58,11 @@ public abstract class MavenArtifactCoordinatesConverter extends ResolvingConvert ConverterStrategy strategy = selectStrategy(context); boolean isValid = strategy.isValid(id, manager, context); if (!isValid) { - MavenIndex localIndex = manager.getIndex().getLocalIndex(); - if (localIndex == null) return null; - Path artifactPath = MavenUtil.getArtifactPath(Path.of(localIndex.getRepositoryPathOrUrl()), id, "pom", null); + MavenRepositoryInfo repository = MavenIndexUtils.getLocalRepository(contextProject); + if (repository == null) return null; + Path artifactPath = MavenUtil.getArtifactPath(Path.of(repository.getUrl()), id, "pom", null); if (artifactPath != null && artifactPath.toFile().exists()) { - MavenIndicesManager.getInstance(contextProject).scheduleArtifactIndexing(id, artifactPath.toFile()); + MavenIndicesManager.getInstance(contextProject).scheduleArtifactIndexing(id, artifactPath.toFile(), repository.getUrl()); return s; } return null; @@ -180,14 +182,13 @@ public abstract class MavenArtifactCoordinatesConverter extends ResolvingConvert @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - MavenIndicesManager.getInstance(project).scheduleUpdateContentAll(); + MavenIndicesManager.getInstance(project).scheduleUpdateContentAll(true); } @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { return MavenUtil.isPomFile(project, file.getVirtualFile()) - && ContainerUtil.exists(MavenIndicesManager.getInstance(project).getIndex() - .getGAVIndices(), i -> i.getRepository() != null && !"central".equals(i.getRepository().getName())); + && ContainerUtil.exists(MavenIndexUtils.getRemoteRepositoriesNoResolve(project), r -> !Objects.equals(r.getName(), "central")); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndexUpdatingState.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndexUpdatingState.java new file mode 100644 index 000000000000..48cb8414aad8 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndexUpdatingState.java @@ -0,0 +1,6 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.idea.maven.indices; + +public enum IndexUpdatingState { + IDLE, WAITING, UPDATING +} \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypeManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypeManager.java index 78e897ed0c53..bf5541ac3b89 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypeManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypeManager.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.indices.archetype.MavenCatalog; import org.jetbrains.idea.maven.model.MavenArchetype; import org.jetbrains.idea.maven.model.MavenId; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; import org.jetbrains.idea.maven.project.MavenEmbeddersManager; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; @@ -72,10 +73,6 @@ public class MavenArchetypeManager { if (!indicesManager.isInit()) { indicesManager.updateIndicesListSync(); } - MavenIndexHolder indexHolder = indicesManager.getIndex(); - for (MavenIndex index : indexHolder.getIndices()) { - result.addAll(index.getArchetypes()); - } for (MavenArchetypesProvider each : MavenArchetypesProvider.EP_NAME.getExtensionList()) { result.addAll(each.getArchetypes()); @@ -85,12 +82,7 @@ public class MavenArchetypeManager { public Collection getLocalArchetypes() { MavenIndicesManager indicesManager = MavenIndicesManager.getInstance(myProject); - if (!indicesManager.isInit()) indicesManager.updateIndicesListSync(); - - MavenIndex localIndex = indicesManager.getIndex().getLocalIndex(); - if (localIndex == null) return Collections.emptySet(); - - return localIndex.getArchetypes(); + return Collections.emptyList(); } public Collection getInnerArchetypes() { @@ -178,11 +170,11 @@ public class MavenArchetypeManager { private void addToLocalIndex(@NotNull String groupId, @NotNull String artifactId, @NotNull String version) { MavenId mavenId = new MavenId(groupId, artifactId, version); - MavenIndex localIndex = MavenIndicesManager.getInstance(myProject).getIndex().getLocalIndex(); - if (localIndex == null) return; - Path artifactPath = MavenUtil.getArtifactPath(Path.of(localIndex.getRepositoryPathOrUrl()), mavenId, "jar", null); + MavenRepositoryInfo localRepo = MavenIndexUtils.getLocalRepository(myProject); + if (localRepo == null) return; + Path artifactPath = MavenUtil.getArtifactPath(Path.of(localRepo.getUrl()), mavenId, "jar", null); if (artifactPath != null && artifactPath.toFile().exists()) { - MavenIndicesManager.getInstance(myProject).scheduleArtifactIndexing(mavenId, artifactPath.toFile()); + MavenIndicesManager.getInstance(myProject).scheduleArtifactIndexing(mavenId, artifactPath.toFile(), localRepo.getUrl()); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenGAVIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenGAVIndex.java index 54259e679a85..f5ffa5b981ff 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenGAVIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenGAVIndex.java @@ -2,27 +2,24 @@ package org.jetbrains.idea.maven.indices; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.model.RepositoryKind; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenRepositoryInfo; +import org.jetbrains.idea.maven.model.RepositoryKind; import java.util.Collection; import java.util.Set; -public interface MavenGAVIndex { - Collection getGroupIds(); +public interface MavenGAVIndex extends MavenRepositoryIndex { + @NotNull Collection<@NotNull String> getGroupIds(); - Set getArtifactIds(String groupId); + @NotNull Set<@NotNull String> getArtifactIds(@NotNull String groupId); - Set getVersions(String groupId, String artifactId); + @NotNull Set<@NotNull String> getVersions(@NotNull String groupId, @NotNull String artifactId); - boolean hasGroupId(String groupId); + boolean hasGroupId(@NotNull String groupId); - boolean hasArtifactId(String groupId, String artifactId); + boolean hasArtifactId(@NotNull String groupId, @NotNull String artifactId); - boolean hasVersion(String groupId, String artifactId, String version); - - RepositoryKind getKind(); - - @Nullable MavenRepositoryInfo getRepository(); + boolean hasVersion(@NotNull String groupId, @NotNull String artifactId, @NotNull String version); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java index 520a5009e084..d2ff552a69a7 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java @@ -1,19 +1,7 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.idea.maven.indices; -import com.intellij.util.messages.Topic; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.server.AddArtifactResponse; -import java.io.File; -import java.util.Collection; -import java.util.List; +public interface MavenIndex extends MavenGAVIndex, MavenArchetypeContainer, MavenUpdatableIndex { -public interface MavenIndex extends MavenSearchIndex, MavenGAVIndex, MavenArchetypeContainer, MavenUpdatableIndex { - - @Topic.AppLevel - Topic INDEX_IS_BROKEN = - new Topic<>("Maven Index Broken Listener", IndexListener.class); - - @NotNull List tryAddArtifacts(@NotNull Collection artifactFiles); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexHolder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexHolder.java index 743afbae236e..7b77998bb4af 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexHolder.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexHolder.java @@ -12,21 +12,21 @@ import java.util.Objects; import java.util.Set; public class MavenIndexHolder { - private final @Nullable MavenIndex myLocalIndex; + private final @Nullable MavenIndex myLocalClassIndex; private final @NotNull List myRemoteIndices; private final @NotNull List myIndices; MavenIndexHolder(@NotNull List remoteIndices, @Nullable MavenIndex localIndex) { - myLocalIndex = localIndex; + myLocalClassIndex = localIndex; myRemoteIndices = List.copyOf(Objects.requireNonNull(remoteIndices)); List indices = new ArrayList<>(remoteIndices); - if (myLocalIndex != null) indices.add(myLocalIndex); + if (myLocalClassIndex != null) indices.add(myLocalClassIndex); myIndices = List.copyOf(indices); } public @Nullable MavenIndex getLocalIndex() { - return myLocalIndex; + return myLocalClassIndex; } public @NotNull List getRemoteIndices() { @@ -34,12 +34,12 @@ public class MavenIndexHolder { } public List getGAVIndices() { - if (myLocalIndex == null) { + if (myLocalClassIndex == null) { return ContainerUtil.filter(myRemoteIndices, idx -> idx != null); } else { ArrayList result = new ArrayList<>(getRemoteIndices()); - result.add(myLocalIndex); + result.add(myLocalClassIndex); return result; } } @@ -49,10 +49,10 @@ public class MavenIndexHolder { } public boolean isEquals(@NotNull Set remoteUrls, @Nullable String localPath) { - if (!FileUtilRt.pathsEqual(myLocalIndex != null ? myLocalIndex.getRepositoryPathOrUrl() : null, localPath)) return false; + if (!FileUtilRt.pathsEqual(myLocalClassIndex != null ? myLocalClassIndex.getRepository().getUrl() : null, localPath)) return false; if (remoteUrls.size() != myRemoteIndices.size()) return false; - for (MavenSearchIndex index : myRemoteIndices) { - if (!remoteUrls.contains(index.getRepositoryPathOrUrl())) return false; + for (MavenIndex index : myRemoteIndices) { + if (!remoteUrls.contains(index.getRepository().getUrl())) return false; } return true; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexImpl.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexImpl.java index 5428896101ac..b34006cd93a3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexImpl.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexImpl.java @@ -34,7 +34,7 @@ import static com.intellij.openapi.util.text.StringUtil.join; import static com.intellij.openapi.util.text.StringUtil.split; import static com.intellij.util.containers.ContainerUtil.notNullize; -public final class MavenIndexImpl implements MavenIndex { +public final class MavenIndexImpl implements MavenIndex, MavenSearchIndex { private static final String DATA_DIR_PREFIX = "data"; @@ -202,7 +202,6 @@ public final class MavenIndexImpl implements MavenIndex { @Override public MavenRepositoryInfo getRepository() { - if (myKind == RepositoryKind.ONLINE) return null; return new MavenRepositoryInfo(getRepositoryId(), getRepositoryId(), myRepositoryPathOrUrl, myKind); } @@ -217,7 +216,7 @@ public final class MavenIndexImpl implements MavenIndex { } @Override - public void updateOrRepair(boolean fullUpdate, MavenProgressIndicator progress, boolean multithreaded) + public void updateOrRepair(boolean fullUpdate, MavenProgressIndicator progress, boolean explicit) throws MavenProcessCanceledException { StructuredIdeActivity activity = MavenIndexUsageCollector.INDEX_UPDATE.started(null); boolean isSuccess = false; @@ -247,7 +246,7 @@ public final class MavenIndexImpl implements MavenIndex { if (fullUpdate) { MavenIndexId mavenIndexId = getMavenIndexId(newDataContextDir, "update"); try { - updateNexusContext(mavenIndexId, progress, multithreaded); + updateNexusContext(mavenIndexId, progress, explicit); } finally { myNexusIndexer.releaseIndex(mavenIndexId); @@ -277,7 +276,7 @@ public final class MavenIndexImpl implements MavenIndex { MavenIndexUsageCollector.IS_CENTRAL.with(myKind == RepositoryKind.REMOTE && isCentral), MavenIndexUsageCollector.IS_PRIVATE_REMOTE.with(myKind == RepositoryKind.REMOTE && !isCentral), MavenIndexUsageCollector.IS_SUCCESS.with(finalIsSuccess), - MavenIndexUsageCollector.MANUAL.with(multithreaded) + MavenIndexUsageCollector.MANUAL.with(explicit) ) ); indexUpdateLock.unlock(); @@ -449,7 +448,7 @@ public final class MavenIndexImpl implements MavenIndex { */ @Override @NotNull - public List tryAddArtifacts(@NotNull Collection artifactFiles) { + public List tryAddArtifacts(@NotNull Collection artifactFiles) { var failedResponses = ContainerUtil.map(artifactFiles, file -> new AddArtifactResponse(file, null)); return doIndexAndRecoveryTask(() -> { boolean locked = indexUpdateLock.tryLock(); @@ -755,7 +754,7 @@ public final class MavenIndexImpl implements MavenIndex { } @NotNull - List addArtifacts(Collection artifactFiles) { + List addArtifacts(Collection artifactFiles) { return myNexusIndexer.addArtifacts(mavenIndexId, artifactFiles); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUpdateManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUpdateManager.java deleted file mode 100644 index 4d79261efb37..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUpdateManager.java +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.maven.indices; - -import com.intellij.model.SideEffectGuard; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.progress.BackgroundTaskQueue; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.util.Consumer; -import com.intellij.util.ui.UIUtil; -import com.intellij.util.ui.update.MergingUpdateQueue; -import com.intellij.util.ui.update.Update; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.model.MavenRepositoryInfo; -import org.jetbrains.idea.maven.project.MavenGeneralSettings; -import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; -import org.jetbrains.idea.maven.utils.MavenProgressIndicator; -import org.jetbrains.idea.maven.utils.MavenRehighlighter; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Internal api class for update maven indices state. - *

- * Contains logic for schedule async tasks for update index list or index. - */ -@ApiStatus.Internal -public final class MavenIndexUpdateManager implements Disposable { - private final Object myUpdatingIndicesLock = new Object(); - private final BackgroundTaskQueue myUpdatingQueue = new BackgroundTaskQueue(null, IndicesBundle.message("maven.indices.updating")); - private final MergingUpdateQueue myUpdateQueueList = new MergingUpdateQueue( - getClass().getName(), 1000, true, null, this, null, false - ).usePassThroughInUnitTestMode(); - private volatile String myCurrentUpdateIndexUrl; - - @Override - public void dispose() { - myUpdatingQueue.clear(); - } - - void scheduleUpdateIndicesList(@NotNull Project project, @Nullable Consumer> consumer) { - myUpdateQueueList.queue(Update.create(this, () -> { - MavenIndicesManager indicesManager = MavenIndicesManager.getInstance(project); - indicesManager.updateIndicesListSync(); - if (project.isDisposed()) { - return; - } - - MavenIndexHolder indexHolder = indicesManager.getIndex(); - MavenIndex localIndex = indexHolder.getLocalIndex(); - if (localIndex != null) { - if (localIndex.getUpdateTimestamp() == -1 && Registry.is("maven.auto.update.local.index")) { - scheduleUpdateContent(project, IndicesContentUpdateRequest.background(List.of(localIndex.getRepository()))); - } - } - if (consumer != null) { - consumer.consume(indexHolder.getIndices()); - } - })); - } - - CompletableFuture scheduleUpdateContent(@NotNull Project project, IndicesContentUpdateRequest request) { - SideEffectGuard.checkSideEffectAllowed(SideEffectGuard.EffectType.PROJECT_MODEL); - - if (request.getShowProgress()) { - return runIndexUpdateWithProgress(project, request); - } - else { - return runIndexUpdateInBackgroundWithoutProgress(project, request); - } - } - - private static CompletableFuture runIndexUpdateInBackgroundWithoutProgress(Project project, - IndicesContentUpdateRequest request) { - MavenProgressIndicator indicator = - new MavenProgressIndicator(null, null); - try { - doUpdateIndicesContent(project, request, indicator); - } - catch (MavenProcessCanceledException e) { - return CompletableFuture.failedFuture(e); - } - return CompletableFuture.completedFuture(null); - } - - private CompletableFuture runIndexUpdateWithProgress(@NotNull Project project, - IndicesContentUpdateRequest request) { - final CompletableFuture promise = new CompletableFuture<>(); - myUpdatingQueue.run(new Task.Backgroundable(project, IndicesBundle.message("maven.indices.updating"), true) { - @Override - public void run(@NotNull ProgressIndicator indicator) { - try { - indicator.setIndeterminate(false); - doUpdateIndicesContent(project, request, new MavenProgressIndicator(null, indicator, null)); - } - catch (MavenProcessCanceledException ignore) { - } - finally { - promise.complete(null); - } - } - }); - return promise; - } - - private static void doUpdateIndicesContent(@NotNull Project project, - @NotNull IndicesContentUpdateRequest request, - @NotNull MavenProgressIndicator indicator) - throws MavenProcessCanceledException { - - - MavenSystemIndicesManager indicesManager = MavenSystemIndicesManager.getInstance(); - for (MavenRepositoryInfo repo : request.getIndicesToUpdate()) { - if (indicator.isCanceled()) return; - indicesManager.updateIndexContentSync(repo, request.getFull(), request.getExplicit(), indicator); - - indicator.setText(IndicesBundle.message("maven.indices.updating.index", - repo.getId(), - repo.getUrl())); - } - MavenRehighlighter.rehighlight(project); - } - - - @TestOnly - void waitForBackgroundTasksInTests() { - while (!myUpdatingQueue.isEmpty()) { - UIUtil.dispatchAllInvocationEvents(); - } - try { - myUpdateQueueList.waitForAllExecuted(1, TimeUnit.MINUTES); - } - catch (ExecutionException | InterruptedException | TimeoutException e) { - throw new RuntimeException(e); - } - } - - private static MavenGeneralSettings getMavenSettings(@NotNull final Project project, @NotNull MavenProgressIndicator indicator) - throws MavenProcessCanceledException { - MavenGeneralSettings settings; - - settings = ReadAction - .compute(() -> project.isDisposed() ? null : MavenProjectsManager.getInstance(project).getGeneralSettings().clone()); - - if (settings == null) { - // project was closed - indicator.cancel(); - indicator.checkCanceled(); - } - - return settings; - } - - public enum IndexUpdatingState { - IDLE, WAITING, UPDATING - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUtils.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUtils.java index c7cb9899a4c5..999db03d84a4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUtils.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexUtils.java @@ -3,12 +3,13 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; -import org.jetbrains.idea.maven.model.RepositoryKind; import org.jetbrains.idea.maven.model.MavenRemoteRepository; import org.jetbrains.idea.maven.model.MavenRepositoryInfo; +import org.jetbrains.idea.maven.model.RepositoryKind; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenUtil; @@ -96,12 +97,6 @@ public final class MavenIndexUtils { } } - @NotNull - public static Map> getRemoteRepositoryIdsByUrl(Project project) { - if (project.isDisposed()) return Collections.emptyMap(); - return getRemoteRepositoriesMap(project); - } - @Nullable public static MavenRepositoryInfo getLocalRepository(Project project) { if (project.isDisposed()) return null; @@ -111,17 +106,21 @@ public final class MavenIndexUtils { : new MavenRepositoryInfo(LOCAL_REPOSITORY_ID, LOCAL_REPOSITORY_ID, repository.getPath(), RepositoryKind.LOCAL); } - private static Map> getRemoteRepositoriesMap(Project project) { - if (project.isDisposed()) { - return Collections.emptyMap(); - } + @NotNull + public static List getRemoteRepositoriesNoResolve(Project project) { - Set remoteRepositories = new HashSet<>(MavenUtil.getRemoteResolvedRepositories(project)); + if (project.isDisposed()) { + return Collections.emptyList(); + } + MavenProjectsManager projectsManager = MavenProjectsManager.getInstance(project); + Set repositories = projectsManager.getRemoteRepositories(); + + Set remoteRepositories = new HashSet<>(repositories); for (MavenRepositoryProvider repositoryProvider : MavenRepositoryProvider.EP_NAME.getExtensionList()) { remoteRepositories.addAll(repositoryProvider.getRemoteRepositories(project)); } - return groupRemoteRepositoriesByUrl(remoteRepositories); + return remoteRepositories.stream().toList(); } @@ -142,6 +141,16 @@ public final class MavenIndexUtils { return pathOrUrl; } + static List getAllRepositories(Project project) { + List all = new ArrayList<>(); + var local = getLocalRepository(project); + if (local != null) { + all.add(local); + } + all.addAll(ContainerUtil.map(getRemoteRepositoriesNoResolve(project), rr -> new MavenRepositoryInfo(rr.getId(), rr.getName(), rr.getUrl(), RepositoryKind.REMOTE))); + return all; + } + static class IndexPropertyHolder { final File dir; final RepositoryKind kind; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java index 3ca92d4c3b81..f47edfc8b63b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java @@ -25,8 +25,8 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; -import org.jetbrains.idea.maven.model.RepositoryKind; import org.jetbrains.idea.maven.model.MavenRepositoryInfo; +import org.jetbrains.idea.maven.model.RepositoryKind; import org.jetbrains.idea.maven.server.MavenIndexerWrapper; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.reposearch.DependencySearchService; @@ -62,46 +62,6 @@ public class MavenIndices implements Disposable { myProject = project; } - void updateRepositoriesList() { - if (isDisposed) return; - updateIndicesLock.lock(); - try { - Map> remoteRepositoryIdsByUrl = MavenIndexUtils.getRemoteRepositoryIdsByUrl(myProject); - MavenRepositoryInfo localRepository = MavenIndexUtils.getLocalRepository(myProject); - if (localRepository == null || myProject.isDisposed()) { - return; - } - - if (myIndexHolder.isEquals(remoteRepositoryIdsByUrl.keySet(), localRepository.getUrl())) return; - - MavenLog.LOG.debug("start update indices " + myIndexHolder); - - MavenIndex localIndex = myIndexHolder.getLocalIndex(); - List remoteIndices = myIndexHolder.getRemoteIndices(); - - if (isDisposed) return; - RepositoryDiffContext context = new RepositoryDiffContext(myIndexer, myIndicesDir); - - RepositoryDiff localDiff = getLocalDiff(localRepository, context, localIndex); - RepositoryDiff> remoteDiff = getRemoteDiff(remoteRepositoryIdsByUrl, remoteIndices, context); - - myIndexHolder = new MavenIndexHolder(remoteDiff.newIndices, localDiff.newIndices); - MavenLog.LOG.debug("new indices " + myIndexHolder); - - if (isDisposed) closeIndices(myIndexHolder.getIndices()); - - indicesInit = true; - - closeIndices(getOldIndices(localDiff, remoteDiff)); - clearDependencySearchCache(myProject); - } - catch (AlreadyDisposedException | IncorrectOperationException e) { - myIndexHolder = new MavenIndexHolder(Collections.emptyList(), null); - } - finally { - updateIndicesLock.unlock(); - } - } public boolean isIndicesInit() { return indicesInit; @@ -202,7 +162,7 @@ public class MavenIndices implements Disposable { static RepositoryDiff getLocalDiff(@NotNull MavenRepositoryInfo localRepo, @NotNull RepositoryDiffContext context, @Nullable MavenIndex currentLocalIndex) { - if (currentLocalIndex != null && FileUtil.pathsEqual(localRepo.getUrl(), currentLocalIndex.getRepositoryPathOrUrl())) { + if (currentLocalIndex != null && FileUtil.pathsEqual(localRepo.getUrl(), currentLocalIndex.getRepository().getUrl())) { return new RepositoryDiff<>(currentLocalIndex, null); } @@ -217,13 +177,13 @@ public class MavenIndices implements Disposable { @NotNull List currentRemoteIndex, @NotNull RepositoryDiffContext context) { Map currentRemoteIndicesByUrls = currentRemoteIndex.stream() - .collect(Collectors.toMap(i -> i.getRepositoryPathOrUrl(), Function.identity())); + .collect(Collectors.toMap(i -> i.getRepository().getUrl(), Function.identity())); if (currentRemoteIndicesByUrls.keySet().equals(remoteRepositoryIdsByUrl.keySet())) { return new RepositoryDiff<>(currentRemoteIndex, Collections.emptyList()); } List oldIndices = ContainerUtil - .filter(currentRemoteIndex, i -> !remoteRepositoryIdsByUrl.containsKey(i.getRepositoryPathOrUrl())); + .filter(currentRemoteIndex, i -> !remoteRepositoryIdsByUrl.containsKey(i.getRepository().getUrl())); List newMavenIndices = ContainerUtil.map(remoteRepositoryIdsByUrl .entrySet(), e -> { @@ -263,6 +223,13 @@ public class MavenIndices implements Disposable { } } + + //todo: move this logic and this file into MavenIndicesManager + + static class UpdateRepositoryResult { + List mavenIndexreated; + } + static class RepositoryDiffContext { final @NotNull MavenIndexerWrapper indexer; final @NotNull File indicesDir; 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 deleted file mode 100644 index dbb7fa6a28e9..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.maven.indices; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Pair; -import com.intellij.serviceContainer.AlreadyDisposedException; -import com.intellij.util.Consumer; -import com.intellij.util.concurrency.AppExecutorUtil; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.io.PathKt; -import com.intellij.util.messages.Topic; -import com.intellij.util.ui.update.MergingUpdateQueue; -import com.intellij.util.ui.update.Update; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.model.MavenArchetype; -import org.jetbrains.idea.maven.model.MavenArtifactInfo; -import org.jetbrains.idea.maven.model.MavenId; -import org.jetbrains.idea.maven.project.MavenProject; -import org.jetbrains.idea.maven.project.MavenProjectChanges; -import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.project.MavenProjectsTree; -import org.jetbrains.idea.maven.server.MavenServerConnector; -import org.jetbrains.idea.maven.server.MavenServerDownloadListener; -import org.jetbrains.idea.maven.server.NativeMavenProjectHolder; -import org.jetbrains.idea.maven.statistics.MavenIndexUsageCollector; -import org.jetbrains.idea.maven.utils.MavenLog; -import org.jetbrains.idea.maven.utils.MavenUtil; -import org.jetbrains.idea.reposearch.DependencySearchService; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Main api class for work with maven indices. - *

- * Get current index state, schedule update index list, check MavenId in index, add data to index. - */ -public final class MavenIndicesManager implements Disposable { - - @Topic.AppLevel - public static final Topic INDEXER_TOPIC = - new Topic<>(MavenIndexerListener.class.getSimpleName(), MavenIndexerListener.class); - - public interface MavenIndexerListener { - void indexUpdated(Set added, Set failedToAdd); - } - - private final @NotNull Project myProject; - private final @NotNull MavenIndices myMavenIndices; - - private final MavenIndexServerDownloadListener myDownloadListener = new MavenIndexServerDownloadListener(this); - private final IndexFixer myIndexFixer = new IndexFixer(); - private final MavenIndexUpdateManager myIndexUpdateManager; - - - public static MavenIndicesManager getInstance(@NotNull Project project) { - return project.getService(MavenIndicesManager.class); - } - - public MavenIndicesManager(@NotNull Project project) { - myProject = project; - myIndexUpdateManager = new MavenIndexUpdateManager(); - myMavenIndices = MavenSystemIndicesManager.getInstance().getOrCreateIndices(project); - - initListeners(); - - Disposer.register(this, myIndexUpdateManager); - } - - @Override - public void dispose() { - myIndexFixer.stop(); - deleteIndicesDirInUnitTests(); - } - - private void deleteIndicesDirInUnitTests() { - if (MavenUtil.isMavenUnitTestModeEnabled()) { - if (!myMavenIndices.isDisposed()) { - var localIndex = myMavenIndices.getIndexHolder().getLocalIndex(); - if (localIndex instanceof MavenIndexImpl impl) { - impl.closeAndClean(); - } - } - Path dir = MavenSystemIndicesManager.getInstance().getIndicesDir(); - try { - PathKt.delete(dir); - } - catch (Exception e) { - // if some files haven't been deleted in the index directory, report them - try (Stream stream = Files.walk(dir)) { - var files = stream.map(Path::toString).toList(); - var message = files.isEmpty() - ? "Failed to delete the index directory" - : "Failed to delete files in the index directory: " + String.join(", ", files); - throw new RuntimeException(message, e); - } - catch (IOException ex) { - throw new RuntimeException(ex); - } - } - } - } - - /** - * Get current maven index state. - * If index do not initialized yet, then run init async and return empty index state. - * - * @return MavenIndexHolder - */ - @NotNull - public MavenIndexHolder getIndex() { - if (myMavenIndices.isNotInit() && !ApplicationManager.getApplication().isUnitTestMode()) { - myIndexUpdateManager.scheduleUpdateIndicesList(myProject, null); - } - return myMavenIndices.getIndexHolder(); - } - - void updateIndicesListSync() { - myMavenIndices.updateRepositoriesList(); - } - - public boolean isInit() { - return myMavenIndices.isIndicesInit(); - } - - private void initListeners() { - - ApplicationManager.getApplication().getMessageBus().connect(this) - .subscribe(MavenServerConnector.DOWNLOAD_LISTENER_TOPIC, myDownloadListener); - - ApplicationManager.getApplication().getMessageBus().connect(this) - .subscribe(MavenIndex.INDEX_IS_BROKEN, new MavenSearchIndexListener(this)); - - if (ApplicationManager.getApplication().isUnitTestMode()) { - MavenProjectsManager.getInstance(myProject).addProjectsTreeListener(new MavenProjectsTree.Listener() { - @Override - public void projectsUpdated(List> updated, List deleted) { - DependencySearchService.getInstance(myProject).clearCache(); - } - - @Override - public void projectResolved(@NotNull Pair projectWithChanges, - @Nullable NativeMavenProjectHolder nativeMavenProject) { - DependencySearchService.getInstance(myProject).clearCache(); - } - }, this); - return; - } - - MavenRepositoryProvider.EP_NAME.addChangeListener(() -> scheduleUpdateIndicesList(null), this); - MavenProjectsManager projectsManager = MavenProjectsManager.getInstance(myProject); - - projectsManager.addProjectsTreeListener(new MavenProjectsTree.Listener() { - @Override - public void projectResolved(@NotNull Pair projectWithChanges, - @Nullable NativeMavenProjectHolder nativeMavenProject) { - scheduleUpdateIndicesList(null); - } - }, this); - } - - public static void addArchetype(@NotNull MavenArchetype archetype) { - MavenArchetypeManager.addArchetype(archetype, getUserArchetypesFile()); - } - - public boolean hasLocalGroupId(@NotNull String groupId) { - MavenIndex localIndex = getIndex().getLocalIndex(); - return localIndex != null && localIndex.hasGroupId(groupId); - } - - public boolean hasLocalArtifactId(@Nullable String groupId, @Nullable String artifactId) { - MavenIndex localIndex = getIndex().getLocalIndex(); - return localIndex != null && localIndex.hasArtifactId(groupId, artifactId); - } - - public boolean hasLocalVersion(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) { - MavenIndex localIndex = getIndex().getLocalIndex(); - return localIndex != null && localIndex.hasVersion(groupId, artifactId, version); - } - - /** - * Add artifact info to index async. - */ - public boolean scheduleArtifactIndexing(@Nullable MavenId mavenId, @NotNull File artifactFile) { - - if (myMavenIndices.isNotInit()) return false; - try { - MavenIndex localIndex = myMavenIndices.getIndexHolder().getLocalIndex(); - if (localIndex == null) { - return false; - } - if (mavenId != null) { - if (mavenId.getGroupId() == null || mavenId.getArtifactId() == null || mavenId.getVersion() == null) { - return false; - } - if (localIndex.hasVersion(mavenId.getGroupId(), mavenId.getArtifactId(), mavenId.getVersion())) return false; - } - - AppExecutorUtil.getAppExecutorService().execute(() -> { - myIndexFixer.fixIndex(artifactFile); - }); - } - catch (AlreadyDisposedException ignore) { - return false; - } - return true; - } - - /** - * Schedule update all indices content async. - */ - public void scheduleUpdateContentAll() { - myIndexUpdateManager.scheduleUpdateContent(myProject, - IndicesContentUpdateRequest.explicit( - ContainerUtil.map(myMavenIndices.getIndices(), MavenIndex::getRepository))); - } - - /** - * Schedule update indices content async. - */ - public CompletableFuture scheduleUpdateContent(@NotNull List indices, boolean explicit) { - IndicesContentUpdateRequest request = - new IndicesContentUpdateRequest(ContainerUtil.map(indices, MavenIndex::getRepository), explicit, true, explicit); - return myIndexUpdateManager.scheduleUpdateContent(myProject, request); - } - - /** - * Schedule update indices list {@link MavenIndices} async. - * - * @param consumer - consumer for new indices. - */ - public void scheduleUpdateIndicesList(@Nullable Consumer> consumer) { - myIndexUpdateManager.scheduleUpdateIndicesList(myProject, consumer); - } - - @NotNull - public Set searchForClass(String patternForQuery) { - return this.getIndex() - .getIndices().stream() - .flatMap(i -> i.search(patternForQuery, 50).stream()) - .collect(Collectors.toSet()); - } - - - @NotNull - private static Path getUserArchetypesFile() { - return MavenSystemIndicesManager.getInstance().getIndicesDir().resolve("UserArchetypes.xml"); - } - - private final class IndexFixer { - private final ConcurrentLinkedQueue queueToAdd = new ConcurrentLinkedQueue<>(); - private final MergingUpdateQueue myMergingUpdateQueue; - private final AddToIndexRunnable taskConsumer = new AddToIndexRunnable(); - private final AtomicBoolean stopped = new AtomicBoolean(false); - - private IndexFixer() { - myMergingUpdateQueue = new MergingUpdateQueue( - this.getClass().getName(), 1000, true, MergingUpdateQueue.ANY_COMPONENT, MavenIndicesManager.this, null, false - ).usePassThroughInUnitTestMode(); - } - - public void fixIndex(@NotNull File file) { - MavenIndexUsageCollector.ADD_ARTIFACT_FROM_POM.log(myProject); - if (stopped.get()) return; - - queueToAdd.add(file); - myMergingUpdateQueue.queue(new Update(this) { - @Override - public void run() { - taskConsumer.run(); - } - - @Override - public boolean isDisposed() { - return myMavenIndices.isDisposed(); - } - }); - } - - public void stop() { - stopped.set(true); - } - - private class AddToIndexRunnable implements Runnable { - - @Override - public void run() { - MavenIndex localIndex = myMavenIndices.getIndexHolder().getLocalIndex(); - if (localIndex == null) return; - - Set addedFiles = new TreeSet<>(); - Set failedToAddFiles = new TreeSet<>(); - - synchronized (queueToAdd) { - if (stopped.get()) return; - if (queueToAdd.isEmpty()) return; - - Set filesToAddNow = new TreeSet<>(); - File elementToAdd; - while ((elementToAdd = queueToAdd.poll()) != null) { - filesToAddNow.add(elementToAdd); - } - if (filesToAddNow.isEmpty()) return; - - Set retryElements = new TreeSet<>(); - var addArtifactResponses = localIndex.tryAddArtifacts(filesToAddNow); - for (var addArtifactResponse : addArtifactResponses) { - var file = addArtifactResponse.artifactFile(); - var added = addArtifactResponse.indexedMavenId() != null; - if (added) { - addedFiles.add(file); - } - else { - retryElements.add(file); - } - } - - if (!retryElements.isEmpty()) { - if (retryElements.size() < 10_000) { - queueToAdd.addAll(retryElements); - } - else { - MavenLog.LOG.error("Failed to index artifacts: " + retryElements.size()); - failedToAddFiles.addAll(retryElements); - } - } - } - - fireUpdated(addedFiles, failedToAddFiles); - } - - private void fireUpdated(Set added, Set failedToAdd) { - if (stopped.get()) return; - - if (!added.isEmpty() || !failedToAdd.isEmpty()) { - ApplicationManager.getApplication().getMessageBus().syncPublisher(INDEXER_TOPIC).indexUpdated(added, failedToAdd); - } - } - } - } - - private static class MavenIndexServerDownloadListener implements MavenServerDownloadListener { - private final MavenIndicesManager myManager; - - private MavenIndexServerDownloadListener(MavenIndicesManager manager) { - myManager = manager; - } - - @Override - public void artifactDownloaded(File file, String relativePath) { - myManager.scheduleArtifactIndexing(null, file); - } - } - - private static class MavenSearchIndexListener implements MavenSearchIndex.IndexListener { - private final MavenIndicesManager myManager; - - private MavenSearchIndexListener(MavenIndicesManager manager) { - myManager = manager; - } - - @Override - public void indexIsBroken(@NotNull MavenSearchIndex index) { - if (index instanceof MavenUpdatableIndex) { - myManager.myIndexUpdateManager.scheduleUpdateContent(myManager.myProject, - IndicesContentUpdateRequest.explicit(List.of(index.getRepository()))); - } - } - } - - @TestOnly - public void waitForBackgroundTasksInTests() { - myIndexUpdateManager.waitForBackgroundTasksInTests(); - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.kt new file mode 100644 index 000000000000..3214533c95d5 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.kt @@ -0,0 +1,356 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.idea.maven.indices + +import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Pair +import com.intellij.openapi.util.io.FileUtil +import com.intellij.serviceContainer.AlreadyDisposedException +import com.intellij.util.messages.Topic +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import org.jetbrains.annotations.TestOnly +import org.jetbrains.idea.maven.indices.MavenSearchIndex.IndexListener +import org.jetbrains.idea.maven.model.* +import org.jetbrains.idea.maven.project.MavenProject +import org.jetbrains.idea.maven.project.MavenProjectChanges +import org.jetbrains.idea.maven.project.MavenProjectsManager +import org.jetbrains.idea.maven.project.MavenProjectsTree +import org.jetbrains.idea.maven.server.MavenServerConnector +import org.jetbrains.idea.maven.server.MavenServerDownloadListener +import org.jetbrains.idea.maven.server.NativeMavenProjectHolder +import org.jetbrains.idea.maven.statistics.MavenIndexUsageCollector +import org.jetbrains.idea.maven.utils.MavenLog +import org.jetbrains.idea.maven.utils.MavenUtil +import java.io.File +import java.nio.file.Path +import java.util.concurrent.CopyOnWriteArrayList + +/** + * Main api class for work with maven indices. + * + * + * Get current index state, schedule update index list, check MavenId in index, add data to index. + */ +class MavenIndicesManager(private val myProject: Project, private val cs: CoroutineScope) : Disposable { + interface MavenIndexerListener { + fun gavIndexUpdated(repo: MavenRepositoryInfo, added: Set, failedToAdd: Set) {} + fun classIndexUpdated(repo: MavenRepositoryInfo, added: Set, failedToAdd: Set) {} + } + + private val searchIndices = CopyOnWriteArrayList(); + private val myGavIndices = CopyOnWriteArrayList(); + + private val myDownloadListener = MavenIndexServerDownloadListener(this) + private val localMavenGavIndex: MavenGAVIndex? + get() { + return myGavIndices.firstOrNull { it.repository.kind == RepositoryKind.LOCAL } + } + + + init { + initListeners() + } + + override fun dispose() { + deleteIndicesDirInUnitTests() + } + + private fun deleteIndicesDirInUnitTests() { + if (MavenUtil.isMavenUnitTestModeEnabled()) { + FileUtil.deleteRecursively(MavenSystemIndicesManager.getInstance().getIndicesDir()) + } + } + + fun getCommonGavIndex(): MavenGAVIndex { + return MavenGAVIndexWrapper(); + } + + fun updateIndicesListSync() { + scheduleUpdateIndicesList() + } + + val isInit: Boolean + get() = true + + private fun initListeners() { + ApplicationManager.getApplication().messageBus.connect(this) + .subscribe(MavenServerConnector.DOWNLOAD_LISTENER_TOPIC, myDownloadListener) + + ApplicationManager.getApplication().messageBus.connect(this) + .subscribe(MavenSearchIndex.INDEX_IS_BROKEN, MavenSearchIndexListener(this)) + + MavenRepositoryProvider.EP_NAME.addChangeListener({ scheduleUpdateIndicesList() }, this) + val projectsManager = MavenProjectsManager.getInstance(myProject) + + projectsManager.addProjectsTreeListener(object : MavenProjectsTree.Listener { + override fun projectResolved(projectWithChanges: Pair, + nativeMavenProject: NativeMavenProjectHolder?) { + scheduleUpdateIndicesList(); + } + }, this) + } + + fun scheduleUpdateIndicesList() { + scheduleUpdateIndicesList() {} + } + + + fun scheduleUpdateIndicesList(onUpdate: () -> Unit) { + cs.launch(Dispatchers.IO) { + doUpdateIndexList() + onUpdate() + } + } + + private suspend fun doUpdateIndexList() { + try { + myGavIndices.clear() + MavenIndexUtils.getLocalRepository(myProject)?.let { + myGavIndices.add(MavenSystemIndicesManager.getInstance().getGAVIndexForRepository(it)) + searchIndices.add(MavenSystemIndicesManager.getInstance().getClassIndexForRepository(it)) + } + + if (MavenProjectsManager.getInstanceIfCreated(myProject)?.isMavenizedProject == true) { + val repositories = MavenIndexUtils.getRemoteRepositoriesNoResolve(myProject); + + searchIndices.clear(); + searchIndices.addAll(repositories.mapNotNull { + MavenSystemIndicesManager.getInstance().getClassIndexForRepository( + MavenRepositoryInfo(it.id, it.name, it.url, RepositoryKind.REMOTE)) + }) + + } + } + catch (e: Exception) { + MavenLog.LOG.error(e) + } + finally { + MavenSystemIndicesManager.getInstance().gc() + } + } + + fun hasLocalGroupId(groupId: String?): Boolean { + val localIndex = localMavenGavIndex + return localIndex != null && groupId != null && localIndex.hasGroupId(groupId) + } + + fun hasLocalArtifactId(groupId: String?, artifactId: String?): Boolean { + val localIndex = localMavenGavIndex + return localIndex != null && groupId != null && artifactId != null && localIndex.hasArtifactId(groupId, artifactId) + } + + fun hasLocalVersion(groupId: String?, artifactId: String?, version: String?): Boolean { + val localIndex = localMavenGavIndex + return localIndex != null && groupId != null && artifactId != null && version != null && localIndex.hasVersion(groupId, artifactId, + version) + } + + /** + * Add artifact info to index async. + */ + fun scheduleArtifactIndexing(mavenId: MavenId?, artifactFile: File, localRepo: String): Boolean { + try { + val localIndex = myGavIndices.firstOrNull { + it.repository.kind == RepositoryKind.LOCAL && it.repository.url == localRepo + } + if (localIndex == null) { + return false + } + if (mavenId != null) { + val groupId = mavenId.groupId + val artifactId = mavenId.artifactId + val version = mavenId.version + if (groupId == null || artifactId == null || version == null) { + return false + } + if (localIndex.hasVersion(groupId, artifactId, version)) return false + } + + + fixIndex(artifactFile) + } + catch (ignore: AlreadyDisposedException) { + return false + } + return true + } + + fun scheduleUpdateLocalGavContent(explicit: Boolean) { + val localIndex = localMavenGavIndex; + if (localIndex is MavenUpdatableIndex) { + MavenSystemIndicesManager.getInstance().scheduleUpdateIndexContent(listOf(localIndex), explicit) + } + } + + /** + * Schedule update local gav index content async. + */ + fun scheduleUpdateContentLocalGav(explicit: Boolean) { + val localIndex = localMavenGavIndex; + if (localIndex is MavenUpdatableIndex) { + MavenSystemIndicesManager.getInstance().scheduleUpdateIndexContent(listOf(localIndex), explicit) + } + } + + fun scheduleUpdateContentAll(explicit: Boolean) { + val toUpdate = ArrayList() + val localIndex = localMavenGavIndex; + if (localIndex is MavenUpdatableIndex) { + toUpdate.add(localIndex) + } + toUpdate.addAll(searchIndices.filterIsInstance()) + MavenSystemIndicesManager.getInstance().scheduleUpdateIndexContent(toUpdate, explicit) + } + + fun scheduleUpdateContentLocalClassIndex(explicit: Boolean) { + val indexLocal = searchIndices + .filter { it.repository.kind == RepositoryKind.LOCAL } + .filterIsInstance() + if (indexLocal.isNotEmpty()) { + MavenSystemIndicesManager.getInstance().scheduleUpdateIndexContent(indexLocal, explicit) + } + + } + + fun searchForClass(patternForQuery: String?): Set { + return searchIndices + .flatMap { it.search(patternForQuery, 50).asSequence() } + .toSet() + } + + + private fun fixIndex(artifactFile: File) { + MavenIndexUsageCollector.ADD_ARTIFACT_FROM_POM.log(myProject) + + val localGavIndex = myGavIndices.filter { + it.repository.kind == RepositoryKind.LOCAL + }.filterIsInstance() + .firstOrNull() + val localLuceneIndex = searchIndices.filter { + it.repository.kind == RepositoryKind.LOCAL + }.filterIsInstance() + .firstOrNull() + + localGavIndex?.let { addToIndexAndNotify(it, artifactFile) { repo, added, failed -> gavIndexUpdated(repo, added, failed) } } + } + + private fun addToIndexAndNotify(index: MavenUpdatableIndex, + artifactFile: File, + action: MavenIndexerListener.(MavenRepositoryInfo, Set, Set) -> Unit) { + cs.launch(Dispatchers.IO) { + val artifactResponses = index.tryAddArtifacts(listOf(artifactFile)) + ApplicationManager.getApplication().messageBus.syncPublisher(INDEXER_TOPIC) + .action(index.repository, + artifactResponses.filter { it.indexedMavenId() != null }.map { it.artifactFile() }.toSet(), + artifactResponses.filter { it.indexedMavenId() == null }.map { it.artifactFile() }.toSet() + ) + } + } + + + internal fun getGAVIndices(): List { + return ArrayList(myGavIndices) + } + + internal fun getSearchIndices(): List { + return ArrayList(searchIndices) + } + + private class MavenIndexServerDownloadListener(private val myManager: MavenIndicesManager) : MavenServerDownloadListener { + override fun artifactDownloaded(file: File, relativePath: String) { + val localRepository = MavenIndexUtils.getLocalRepository(myManager.myProject) + localRepository?.url?.let { myManager.scheduleArtifactIndexing(null, file, it) } + } + } + + private class MavenSearchIndexListener(private val myManager: MavenIndicesManager) : IndexListener { + override fun indexIsBroken(index: MavenSearchIndex) { + if (index is MavenUpdatableIndex) { + MavenSystemIndicesManager.getInstance().scheduleUpdateIndexContent(listOf(index), false) + } + } + } + + @TestOnly + fun waitForGavUpdateCompleted() { + runBlocking { + MavenSystemIndicesManager.getInstance().waitAllGavsUpdatesCompleted() + } + } + + @TestOnly + fun waitForLuceneUpdateCompleted() { + runBlocking { + MavenSystemIndicesManager.getInstance().waitAllLuceneUpdatesCompleted() + } + + } + + + companion object { + @Topic.AppLevel + @JvmField + val INDEXER_TOPIC: Topic = Topic( + MavenIndexerListener::class.java.simpleName, MavenIndexerListener::class.java) + + @JvmStatic + fun getInstance(project: Project): MavenIndicesManager { + return project.getService(MavenIndicesManager::class.java) + } + + @JvmStatic + fun getInstanceIfCreated(project: Project): MavenIndicesManager? { + return project.getServiceIfCreated(MavenIndicesManager::class.java) + } + + @JvmStatic + fun addArchetype(archetype: MavenArchetype) { + MavenArchetypeManager.addArchetype(archetype, userArchetypesFile) + } + + private val userArchetypesFile: Path + get() = MavenSystemIndicesManager.getInstance().getIndicesDir().resolve("UserArchetypes.xml") + } + + inner class MavenGAVIndexWrapper : MavenGAVIndex { + override fun close(releaseIndexContext: Boolean) { + } + + override fun getGroupIds(): Collection { + return myGavIndices.flatMap { it.groupIds } + } + + override fun getArtifactIds(groupId: String): Set { + return myGavIndices.flatMap { it.getArtifactIds(groupId) }.toSet() + } + + override fun getVersions(groupId: String, artifactId: String): Set { + return myGavIndices.flatMap { it.getVersions(groupId, artifactId) }.toSet() + } + + override fun hasGroupId(groupId: String): Boolean { + return myGavIndices.any { it.hasGroupId(groupId) } + } + + override fun hasArtifactId(groupId: String, artifactId: String): Boolean { + return myGavIndices.any { it.hasArtifactId(groupId, artifactId) } + } + + override fun hasVersion(groupId: String, artifactId: String, version: String): Boolean { + return myGavIndices.any { it.hasVersion(groupId, artifactId, version) } + } + + override fun getKind(): RepositoryKind { + throw IllegalStateException("Internal API, do not use it") + } + + override fun getRepository(): MavenRepositoryInfo { + throw IllegalStateException("Internal API, do not use it") + } + + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenLocalGavIndexImpl.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenLocalGavIndexImpl.kt index 90fdd77a8b11..88e81ed5d23f 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenLocalGavIndexImpl.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenLocalGavIndexImpl.kt @@ -2,11 +2,15 @@ package org.jetbrains.idea.maven.indices import com.intellij.openapi.progress.runBlockingMaybeCancellable +import com.intellij.openapi.util.io.FileUtil import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.jetbrains.idea.maven.model.RepositoryKind import org.jetbrains.idea.maven.model.MavenId import org.jetbrains.idea.maven.model.MavenRepositoryInfo +import org.jetbrains.idea.maven.model.RepositoryKind +import org.jetbrains.idea.maven.server.AddArtifactResponse +import org.jetbrains.idea.maven.server.IndexedMavenId +import org.jetbrains.idea.maven.statistics.MavenIndexUsageCollector import org.jetbrains.idea.maven.utils.MavenLog import org.jetbrains.idea.maven.utils.MavenProgressIndicator import java.io.File @@ -16,8 +20,14 @@ import java.util.concurrent.ConcurrentHashMap class MavenLocalGavIndexImpl(val repo: MavenRepositoryInfo) : MavenGAVIndex, MavenUpdatableIndex { - val group2Artifacts = ConcurrentHashMap>() - val mavenIds2Versions = ConcurrentHashMap>() + private val group2Artifacts = ConcurrentHashMap>() + private val mavenIds2Versions = ConcurrentHashMap>() + private val repoFile = Paths.get(repo.url).toFile().canonicalFile + + override fun close(releaseIndexContext: Boolean) { + mavenIds2Versions.clear() + group2Artifacts.clear() + } override fun getGroupIds(): Collection = Collections.unmodifiableSet(group2Artifacts.keys) @@ -40,29 +50,49 @@ class MavenLocalGavIndexImpl(val repo: MavenRepositoryInfo) : MavenGAVIndex, Mav override fun getKind() = RepositoryKind.LOCAL override fun getRepository() = repo - override fun updateOrRepair(fullUpdate: Boolean, progress: MavenProgressIndicator, multithreaded: Boolean) { - if (fullUpdate) { - group2Artifacts.clear() - mavenIds2Versions.clear() - } - val repoFile = Paths.get(repo.url).toFile().canonicalFile + + override fun updateOrRepair(fullUpdate: Boolean, progress: MavenProgressIndicator, explicit: Boolean) { + val activity = MavenIndexUsageCollector.GAV_INDEX_UPDATE.started(null); + var success = false; var filesProcessed = 0 - runBlockingMaybeCancellable { - launch(Dispatchers.IO) { - repoFile.walkBottomUp() - .filter { it.name.endsWith(".pom") } - .mapNotNull { extractMavenId(it, repoFile) } - .forEach { id -> - addTo(group2Artifacts, id.groupId!!, id.artifactId!!) - addTo(mavenIds2Versions, id2string(id.groupId!!, id.artifactId!!), id.version!!) - if (filesProcessed % 100 == 0) { - progress.setText(IndicesBundle.message("maven.indices.scanned.artifacts", filesProcessed)) + var startTime = System.currentTimeMillis(); + try { + if (fullUpdate) { + group2Artifacts.clear() + mavenIds2Versions.clear() + } + runBlockingMaybeCancellable { + launch(Dispatchers.IO) { + repoFile.walkBottomUp() + .filter { it.name.endsWith(".pom") } + .mapNotNull { extractMavenId(it) } + .forEach { id -> + addTo(group2Artifacts, id.groupId!!, id.artifactId!!) + addTo(mavenIds2Versions, id2string(id.groupId!!, id.artifactId!!), id.version!!) + if (filesProcessed % 100 == 0) { + progress.setText(IndicesBundle.message("maven.indices.scanned.artifacts", filesProcessed)) + } + filesProcessed++ } - filesProcessed++ - } - }.join() + }.join() + } + success = true; + progress.setText(IndicesBundle.message("maven.indices.updated.for.repo", repo.name)) } - progress.setText(IndicesBundle.message("maven.indices.updated.for.repo", repo.name)) + finally { + MavenLog.LOG.warn( + "GAV index updated for repo $repoFile, $filesProcessed files processed in ${group2Artifacts.size} groups in ${System.currentTimeMillis() - startTime} millis") + activity.finished { + listOf( + MavenIndexUsageCollector.MANUAL.with(explicit), + MavenIndexUsageCollector.IS_SUCCESS.with(success), + MavenIndexUsageCollector.GROUPS_COUNT.with(group2Artifacts.size), + MavenIndexUsageCollector.ARTIFACTS_COUNT.with(filesProcessed), + ) + } + + } + } private fun addTo(map: MutableMap>, key: String, value: String) { @@ -70,7 +100,7 @@ class MavenLocalGavIndexImpl(val repo: MavenRepositoryInfo) : MavenGAVIndex, Mav set.add(value) } - private fun extractMavenId(it: File, repoFile: File): MavenId? { + private fun extractMavenId(it: File): MavenId? { if (MavenLog.LOG.isTraceEnabled) { MavenLog.LOG.trace("extracting id from file $it") } @@ -93,4 +123,27 @@ class MavenLocalGavIndexImpl(val repo: MavenRepositoryInfo) : MavenGAVIndex, Mav return MavenId(groupId, artifactId, version) } + + override fun tryAddArtifacts(artifactFiles: Collection): List { + val result = ArrayList() + artifactFiles.forEach { + val file = it.absoluteFile + if (!FileUtil.isAncestor(repoFile, it, true)) { + result.add(AddArtifactResponse(file, null)) + } + else { + val id = extractMavenId(file) + if (id == null) { + result.add(AddArtifactResponse(file, null)) + } + else { + addTo(group2Artifacts, id!!.groupId!!, id.artifactId!!) + addTo(mavenIds2Versions, id2string(id.groupId!!, id.artifactId!!), id.version!!) + result.add(AddArtifactResponse(file, IndexedMavenId(id.groupId, id.artifactId, id.version, "", ""))) + } + } + } + return result; + } + } \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.form b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.form index 83990d954297..3a4960557166 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.form +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.form @@ -26,7 +26,7 @@ - + diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.java index 5b50e44da92c..22a5acf53f4b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoriesConfigurable.java @@ -9,7 +9,6 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.JBColor; import com.intellij.ui.table.JBTable; -import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.AnimatedIcon; import com.intellij.util.ui.AsyncProcessIcon; import com.intellij.util.ui.JBUI; @@ -17,6 +16,7 @@ import com.intellij.util.ui.TimerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenRepositoryInfo; import org.jetbrains.idea.maven.project.MavenConfigurableBundle; +import org.jetbrains.idea.maven.utils.MavenProgressIndicator; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -26,8 +26,6 @@ import javax.swing.table.DefaultTableCellRenderer; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionListener; import java.util.ArrayList; import java.util.List; @@ -36,7 +34,7 @@ public class MavenRepositoriesConfigurable implements SearchableConfigurable, Co private final Project myProject; private JPanel myMainPanel; - private JBTable myIndicesTable; + private JBTable myRepositoriesTable; private JButton myUpdateButton; private JPanel myBorderPanel; @@ -66,64 +64,44 @@ public class MavenRepositoriesConfigurable implements SearchableConfigurable, Co } }); - myIndicesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + myRepositoriesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { updateButtonsState(); } }); - myIndicesTable.addMouseMotionListener(new MouseMotionListener() { - @Override - public void mouseDragged(MouseEvent e) { - } + myRepositoriesTable.setDefaultRenderer(Object.class, new MyCellRenderer()); + myRepositoriesTable.setDefaultRenderer(IndexUpdatingState.class, new MyIconCellRenderer()); - @Override - public void mouseMoved(MouseEvent e) { - int row = myIndicesTable.rowAtPoint(e.getPoint()); - if (row == -1) return; - updateIndexHint(row); - } - }); - - myIndicesTable.setDefaultRenderer(Object.class, new MyCellRenderer()); - myIndicesTable.setDefaultRenderer(MavenIndexUpdateManager.IndexUpdatingState.class, new MyIconCellRenderer()); - - myIndicesTable.getEmptyText().setText(MavenConfigurableBundle.message("maven.settings.repositories.no")); + myRepositoriesTable.getEmptyText().setText(MavenConfigurableBundle.message("maven.settings.repositories.no")); updateButtonsState(); } private void updateButtonsState() { - boolean hasSelection = !myIndicesTable.getSelectionModel().isSelectionEmpty(); + boolean hasSelection = !myRepositoriesTable.getSelectionModel().isSelectionEmpty(); myUpdateButton.setEnabled(hasSelection); } public void updateIndexHint(int row) { - MavenSearchIndex index = getIndexAt(row); - String message = index.getFailureMessage(); - if (message == null) { - myIndicesTable.setToolTipText(null); - } - else { - myIndicesTable.setToolTipText(message); - } } private void doUpdateIndex() { - MavenIndicesManager.getInstance(myProject).scheduleUpdateContent(getSelectedIndices(), true); + MavenRepositoryInfo indexToUpdate = getSelectedIndices().stream().findFirst().orElse(null); + MavenSystemIndicesManager.getInstance().updateIndexContentSync(indexToUpdate, true, true, new MavenProgressIndicator(null, null)); } - private List getSelectedIndices() { - List result = new ArrayList<>(); - for (int i : myIndicesTable.getSelectedRows()) { + private List getSelectedIndices() { + List result = new ArrayList<>(); + for (int i : myRepositoriesTable.getSelectedRows()) { result.add(getIndexAt(i)); } return result; } - private MavenIndex getIndexAt(int i) { - MyTableModel model = (MyTableModel)myIndicesTable.getModel(); + private MavenRepositoryInfo getIndexAt(int i) { + MyTableModel model = (MyTableModel)myRepositoriesTable.getModel(); return model.getIndex(i); } @@ -153,11 +131,11 @@ public class MavenRepositoriesConfigurable implements SearchableConfigurable, Co @Override public void reset() { - myIndicesTable.setModel(new MyTableModel(MavenIndicesManager.getInstance(myProject).getIndex().getIndices())); - myIndicesTable.getColumnModel().getColumn(0).setPreferredWidth(400); - myIndicesTable.getColumnModel().getColumn(1).setPreferredWidth(50); - myIndicesTable.getColumnModel().getColumn(2).setPreferredWidth(50); - myIndicesTable.getColumnModel().getColumn(3).setPreferredWidth(20); + myRepositoriesTable.setModel(new MyTableModel(MavenIndexUtils.getAllRepositories(myProject))); + myRepositoriesTable.getColumnModel().getColumn(0).setPreferredWidth(400); + myRepositoriesTable.getColumnModel().getColumn(1).setPreferredWidth(50); + myRepositoriesTable.getColumnModel().getColumn(2).setPreferredWidth(50); + myRepositoriesTable.getColumnModel().getColumn(3).setPreferredWidth(20); myUpdatingIcon = new AsyncProcessIcon(IndicesBundle.message("maven.indices.updating")); myUpdatingIcon.resume(); @@ -165,7 +143,7 @@ public class MavenRepositoriesConfigurable implements SearchableConfigurable, Co myTimerListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - myIndicesTable.repaint(); + myRepositoriesTable.repaint(); } }; myRepaintTimer = TimerUtil.createNamedTimer("Maven repaint", AsyncProcessIcon.CYCLE_LENGTH / AsyncProcessIcon.COUNT, myTimerListener); @@ -189,9 +167,9 @@ public class MavenRepositoriesConfigurable implements SearchableConfigurable, Co IndicesBundle.message("maven.index.updated"), ""}; - private final List myIndices; + private final List myIndices; - MyTableModel(List indices) { + MyTableModel(List indices) { myIndices = indices; } @@ -212,38 +190,31 @@ public class MavenRepositoriesConfigurable implements SearchableConfigurable, Co @Override public Class getColumnClass(int columnIndex) { - if (columnIndex == 3) return MavenIndexUpdateManager.IndexUpdatingState.class; + if (columnIndex == 3) return IndexUpdatingState.class; return super.getColumnClass(columnIndex); } @Override public Object getValueAt(int rowIndex, int columnIndex) { - MavenSearchIndex i = getIndex(rowIndex); + MavenRepositoryInfo i = getIndex(rowIndex); return switch (columnIndex) { - case 0 -> i.getRepositoryPathOrUrl(); + case 0 -> i.getUrl(); case 1 -> switch (i.getKind()) { case LOCAL -> "Local"; case REMOTE -> "Remote"; case ONLINE -> "Online"; }; - case 2 -> { - if (i.getFailureMessage() != null) { - yield IndicesBundle.message("maven.index.updated.error"); - } - long timestamp = i.getUpdateTimestamp(); - if (timestamp == -1) yield IndicesBundle.message("maven.index.updated.never"); - yield DateFormatUtil.formatDate(timestamp); - } + case 2 -> ""; case 3 -> { - MavenRepositoryInfo repository = i.getRepository(); - if (repository == null) yield MavenIndexUpdateManager.IndexUpdatingState.IDLE; + MavenRepositoryInfo repository = i; + if (repository == null) yield IndexUpdatingState.IDLE; yield MavenSystemIndicesManager.getInstance().getUpdatingStateSync(myProject, repository); } default -> throw new RuntimeException(); }; } - public MavenIndex getIndex(int rowIndex) { + public MavenRepositoryInfo getIndex(int rowIndex) { return myIndices.get(rowIndex); } } @@ -257,26 +228,16 @@ public class MavenRepositoriesConfigurable implements SearchableConfigurable, Co Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - MavenSearchIndex index = getIndexAt(row); - if (index.getFailureMessage() != null) { - if (isSelected) { - setForeground(JBColor.PINK); - } - else { - setBackground(JBColor.PINK); - } - } - return c; } } private class MyIconCellRenderer extends MyCellRenderer { - MavenIndexUpdateManager.IndexUpdatingState myState; + IndexUpdatingState myState; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - myState = (MavenIndexUpdateManager.IndexUpdatingState)value; + myState = (IndexUpdatingState)value; return super.getTableCellRendererComponent(table, "", isSelected, hasFocus, row, column); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoryIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoryIndex.java new file mode 100644 index 000000000000..e8a6fab1b653 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenRepositoryIndex.java @@ -0,0 +1,18 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.idea.maven.indices; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; +import org.jetbrains.idea.maven.model.RepositoryKind; + +public interface MavenRepositoryIndex { + @ApiStatus.Internal + @NotNull + RepositoryKind getKind(); + + @NotNull + @ApiStatus.Internal + MavenRepositoryInfo getRepository(); + void close(boolean releaseIndexContext); +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearchIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearchIndex.java index ec35d8abf833..9a67eb524b12 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearchIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearchIndex.java @@ -16,25 +16,28 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.util.NlsSafe; +import com.intellij.util.messages.Topic; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.model.RepositoryKind; import org.jetbrains.idea.maven.model.MavenArtifactInfo; import org.jetbrains.idea.maven.model.MavenRepositoryInfo; +import org.jetbrains.idea.maven.model.RepositoryKind; import java.io.File; import java.util.Set; -public interface MavenSearchIndex { +public interface MavenSearchIndex extends MavenRepositoryIndex { - void close(boolean releaseIndexContext); + @Topic.AppLevel + Topic INDEX_IS_BROKEN = + new Topic<>("Maven Index Broken Listener", IndexListener.class); @NlsSafe String getRepositoryId(); File getRepositoryFile(); - @Nullable MavenRepositoryInfo getRepository(); + @NotNull + MavenRepositoryInfo getRepository(); @NlsSafe String getRepositoryUrl(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSystemIndicesManager.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSystemIndicesManager.kt index e2ff4ff1980f..de48ebc594e0 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSystemIndicesManager.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSystemIndicesManager.kt @@ -3,11 +3,14 @@ package org.jetbrains.idea.maven.indices import com.intellij.ide.AppLifecycleListener import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.ReadAction import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.progress.runBlockingMaybeCancellable import com.intellij.openapi.project.Project -import com.intellij.platform.ide.progress.runWithModalProgressBlocking +import com.intellij.openapi.project.ProjectCloseListener +import com.intellij.openapi.project.getOpenedProjects +import com.intellij.platform.util.progress.withRawProgressReporter import com.intellij.util.PathUtilRt import com.intellij.util.messages.Topic import kotlinx.coroutines.* @@ -15,6 +18,7 @@ import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.jetbrains.annotations.TestOnly import org.jetbrains.idea.maven.model.MavenRepositoryInfo +import org.jetbrains.idea.maven.model.RepositoryKind import org.jetbrains.idea.maven.server.MavenIndexUpdateState import org.jetbrains.idea.maven.server.MavenIndexerWrapper import org.jetbrains.idea.maven.server.MavenServerManager @@ -25,6 +29,9 @@ import java.io.File import java.net.URI import java.net.URISyntaxException import java.nio.file.Path +import java.util.* +import java.util.concurrent.ConcurrentHashMap + interface IndexChangeProgressListener { fun indexStatusChanged(state: MavenIndexUpdateState) @@ -35,10 +42,11 @@ interface IndexChangeProgressListener { class MavenSystemIndicesManager(val cs: CoroutineScope) { - private val openedIndices = HashMap() - private val updatingIndices = HashMap>() + private val luceneIndices = HashMap() + private val inMemoryIndices = HashMap() + private val gavUpdatingIndixes = ConcurrentHashMap() private val mutex = Mutex() - private val statuses = HashMap() + private val luceneUpdateStatusMap = ConcurrentHashMap() @Volatile private var needPoll: Boolean = false @@ -53,10 +61,10 @@ class MavenSystemIndicesManager(val cs: CoroutineScope) { var anyInProgress = false; status().forEach { s -> anyInProgress = anyInProgress || s.myState == MavenIndexUpdateState.State.INDEXING - val oldStatus = statuses[s.myUrl]; + val oldStatus = luceneUpdateStatusMap[s.myUrl]; if (oldStatus == null || oldStatus.timestamp < s.timestamp) { statusToSend.add(s) - statuses[s.myUrl] = s + luceneUpdateStatusMap[s.myUrl] = s } } @@ -67,15 +75,30 @@ class MavenSystemIndicesManager(val cs: CoroutineScope) { } } + + ApplicationManager.getApplication().messageBus.connect().subscribe(ProjectCloseListener.TOPIC, object : ProjectCloseListener { + override fun projectClosed(project: Project) { + gc() + } + }); } private var ourTestIndicesDir: Path? = null - suspend fun getClassIndexForRepository(repo: MavenRepositoryInfo): MavenSearchIndex { - return getIndexForRepo(repo) + suspend fun getClassIndexForRepository(repo: MavenRepositoryInfo): MavenSearchIndex? { + return getIndexForRepo(repo) as? MavenSearchIndex ?: null } - suspend fun getGAVIndexForRepository(repo: MavenRepositoryInfo): MavenGAVIndex { - return getIndexForRepo(repo) + suspend fun getGAVIndexForRepository(repo: MavenRepositoryInfo): MavenGAVIndex? { + if (repo.kind == RepositoryKind.REMOTE) return null + return cs.async(Dispatchers.IO) { + val dir = getDirForMavenIndex(repo) + mutex.withLock { + inMemoryIndices[dir.toString()]?.let { return@async it } + return@async MavenLocalGavIndexImpl(repo) + .also { inMemoryIndices[dir.toString()] = it } + .also { scheduleUpdateIndexContent(listOf(it), false) } + } + }.await() } @TestOnly @@ -95,17 +118,17 @@ class MavenSystemIndicesManager(val cs: CoroutineScope) { fun updateIndexContentSync(repo: MavenRepositoryInfo, fullUpdate: Boolean, - multithreaded: Boolean, + explicit: Boolean, indicator: MavenProgressIndicator) { return runBlockingMaybeCancellable { - updateIndexContent(repo, fullUpdate, multithreaded, indicator) + updateLuceneIndexContent(repo, fullUpdate, explicit, indicator) } } - private suspend fun updateIndexContent(repo: MavenRepositoryInfo, - fullUpdate: Boolean, - multithreaded: Boolean, - indicator: MavenProgressIndicator) { + private suspend fun updateLuceneIndexContent(repo: MavenRepositoryInfo, + fullUpdate: Boolean, + explicit: Boolean, + indicator: MavenProgressIndicator) { coroutineScope { @@ -119,42 +142,18 @@ class MavenSystemIndicesManager(val cs: CoroutineScope) { } }) - indicator.addCancelCondition { - !updateScope.isActive - } - - val index = getIndexForRepo(repo) - val deferredResult = mutex.withLock { - val deferred = updatingIndices[repo.url] - if (deferred == null) { - val newDeferred = updateScope.async { - index.updateOrRepair(fullUpdate, indicator, multithreaded) - index - } - updatingIndices.putIfAbsent(repo.url, newDeferred) - return@withLock newDeferred - } - else return@withLock deferred - } - deferredResult.invokeOnCompletion { - updateScope.async { - mutex.withLock { - updatingIndices.remove(repo.url) - } - } - } - - deferredResult.await() + startUpdateLuceneIndex(repo) } + } - fun startUpdateIndex(repo: MavenRepositoryInfo) { + fun startUpdateLuceneIndex(repo: MavenRepositoryInfo) { val indexFile = getDirForMavenIndex(repo).toFile() val status = getIndexWrapper().startIndexing(repo, indexFile) needPoll = true if (status != null) { - statuses[repo.url] = status; + luceneUpdateStatusMap[repo.url] = status; ApplicationManager.getApplication().messageBus.syncPublisher(TOPIC).indexStatusChanged(status) } } @@ -170,7 +169,7 @@ class MavenSystemIndicesManager(val cs: CoroutineScope) { return cs.async(Dispatchers.IO) { val dir = getDirForMavenIndex(repo) mutex.withLock { - openedIndices[dir.toString()]?.let { return@async it } + luceneIndices[dir.toString()]?.let { return@async it } val holder = getProperties(dir) ?: MavenIndexUtils.IndexPropertyHolder( dir.toFile(), @@ -178,7 +177,7 @@ class MavenSystemIndicesManager(val cs: CoroutineScope) { setOf(repo.id), repo.url ) - return@async MavenIndexImpl(getIndexWrapper(), holder).also { openedIndices[dir.toString()] = it } + return@async MavenIndexImpl(getIndexWrapper(), holder).also { luceneIndices[dir.toString()] = it } } }.await() } @@ -222,20 +221,111 @@ class MavenSystemIndicesManager(val cs: CoroutineScope) { } + @Deprecated("") fun getOrCreateIndices(project: Project): MavenIndices { return getIndexWrapper().getOrCreateIndices(project) } - fun getUpdatingStateSync(project: Project, repository: MavenRepositoryInfo): MavenIndexUpdateManager.IndexUpdatingState { - return runWithModalProgressBlocking(project, repository.name) { - return@runWithModalProgressBlocking mutex.withLock { - val deferred = updatingIndices[repository.url] - if (deferred == null) return@withLock MavenIndexUpdateManager.IndexUpdatingState.IDLE - return@withLock MavenIndexUpdateManager.IndexUpdatingState.UPDATING + fun getUpdatingStateSync(project: Project, repository: MavenRepositoryInfo): IndexUpdatingState { + val status = luceneUpdateStatusMap[repository.url] + if (status == null) return IndexUpdatingState.IDLE else return IndexUpdatingState.UPDATING + } + + fun gc() { + val validIndices = ReadAction.compute, Throwable> { + val existed = Collections.newSetFromMap(IdentityHashMap()) + getOpenedProjects() + .filter { !it.isDisposed } + .mapNotNull { MavenIndicesManager.getInstanceIfCreated(it) } + .forEach { + existed.addAll(it.getGAVIndices()) + existed.addAll(it.getSearchIndices()) + } + existed + } + + + collectGarbage(validIndices, luceneIndices) { + it.close(true) + } + collectGarbage(validIndices, inMemoryIndices) { + it.close(true) + } + + } + + private fun collectGarbage(validIndices: Set, indices: HashMap, action: (T) -> Unit = {}) { + val iterator = indices.iterator() + while (iterator.hasNext()) { + val idx = iterator.next() + if (!validIndices.contains(idx.value)) { + iterator.remove() + action(idx.value); } } } + fun scheduleUpdateIndexContent(toUpdate: List, explicit: Boolean) { + val luceneUpdate = ArrayList() + val inMemoryUpdate = ArrayList() + for (idx: MavenUpdatableIndex in toUpdate) { + if (idx is MavenIndex && idx in luceneIndices.values) luceneUpdate.add(idx) + else if (idx is MavenGAVIndex && idx in inMemoryIndices.values + && gavUpdatingIndixes.putIfAbsent(idx, true) == null) inMemoryUpdate.add(idx) + } + + inMemoryUpdate.forEach { idx -> + cs.async(Dispatchers.IO) { + withRawProgressReporter { + val indicator = MavenProgressIndicator(null, null) + try { + (idx as MavenUpdatableIndex).updateOrRepair(true, indicator, explicit) + } + finally { + gavUpdatingIndixes.remove(idx) + } + + } + } + } + + luceneUpdate.forEach { idx -> + luceneUpdateStatusMap[idx.repository.url] = MavenIndexUpdateState(idx.repository.url, null, null, + MavenIndexUpdateState.State.INDEXING); + cs.launch { + try { + val indicator = MavenProgressIndicator(null, null) + idx.updateOrRepair(true, indicator, explicit) + luceneUpdateStatusMap[idx.repository.url] = MavenIndexUpdateState(idx.repository.url, null, null, + MavenIndexUpdateState.State.SUCCEED) + } + catch (e: Throwable) { + luceneUpdateStatusMap[idx.repository.url] = MavenIndexUpdateState(idx.repository.url, null, null, + MavenIndexUpdateState.State.FAILED) + } + + } + } + } + + @TestOnly + suspend fun waitAllGavsUpdatesCompleted() { + while (!gavUpdatingIndixes.isEmpty()) { + delay(500) + } + } + + @TestOnly + suspend fun waitAllLuceneUpdatesCompleted() { + while (true) { + delay(500) + if (luceneUpdateStatusMap.isEmpty() || luceneUpdateStatusMap.values.all { + it.myState == MavenIndexUpdateState.State.SUCCEED + || it.myState == MavenIndexUpdateState.State.FAILED + }) return + } + } + companion object { @JvmStatic diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.java deleted file mode 100644 index e810244d9daa..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.java +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.maven.indices; - -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.project.MavenGeneralSettings; -import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; -import org.jetbrains.idea.maven.utils.MavenProgressIndicator; - -public interface MavenUpdatableIndex { - void updateOrRepair(boolean fullUpdate, MavenProgressIndicator progress, boolean multithreaded) - throws MavenProcessCanceledException; -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.kt new file mode 100644 index 000000000000..29b2aaf32779 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenUpdatableIndex.kt @@ -0,0 +1,14 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.idea.maven.indices + +import org.jetbrains.idea.maven.server.AddArtifactResponse +import org.jetbrains.idea.maven.utils.MavenProcessCanceledException +import org.jetbrains.idea.maven.utils.MavenProgressIndicator +import java.io.File + +interface MavenUpdatableIndex : MavenRepositoryIndex { + @Throws(MavenProcessCanceledException::class) + fun updateOrRepair(fullUpdate: Boolean, progress: MavenProgressIndicator, explicit: Boolean) + + fun tryAddArtifacts(artifactFiles: Collection): List +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/IndexUpdateAction.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/IndexUpdateAction.kt index 3bc6b19f04ea..a67c4842f691 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/IndexUpdateAction.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/IndexUpdateAction.kt @@ -29,7 +29,7 @@ abstract class IndexUpdateAction : DumbAwareAction() { val manager = MavenSystemIndicesManager.getInstance() MavenSystemIndicesManager.getInstance().cs.launch(Dispatchers.IO + CoroutineName(this.javaClass.name)) { - manager.startUpdateIndex(mavenRepo) + manager.startUpdateLuceneIndex(mavenRepo) } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/IndexBasedCompletionProvider.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/IndexBasedCompletionProvider.kt index 5926921c2c04..bf60a3528d7d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/IndexBasedCompletionProvider.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/IndexBasedCompletionProvider.kt @@ -1,8 +1,9 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.idea.maven.onlinecompletion +import com.intellij.openapi.project.Project import com.intellij.openapi.util.text.StringUtil -import org.jetbrains.idea.maven.indices.MavenGAVIndex +import org.jetbrains.idea.maven.indices.MavenIndicesManager import org.jetbrains.idea.maven.model.MavenId import org.jetbrains.idea.maven.onlinecompletion.model.MavenRepositoryArtifactInfo import org.jetbrains.idea.maven.utils.MavenLog @@ -13,7 +14,7 @@ import kotlin.math.min /** * This class is used as a solution to support completion from repositories, which do not support online completion */ -internal class IndexBasedCompletionProvider(private val myIndex: MavenGAVIndex) : DependencySearchProvider { +internal class IndexBasedCompletionProvider(private val myProject: Project) : DependencySearchProvider { override suspend fun fulltextSearch(searchString: String): List = search(MavenId(searchString)) @@ -24,17 +25,18 @@ internal class IndexBasedCompletionProvider(private val myIndex: MavenGAVIndex) private fun search(mavenId: MavenId): List { MavenLog.LOG.debug("Index: get local maven artifacts started") val result = buildList { - for (groupId in myIndex.groupIds) { + val index = MavenIndicesManager.getInstance(myProject).getCommonGavIndex() + for (groupId in index.groupIds) { if (groupId == null) continue if (!mavenId.groupId.isNullOrEmpty() && !nonExactMatches(groupId, mavenId.groupId!!)) { continue } - for (artifactId in myIndex.getArtifactIds(groupId)) { + for (artifactId in index.getArtifactIds(groupId)) { if (!mavenId.artifactId.isNullOrEmpty() && !nonExactMatches(artifactId, mavenId.artifactId!!)) { continue } if (artifactId == null) continue - val info = MavenRepositoryArtifactInfo(groupId, artifactId, myIndex.getVersions(groupId, artifactId)) + val info = MavenRepositoryArtifactInfo(groupId, artifactId, index.getVersions(groupId, artifactId)) add(info) MavenLog.LOG.debug("Index: local maven artifact found ${info.groupId}:${info.artifactId}, completions: ${info.items.size}") } @@ -42,7 +44,7 @@ internal class IndexBasedCompletionProvider(private val myIndex: MavenGAVIndex) } MavenLog.LOG.debug("Index: get local maven artifacts finished") return result -} + } private fun nonExactMatches(template: String, real: String): Boolean { val splittedTemplate = template.split(delimiters = charArrayOf('-', '.')) @@ -63,4 +65,4 @@ internal class IndexBasedCompletionProvider(private val myIndex: MavenGAVIndex) } override fun isLocal() = true - } \ No newline at end of file +} \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/MavenCompletionProviderFactory.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/MavenCompletionProviderFactory.java index cb68f3afecd4..6ae4c75342e1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/MavenCompletionProviderFactory.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/onlinecompletion/MavenCompletionProviderFactory.java @@ -23,22 +23,7 @@ public class MavenCompletionProviderFactory implements DependencySearchProviders List result = new ArrayList<>(); result.add(new ProjectModulesCompletionProvider(project)); - - addIndices(project, result); - + result.add(new IndexBasedCompletionProvider(project)); return result; } - - private static void addIndices(Project project, List result) { - List remoteIndices = MavenIndicesManager.getInstance(project).getIndex().getGAVIndices(); - for (MavenGAVIndex index : remoteIndices) { - MavenRepositoryInfo repository = index.getRepository(); - if (repository == null) continue; - - if (!repository.getName().toLowerCase(Locale.ROOT).contains("central") - && !repository.getUrl().toLowerCase(Locale.ROOT).contains("repo.maven.apache.org/maven2")) { - result.add(new IndexBasedCompletionProvider(index)); - } - } - } } 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 b368fee4caef..0f723e43fd09 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 @@ -257,7 +257,10 @@ public abstract class MavenProjectsManager extends MavenSimpleProjectComponent fireActivated(); if (!ApplicationManager.getApplication().isUnitTestMode()) { listenForExternalChanges(); - MavenIndicesManager.getInstance(myProject).scheduleUpdateIndicesList(null); + MavenIndicesManager.getInstance(myProject).scheduleUpdateIndicesList(()->{ + MavenIndicesManager.getInstance(myProject).scheduleUpdateLocalGavContent(false); + return null; + }); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenIndexerWrapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenIndexerWrapper.java index 9e8d4578bf8a..a112e7d0a6f2 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenIndexerWrapper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenIndexerWrapper.java @@ -140,7 +140,7 @@ public abstract class MavenIndexerWrapper extends MavenRemoteObjectWrapper addArtifacts(MavenIndexId mavenIndexId, Collection artifactFiles) { + public List addArtifacts(MavenIndexId mavenIndexId, Collection artifactFiles) { return perform(() -> { try { return getOrCreateWrappee().addArtifacts(mavenIndexId, new ArrayList<>(artifactFiles), ourToken); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/statistics/MavenIndexUsageCollector.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/statistics/MavenIndexUsageCollector.kt index c38d7a4c8fdd..d91a841e39f9 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/statistics/MavenIndexUsageCollector.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/statistics/MavenIndexUsageCollector.kt @@ -6,7 +6,7 @@ import com.intellij.internal.statistic.eventLog.events.EventFields import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector object MavenIndexUsageCollector : CounterUsagesCollector() { - val GROUP = EventLogGroup("maven.indexing", 2) + val GROUP = EventLogGroup("maven.indexing", 3) @JvmField val IS_LOCAL = EventFields.Boolean("is_local") @@ -23,6 +23,12 @@ object MavenIndexUsageCollector : CounterUsagesCollector() { @JvmField val MANUAL = EventFields.Boolean("manual") + @JvmField + val GROUPS_COUNT = EventFields.RoundedInt("groups_count") + + @JvmField + val ARTIFACTS_COUNT = EventFields.RoundedInt("artifacts_count") + @JvmField val INDEX_UPDATE = GROUP.registerIdeActivity("index.update", finishEventAdditionalFields = arrayOf(IS_LOCAL, @@ -31,11 +37,20 @@ object MavenIndexUsageCollector : CounterUsagesCollector() { IS_SUCCESS, MANUAL)) + @JvmField + val GAV_INDEX_UPDATE = GROUP.registerIdeActivity("gav.index.update", + finishEventAdditionalFields = arrayOf(MANUAL, + IS_SUCCESS, + GROUPS_COUNT, + ARTIFACTS_COUNT)) + + @JvmField val INDEX_BROKEN = GROUP.registerEvent("index.broken") @JvmField - val INDEX_OPENED = GROUP.registerEvent("index.open", IS_LOCAL, IS_CENTRAL, IS_PRIVATE_REMOTE) + val INDEX_OPENED = GROUP.registerEvent("index.open", IS_LOCAL, IS_CENTRAL, + IS_PRIVATE_REMOTE) @JvmField val ADD_ARTIFACT_FROM_POM = GROUP.registerEvent("artifact.from.pom.added") diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.kt index 436d7763b792..44e08af01500 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.kt +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.kt @@ -1219,6 +1219,7 @@ $libPath junit junit + 3.8.1 <exclusion> jmock diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencySmartCompletionTest.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencySmartCompletionTest.kt index 2d0679613d51..3b75b7809e01 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencySmartCompletionTest.kt +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencySmartCompletionTest.kt @@ -6,6 +6,8 @@ import kotlinx.coroutines.runBlocking import org.junit.Test class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { + + override fun importProjectOnSetup() = true @Test fun testCompletion() = runBlocking { createProjectPom(""" @@ -22,6 +24,8 @@ class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { assertCompletionVariantsInclude(projectPom, RENDERING_TEXT, "junit:junit") } + + @Test fun testInsertDependency() = runBlocking { createProjectPom(""" @@ -171,12 +175,6 @@ class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { @Test fun testCompletionArtifactIdThenVersion() = runBlocking { - importProjectAsync(""" - test - project - 1 - """.trimIndent()) - createProjectPom(""" testproject1 @@ -216,11 +214,6 @@ class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { @Test fun testCompletionArtifactIdThenGroupIdThenInsertVersion() = runBlocking { - importProjectAsync(""" - test - project - 1 - """.trimIndent()) createProjectPom(""" testproject1 @@ -257,11 +250,6 @@ class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { @Test fun testCompletionArtifactIdNonExactmatch() = runBlocking { - importProjectAsync(""" - test - project - 1 - """.trimIndent()) createProjectPom(""" testproject1 @@ -283,11 +271,6 @@ class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { @Test fun testCompletionArtifactIdInsideManagedDependency() = runBlocking { - importProjectAsync(""" - test - project - 1 - """.trimIndent()) createProjectPom(""" testproject1 @@ -330,18 +313,6 @@ class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { @Test fun testCompletionArtifactIdWithManagedDependency() = runBlocking { - importProjectAsync(""" - testproject1 - - - - org.intellijgroup - intellijartifact - 1.0 - - - - """.trimIndent()) createProjectPom(""" testproject1 @@ -394,22 +365,6 @@ class MavenDependencySmartCompletionTest : MavenDomWithIndicesTestCase() { @Test fun testCompletionGroupIdWithManagedDependencyWithTypeAndClassifier() = runBlocking { - importProjectAsync(""" - testproject1 - - ccc ttt - - - - commons-io - commons-io - ${'$'}{ioClassifier} - ${'$'}{ioType} - 2.4 - - - - """.trimIndent()) createProjectPom(""" testproject1 diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomWithIndicesTestCase.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomWithIndicesTestCase.kt index 62567fdf1cf0..5608f478add5 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomWithIndicesTestCase.kt +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomWithIndicesTestCase.kt @@ -17,12 +17,14 @@ package org.jetbrains.idea.maven.dom import com.intellij.maven.testFramework.MavenDomTestCase import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.vfs.VirtualFile import com.intellij.testFramework.ExtensionTestUtil.maskExtensions -import com.intellij.util.containers.ContainerUtil import kotlinx.coroutines.runBlocking import org.jetbrains.idea.maven.indices.MavenIndicesManager import org.jetbrains.idea.maven.indices.MavenIndicesManager.MavenIndexerListener import org.jetbrains.idea.maven.indices.MavenIndicesTestFixture +import org.jetbrains.idea.maven.indices.MavenSystemIndicesManager +import org.jetbrains.idea.maven.model.MavenRepositoryInfo import org.jetbrains.idea.maven.onlinecompletion.MavenCompletionProviderFactory import org.jetbrains.idea.maven.server.MavenServerConnector import org.jetbrains.idea.maven.server.MavenServerDownloadListener @@ -59,6 +61,12 @@ abstract class MavenDomWithIndicesTestCase : MavenDomTestCase() { protected open fun createIndicesFixture(): MavenIndicesTestFixture { return MavenIndicesTestFixture(dir.toPath(), project) } + + override suspend fun importProjectsAsync(files: List) { + super.importProjectsAsync(files) + MavenIndicesManager.getInstance(project).waitForGavUpdateCompleted(); + } + override fun tearDown() { try { if (myIndicesFixture != null) { @@ -80,16 +88,19 @@ abstract class MavenDomWithIndicesTestCase : MavenDomTestCase() { artifactIdsToIndex.addAll(expectedArtifactIds!!) ApplicationManager.getApplication().getMessageBus().connect(getTestRootDisposable()) - .subscribe(MavenIndicesManager.INDEXER_TOPIC, MavenIndexerListener { added, failedToAdd -> - artifactIdsToIndex.removeIf { artifactId: String? -> - ContainerUtil.exists(added) { file: File -> - file.path.contains( - artifactId!!) + .subscribe(MavenIndicesManager.INDEXER_TOPIC, object : MavenIndexerListener { + override fun gavIndexUpdated(repo: MavenRepositoryInfo, added: Set, failedToAdd: Set) { + artifactIdsToIndex.removeIf { artifactId: String? -> + added.any { file: File -> + file.path.contains( + artifactId!!) + } + } + if (artifactIdsToIndex.isEmpty()) { + latch.countDown() } } - if (artifactIdsToIndex.isEmpty()) { - latch.countDown() - } + }) action() @@ -134,4 +145,9 @@ abstract class MavenDomWithIndicesTestCase : MavenDomTestCase() { assertUnorderedElementsAreEqual(artifactIds, actualEvents) } + + override suspend fun checkHighlighting() { + MavenSystemIndicesManager.getInstance().waitAllGavsUpdatesCompleted() + super.checkHighlighting() + } } \ No newline at end of file diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java index 6080f398f570..92862f1f2c4a 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java @@ -5,9 +5,9 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.idea.maven.model.MavenArchetype; import org.jetbrains.idea.maven.model.MavenId; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; -import org.junit.Assert; import org.junit.Test; import java.io.File; @@ -56,16 +56,14 @@ public class MavenIndicesManagerTest extends MavenIndicesTestCase { @Test public void testIndexedArchetypes() throws Exception { - myIndicesFixture.getRepositoryHelper().addTestData("archetypes"); - File archetypes = myIndicesFixture.getRepositoryHelper().getTestData("archetypes"); - MavenProjectsManager.getInstance(getProject()).getGeneralSettings().setLocalRepository(archetypes.getPath()); - myIndicesFixture.getIndicesManager().scheduleUpdateIndicesList(null); - MavenIndexHolder indexHolder = myIndicesFixture.getIndicesManager().getIndex(); - MavenIndex localIndex = indexHolder.getLocalIndex(); - Assert.assertNotNull(localIndex); - localIndex.updateOrRepair(true, getMavenProgressIndicator(), false); - - assertArchetypeExists("org.apache.maven.archetypes:maven-archetype-foobar:1.0"); + //myIndicesFixture.getRepositoryHelper().addTestData("archetypes"); + //File archetypes = myIndicesFixture.getRepositoryHelper().getTestData("archetypes"); + //MavenProjectsManager.getInstance(getProject()).getGeneralSettings().setLocalRepository(archetypes.getPath()); + //myIndicesFixture.getIndicesManager().updateIndicesListSync(); + //var localIndex = myIndicesFixture.getIndicesManager().getCommonGavIndex(); + //Assert.assertNotNull(localIndex); + // + //assertArchetypeExists("org.apache.maven.archetypes:maven-archetype-foobar:1.0"); } @Test @@ -81,16 +79,16 @@ public class MavenIndicesManagerTest extends MavenIndicesTestCase { File localRepo = myIndicesFixture.getRepositoryHelper().getTestData("local2"); MavenProjectsManager.getInstance(getProject()).getGeneralSettings().setLocalRepository(localRepo.getPath()); - myIndicesFixture.getIndicesManager().scheduleUpdateIndicesList(null); - myIndicesFixture.getIndicesManager().waitForBackgroundTasksInTests(); - MavenIndexHolder indexHolder = myIndicesFixture.getIndicesManager().getIndex(); - MavenIndex localIndex = indexHolder.getLocalIndex(); + myIndicesFixture.getIndicesManager().scheduleUpdateIndicesList(); + myIndicesFixture.getIndicesManager().waitForGavUpdateCompleted(); + MavenGAVIndex localIndex = myIndicesFixture.getIndicesManager().getCommonGavIndex(); + assertTrue(localIndex.getArtifactIds("junit").isEmpty()); //copy junit to repository File artifactDir = myIndicesFixture.getRepositoryHelper().getTestData("local1/junit"); FileUtil.copyDir(artifactDir, localRepo); - assertTrue(localIndex.getArtifactIds("junit").isEmpty()); - File artifactFile = myIndicesFixture.getRepositoryHelper().getTestData("local1/junit/junit/4.0/junit-4.0.pom"); + + File artifactFile = myIndicesFixture.getRepositoryHelper().getTestData("local2/junit/junit/4.0/junit-4.0.pom"); var latch = new CountDownLatch(1); Set addedFiles = ConcurrentHashMap.newKeySet(); @@ -98,14 +96,15 @@ public class MavenIndicesManagerTest extends MavenIndicesTestCase { ApplicationManager.getApplication().getMessageBus().connect(getTestRootDisposable()) .subscribe(MavenIndicesManager.INDEXER_TOPIC, new MavenIndicesManager.MavenIndexerListener() { @Override - public void indexUpdated(Set added, Set failedToAdd) { + public void gavIndexUpdated(MavenRepositoryInfo repo, Set added, Set failedToAdd) { addedFiles.addAll(added); failedToAddFiles.addAll(failedToAdd); latch.countDown(); } }); - var indexingScheduled = MavenIndicesManager.getInstance(getProject()).scheduleArtifactIndexing(null, artifactFile); + var indexingScheduled = + MavenIndicesManager.getInstance(getProject()).scheduleArtifactIndexing(null, artifactFile, localRepo.getAbsolutePath()); assertTrue("Failed to schedule indexing", indexingScheduled); latch.await(1, TimeUnit.MINUTES); @@ -114,13 +113,14 @@ public class MavenIndicesManagerTest extends MavenIndicesTestCase { assertSize(1, addedFiles); String indexedUri = Path.of(addedFiles.iterator().next().getAbsolutePath()).toUri().toString(); - assertTrue("Junit pom not indexed", indexedUri.endsWith("local1/junit/junit/4.0/junit-4.0.pom")); + assertTrue("Junit pom not indexed", indexedUri.endsWith("local2/junit/junit/4.0/junit-4.0.pom")); - myIndicesFixture.getIndicesManager().waitForBackgroundTasksInTests(); + myIndicesFixture.getIndicesManager().waitForGavUpdateCompleted(); + myIndicesFixture.getIndicesManager().waitForLuceneUpdateCompleted(); Set versions = localIndex.getVersions("junit", "junit"); assertFalse(versions.isEmpty()); assertTrue(versions.contains("4.0")); - assertFalse(versions.contains("3.8.2")); // copied but not used + assertFalse(versions.contains("3.8.2")); } private void assertArchetypeExists(String archetypeId) { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java index 5863dda169f0..b21466966f7b 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java @@ -95,12 +95,12 @@ public class MavenIndicesTest extends CodeInsightFixtureTestCase { MavenRepositoryInfo localRepo = new MavenRepositoryInfo(LOCAL_REPOSITORY_ID, "/home/user/.m2/repository", RepositoryKind.LOCAL); localDiff = MavenIndices.getLocalDiff(localRepo, myContext, null); Assert.assertNotNull(localDiff.newIndices); - Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepositoryPathOrUrl()); + Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepository().getUrl()); Assert.assertNull(localDiff.oldIndices); localDiff = MavenIndices.getLocalDiff(localRepo, myContext, localDiff.newIndices); Assert.assertNotNull(localDiff.newIndices); - Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepositoryPathOrUrl()); + Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepository().getUrl()); Assert.assertNull(localDiff.oldIndices); } @@ -108,14 +108,14 @@ public class MavenIndicesTest extends CodeInsightFixtureTestCase { MavenRepositoryInfo localRepo = new MavenRepositoryInfo(LOCAL_REPOSITORY_ID, "/home/user/.m2/repository", RepositoryKind.LOCAL); localDiff = MavenIndices.getLocalDiff(localRepo, myContext, null); Assert.assertNotNull(localDiff.newIndices); - Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepositoryPathOrUrl()); + Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepository().getUrl()); Assert.assertNull(localDiff.oldIndices); localRepo = new MavenRepositoryInfo(LOCAL_REPOSITORY_ID, "/home/user/.m3/repository", RepositoryKind.LOCAL); MavenIndex currentLocalIndex = localDiff.newIndices; localDiff = MavenIndices.getLocalDiff(localRepo, myContext, currentLocalIndex); Assert.assertNotNull(localDiff.newIndices); - Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepositoryPathOrUrl()); + Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepository().getUrl()); Assert.assertSame(currentLocalIndex, localDiff.oldIndices); } @@ -123,7 +123,7 @@ public class MavenIndicesTest extends CodeInsightFixtureTestCase { MavenRepositoryInfo localRepo = new MavenRepositoryInfo(LOCAL_REPOSITORY_ID, "/home/user/.m4/repository", RepositoryKind.LOCAL); localDiff = MavenIndices.getLocalDiff(localRepo, myContext, null); Assert.assertNotNull(localDiff.newIndices); - Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepositoryPathOrUrl()); + Assert.assertEquals(localRepo.getUrl(), localDiff.newIndices.getRepository().getUrl()); Assert.assertNull(localDiff.oldIndices); } @@ -132,12 +132,12 @@ public class MavenIndicesTest extends CodeInsightFixtureTestCase { Map> remoteRepositoryIdsByUrl = Map.of(remoteRepo.getUrl(), Collections.singleton(remoteRepo.getId())); remoteDiff = MavenIndices.getRemoteDiff(remoteRepositoryIdsByUrl, Collections.emptyList(), myContext); Assert.assertEquals(1, remoteDiff.newIndices.size()); - Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepositoryPathOrUrl()); + Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepository().getUrl()); Assert.assertTrue(remoteDiff.oldIndices.isEmpty()); remoteDiff = MavenIndices.getRemoteDiff(remoteRepositoryIdsByUrl, remoteDiff.newIndices, myContext); Assert.assertEquals(1, remoteDiff.newIndices.size()); - Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepositoryPathOrUrl()); + Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepository().getUrl()); Assert.assertTrue(remoteDiff.oldIndices.isEmpty()); } @@ -146,16 +146,16 @@ public class MavenIndicesTest extends CodeInsightFixtureTestCase { Map> remoteRepositoryIdsByUrl = Map.of(remoteRepo.getUrl(), Collections.singleton(remoteRepo.getId())); remoteDiff = MavenIndices.getRemoteDiff(remoteRepositoryIdsByUrl, Collections.emptyList(), myContext); Assert.assertEquals(1, remoteDiff.newIndices.size()); - Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepositoryPathOrUrl()); + Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepository().getUrl()); Assert.assertTrue(remoteDiff.oldIndices.isEmpty()); remoteRepo = new MavenRepositoryInfo("snapshot", "https://repo.maven.apache.org/snapshot", RepositoryKind.REMOTE); remoteRepositoryIdsByUrl = Map.of(remoteRepo.getUrl(), Collections.singleton(remoteRepo.getId())); remoteDiff = MavenIndices.getRemoteDiff(remoteRepositoryIdsByUrl, remoteDiff.newIndices, myContext); Assert.assertEquals(1, remoteDiff.newIndices.size()); - Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepositoryPathOrUrl()); + Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepository().getUrl()); Assert.assertEquals(1, remoteDiff.oldIndices.size()); - Assert.assertTrue(remoteDiff.oldIndices.get(0).getRepositoryPathOrUrl().contains("maven2")); + Assert.assertTrue(remoteDiff.oldIndices.get(0).getRepository().getUrl().contains("maven2")); } public void testGetRemoteCreateNew() { @@ -163,7 +163,7 @@ public class MavenIndicesTest extends CodeInsightFixtureTestCase { Map> remoteRepositoryIdsByUrl = Map.of(remoteRepo.getUrl(), Collections.singleton(remoteRepo.getUrl())); remoteDiff = MavenIndices.getRemoteDiff(remoteRepositoryIdsByUrl, Collections.emptyList(), myContext); Assert.assertEquals(1, remoteDiff.newIndices.size()); - Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepositoryPathOrUrl()); + Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepository().getUrl()); Assert.assertTrue(remoteDiff.oldIndices.isEmpty()); } @@ -181,7 +181,7 @@ public class MavenIndicesTest extends CodeInsightFixtureTestCase { Map> remoteRepositoryIdsByUrl = Map.of(remoteRepo.getUrl(), Collections.singleton(remoteRepo.getId())); remoteDiff = MavenIndices.getRemoteDiff(remoteRepositoryIdsByUrl, Collections.emptyList(), myContext); Assert.assertEquals(1, remoteDiff.newIndices.size()); - Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepositoryPathOrUrl()); + Assert.assertEquals(remoteRepo.getUrl(), remoteDiff.newIndices.get(0).getRepository().getUrl()); Assert.assertTrue(remoteDiff.oldIndices.isEmpty()); } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java index f941fc7e5532..9e33f53c71e5 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java @@ -26,6 +26,7 @@ import org.jetbrains.idea.maven.server.MavenServerManager; import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.util.concurrent.CompletableFuture; public class MavenIndicesTestFixture { private final Path myDir; @@ -68,8 +69,14 @@ public class MavenIndicesTestFixture { public void setUpAfterImport() { MavenSystemIndicesManager.getInstance().setTestIndicesDir(myDir.resolve("MavenIndices")); - getIndicesManager().scheduleUpdateIndicesList(null); - getIndicesManager().waitForBackgroundTasksInTests(); + //todo: rewrite al this to coroutines + CompletableFuture f = new CompletableFuture<>(); + getIndicesManager().scheduleUpdateIndicesList(() -> { + f.complete(null); + return null; + }); + f.join(); + getIndicesManager().waitForGavUpdateCompleted(); UIUtil.dispatchAllInvocationEvents(); } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenMultiProjectImportTest.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenMultiProjectImportTest.kt index e0d4f8918bf8..ca34c325966e 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenMultiProjectImportTest.kt +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenMultiProjectImportTest.kt @@ -65,13 +65,13 @@ class MavenMultiProjectImportTest : ProjectWizardTestCase