001package org.apache.maven.plugin.internal; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.LinkedHashMap; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.maven.ArtifactFilterManager; 027import org.apache.maven.RepositoryUtils; 028import org.apache.maven.model.Dependency; 029import org.apache.maven.model.Plugin; 030import org.apache.maven.plugin.PluginResolutionException; 031import org.codehaus.plexus.component.annotations.Component; 032import org.codehaus.plexus.component.annotations.Requirement; 033import org.codehaus.plexus.logging.Logger; 034import org.eclipse.aether.DefaultRepositorySystemSession; 035import org.eclipse.aether.RepositorySystem; 036import org.eclipse.aether.RepositorySystemSession; 037import org.eclipse.aether.RequestTrace; 038import org.eclipse.aether.artifact.Artifact; 039import org.eclipse.aether.artifact.DefaultArtifact; 040import org.eclipse.aether.collection.CollectRequest; 041import org.eclipse.aether.collection.DependencyCollectionException; 042import org.eclipse.aether.collection.DependencyGraphTransformer; 043import org.eclipse.aether.collection.DependencySelector; 044import org.eclipse.aether.graph.DependencyFilter; 045import org.eclipse.aether.graph.DependencyNode; 046import org.eclipse.aether.graph.DependencyVisitor; 047import org.eclipse.aether.repository.RemoteRepository; 048import org.eclipse.aether.resolution.ArtifactDescriptorException; 049import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 050import org.eclipse.aether.resolution.ArtifactDescriptorResult; 051import org.eclipse.aether.resolution.ArtifactRequest; 052import org.eclipse.aether.resolution.ArtifactResolutionException; 053import org.eclipse.aether.resolution.DependencyRequest; 054import org.eclipse.aether.resolution.DependencyResolutionException; 055import org.eclipse.aether.util.artifact.JavaScopes; 056import org.eclipse.aether.util.filter.AndDependencyFilter; 057import org.eclipse.aether.util.filter.ExclusionsDependencyFilter; 058import org.eclipse.aether.util.filter.ScopeDependencyFilter; 059import org.eclipse.aether.util.graph.selector.AndDependencySelector; 060import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer; 061import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy; 062 063/** 064 * Assists in resolving the dependencies of a plugin. <strong>Warning:</strong> This is an internal utility class that 065 * is only public for technical reasons, it is not part of the public API. In particular, this class can be changed or 066 * deleted without prior notice. 067 * 068 * @since 3.0 069 * @author Benjamin Bentmann 070 */ 071@Component( role = PluginDependenciesResolver.class ) 072public class DefaultPluginDependenciesResolver 073 implements PluginDependenciesResolver 074{ 075 076 private static final String REPOSITORY_CONTEXT = "plugin"; 077 078 @Requirement 079 private Logger logger; 080 081 @Requirement 082 private ArtifactFilterManager artifactFilterManager; 083 084 @Requirement 085 private RepositorySystem repoSystem; 086 087 private Artifact toArtifact( Plugin plugin, RepositorySystemSession session ) 088 { 089 return new DefaultArtifact( plugin.getGroupId(), plugin.getArtifactId(), null, "jar", plugin.getVersion(), 090 session.getArtifactTypeRegistry().get( "maven-plugin" ) ); 091 } 092 093 public Artifact resolve( Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session ) 094 throws PluginResolutionException 095 { 096 RequestTrace trace = RequestTrace.newChild( null, plugin ); 097 098 Artifact pluginArtifact = toArtifact( plugin, session ); 099 100 try 101 { 102 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session ); 103 pluginSession.setArtifactDescriptorPolicy( new SimpleArtifactDescriptorPolicy( true, false ) ); 104 105 ArtifactDescriptorRequest request = 106 new ArtifactDescriptorRequest( pluginArtifact, repositories, REPOSITORY_CONTEXT ); 107 request.setTrace( trace ); 108 ArtifactDescriptorResult result = repoSystem.readArtifactDescriptor( pluginSession, request ); 109 110 pluginArtifact = result.getArtifact(); 111 112 String requiredMavenVersion = (String) result.getProperties().get( "prerequisites.maven" ); 113 if ( requiredMavenVersion != null ) 114 { 115 Map<String, String> props = new LinkedHashMap<String, String>( pluginArtifact.getProperties() ); 116 props.put( "requiredMavenVersion", requiredMavenVersion ); 117 pluginArtifact = pluginArtifact.setProperties( props ); 118 } 119 } 120 catch ( ArtifactDescriptorException e ) 121 { 122 throw new PluginResolutionException( plugin, e ); 123 } 124 125 try 126 { 127 ArtifactRequest request = new ArtifactRequest( pluginArtifact, repositories, REPOSITORY_CONTEXT ); 128 request.setTrace( trace ); 129 pluginArtifact = repoSystem.resolveArtifact( session, request ).getArtifact(); 130 } 131 catch ( ArtifactResolutionException e ) 132 { 133 throw new PluginResolutionException( plugin, e ); 134 } 135 136 return pluginArtifact; 137 } 138 139 public DependencyNode resolve( Plugin plugin, Artifact pluginArtifact, DependencyFilter dependencyFilter, 140 List<RemoteRepository> repositories, RepositorySystemSession session ) 141 throws PluginResolutionException 142 { 143 RequestTrace trace = RequestTrace.newChild( null, plugin ); 144 145 if ( pluginArtifact == null ) 146 { 147 pluginArtifact = toArtifact( plugin, session ); 148 } 149 150 DependencyFilter collectionFilter = new ScopeDependencyFilter( "provided", "test" ); 151 152 DependencyFilter resolutionFilter = 153 new ExclusionsDependencyFilter( artifactFilterManager.getCoreArtifactExcludes() ); 154 resolutionFilter = AndDependencyFilter.newInstance( resolutionFilter, dependencyFilter ); 155 resolutionFilter = new AndDependencyFilter( collectionFilter, resolutionFilter ); 156 157 DependencyNode node; 158 159 try 160 { 161 DependencySelector selector = 162 AndDependencySelector.newInstance( session.getDependencySelector(), new WagonExcluder() ); 163 164 DependencyGraphTransformer transformer = 165 ChainedDependencyGraphTransformer.newInstance( session.getDependencyGraphTransformer(), 166 new PlexusUtilsInjector() ); 167 168 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session ); 169 pluginSession.setDependencySelector( selector ); 170 pluginSession.setDependencyGraphTransformer( transformer ); 171 172 CollectRequest request = new CollectRequest(); 173 request.setRequestContext( REPOSITORY_CONTEXT ); 174 request.setRepositories( repositories ); 175 request.setRoot( new org.eclipse.aether.graph.Dependency( pluginArtifact, null ) ); 176 for ( Dependency dependency : plugin.getDependencies() ) 177 { 178 org.eclipse.aether.graph.Dependency pluginDep = 179 RepositoryUtils.toDependency( dependency, session.getArtifactTypeRegistry() ); 180 if ( !JavaScopes.SYSTEM.equals( pluginDep.getScope() ) ) 181 { 182 pluginDep = pluginDep.setScope( JavaScopes.RUNTIME ); 183 } 184 request.addDependency( pluginDep ); 185 } 186 187 DependencyRequest depRequest = new DependencyRequest( request, resolutionFilter ); 188 depRequest.setTrace( trace ); 189 190 request.setTrace( RequestTrace.newChild( trace, depRequest ) ); 191 192 node = repoSystem.collectDependencies( pluginSession, request ).getRoot(); 193 194 if ( logger.isDebugEnabled() ) 195 { 196 node.accept( new GraphLogger() ); 197 } 198 199 depRequest.setRoot( node ); 200 repoSystem.resolveDependencies( session, depRequest ); 201 } 202 catch ( DependencyCollectionException e ) 203 { 204 throw new PluginResolutionException( plugin, e ); 205 } 206 catch ( DependencyResolutionException e ) 207 { 208 throw new PluginResolutionException( plugin, e.getCause() ); 209 } 210 211 return node; 212 } 213 214 class GraphLogger 215 implements DependencyVisitor 216 { 217 218 private String indent = ""; 219 220 public boolean visitEnter( DependencyNode node ) 221 { 222 StringBuilder buffer = new StringBuilder( 128 ); 223 buffer.append( indent ); 224 org.eclipse.aether.graph.Dependency dep = node.getDependency(); 225 if ( dep != null ) 226 { 227 Artifact art = dep.getArtifact(); 228 229 buffer.append( art ); 230 buffer.append( ':' ).append( dep.getScope() ); 231 } 232 233 logger.debug( buffer.toString() ); 234 indent += " "; 235 return true; 236 } 237 238 public boolean visitLeave( DependencyNode node ) 239 { 240 indent = indent.substring( 0, indent.length() - 3 ); 241 return true; 242 } 243 244 } 245 246}