/* * Copyright 2014 Bernd Vogt and others. * * 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.sourcepit.b2.internal.maven; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.inject.Inject; import javax.inject.Named; import org.apache.maven.execution.MavenSession; import org.apache.maven.project.DefaultDependencyResolutionRequest; import org.apache.maven.project.DependencyResolutionException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectDependenciesResolver; import org.eclipse.aether.AbstractForwardingRepositorySystemSession; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.ArtifactProperties; import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.collection.DependencyCollectionContext; import org.eclipse.aether.collection.DependencySelector; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyFilter; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.util.graph.selector.AndDependencySelector; import org.eclipse.aether.util.graph.selector.ScopeDependencySelector; import org.sourcepit.common.maven.artifact.MavenArtifactUtils; import org.sourcepit.common.maven.model.MavenArtifact; import org.sourcepit.common.utils.lang.Exceptions; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.SetMultimap; @Named public class DefaultModuleArtifactResolver implements ModuleArtifactResolver { @Inject private ProjectDependenciesResolver dependenciesResolver; public SetMultimap<MavenArtifact, String> resolve(MavenSession session, MavenProject project, String scope) { final SetMultimap<Artifact, String> artifactToClassifiers = resolveModuleDependencies(session, project, scope); final SetMultimap<MavenArtifact, String> moduleArtifactToClassifiers = LinkedHashMultimap.create(); for (Entry<Artifact, Collection<String>> entry : artifactToClassifiers.asMap().entrySet()) { Artifact artifact = entry.getKey(); Collection<String> classifiers = entry.getValue(); final MavenArtifact mavenArtifact = MavenArtifactUtils.toMavenArtifact(artifact); moduleArtifactToClassifiers.get(mavenArtifact).addAll(classifiers); } return moduleArtifactToClassifiers; } private SetMultimap<Artifact, String> resolveModuleDependencies(final MavenSession session, MavenProject project, final String scope) { final Map<DependencyNode, String> moduleNodeToClassifiers = new LinkedHashMap<DependencyNode, String>(); final DependencyFilter resolutionFilter = new DependencyFilter() { public boolean accept(DependencyNode node, List<DependencyNode> parents) { Artifact moduleArtifact = getModuleArtifact(node); if (moduleArtifact != null) { final String classifier = moduleArtifact.getClassifier(); final Artifact newArtifact; newArtifact = new DefaultArtifact(moduleArtifact.getGroupId(), moduleArtifact.getArtifactId(), "", moduleArtifact.getExtension(), moduleArtifact.getVersion(), moduleArtifact.getProperties(), moduleArtifact.getFile()); node.setArtifact(newArtifact); moduleNodeToClassifiers.put(node, classifier); } return true; } private Artifact getModuleArtifact(DependencyNode node) { if (node.getDependency() != null) { final Dependency dependency = node.getDependency(); if (dependency.getArtifact() != null) { final Artifact artifact = dependency.getArtifact(); if ("module".equals(artifact.getExtension())) { return artifact; } } } return null; } }; final DependencySelector dependencySelector = createDependencySelector(scope); final AbstractForwardingRepositorySystemSession systemSession = new AbstractForwardingRepositorySystemSession() { @Override public DependencySelector getDependencySelector() { return dependencySelector; } @Override protected RepositorySystemSession getSession() { return session.getRepositorySession(); } }; final DefaultDependencyResolutionRequest request; request = new DefaultDependencyResolutionRequest(project, systemSession); request.setResolutionFilter(resolutionFilter); try { dependenciesResolver.resolve(request); } catch (DependencyResolutionException e) { throw Exceptions.pipe(e); } final SetMultimap<Artifact, String> artifactToClassifiers = LinkedHashMultimap.create(); for (Entry<DependencyNode, String> entry : moduleNodeToClassifiers.entrySet()) { DependencyNode dependencyNode = entry.getKey(); artifactToClassifiers.get(dependencyNode.getDependency().getArtifact()).add(entry.getValue()); } return artifactToClassifiers; } private static DependencySelector createDependencySelector(final String scope) { final DependencySelector moduleDependencySelector = new DependencySelector() { public boolean selectDependency(Dependency dependency) { final Artifact artifact = dependency.getArtifact(); final String type = artifact.getProperty(ArtifactProperties.TYPE, artifact.getExtension()); return "module".equals(type); } public DependencySelector deriveChildSelector(DependencyCollectionContext context) { return this; } }; final ScopeDependencySelector scopeDependencySelector = new ScopeDependencySelector(null, negate(Collections.singleton(scope))); return AndDependencySelector.newInstance(moduleDependencySelector, scopeDependencySelector); } private static Collection<String> negate(Collection<String> scopes) { Collection<String> result = new HashSet<String>(); Collections.addAll(result, "system", "compile", "provided", "runtime", "test"); for (String scope : scopes) { if ("compile".equals(scope)) { result.remove("compile"); result.remove("system"); result.remove("provided"); } else if ("runtime".equals(scope)) { result.remove("compile"); result.remove("runtime"); } else if ("compile+runtime".equals(scope)) { result.remove("compile"); result.remove("system"); result.remove("provided"); result.remove("runtime"); } else if ("runtime+system".equals(scope)) { result.remove("compile"); result.remove("system"); result.remove("runtime"); } else if ("test".equals(scope)) { result.clear(); } } return result; } }