Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael Istria2018-11-22 08:54:05 -0500
committerMickael Istria2019-05-09 07:45:51 -0400
commit15d9b8d7181c39369615107519830590b6d7a2b4 (patch)
tree989f37e675382d7f2537912d28b94173aa19e5b8
parentd0cd1dbaf370f7e7602c21ed653abc1e4f825f0a (diff)
downloadm2e-core-15d9b8d7181c39369615107519830590b6d7a2b4.tar.gz
m2e-core-15d9b8d7181c39369615107519830590b6d7a2b4.tar.xz
m2e-core-15d9b8d7181c39369615107519830590b6d7a2b4.zip
Bug 515668 - Use more efficient APIs to read projects during refresh
Instead of iterating on projects to invoke N times readMavenProjectFacades (L399) and each of this time creating depth(N) MavenProjects (1 for each stage of the parent hierarchy), we accumulate the projects to update and call readManageProjectFacades only once that shares hierarchy of objects, resulting in O(N) MavenProject instances. As a result, we replace "sum of all depths of all projects" instances by "amount of project" instances, which in most case can be a 2 or 3 factor, and for biggest projects can be a 6 or 7 factor. The further steps of the refresh operation are not optimized at the moment, as they're not involved in the usual import step. But they would be worth a further improvement. Change-Id: Icf38520d1c220590612dd32f4481eb703827e747 Signed-off-by: Mickael Istria <mistria@redhat.com>
-rw-r--r--org.eclipse.m2e.core.tests/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.m2e.core.tests/pom.xml5
-rw-r--r--org.eclipse.m2e.core.tests/resources/projects/missingParent/pom.xml11
-rw-r--r--org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/AllTests.java (renamed from org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/AllTests.java)7
-rw-r--r--org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/MavenBugsTest.java (renamed from org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/MavenBugsTest.java)16
-rw-r--r--org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/MemoryConsumptionTest.java108
-rw-r--r--org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/RegistryTest.java (renamed from org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/RegistryTest.java)15
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/ProjectRegistryManager.java172
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java12
9 files changed, 262 insertions, 85 deletions
diff --git a/org.eclipse.m2e.core.tests/META-INF/MANIFEST.MF b/org.eclipse.m2e.core.tests/META-INF/MANIFEST.MF
index dcc06c3c..40de5f94 100644
--- a/org.eclipse.m2e.core.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.m2e.core.tests/META-INF/MANIFEST.MF
@@ -1,4 +1,5 @@
Manifest-Version: 1.0
+Fragment-Host: org.eclipse.m2e.core
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.m2e.core.tests
diff --git a/org.eclipse.m2e.core.tests/pom.xml b/org.eclipse.m2e.core.tests/pom.xml
index 73b75934..d651eabf 100644
--- a/org.eclipse.m2e.core.tests/pom.xml
+++ b/org.eclipse.m2e.core.tests/pom.xml
@@ -22,6 +22,11 @@ Contributors:
<artifactId>org.eclipse.m2e.core.tests</artifactId>
<packaging>eclipse-test-plugin</packaging>
+ <properties>
+ <testSuite>${project.artifactId}</testSuite>
+ <testClass>org.eclipse.m2e.core.AllTests</testClass>
+ </properties>
+
<build>
<pluginManagement>
<plugins>
diff --git a/org.eclipse.m2e.core.tests/resources/projects/missingParent/pom.xml b/org.eclipse.m2e.core.tests/resources/projects/missingParent/pom.xml
new file mode 100644
index 00000000..4663ebe7
--- /dev/null
+++ b/org.eclipse.m2e.core.tests/resources/projects/missingParent/pom.xml
@@ -0,0 +1,11 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>missingGroup</groupId>
+ <artifactId>missingArtifactId</artifactId>
+ <version>1</version>
+ </parent>
+ <groupId>org.eclipse.m2e.tests.projects</groupId>
+ <artifactId>simplePomOK</artifactId>
+ <version>1</version>
+</project> \ No newline at end of file
diff --git a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/AllTests.java b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/AllTests.java
index 3c1a3c87..f1e4485d 100644
--- a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/AllTests.java
+++ b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/AllTests.java
@@ -9,15 +9,18 @@
* - Mickael Istria (Red Hat Inc.) - Initial implementation
*******************************************************************************/
-package org.eclipse.m2e.core.tests;
+package org.eclipse.m2e.core;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
+import org.eclipse.m2e.core.internal.project.registry.MemoryConsumptionTest;
+import org.eclipse.m2e.core.internal.project.registry.RegistryTest;
+
@RunWith(Suite.class)
-@SuiteClasses({MavenBugsTest.class, RegistryTest.class})
+@SuiteClasses({MavenBugsTest.class, RegistryTest.class, MemoryConsumptionTest.class})
public class AllTests {
}
diff --git a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/MavenBugsTest.java b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/MavenBugsTest.java
index 41598fcd..e11e102b 100644
--- a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/MavenBugsTest.java
+++ b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/MavenBugsTest.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
-package org.eclipse.m2e.core.tests;
+package org.eclipse.m2e.core;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -14,6 +14,7 @@ import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
+import org.junit.After;
import org.junit.Test;
import org.eclipse.core.resources.IProject;
@@ -34,6 +35,13 @@ import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
public class MavenBugsTest extends AbstractMavenProjectTestCase {
+ @After
+ public void clearWorkspace() throws Exception {
+ for(IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
+ p.delete(true, null);
+ }
+ }
+
@Test
public void testMNG6530() throws Exception {
File sourceDirectory = new File(
@@ -50,14 +58,14 @@ public class MavenBugsTest extends AbstractMavenProjectTestCase {
IProject parent = ResourcesPlugin.getWorkspace().getRoot().getProject("testMNG6530");
IProject child = ResourcesPlugin.getWorkspace().getRoot().getProject("child");
try {
- IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().getProject(child);
- MavenProject mavenProject = facade.getMavenProject(new NullProgressMonitor());
+ IMavenProjectFacade childFacade = MavenPlugin.getMavenProjectRegistry().getProject(child);
+ MavenProject mavenProject = childFacade.getMavenProject(new NullProgressMonitor());
assertEquals("bar", mavenProject.getProperties().get("foo"));
String content = IOUtil.toString(parent.getFile("pom.xml").getContents()).replaceAll("bar", "lol");
parent.getFile("pom.xml").setContents(new ByteArrayInputStream(content.getBytes()), true, false, null);
MavenPlugin.getProjectConfigurationManager().updateProjectConfiguration(child, monitor);
waitForJobsToComplete();
- mavenProject = facade.getMavenProject(monitor);
+ mavenProject = childFacade.getMavenProject(monitor);
assertEquals("lol", mavenProject.getProperties().get("foo"));
} finally {
parent.delete(true, null);
diff --git a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/MemoryConsumptionTest.java b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/MemoryConsumptionTest.java
new file mode 100644
index 00000000..8d72a6d4
--- /dev/null
+++ b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/MemoryConsumptionTest.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * - Mickael Istria (Red Hat Inc.) - Initial implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.project.registry;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.utils.io.FileUtils;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.IMavenConstants;
+import org.eclipse.m2e.core.internal.MavenPluginActivator;
+import org.eclipse.m2e.core.project.MavenProjectInfo;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
+
+
+public class MemoryConsumptionTest extends AbstractMavenProjectTestCase {
+
+ @Test
+ public void testImportLongBuildChain() throws Exception {
+ int[] maxMavenProjectInstancesInContext = new int[] {0};
+ MavenPluginActivator.getDefault().getMavenProjectManagerImpl().addContextProjectListener = context -> {
+ Map<MavenProject, Object> allMavenProjects = new IdentityHashMap<>();
+ context.values().forEach(mavenProject -> {
+ while(mavenProject != null) {
+ allMavenProjects.put(mavenProject, new Object());
+ mavenProject = mavenProject.getParent();
+ }
+ });
+ maxMavenProjectInstancesInContext[0] = Math.max(maxMavenProjectInstancesInContext[0], allMavenProjects.size());
+ };
+ File tempDirectory = Files.createTempDirectory(getClass().getSimpleName()).toFile();
+ int nbProjects = 50;
+ Set<File> poms = buildLinearHierarchy(nbProjects, tempDirectory);
+ try {
+ List<MavenProjectInfo> toImport = poms.stream().map(pom -> new MavenProjectInfo("", pom, null, null))
+ .collect(Collectors.toList());
+ MavenPlugin.getProjectConfigurationManager().importProjects(toImport, new ProjectImportConfiguration(), null,
+ new NullProgressMonitor());
+ waitForJobsToComplete(monitor);
+ for(IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
+ if(p.hasNature(IMavenConstants.NATURE_ID)) {
+ poms.remove(p.getFile("pom.xml").getLocation().toFile());
+ }
+ }
+ Assert.assertEquals("Some poms were not imported as project", Collections.emptySet(), poms);
+ Assert.assertEquals(nbProjects, maxMavenProjectInstancesInContext[0]);
+ } finally {
+ MavenPluginActivator.getDefault().getMavenProjectManagerImpl().addContextProjectListener = null;
+ FileUtils.deleteDirectory(tempDirectory);
+ }
+ }
+
+ private Set<File> buildLinearHierarchy(int depth, File tempDirectory) throws FileNotFoundException {
+ Set<File> poms = new HashSet<>(depth, 1.f);
+ for(int i = 0; i < depth; i++ ) {
+ File projectDir = new File(tempDirectory, "p" + i);
+ projectDir.mkdirs();
+ File pom = new File(projectDir, "pom.xml");
+ poms.add(pom);
+ try (PrintStream content = new PrintStream(pom);) {
+ content.println("<project>");
+ content.println(" <modelVersion>4.0.0</modelVersion>");
+ content.println(" <groupId>org.eclipse.m2e.core.tests.hierarchy</groupId>");
+ content.println(" <artifactId>pNUMBER</artifactId>".replace("NUMBER", Integer.toString(i)));
+ content.println(" <version>1</version>");
+ content.println(" <packaging>pom</packaging>");
+ if(i > 1) {
+ content.println(" <parent>");
+ content.println(" <groupId>org.eclipse.m2e.core.tests.hierarchy</groupId>");
+ content.println(" <artifactId>pNUMBER</artifactId>".replace("NUMBER", Integer.toString(i - 1)));
+ content.println(" <version>1</version>");
+ content.println(" <relativePath>../pNUMBER</relativePath>".replace("NUMBER", Integer.toString(i - 1)));
+ content.println(" </parent>");
+ }
+ content.println("</project>");
+ }
+ }
+ return poms;
+ }
+}
diff --git a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/RegistryTest.java b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/RegistryTest.java
index 80b77d4e..1d39f441 100644
--- a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/tests/RegistryTest.java
+++ b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/RegistryTest.java
@@ -9,9 +9,10 @@
* - Mickael Istria (Red Hat, Inc.) - initial API and implementation
*******************************************************************************/
-package org.eclipse.m2e.core.tests;
+package org.eclipse.m2e.core.internal.project.registry;
import java.io.IOException;
+import java.util.Collections;
import org.junit.Assert;
import org.junit.Test;
@@ -20,6 +21,7 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
import org.eclipse.m2e.core.internal.MavenPluginActivator;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
@@ -43,4 +45,15 @@ public class RegistryTest extends AbstractMavenProjectTestCase {
Assert.assertNull(facade);
}
+ @Test
+ public void testMissingParentCapabilityStored() throws IOException, CoreException, InterruptedException {
+ IProject project = createExisting(getClass().getSimpleName(), "resources/projects/missingParent", true);
+ waitForJobsToComplete(monitor);
+ MutableProjectRegistry registry = MavenPluginActivator.getDefault().getMavenProjectManagerImpl()
+ .newMutableProjectRegistry();
+ MavenCapability parentCapability = MavenCapability
+ .createMavenParent(new ArtifactKey("missingGroup", "missingArtifactId", "1", null));
+ assertEquals(Collections.singleton(project.getFile("pom.xml")), registry.getDependents(parentCapability, false));
+ }
+
}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/ProjectRegistryManager.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/ProjectRegistryManager.java
index 4c41e37d..a6b8f455 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/ProjectRegistryManager.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/ProjectRegistryManager.java
@@ -31,6 +31,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.slf4j.Logger;
@@ -160,6 +161,11 @@ public class ProjectRegistryManager {
private final Cache<MavenProjectFacade, MavenProject> mavenProjectCache;
+ /**
+ * @noreference For tests only
+ */
+ Consumer<Map<MavenProjectFacade, MavenProject>> addContextProjectListener;
+
public ProjectRegistryManager(MavenImpl maven, File stateLocationDir, boolean readState,
IMavenMarkerManager mavenMarkerManager) {
this.markerManager = mavenMarkerManager;
@@ -363,93 +369,109 @@ public class ProjectRegistryManager {
private void refresh(final MutableProjectRegistry newState, final DependencyResolutionContext context,
IProgressMonitor monitor) throws CoreException {
- Set<IFile> secondPhaseBacklog = new LinkedHashSet<IFile>();
+ Set<IFile> allProcessedPoms = new HashSet<>();
+ Set<IFile> allNewFacades = new HashSet<>();
- final Map<IFile, Set<Capability>> originalCapabilities = new HashMap<IFile, Set<Capability>>();
- final Map<IFile, Set<RequiredCapability>> originalRequirements = new HashMap<IFile, Set<RequiredCapability>>();
+ final Map<IFile, Set<Capability>> originalCapabilities = new HashMap<>();
+ final Map<IFile, Set<RequiredCapability>> originalRequirements = new HashMap<>();
// phase 1: build projects without dependencies and populate workspace with known projects
- while(!context.isEmpty()) {
- if(monitor.isCanceled()) {
- throw new OperationCanceledException();
- }
+ while(!context.isEmpty()) { // context may be augmented, so we need to keep processing
+ List<IFile> toReadPomFiles = new ArrayList<>();
+ while(!context.isEmpty()) { // Group build of all current context
+ if(monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
- if(newState.isStale() || (syncRefreshThread != null && syncRefreshThread != Thread.currentThread())) {
- throw new StaleMutableProjectRegistryException();
- }
+ if(newState.isStale() || (syncRefreshThread != null && syncRefreshThread != Thread.currentThread())) {
+ throw new StaleMutableProjectRegistryException();
+ }
- IFile pom = context.pop();
+ IFile pom = context.pop();
+ if(allNewFacades.contains(pom)) {
+ // pom was already in context and successfully read
+ continue;
+ }
+ allProcessedPoms.add(pom);
- monitor.subTask(NLS.bind(Messages.ProjectRegistryManager_task_project, pom.getProject().getName()));
- MavenProjectFacade oldFacade = newState.getProjectFacade(pom);
+ monitor.subTask(NLS.bind(Messages.ProjectRegistryManager_task_project, pom.getProject().getName()));
+ MavenProjectFacade oldFacade = newState.getProjectFacade(pom);
- context.forcePomFiles(flushCaches(newState, pom, oldFacade, isForceDependencyUpdate()));
- if(oldFacade != null) {
- putMavenProject(oldFacade, null); // maintain maven project cache
- }
- MavenProjectFacade newFacade = null;
- if(pom.isAccessible() && pom.getProject().hasNature(IMavenConstants.NATURE_ID)) {
+ context.forcePomFiles(flushCaches(newState, pom, oldFacade, isForceDependencyUpdate()));
if(oldFacade != null) {
- // refresh old child modules
- MavenCapability mavenParentCapability = MavenCapability.createMavenParent(oldFacade.getArtifactKey());
+ putMavenProject(oldFacade, null); // maintain maven project cache
+ }
+ if(pom.isAccessible() && pom.getProject().hasNature(IMavenConstants.NATURE_ID)) {
+ toReadPomFiles.add(pom);
+ if(oldFacade != null) {
+ // refresh old child modules
+ MavenCapability mavenParentCapability = MavenCapability.createMavenParent(oldFacade.getArtifactKey());
+ context.forcePomFiles(newState.getVersionedDependents(mavenParentCapability, true));
+
+ // refresh projects that import dependencyManagement from this one
+ MavenCapability mavenArtifactImportCapability = MavenCapability
+ .createMavenArtifactImport(oldFacade.getArtifactKey());
+ context.forcePomFiles(newState.getVersionedDependents(mavenArtifactImportCapability, true));
+ }
+ } else {
+ newState.setProject(pom, null); // discard closed/deleted pom in workspace
+ // refresh children of deleted/closed parent
+ if(oldFacade != null) {
+ MavenCapability mavenParentCapability = MavenCapability.createMavenParent(oldFacade.getArtifactKey());
+ context.forcePomFiles(newState.getDependents(mavenParentCapability, true));
+
+ MavenCapability mavenArtifactImportCapability = MavenCapability
+ .createMavenArtifactImport(oldFacade.getArtifactKey());
+ context.forcePomFiles(newState.getVersionedDependents(mavenArtifactImportCapability, true));
+ }
+ }
+ }
+ Map<IFile, MavenProjectFacade> newFacades = readMavenProjectFacades(toReadPomFiles, newState, monitor);
+ for(Entry<IFile, MavenProjectFacade> entry : newFacades.entrySet()) {
+ IFile pom = entry.getKey();
+ MavenProjectFacade newFacade = entry.getValue();
+ newState.setProject(pom, newFacade);
+ if(newFacade != null) {
+ // refresh new child modules
+ MavenCapability mavenParentCapability = MavenCapability.createMavenParent(newFacade.getArtifactKey());
context.forcePomFiles(newState.getVersionedDependents(mavenParentCapability, true));
// refresh projects that import dependencyManagement from this one
MavenCapability mavenArtifactImportCapability = MavenCapability
- .createMavenArtifactImport(oldFacade.getArtifactKey());
+ .createMavenArtifactImport(newFacade.getArtifactKey());
context.forcePomFiles(newState.getVersionedDependents(mavenArtifactImportCapability, true));
- }
- newFacade = readMavenProjectFacades(Collections.singletonList(pom), newState, monitor).get(pom);
- } else {
- // refresh children of deleted/closed parent
- if(oldFacade != null) {
- MavenCapability mavenParentCapability = MavenCapability.createMavenParent(oldFacade.getArtifactKey());
- context.forcePomFiles(newState.getDependents(mavenParentCapability, true));
+ Set<Capability> capabilities = new LinkedHashSet<Capability>();
+ capabilities.add(mavenParentCapability);
+ capabilities.add(MavenCapability.createMavenArtifact(newFacade.getArtifactKey()));
+ Set<Capability> oldCapabilities = newState.setCapabilities(pom, capabilities);
+ if(!originalCapabilities.containsKey(pom)) {
+ originalCapabilities.put(pom, oldCapabilities);
+ }
- MavenCapability mavenArtifactImportCapability = MavenCapability
- .createMavenArtifactImport(oldFacade.getArtifactKey());
- context.forcePomFiles(newState.getVersionedDependents(mavenArtifactImportCapability, true));
+ MavenProject mavenProject = getMavenProject(newFacade);
+ Set<RequiredCapability> requirements = new LinkedHashSet<RequiredCapability>();
+ DefaultMavenDependencyResolver.addProjectStructureRequirements(requirements, mavenProject);
+ Set<RequiredCapability> oldRequirements = newState.setRequirements(pom, requirements);
+ if(!originalRequirements.containsKey(pom)) {
+ originalRequirements.put(pom, oldRequirements);
+ }
}
}
-
- newState.setProject(pom, newFacade);
-
- if(newFacade != null) {
- // refresh new child modules
- MavenCapability mavenParentCapability = MavenCapability.createMavenParent(newFacade.getArtifactKey());
- context.forcePomFiles(newState.getVersionedDependents(mavenParentCapability, true));
-
- // refresh projects that import dependencyManagement from this one
- MavenCapability mavenArtifactImportCapability = MavenCapability
- .createMavenArtifactImport(newFacade.getArtifactKey());
- context.forcePomFiles(newState.getVersionedDependents(mavenArtifactImportCapability, true));
-
- Set<Capability> capabilities = new LinkedHashSet<Capability>();
- capabilities.add(mavenParentCapability);
- capabilities.add(MavenCapability.createMavenArtifact(newFacade.getArtifactKey()));
- Set<Capability> oldCapabilities = newState.setCapabilities(pom, capabilities);
- if(!originalCapabilities.containsKey(pom)) {
- originalCapabilities.put(pom, oldCapabilities);
- }
-
- MavenProject mavenProject = getMavenProject(newFacade);
- Set<RequiredCapability> requirements = new LinkedHashSet<RequiredCapability>();
- DefaultMavenDependencyResolver.addProjectStructureRequirements(requirements, mavenProject);
- Set<RequiredCapability> oldRequirements = newState.setRequirements(pom, requirements);
- if(!originalRequirements.containsKey(pom)) {
- originalRequirements.put(pom, oldRequirements);
- }
-
+ allNewFacades.addAll(newFacades.keySet());
+ List<IFile> erroneousPoms = new ArrayList<IFile>(toReadPomFiles);
+ erroneousPoms.removeAll(newFacades.keySet());
+ erroneousPoms.forEach(pom -> newState.setProject(pom, null));
+ if(!newFacades.isEmpty()) { // progress did happen
+ // push files that could't be read back into context for a second pass.
+ // This can help if some read files are parent of other ones in the same
+ // request -> the child wouldn't be read immediately, but would be in a
+ // 2nd pass once parent was read.
+ context.forcePomFiles(new HashSet<IFile>(erroneousPoms));
}
-
- // at this point project facade and project capabilities/requirements are inconsistent in the state
- // this will be reconciled during the second phase
-
- secondPhaseBacklog.add(pom);
}
- context.forcePomFiles(secondPhaseBacklog);
+ context.forcePomFiles(allProcessedPoms);
// phase 2: resolve project dependencies
Set<IFile> secondPhaseProcessed = new HashSet<IFile>();
@@ -475,7 +497,7 @@ public class ProjectRegistryManager {
}
if(newFacade != null) {
MavenProject mavenProject = getMavenProject(newFacade);
- if(mavenProject == null || mavenProject.getArtifact() != null) {
+ if(!allProcessedPoms.contains(newFacade.getPom())) {
// facade from workspace state that has not been refreshed yet
newFacade = readMavenProjectFacades(Collections.singletonList(pom), newState, monitor).get(pom);
} else {
@@ -490,12 +512,12 @@ public class ProjectRegistryManager {
if(newFacade != null) {
final MavenProjectFacade _newFacade = newFacade;
- final MavenProject mavenProject = getMavenProject(newFacade);
final ResolverConfiguration resolverConfiguration = _newFacade.getResolverConfiguration();
- createExecutionContext(newState, pom, resolverConfiguration).execute(mavenProject, (executionContext, pm) -> {
- refreshPhase2(newState, context, originalCapabilities, originalRequirements, pom, _newFacade, pm);
- return null;
- }, monitor);
+ createExecutionContext(newState, pom, resolverConfiguration).execute(getMavenProject(newFacade),
+ (executionContext, pm) -> {
+ refreshPhase2(newState, context, originalCapabilities, originalRequirements, pom, _newFacade, pm);
+ return null;
+ }, monitor);
} else {
refreshPhase2(newState, context, originalCapabilities, originalRequirements, pom, newFacade, monitor);
}
@@ -1076,6 +1098,9 @@ public class ProjectRegistryManager {
Map<MavenProjectFacade, MavenProject> mavenProjects = getContextProjects();
if(mavenProject != null) {
mavenProjects.put(facade, mavenProject);
+ if(this.addContextProjectListener != null) {
+ this.addContextProjectListener.accept(mavenProjects);
+ }
} else {
mavenProjects.remove(facade);
synchronized(legacyMavenProjects) {
@@ -1083,7 +1108,6 @@ public class ProjectRegistryManager {
}
}
}
-
/**
* Do not modify this map directly, use {@link #putMavenProject(MavenProjectFacade, MavenProject)}
*
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java
index 33aae13f..189ee873 100644
--- a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java
@@ -48,7 +48,12 @@ public class JobHelpers {
}
public static void waitForJobsToComplete(IProgressMonitor monitor) throws InterruptedException, CoreException {
- waitForBuildJobs();
+ waitForJobsToComplete(60_000, monitor);
+ }
+
+ public static void waitForJobsToComplete(int buildTimeoutMilliseconds, IProgressMonitor monitor)
+ throws InterruptedException, CoreException {
+ waitForBuildJobs(buildTimeoutMilliseconds);
/*
* First, make sure refresh job gets all resource change events
@@ -93,7 +98,6 @@ public class JobHelpers {
jobManager.resume();
}
- waitForBuildJobs();
}
private static boolean flushProcessingQueues(IJobManager jobManager, IProgressMonitor monitor)
@@ -130,8 +134,8 @@ public class JobHelpers {
return queues;
}
- private static void waitForBuildJobs() {
- waitForJobs(BuildJobMatcher.INSTANCE, 60 * 1000);
+ private static void waitForBuildJobs(int timeOutMilliseconds) {
+ waitForJobs(BuildJobMatcher.INSTANCE, timeOutMilliseconds);
}
public static void waitForJobs(IJobMatcher matcher, int maxWaitMillis) {

Back to the top