1 package org.apache.maven.plugin.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Collection;
23 import java.util.LinkedHashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27
28 import javax.inject.Inject;
29 import javax.inject.Named;
30 import javax.inject.Singleton;
31
32 import org.apache.maven.RepositoryUtils;
33 import org.apache.maven.model.Dependency;
34 import org.apache.maven.model.Plugin;
35 import org.apache.maven.plugin.PluginResolutionException;
36 import org.codehaus.plexus.util.StringUtils;
37 import org.eclipse.aether.DefaultRepositorySystemSession;
38 import org.eclipse.aether.RepositorySystem;
39 import org.eclipse.aether.RepositorySystemSession;
40 import org.eclipse.aether.RequestTrace;
41 import org.eclipse.aether.artifact.Artifact;
42 import org.eclipse.aether.artifact.DefaultArtifact;
43 import org.eclipse.aether.collection.CollectRequest;
44 import org.eclipse.aether.collection.DependencyCollectionException;
45 import org.eclipse.aether.graph.DependencyFilter;
46 import org.eclipse.aether.graph.DependencyNode;
47 import org.eclipse.aether.graph.DependencyVisitor;
48 import org.eclipse.aether.repository.RemoteRepository;
49 import org.eclipse.aether.resolution.ArtifactDescriptorException;
50 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
51 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
52 import org.eclipse.aether.resolution.ArtifactRequest;
53 import org.eclipse.aether.resolution.ArtifactResolutionException;
54 import org.eclipse.aether.resolution.DependencyRequest;
55 import org.eclipse.aether.resolution.DependencyResolutionException;
56 import org.eclipse.aether.util.artifact.JavaScopes;
57 import org.eclipse.aether.util.filter.AndDependencyFilter;
58 import org.eclipse.aether.util.filter.ScopeDependencyFilter;
59 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
60 import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64
65
66
67
68
69
70
71
72 @Named
73 @Singleton
74 public class DefaultPluginDependenciesResolver
75 implements PluginDependenciesResolver
76 {
77 private static final String REPOSITORY_CONTEXT = "plugin";
78
79 private final Logger logger = LoggerFactory.getLogger( getClass() );
80
81 private final RepositorySystem repoSystem;
82
83 @Inject
84 public DefaultPluginDependenciesResolver( RepositorySystem repoSystem )
85 {
86 this.repoSystem = repoSystem;
87 }
88
89 private Artifact toArtifact( Plugin plugin, RepositorySystemSession session )
90 {
91 return new DefaultArtifact( plugin.getGroupId(), plugin.getArtifactId(), null, "jar", plugin.getVersion(),
92 session.getArtifactTypeRegistry().get( "maven-plugin" ) );
93 }
94
95 public Artifact resolve( Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session )
96 throws PluginResolutionException
97 {
98 RequestTrace trace = RequestTrace.newChild( null, plugin );
99
100 Artifact pluginArtifact = toArtifact( plugin, session );
101
102 try
103 {
104 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session );
105 pluginSession.setArtifactDescriptorPolicy( new SimpleArtifactDescriptorPolicy( true, false ) );
106
107 ArtifactDescriptorRequest request =
108 new ArtifactDescriptorRequest( pluginArtifact, repositories, REPOSITORY_CONTEXT );
109 request.setTrace( trace );
110 ArtifactDescriptorResult result = repoSystem.readArtifactDescriptor( pluginSession, request );
111
112 pluginArtifact = result.getArtifact();
113
114 if ( logger.isWarnEnabled() )
115 {
116 if ( !result.getRelocations().isEmpty() )
117 {
118 String message = pluginArtifact instanceof org.apache.maven.repository.internal.RelocatedArtifact
119 ? ( ( org.apache.maven.repository.internal.RelocatedArtifact ) pluginArtifact ).getMessage()
120 : null;
121 logger.warn( "The artifact " + result.getRelocations().get( 0 ) + " has been relocated to "
122 + pluginArtifact + ( message != null ? ": " + message : "" ) );
123 }
124 }
125
126 String requiredMavenVersion = (String) result.getProperties().get( "prerequisites.maven" );
127 if ( requiredMavenVersion != null )
128 {
129 Map<String, String> props = new LinkedHashMap<>( pluginArtifact.getProperties() );
130 props.put( "requiredMavenVersion", requiredMavenVersion );
131 pluginArtifact = pluginArtifact.setProperties( props );
132 }
133 }
134 catch ( ArtifactDescriptorException e )
135 {
136 throw new PluginResolutionException( plugin, e );
137 }
138
139 try
140 {
141 ArtifactRequest request = new ArtifactRequest( pluginArtifact, repositories, REPOSITORY_CONTEXT );
142 request.setTrace( trace );
143 pluginArtifact = repoSystem.resolveArtifact( session, request ).getArtifact();
144 }
145 catch ( ArtifactResolutionException e )
146 {
147 throw new PluginResolutionException( plugin, e );
148 }
149
150 return pluginArtifact;
151 }
152
153
154
155
156 public DependencyNode resolveCoreExtension( Plugin plugin, DependencyFilter dependencyFilter,
157 List<RemoteRepository> repositories, RepositorySystemSession session )
158 throws PluginResolutionException
159 {
160 return resolveInternal( plugin, null , dependencyFilter,
161 repositories, session );
162 }
163
164 public DependencyNode resolve( Plugin plugin, Artifact pluginArtifact, DependencyFilter dependencyFilter,
165 List<RemoteRepository> repositories, RepositorySystemSession session )
166 throws PluginResolutionException
167 {
168 return resolveInternal( plugin, pluginArtifact, dependencyFilter, repositories,
169 session );
170 }
171
172 private DependencyNode resolveInternal( Plugin plugin, Artifact pluginArtifact, DependencyFilter dependencyFilter,
173 List<RemoteRepository> repositories, RepositorySystemSession session )
174 throws PluginResolutionException
175 {
176 RequestTrace trace = RequestTrace.newChild( null, plugin );
177
178 if ( pluginArtifact == null )
179 {
180 pluginArtifact = toArtifact( plugin, session );
181 }
182
183 DependencyFilter collectionFilter = new ScopeDependencyFilter( "provided", "test" );
184 DependencyFilter resolutionFilter = AndDependencyFilter.newInstance( collectionFilter, dependencyFilter );
185
186 DependencyNode node;
187
188 try
189 {
190 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session );
191 pluginSession.setDependencySelector( session.getDependencySelector() );
192 pluginSession.setDependencyGraphTransformer( session.getDependencyGraphTransformer() );
193
194 CollectRequest request = new CollectRequest();
195 request.setRequestContext( REPOSITORY_CONTEXT );
196 request.setRepositories( repositories );
197 request.setRoot( new org.eclipse.aether.graph.Dependency( pluginArtifact, null ) );
198 for ( Dependency dependency : plugin.getDependencies() )
199 {
200 org.eclipse.aether.graph.Dependency pluginDep =
201 RepositoryUtils.toDependency( dependency, session.getArtifactTypeRegistry() );
202 if ( !JavaScopes.SYSTEM.equals( pluginDep.getScope() ) )
203 {
204 pluginDep = pluginDep.setScope( JavaScopes.RUNTIME );
205 }
206 request.addDependency( pluginDep );
207 }
208
209 DependencyRequest depRequest = new DependencyRequest( request, resolutionFilter );
210 depRequest.setTrace( trace );
211
212 request.setTrace( RequestTrace.newChild( trace, depRequest ) );
213
214 node = repoSystem.collectDependencies( pluginSession, request ).getRoot();
215
216 if ( logger.isDebugEnabled() )
217 {
218 node.accept( new GraphLogger() );
219 }
220
221 depRequest.setRoot( node );
222 repoSystem.resolveDependencies( session, depRequest );
223 }
224 catch ( DependencyCollectionException e )
225 {
226 throw new PluginResolutionException( plugin, e );
227 }
228 catch ( DependencyResolutionException e )
229 {
230 throw new PluginResolutionException( plugin, e.getCause() );
231 }
232
233 return node;
234 }
235
236
237 class GraphLogger
238 implements DependencyVisitor
239 {
240
241 private String indent = "";
242
243 public boolean visitEnter( DependencyNode node )
244 {
245 StringBuilder buffer = new StringBuilder( 128 );
246 buffer.append( indent );
247 org.eclipse.aether.graph.Dependency dep = node.getDependency();
248 if ( dep != null )
249 {
250 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
251
252 buffer.append( art );
253 if ( StringUtils.isNotEmpty( dep.getScope() ) )
254 {
255 buffer.append( ':' ).append( dep.getScope() );
256 }
257
258 if ( dep.isOptional() )
259 {
260 buffer.append( " (optional)" );
261 }
262
263
264
265
266 if ( ( node.getManagedBits() & DependencyNode.MANAGED_SCOPE ) == DependencyNode.MANAGED_SCOPE )
267 {
268 final String premanagedScope = DependencyManagerUtils.getPremanagedScope( node );
269 buffer.append( " (scope managed from " );
270 buffer.append( Objects.toString( premanagedScope, "default" ) );
271 buffer.append( ')' );
272 }
273
274 if ( ( node.getManagedBits() & DependencyNode.MANAGED_VERSION ) == DependencyNode.MANAGED_VERSION )
275 {
276 final String premanagedVersion = DependencyManagerUtils.getPremanagedVersion( node );
277 buffer.append( " (version managed from " );
278 buffer.append( Objects.toString( premanagedVersion, "default" ) );
279 buffer.append( ')' );
280 }
281
282 if ( ( node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL ) == DependencyNode.MANAGED_OPTIONAL )
283 {
284 final Boolean premanagedOptional = DependencyManagerUtils.getPremanagedOptional( node );
285 buffer.append( " (optionality managed from " );
286 buffer.append( Objects.toString( premanagedOptional, "default" ) );
287 buffer.append( ')' );
288 }
289
290 if ( ( node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS )
291 == DependencyNode.MANAGED_EXCLUSIONS )
292 {
293 final Collection<org.eclipse.aether.graph.Exclusion> premanagedExclusions =
294 DependencyManagerUtils.getPremanagedExclusions( node );
295
296 buffer.append( " (exclusions managed from " );
297 buffer.append( Objects.toString( premanagedExclusions, "default" ) );
298 buffer.append( ')' );
299 }
300
301 if ( ( node.getManagedBits() & DependencyNode.MANAGED_PROPERTIES )
302 == DependencyNode.MANAGED_PROPERTIES )
303 {
304 final Map<String, String> premanagedProperties =
305 DependencyManagerUtils.getPremanagedProperties( node );
306
307 buffer.append( " (properties managed from " );
308 buffer.append( Objects.toString( premanagedProperties, "default" ) );
309 buffer.append( ')' );
310 }
311 }
312
313 logger.debug( buffer.toString() );
314 indent += " ";
315 return true;
316 }
317
318 public boolean visitLeave( DependencyNode node )
319 {
320 indent = indent.substring( 0, indent.length() - 3 );
321 return true;
322 }
323
324 }
325
326 }