Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Fedorenko2011-04-15 12:02:28 -0400
committerIgor Fedorenko2011-04-15 18:35:31 -0400
commit9d1d5dfa5bf140ee229fbcfb67929c78e7d92f01 (patch)
tree0f12fe51bb4d1b15701e4c6d9a8945d4e7af7ef0
parenta91c193347dbb09ebd45417a6c89eaa3bb67b557 (diff)
downloadm2e-core-9d1d5dfa5bf140ee229fbcfb67929c78e7d92f01.tar.gz
m2e-core-9d1d5dfa5bf140ee229fbcfb67929c78e7d92f01.tar.xz
m2e-core-9d1d5dfa5bf140ee229fbcfb67929c78e7d92f01.zip
342903 split MavenProject creation and dependency resolution
Reworked ProjectRegistryManager.refresh to properly separate MavenProject instance creation from project dependency resolution. This allowed dependency resolution, the most CPU-expansive part of #refresh, to be executed exactly one time for each affected project. On my hardware and using a snapshot of jboss-as as a test project, the new implementation performs ~50% better compared to the original (~15s vs ~22s). Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/DefaultMavenDependencyResolver.java19
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenCapability.java2
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenProjectFacade.java7
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenRequiredCapability.java2
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/ProjectRegistryManager.java236
5 files changed, 166 insertions, 100 deletions
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/DefaultMavenDependencyResolver.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/DefaultMavenDependencyResolver.java
index 1f0dba68..b53208d4 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/DefaultMavenDependencyResolver.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/DefaultMavenDependencyResolver.java
@@ -69,15 +69,9 @@ public class DefaultMavenDependencyResolver extends AbstractMavenDependencyResol
// dependencies
- // parent
- Artifact parentArtifact = mavenProject.getParentArtifact();
- if(parentArtifact != null) {
- requirements.add(MavenRequiredCapability.createMavenParent(new ArtifactKey(parentArtifact)));
- }
-
// resolved dependencies
for(Artifact artifact : mavenProject.getArtifacts()) {
- requirements.add(MavenRequiredCapability.createMaven(new ArtifactKey(artifact), artifact.getScope(),
+ requirements.add(MavenRequiredCapability.createMavenArtifact(new ArtifactKey(artifact), artifact.getScope(),
artifact.isOptional()));
}
@@ -86,7 +80,7 @@ public class DefaultMavenDependencyResolver extends AbstractMavenDependencyResol
if(plugin.isExtensions()) {
ArtifactKey artifactKey = new ArtifactKey(plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(),
null);
- requirements.add(MavenRequiredCapability.createMaven(artifactKey, "plugin", false)); //$NON-NLS-1$
+ requirements.add(MavenRequiredCapability.createMavenArtifact(artifactKey, "plugin", false)); //$NON-NLS-1$
}
}
@@ -97,11 +91,18 @@ public class DefaultMavenDependencyResolver extends AbstractMavenDependencyResol
org.sonatype.aether.artifact.Artifact artifact = dependency.getArtifact();
ArtifactKey dependencyKey = new ArtifactKey(artifact.getGroupId(), artifact.getArtifactId(),
artifact.getVersion(), null);
- requirements.add(MavenRequiredCapability.createMaven(dependencyKey, dependency.getScope(),
+ requirements.add(MavenRequiredCapability.createMavenArtifact(dependencyKey, dependency.getScope(),
dependency.isOptional()));
}
}
log.debug("Resolved dependencies for {} in {} ms", facade.toString(), System.currentTimeMillis() - start); //$NON-NLS-1$
}
+
+ public static void addParentRequirements(Set<RequiredCapability> requirements, MavenProject mavenProject) {
+ Artifact parentArtifact = mavenProject.getParentArtifact();
+ if(parentArtifact != null) {
+ requirements.add(MavenRequiredCapability.createMavenParent(new ArtifactKey(parentArtifact)));
+ }
+ }
}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenCapability.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenCapability.java
index 445fb35e..20943f9c 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenCapability.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenCapability.java
@@ -65,7 +65,7 @@ public class MavenCapability extends Capability {
return getVersionlessKey().equals(other.getVersionlessKey()) && version.equals(other.version);
}
- public static MavenCapability createMaven(ArtifactKey key) {
+ public static MavenCapability createMavenArtifact(ArtifactKey key) {
return new MavenCapability(NS_MAVEN_ARTIFACT, getId(key), key.getVersion());
}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenProjectFacade.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenProjectFacade.java
index a38b0a26..c5169357 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenProjectFacade.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenProjectFacade.java
@@ -141,6 +141,13 @@ public class MavenProjectFacade implements IMavenProjectFacade, Serializable {
}
/**
+ * Copy constructor. Does NOT preserve session state.
+ */
+ public MavenProjectFacade(MavenProjectFacade other) {
+ this(other.manager, other.pom, other.mavenProject, other.executionPlans, other.resolverConfiguration);
+ }
+
+ /**
* Returns project relative paths of resource directories
*/
public IPath[] getResourceLocations() {
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenRequiredCapability.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenRequiredCapability.java
index 1f0c3dbe..9ef9fde7 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenRequiredCapability.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/MavenRequiredCapability.java
@@ -41,7 +41,7 @@ public class MavenRequiredCapability extends RequiredCapability {
this.optional = optional;
}
- public static MavenRequiredCapability createMaven(ArtifactKey key, String scope, boolean optional) {
+ public static MavenRequiredCapability createMavenArtifact(ArtifactKey key, String scope, boolean optional) {
return new MavenRequiredCapability(MavenCapability.NS_MAVEN_ARTIFACT, MavenCapability.getId(key), key.getVersion(),
scope, optional);
}
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 9487f056..b51e26bd 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
@@ -15,6 +15,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -42,6 +43,7 @@ import org.eclipse.osgi.util.NLS;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.MavenArtifactRepository;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.DefaultMavenExecutionResult;
@@ -227,7 +229,7 @@ public class ProjectRegistryManager {
Set<IFile> pomSet = new LinkedHashSet<IFile>();
- pomSet.addAll(state.getDependents(MavenCapability.createMaven(mavenProject), false));
+ pomSet.addAll(state.getDependents(MavenCapability.createMavenArtifact(mavenProject), false));
pomSet.addAll(state.getDependents(MavenCapability.createMavenParent(mavenProject), false)); // TODO check packaging
state.removeProject(pom, mavenProject);
@@ -297,128 +299,184 @@ public class ProjectRegistryManager {
private void refresh(MutableProjectRegistry newState, DependencyResolutionContext context, IProgressMonitor monitor)
throws CoreException {
+ Set<IFile> secondPhaseBacklog = new LinkedHashSet<IFile>();
+
+ Map<IFile, Set<Capability>> originalCapabilities = new HashMap<IFile, Set<Capability>>();
+ Map<IFile, Set<RequiredCapability>> originalRequirements = new HashMap<IFile, Set<RequiredCapability>>();
+
+ // phase 1: build projects without dependencies and populate workspace with known projects
while(!context.isEmpty()) {
- Map<IFile, MavenProjectFacade> newFacades = new LinkedHashMap<IFile, MavenProjectFacade>();
+ if(monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+
+ if(newState.isStale() || (syncRefreshThread != null && syncRefreshThread != Thread.currentThread())) {
+ throw new StaleMutableProjectRegistryException();
+ }
+
+ IFile pom = context.pop();
- // phase 1: build projects without dependencies and populate workspace with known projects
- while(!context.isEmpty()) {
- if(monitor.isCanceled()) {
- throw new OperationCanceledException();
+ monitor.subTask(NLS.bind(Messages.ProjectRegistryManager_task_project, pom.getProject().getName()));
+ MavenProjectFacade newFacade = null;
+ if(pom.isAccessible() && pom.getProject().hasNature(IMavenConstants.NATURE_ID)) {
+ MavenProjectFacade oldFacade = newState.getProjectFacade(pom);
+
+ if(!context.isForce(pom) && oldFacade != null && !oldFacade.isStale()) {
+ // skip refresh if not forced and up-to-date facade
+ continue;
}
- if(newState.isStale() || (syncRefreshThread != null && syncRefreshThread != Thread.currentThread())) {
- throw new StaleMutableProjectRegistryException();
+ flushCaches(pom, oldFacade);
+
+ if(oldFacade != null) {
+ // refresh old child modules
+ MavenCapability mavenParentCapability = MavenCapability.createMavenParent(oldFacade.getArtifactKey());
+ context.forcePomFiles(newState.getDependents(mavenParentCapability, true));
}
- IFile pom = context.pop();
+ newFacade = readMavenProject(pom, context, newState, monitor);
+ } else {
+ // refresh children of deleted/closed parent
+ MavenProjectFacade oldFacade = newState.getProjectFacade(pom);
+ if(oldFacade != null) {
+ MavenCapability mavenParentCapability = MavenCapability.createMavenParent(oldFacade.getArtifactKey());
+ context.forcePomFiles(newState.getDependents(mavenParentCapability, true));
+ }
+ }
- monitor.subTask(NLS.bind(Messages.ProjectRegistryManager_task_project, pom.getProject().getName()));
- MavenProjectFacade newFacade = null;
- if(pom.isAccessible() && pom.getProject().hasNature(IMavenConstants.NATURE_ID)) {
- MavenProjectFacade oldFacade = newState.getProjectFacade(pom);
+ newState.setProject(pom, newFacade);
- if(!context.isForce(pom) && oldFacade != null && !oldFacade.isStale()) {
- // skip refresh if not forced and up-to-date facade
- continue;
- }
+ if(newFacade != null) {
+ // refresh new child modules
+ MavenCapability mavenParentCapability = MavenCapability.createMavenParent(newFacade.getArtifactKey());
+ context.forcePomFiles(newState.getDependents(mavenParentCapability, true));
- flushCaches(pom, oldFacade);
+ 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);
+ }
- newFacade = readMavenProject(pom, context, newState, monitor);
+ Set<RequiredCapability> requirements = new LinkedHashSet<RequiredCapability>();
+ DefaultMavenDependencyResolver.addParentRequirements(requirements, newFacade.getMavenProject());
+ Set<RequiredCapability> oldRequirements = newState.setRequirements(pom, requirements);
+ if(!originalRequirements.containsKey(pom)) {
+ originalRequirements.put(pom, oldRequirements);
}
+ }
- newState.setProject(pom, newFacade);
+ // 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);
+ }
- // at this point project facade and project capabilities/requirements are inconsistent in the state
- // this will be reconciled during the second phase
+ context.forcePomFiles(secondPhaseBacklog);
- newFacades.put(pom, newFacade); // stash work for the second phase
+ // phase 2: resolve project dependencies
+ Set<IFile> secondPhaseProcessed = new HashSet<IFile>();
+ while(!context.isEmpty()) {
+ if(monitor.isCanceled()) {
+ throw new OperationCanceledException();
}
- // phase 2: resolve project dependencies
- for(Map.Entry<IFile, MavenProjectFacade> entry : newFacades.entrySet()) {
- 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 = entry.getKey();
- MavenProjectFacade newFacade = entry.getValue();
+ if(!secondPhaseProcessed.add(pom)) {
+ // because workspace contents is fully known at this point, each project needs to be resolved at most once
+ continue;
+ }
+
+ MavenProjectFacade newFacade = newState.getProjectFacade(pom);
+ if(newFacade != null) {
+ // loose any session state
+ newFacade = new MavenProjectFacade(newFacade);
+ }
- Set<Capability> capabilities = null;
- Set<RequiredCapability> requirements = null;
- if(newFacade != null) {
- monitor.subTask(NLS.bind(Messages.ProjectRegistryManager_task_project,newFacade.getProject().getName()));
+ Set<Capability> capabilities = null;
+ Set<RequiredCapability> requirements = null;
+ if(newFacade != null) {
+ monitor.subTask(NLS.bind(Messages.ProjectRegistryManager_task_project, newFacade.getProject().getName()));
- setupLifecycleMapping(newState, context, monitor, newFacade);
+ setupLifecycleMapping(newState, context, monitor, newFacade);
- capabilities = new LinkedHashSet<Capability>();
- requirements = new LinkedHashSet<RequiredCapability>();
+ capabilities = new LinkedHashSet<Capability>();
+ requirements = new LinkedHashSet<RequiredCapability>();
- Capability mavenParentCapability = MavenCapability.createMavenParent(newFacade.getArtifactKey());
+ Capability mavenParentCapability = MavenCapability.createMavenParent(newFacade.getArtifactKey());
- // maven projects always have these capabilities
- capabilities.add(MavenCapability.createMaven(newFacade.getArtifactKey()));
- capabilities.add(mavenParentCapability); // TODO consider packaging
+ // maven projects always have these capabilities
+ capabilities.add(MavenCapability.createMavenArtifact(newFacade.getArtifactKey()));
+ capabilities.add(mavenParentCapability); // TODO consider packaging
- AbstractMavenDependencyResolver resolver = getMavenDependencyResolver(newFacade, monitor);
- resolver.setContextProjectRegistry(newState);
- try {
- MavenExecutionRequest mavenRequest = getConfiguredExecutionRequest(context, newState, newFacade.getPom(),
- newFacade.getResolverConfiguration());
- mavenRequest.getProjectBuildingRequest().setProject(newFacade.getMavenProject());
- mavenRequest.getProjectBuildingRequest().setResolveDependencies(true);
- resolver.resolveProjectDependencies(newFacade, mavenRequest, capabilities, requirements, monitor);
- } finally {
- resolver.setContextProjectRegistry(null);
- }
+ // maven projects always have these requirements
+ DefaultMavenDependencyResolver.addParentRequirements(requirements, newFacade.getMavenProject());
- newFacade.setMavenProjectArtifacts();
+ AbstractMavenDependencyResolver resolver = getMavenDependencyResolver(newFacade, monitor);
+ resolver.setContextProjectRegistry(newState);
+ try {
+ MavenExecutionRequest mavenRequest = getConfiguredExecutionRequest(context, newState, newFacade.getPom(),
+ newFacade.getResolverConfiguration());
+ mavenRequest.getProjectBuildingRequest().setProject(newFacade.getMavenProject());
+ mavenRequest.getProjectBuildingRequest().setResolveDependencies(true);
+ resolver.resolveProjectDependencies(newFacade, mavenRequest, capabilities, requirements, monitor);
+ } finally {
+ resolver.setContextProjectRegistry(null);
+ }
- // always refresh child modules
- context.forcePomFiles(newState.getDependents(mavenParentCapability, true));
- } else {
- if(pom.isAccessible() && pom.getProject().hasNature(IMavenConstants.NATURE_ID)) {
- try {
- // MNGECLIPSE-605 embedder is not able to resolve the project due to missing configuration in the parent
- Model model = getMaven().readModel(pom.getLocation().toFile());
- if(model != null && model.getParent() != null) {
- Parent parent = model.getParent();
- if(parent.getGroupId() != null && parent.getArtifactId() != null && parent.getVersion() != null) {
- ArtifactKey parentKey = new ArtifactKey(parent.getGroupId(), parent.getArtifactId(),
- parent.getVersion(), null);
- requirements = new HashSet<RequiredCapability>();
- requirements.add(MavenRequiredCapability.createMavenParent(parentKey));
- }
+ newState.setProject(pom, newFacade);
+
+ newFacade.setMavenProjectArtifacts();
+ } else {
+ if(pom.isAccessible() && pom.getProject().hasNature(IMavenConstants.NATURE_ID)) {
+ try {
+ // MNGECLIPSE-605 embedder is not able to resolve the project due to missing configuration in the parent
+ Model model = getMaven().readModel(pom.getLocation().toFile());
+ if(model != null && model.getParent() != null) {
+ Parent parent = model.getParent();
+ if(parent.getGroupId() != null && parent.getArtifactId() != null && parent.getVersion() != null) {
+ ArtifactKey parentKey = new ArtifactKey(parent.getGroupId(), parent.getArtifactId(),
+ parent.getVersion(), null);
+ requirements = new HashSet<RequiredCapability>();
+ requirements.add(MavenRequiredCapability.createMavenParent(parentKey));
}
- } catch(Exception e) {
- // we've tried our best, there is nothing else we can do
- log.error(e.getMessage(), e);
}
+ } catch(Exception e) {
+ // we've tried our best, there is nothing else we can do
+ log.error(e.getMessage(), e);
}
}
+ }
- Set<Capability> oldCapabilities = newState.setCapabilities(pom, capabilities);
- // if our capabilities changed, recalculate everyone who depends on new/changed/removed capabilities
- Set<Capability> changedCapabilities = diff(oldCapabilities, capabilities);
- for(Capability capability : changedCapabilities) {
- context.forcePomFiles(newState.getDependents(capability, true));
- }
+ Set<Capability> oldCapabilities = newState.setCapabilities(pom, capabilities);
+ if(originalCapabilities.containsKey(pom)) {
+ oldCapabilities = originalCapabilities.get(pom);
+ }
+ // if our capabilities changed, recalculate everyone who depends on new/changed/removed capabilities
+ Set<Capability> changedCapabilities = diff(oldCapabilities, capabilities);
+ for(Capability capability : changedCapabilities) {
+ context.forcePomFiles(newState.getDependents(capability, true));
+ }
- Set<RequiredCapability> oldRequirements = newState.setRequirements(pom, requirements);
- // if our dependencies changed, recalculate everyone who depends on us
- // this is needed to deal with transitive dependency resolution in maven
- if(oldCapabilities != null && hasDiff(oldRequirements, requirements)) {
- for(Capability capability : oldCapabilities) {
- context.forcePomFiles(newState.getDependents(capability.getVersionlessKey(), true));
- }
+ Set<RequiredCapability> oldRequirements = newState.setRequirements(pom, requirements);
+ if(originalRequirements.containsKey(pom)) {
+ oldRequirements = originalRequirements.get(pom);
+ }
+ // if our dependencies changed, recalculate everyone who depends on us
+ // this is needed to deal with transitive dependency resolution in maven
+ if(oldCapabilities != null && hasDiff(oldRequirements, requirements)) {
+ for(Capability capability : oldCapabilities) {
+ context.forcePomFiles(newState.getDependents(capability.getVersionlessKey(), true));
}
-
- monitor.worked(1);
}
+
+ monitor.worked(1);
}
}

Back to the top