/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.shrinkwrap.resolver.impl.maven.bootstrap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.settings.Settings;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResolutionException;
import org.eclipse.aether.resolution.VersionRangeResult;
import org.jboss.shrinkwrap.resolver.api.maven.MavenWorkingSession;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependency;
import org.jboss.shrinkwrap.resolver.api.maven.filter.MavenResolutionFilter;
import org.jboss.shrinkwrap.resolver.impl.maven.convert.MavenConverter;
Abstraction of the repository system for purposes of dependency resolution used by Maven
Author: Karel Piwko, Michal Matloka
/**
* Abstraction of the repository system for purposes of dependency resolution used by Maven
*
* @author <a href="mailto:kpiwko@redhat.com">Karel Piwko</a>
* @author <a href="mailto:mmatloka@gmail.com">Michal Matloka</a>
*/
public class MavenRepositorySystem {
private final RepositorySystem system;
Creates a Maven repository system
/**
* Creates a Maven repository system
*/
public MavenRepositorySystem() {
this.system = getRepositorySystem();
}
Spawns a working session from the repository system. This is used to as environment for execution of Maven
commands
Params: - settings –
A configuration of current session
- legacyLocalRepository –
Whether to ignore origin of artifacts in local repository; defaults to false
Returns: A working session spawned from the repository system.
/**
* Spawns a working session from the repository system. This is used to as environment for execution of Maven
* commands
*
* @param settings
* A configuration of current session
* @param legacyLocalRepository
* Whether to ignore origin of artifacts in local repository; defaults to false
* @return A working session spawned from the repository system.
*/
public DefaultRepositorySystemSession getSession(final Settings settings, boolean legacyLocalRepository) {
DefaultRepositorySystemSession session = new DefaultRepositorySystemSession();
MavenManagerBuilder builder = new MavenManagerBuilder(system, settings);
session.setLocalRepositoryManager(builder.localRepositoryManager(session, legacyLocalRepository));
session.setWorkspaceReader(builder.workspaceReader());
session.setTransferListener(builder.transferListerer());
session.setRepositoryListener(builder.repositoryListener());
session.setOffline(settings.isOffline());
session.setMirrorSelector(builder.mirrorSelector());
session.setProxySelector(builder.proxySelector());
session.setDependencyManager(builder.dependencyManager());
session.setArtifactDescriptorPolicy(builder.artifactRepositoryPolicy());
session.setDependencyTraverser(builder.dependencyTraverser());
session.setDependencyGraphTransformer(builder.dependencyGraphTransformer());
// set artifact stereotypes
session.setArtifactTypeRegistry(builder.artifactTypeRegistry());
// set system properties for interpolation
session.setSystemProperties(SecurityActions.getProperties());
session.setConfigProperties(SecurityActions.getProperties());
return session;
}
Resolves artifact dependencies. The ArtifactResult
contains a reference to a file in Maven local repository. Params: - repoSession – The current Maven session
- swrSession – SWR Aether session abstraction
- request – The request to be computed
- filters – The filters of dependency results
Throws: - DependencyResolutionException – If a dependency could not be computed or collected
Returns: A collection of artifacts which have built dependency tree from request
/**
* Resolves artifact dependencies.
*
* The {@link ArtifactResult} contains a reference to a file in Maven local repository.
*
* @param repoSession The current Maven session
* @param swrSession SWR Aether session abstraction
* @param request The request to be computed
* @param filters The filters of dependency results
* @return A collection of artifacts which have built dependency tree from {@code request}
* @throws DependencyResolutionException If a dependency could not be computed or collected
*/
public Collection<ArtifactResult> resolveDependencies(final RepositorySystemSession repoSession,
final MavenWorkingSession swrSession, final CollectRequest request, final MavenResolutionFilter[] filters)
throws DependencyResolutionException {
final DependencyRequest depRequest = new DependencyRequest(request, new MavenResolutionFilterWrap(filters,
Collections.unmodifiableList(new ArrayList<MavenDependency>(swrSession.getDependenciesForResolution()))));
DependencyResult result = system.resolveDependencies(repoSession, depRequest);
return result.getArtifactResults();
}
Resolves an artifact
Params: - session – The current Maven session
- request – The request to be computed
Throws: - ArtifactResolutionException – If the artifact could not be fetched
Returns: The artifact
/**
* Resolves an artifact
*
* @param session The current Maven session
* @param request The request to be computed
* @return The artifact
* @throws ArtifactResolutionException If the artifact could not be fetched
*/
public ArtifactResult resolveArtifact(final RepositorySystemSession session, final ArtifactRequest request)
throws ArtifactResolutionException {
return system.resolveArtifact(session, request);
}
Resolves versions range
Params: - session – The current Maven session
- request – The request to be computed
Throws: - VersionRangeResolutionException –
If the requested range could not be parsed. Note that an empty range does not raise an exception.
Returns: version range result
/**
* Resolves versions range
*
* @param session The current Maven session
* @param request The request to be computed
* @return version range result
* @throws VersionRangeResolutionException
* If the requested range could not be parsed. Note that an empty range does not raise an exception.
*
*/
public VersionRangeResult resolveVersionRange(final RepositorySystemSession session, final VersionRangeRequest request)
throws VersionRangeResolutionException {
return system.resolveVersionRange(session, request);
}
Finds a current implementation of repository system. A RepositorySystem
is an entry point to dependency resolution Throws: - UnsupportedOperationException – if
RepositorySystem
was not bootstrapped correctly
Returns: A repository system
/**
* Finds a current implementation of repository system. A {@link RepositorySystem} is an entry point to dependency
* resolution
*
* @return A repository system
* @throws UnsupportedOperationException if {@link RepositorySystem} was not bootstrapped correctly
*/
private RepositorySystem getRepositorySystem() throws UnsupportedOperationException {
final ShrinkWrapResolverServiceLocator locator = new ShrinkWrapResolverServiceLocator();
// if running from inside plugin, we required Maven 3.1.0 or newer
// that happens because Maven handles Aether dependencies in plugins a special way so we can't provide our own
// implementation, it is simply removed from classpath and not available at all
//
// locator will throw an exception if repository system cannot be set up
return locator.getService(RepositorySystem.class);
}
}
class MavenResolutionFilterWrap implements org.eclipse.aether.graph.DependencyFilter {
private static final Logger log = Logger.getLogger(MavenResolutionFilterWrap.class.getName());
private final MavenResolutionFilter[] filters;
private final List<MavenDependency> dependenciesForResolution;
MavenResolutionFilterWrap(final MavenResolutionFilter[] filters,
final List<MavenDependency> dependenciesForResolution) {
assert filters != null : "filters must be specified, even if empty";
assert dependenciesForResolution != null : "declaredDependencies must be specified";
this.dependenciesForResolution = dependenciesForResolution;
this.filters = filters;
}
{@inheritDoc}
See Also:
/**
* {@inheritDoc}
*
* @see org.eclipse.aether.graph.DependencyFilter#accept(org.eclipse.aether.graph.DependencyNode, java.util.List)
*/
@Override
public boolean accept(final DependencyNode node, List<DependencyNode> parents) {
Dependency dependency = node.getDependency();
if (dependency == null) {
return false;
}
List<MavenDependency> ancestors = new ArrayList<MavenDependency>();
for (DependencyNode parent : parents) {
Dependency parentDependency = parent.getDependency();
if (parentDependency != null) {
ancestors.add(MavenConverter.fromDependency(parentDependency));
}
}
if (log.isLoggable(Level.FINER)) {
log.log(Level.FINER, "Filtering {0} using {1} filters", new Object[] { dependency, filters.length });
}
for (final MavenResolutionFilter filter : filters) {
if (!filter.accepts(MavenConverter.fromDependency(dependency), dependenciesForResolution, ancestors)) {
if (log.isLoggable(Level.FINER)) {
log.log(Level.FINER, "Dependency {0} rejected by {1}", new Object[] { dependency, filter });
}
return false;
}
}
// All filters passed
if (log.isLoggable(Level.FINER)) {
log.log(Level.FINER, "Dependency {0} was accepted.", dependency);
}
return true;
}
}