maven: use aether for maven3 dependencies resolving

Related issues:
IDEA-99301 Maven import does not honor order of dependencies on classpath
IDEA-120647 a JUnit case succeeds in `mvn test` and eclipse but fails in intellij
IDEA-89979 Module dependency ordering doesn't reflect maven pom dependency ordering
IDEA-73255 IntelliJ test classpath doesn't match Maven's
IDEA-110060 order of classpath entitis of project shall be the same as in maven pom
IDEA-98262 Maven scope "provided" is overriden by "test"
This commit is contained in:
Vladislav.Soroka
2014-09-25 17:45:26 +04:00
parent 77e6dbaac1
commit 992f0debbd
4 changed files with 216 additions and 22 deletions
@@ -0,0 +1,88 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.maven.server;
import gnu.trove.THashMap;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.jetbrains.idea.maven.model.*;
import org.sonatype.aether.graph.DependencyNode;
import java.io.File;
import java.rmi.RemoteException;
import java.util.*;
/**
* {@link AetherModelConverter} provides adapted methods of {@link MavenModelConverter} for aether models conversion
*
* @author Vladislav.Soroka
* @since 9/24/2014
*/
public class AetherModelConverter extends MavenModelConverter {
public static MavenModel convertModelWithAetherDependencyTree(Model model,
List<String> sources,
List<String> testSources,
Collection<Artifact> dependencies,
Collection<DependencyNode> dependencyTree,
Collection<Artifact> extensions,
File localRepository) throws RemoteException {
MavenModel result = new MavenModel();
result.setMavenId(new MavenId(model.getGroupId(), model.getArtifactId(), model.getVersion()));
Parent parent = model.getParent();
if (parent != null) {
result.setParent(new MavenParent(new MavenId(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()),
parent.getRelativePath()));
}
result.setPackaging(model.getPackaging());
result.setName(model.getName());
result.setProperties(model.getProperties() == null ? new Properties() : model.getProperties());
result.setPlugins(convertPlugins(model));
Map<Artifact, MavenArtifact> convertedArtifacts = new THashMap<Artifact, MavenArtifact>();
result.setExtensions(convertArtifacts(extensions, convertedArtifacts, localRepository));
result.setDependencies(convertArtifacts(dependencies, convertedArtifacts, localRepository));
result.setDependencyTree(convertAetherDependencyNodes(null, dependencyTree, convertedArtifacts, localRepository));
result.setRemoteRepositories(convertRepositories(model.getRepositories()));
result.setProfiles(convertProfiles(model.getProfiles()));
result.setModules(model.getModules());
convertBuild(result.getBuild(), model.getBuild(), sources, testSources);
return result;
}
public static List<MavenArtifactNode> convertAetherDependencyNodes(MavenArtifactNode parent,
Collection<DependencyNode> nodes,
Map<Artifact, MavenArtifact> nativeToConvertedMap,
File localRepository) {
List<MavenArtifactNode> result = new ArrayList<MavenArtifactNode>(nodes.size());
for (DependencyNode each : nodes) {
Artifact a = RepositoryUtils.toArtifact(each.getDependency().getArtifact());
MavenArtifact ma = convertArtifact(a, nativeToConvertedMap, localRepository);
MavenArtifactNode newNode = new MavenArtifactNode(
parent, ma, MavenArtifactState.ADDED, null, each.getDependency().getScope(),
each.getPremanagedVersion(), each.getPremanagedScope());
newNode.setDependencies(convertAetherDependencyNodes(newNode, each.getChildren(), nativeToConvertedMap, localRepository));
result.add(newNode);
}
return result;
}
}
@@ -40,6 +40,7 @@ import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.internal.PluginDependenciesResolver;
import org.apache.maven.profiles.activation.*;
import org.apache.maven.project.*;
import org.apache.maven.project.ProjectDependenciesResolver;
import org.apache.maven.project.inheritance.DefaultModelInheritanceAssembler;
import org.apache.maven.project.interpolation.AbstractStringBasedModelInterpolator;
import org.apache.maven.project.interpolation.ModelInterpolationException;
@@ -69,6 +70,8 @@ import org.jetbrains.idea.maven.model.*;
import org.jetbrains.idea.maven.server.embedder.*;
import org.jetbrains.idea.maven.server.embedder.MavenExecutionResult;
import org.sonatype.aether.RepositorySystemSession;
import org.sonatype.aether.graph.Dependency;
import org.sonatype.aether.repository.LocalRepositoryManager;
import org.sonatype.aether.util.DefaultRepositorySystemSession;
import org.sonatype.aether.util.graph.PreorderNodeListGenerator;
@@ -97,6 +100,9 @@ import java.util.concurrent.atomic.AtomicReference;
org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator2 <-> org.apache.maven.model.interpolation.StringSearchModelInterpolator
*/
public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements MavenServerEmbedder {
private final static boolean USE_MVN2_COMPATIBLE_DEPENDENCY_RESOLVING = System.getProperty("maven3.use.compat.resolver") != null;
@NotNull private final DefaultPlexusContainer myContainer;
@NotNull private final Settings myMavenSettings;
@@ -410,23 +416,41 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven
project.setDependencyArtifacts(project.createArtifacts(getComponent(ArtifactFactory.class), null, null));
//
ArtifactResolutionRequest resolutionRequest = new ArtifactResolutionRequest();
resolutionRequest.setArtifactDependencies(project.getDependencyArtifacts());
resolutionRequest.setArtifact(project.getArtifact());
resolutionRequest.setManagedVersionMap(project.getManagedVersionMap());
resolutionRequest.setLocalRepository(myLocalRepository);
resolutionRequest.setRemoteRepositories(project.getRemoteArtifactRepositories());
resolutionRequest.setListeners(listeners);
if (USE_MVN2_COMPATIBLE_DEPENDENCY_RESOLVING) {
ArtifactResolutionRequest resolutionRequest = new ArtifactResolutionRequest();
resolutionRequest.setArtifactDependencies(project.getDependencyArtifacts());
resolutionRequest.setArtifact(project.getArtifact());
resolutionRequest.setManagedVersionMap(project.getManagedVersionMap());
resolutionRequest.setLocalRepository(myLocalRepository);
resolutionRequest.setRemoteRepositories(project.getRemoteArtifactRepositories());
resolutionRequest.setListeners(listeners);
resolutionRequest.setResolveRoot(false);
resolutionRequest.setResolveTransitively(true);
resolutionRequest.setResolveRoot(false);
resolutionRequest.setResolveTransitively(true);
ArtifactResolver resolver = getComponent(ArtifactResolver.class);
ArtifactResolutionResult result = resolver.resolve(resolutionRequest);
ArtifactResolver resolver = getComponent(ArtifactResolver.class);
ArtifactResolutionResult result = resolver.resolve(resolutionRequest);
project.setArtifacts(result.getArtifacts());
project.setArtifacts(result.getArtifacts());
// end copied from DefaultMavenProjectBuilder.buildWithDependencies
ref.set(new MavenExecutionResult(project, exceptions));
ref.set(new MavenExecutionResult(project, exceptions));
}
else {
final DependencyResolutionResult dependencyResolutionResult = resolveDependencies(project, repositorySession);
final List<Dependency> dependencies = dependencyResolutionResult.getDependencies();
Set<Artifact> artifacts = new LinkedHashSet<Artifact>(dependencies.size());
for (Dependency dependency : dependencies) {
final Artifact artifact = RepositoryUtils.toArtifact(dependency.getArtifact());
artifact.setScope(dependency.getScope());
artifact.setOptional(dependency.isOptional());
artifacts.add(artifact);
resolveAsModule(artifact);
}
project.setArtifacts(artifacts);
ref.set(new MavenExecutionResult(project, dependencyResolutionResult, exceptions));
}
}
catch (Exception e) {
ref.set(handleException(e));
@@ -437,6 +461,54 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven
return ref.get();
}
private boolean resolveAsModule(Artifact a) {
MavenWorkspaceMap map = myWorkspaceMap;
if (map == null) return false;
MavenWorkspaceMap.Data resolved = map.findFileAndOriginalId(MavenModelConverter.createMavenId(a));
if (resolved == null) return false;
a.setResolved(true);
a.setFile(resolved.getFile(a.getType()));
a.selectVersion(resolved.originalId.getVersion());
return true;
}
/**
* copied from {@link org.apache.maven.project.DefaultProjectBuilder#resolveDependencies(org.apache.maven.project.MavenProject, org.sonatype.aether.RepositorySystemSession)}
*/
private DependencyResolutionResult resolveDependencies(MavenProject project, RepositorySystemSession session) {
DependencyResolutionResult resolutionResult;
try {
ProjectDependenciesResolver dependencyResolver = getComponent(ProjectDependenciesResolver.class);
DefaultDependencyResolutionRequest resolution = new DefaultDependencyResolutionRequest(project, session);
resolutionResult = dependencyResolver.resolve(resolution);
}
catch (DependencyResolutionException e) {
resolutionResult = e.getResult();
}
Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
if (resolutionResult.getDependencyGraph() != null) {
RepositoryUtils.toArtifacts(artifacts, resolutionResult.getDependencyGraph().getChildren(),
Collections.singletonList(project.getArtifact().getId()), null);
// Maven 2.x quirk: an artifact always points at the local repo, regardless whether resolved or not
LocalRepositoryManager lrm = session.getLocalRepositoryManager();
for (Artifact artifact : artifacts) {
if (!artifact.isResolved()) {
String path = lrm.getPathForLocalArtifact(RepositoryUtils.toArtifact(artifact));
artifact.setFile(new File(lrm.getRepository().getBasedir(), path));
}
}
}
project.setResolvedArtifacts(artifacts);
project.setArtifacts(artifacts);
return resolutionResult;
}
/**
* adapted from {@link org.apache.maven.DefaultMaven#doExecute(org.apache.maven.execution.MavenExecutionRequest)}
*/
@@ -570,10 +642,24 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven
MavenModel model = null;
try {
model = MavenModelConverter
.convertModel(mavenProject.getModel(), mavenProject.getCompileSourceRoots(), mavenProject.getTestCompileSourceRoots(),
mavenProject.getArtifacts(), (rootNode == null ? Collections.emptyList() : rootNode.getChildren()),
mavenProject.getExtensionArtifacts(), getLocalRepositoryFile());
if (USE_MVN2_COMPATIBLE_DEPENDENCY_RESOLVING) {
//noinspection unchecked
final List<DependencyNode> dependencyNodes = rootNode == null ? Collections.emptyList() : rootNode.getChildren();
model = MavenModelConverter.convertModel(
mavenProject.getModel(), mavenProject.getCompileSourceRoots(), mavenProject.getTestCompileSourceRoots(),
mavenProject.getArtifacts(), dependencyNodes, mavenProject.getExtensionArtifacts(), getLocalRepositoryFile());
}
else {
final DependencyResolutionResult dependencyResolutionResult = result.getDependencyResolutionResult();
final org.sonatype.aether.graph.DependencyNode dependencyGraph =
dependencyResolutionResult != null ? dependencyResolutionResult.getDependencyGraph() : null;
final List<org.sonatype.aether.graph.DependencyNode> dependencyNodes =
dependencyGraph != null ? dependencyGraph.getChildren() : Collections.<org.sonatype.aether.graph.DependencyNode>emptyList();
model = AetherModelConverter.convertModelWithAetherDependencyTree(
mavenProject.getModel(), mavenProject.getCompileSourceRoots(), mavenProject.getTestCompileSourceRoots(),
mavenProject.getArtifacts(), dependencyNodes, mavenProject.getExtensionArtifacts(), getLocalRepositoryFile());
}
}
catch (Exception e) {
validate(mavenProject.getFile(), Collections.singleton(e), problems, null);
@@ -83,7 +83,7 @@ public class MavenModelConverter {
return result;
}
private static void convertBuild(MavenBuild result, Build build, List<String> sources, List<String> testSources) {
public static void convertBuild(MavenBuild result, Build build, List<String> sources, List<String> testSources) {
convertBuildBase(result, build);
result.setOutputDirectory(build.getOutputDirectory());
result.setTestOutputDirectory(build.getTestOutputDirectory());
@@ -122,7 +122,7 @@ public class MavenModelConverter {
return patterns == null ? Collections.<String>emptyList() : patterns;
}
private static List<MavenRemoteRepository> convertRepositories(List<Repository> repositories) {
public static List<MavenRemoteRepository> convertRepositories(List<Repository> repositories) {
if (repositories == null) return new ArrayList<MavenRemoteRepository>();
List<MavenRemoteRepository> result = new ArrayList<MavenRemoteRepository>(repositories.size());
@@ -191,7 +191,7 @@ public class MavenModelConverter {
return result;
}
private static MavenArtifact convertArtifact(Artifact artifact, Map<Artifact, MavenArtifact> nativeToConvertedMap, File localRepository) {
public static MavenArtifact convertArtifact(Artifact artifact, Map<Artifact, MavenArtifact> nativeToConvertedMap, File localRepository) {
MavenArtifact result = nativeToConvertedMap.get(artifact);
if (result == null) {
result = convertArtifact(artifact, localRepository);
@@ -228,7 +228,7 @@ public class MavenModelConverter {
return result;
}
private static List<MavenPlugin> convertPlugins(Model mavenModel) throws RemoteException {
public static List<MavenPlugin> convertPlugins(Model mavenModel) throws RemoteException {
List<MavenPlugin> result = new ArrayList<MavenPlugin>();
Build build = mavenModel.getBuild();
@@ -15,18 +15,32 @@
*/
package org.jetbrains.idea.maven.server.embedder;
import org.apache.maven.project.DependencyResolutionResult;
import org.apache.maven.project.MavenProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class MavenExecutionResult {
private final MavenProject myMavenProject;
private final List<Exception> myExceptions;
private final DependencyResolutionResult myDependencyResolutionResult;
public MavenExecutionResult(@Nullable MavenProject mavenProject, List<Exception> exceptions) {
this(mavenProject, null, exceptions);
}
public MavenExecutionResult(@Nullable MavenProject mavenProject,
@Nullable DependencyResolutionResult dependencyResolutionResult,
List<Exception> exceptions) {
myMavenProject = mavenProject;
myExceptions = exceptions;
myExceptions = exceptions == null ? new ArrayList<Exception>() : exceptions;
myDependencyResolutionResult = dependencyResolutionResult;
if(myDependencyResolutionResult != null && myDependencyResolutionResult.getCollectionErrors() != null) {
myExceptions.addAll(myDependencyResolutionResult.getCollectionErrors());
}
}
@Nullable
@@ -34,6 +48,12 @@ public class MavenExecutionResult {
return myMavenProject;
}
@Nullable
public DependencyResolutionResult getDependencyResolutionResult() {
return myDependencyResolutionResult;
}
@NotNull
public List<Exception> getExceptions() {
return myExceptions;
}