1 package org.apache.maven.project;
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.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.maven.RepositoryUtils;
28 import org.apache.maven.artifact.Artifact;
29 import org.apache.maven.model.Dependency;
30 import org.apache.maven.model.DependencyManagement;
31 import org.apache.maven.model.Exclusion;
32 import org.apache.maven.model.InputLocation;
33 import org.apache.maven.model.InputSource;
34 import org.codehaus.plexus.component.annotations.Component;
35 import org.codehaus.plexus.component.annotations.Requirement;
36 import org.codehaus.plexus.logging.Logger;
37 import org.codehaus.plexus.util.StringUtils;
38 import org.eclipse.aether.DefaultRepositorySystemSession;
39 import org.eclipse.aether.RepositorySystem;
40 import org.eclipse.aether.RepositorySystemSession;
41 import org.eclipse.aether.RequestTrace;
42 import org.eclipse.aether.artifact.ArtifactProperties;
43 import org.eclipse.aether.artifact.ArtifactType;
44 import org.eclipse.aether.artifact.ArtifactTypeRegistry;
45 import org.eclipse.aether.collection.CollectRequest;
46 import org.eclipse.aether.collection.DependencyCollectionException;
47 import org.eclipse.aether.graph.DependencyFilter;
48 import org.eclipse.aether.graph.DependencyNode;
49 import org.eclipse.aether.graph.DependencyVisitor;
50 import org.eclipse.aether.resolution.ArtifactResult;
51 import org.eclipse.aether.resolution.DependencyRequest;
52 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
53 import org.eclipse.aether.util.artifact.JavaScopes;
54 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
55
56
57
58
59 @Component( role = ProjectDependenciesResolver.class )
60 public class DefaultProjectDependenciesResolver
61 implements ProjectDependenciesResolver
62 {
63
64 @Requirement
65 private Logger logger;
66
67 @Requirement
68 private RepositorySystem repoSystem;
69
70 @Requirement
71 private List<RepositorySessionDecorator> decorators;
72
73 public DependencyResolutionResult resolve( DependencyResolutionRequest request )
74 throws DependencyResolutionException
75 {
76 final RequestTrace trace = RequestTrace.newChild( null, request );
77
78 final DefaultDependencyResolutionResult result = new DefaultDependencyResolutionResult();
79
80 final MavenProject project = request.getMavenProject();
81 final DependencyFilter filter = request.getResolutionFilter();
82 RepositorySystemSession session = request.getRepositorySession();
83 ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry();
84
85 if ( logger.isDebugEnabled()
86 && session.getConfigProperties().get( DependencyManagerUtils.CONFIG_PROP_VERBOSE ) == null )
87 {
88 DefaultRepositorySystemSession verbose = new DefaultRepositorySystemSession( session );
89 verbose.setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, Boolean.TRUE );
90 session = verbose;
91 }
92
93 for ( RepositorySessionDecorator decorator : decorators )
94 {
95 RepositorySystemSession decorated = decorator.decorate( project, session );
96 if ( decorated != null )
97 {
98 session = decorated;
99 }
100 }
101
102 CollectRequest collect = new CollectRequest();
103 collect.setRootArtifact( RepositoryUtils.toArtifact( project.getArtifact() ) );
104 collect.setRequestContext( "project" );
105 collect.setRepositories( project.getRemoteProjectRepositories() );
106
107 if ( project.getDependencyArtifacts() == null )
108 {
109 for ( Dependency dependency : project.getDependencies() )
110 {
111 if ( StringUtils.isEmpty( dependency.getGroupId() ) || StringUtils.isEmpty( dependency.getArtifactId() )
112 || StringUtils.isEmpty( dependency.getVersion() ) )
113 {
114
115 continue;
116 }
117 collect.addDependency( RepositoryUtils.toDependency( dependency, stereotypes ) );
118 }
119 }
120 else
121 {
122 Map<String, Dependency> dependencies = new HashMap<>();
123 for ( Dependency dependency : project.getDependencies() )
124 {
125 String classifier = dependency.getClassifier();
126 if ( classifier == null )
127 {
128 ArtifactType type = stereotypes.get( dependency.getType() );
129 if ( type != null )
130 {
131 classifier = type.getClassifier();
132 }
133 }
134 String key =
135 ArtifactIdUtils.toVersionlessId( dependency.getGroupId(), dependency.getArtifactId(),
136 dependency.getType(), classifier );
137 dependencies.put( key, dependency );
138 }
139 for ( Artifact artifact : project.getDependencyArtifacts() )
140 {
141 String key = artifact.getDependencyConflictId();
142 Dependency dependency = dependencies.get( key );
143 Collection<Exclusion> exclusions = dependency != null ? dependency.getExclusions() : null;
144 org.eclipse.aether.graph.Dependency dep = RepositoryUtils.toDependency( artifact, exclusions );
145 if ( !JavaScopes.SYSTEM.equals( dep.getScope() ) && dep.getArtifact().getFile() != null )
146 {
147
148 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
149 art = art.setFile( null ).setVersion( art.getBaseVersion() );
150 dep = dep.setArtifact( art );
151 }
152 collect.addDependency( dep );
153 }
154 }
155
156 DependencyManagement depMgmt = project.getDependencyManagement();
157 if ( depMgmt != null )
158 {
159 for ( Dependency dependency : depMgmt.getDependencies() )
160 {
161 collect.addManagedDependency( RepositoryUtils.toDependency( dependency, stereotypes ) );
162 }
163 }
164
165 DependencyRequest depRequest = new DependencyRequest( collect, filter );
166 depRequest.setTrace( trace );
167
168 DependencyNode node;
169 try
170 {
171 collect.setTrace( RequestTrace.newChild( trace, depRequest ) );
172 node = repoSystem.collectDependencies( session, collect ).getRoot();
173 result.setDependencyGraph( node );
174 }
175 catch ( DependencyCollectionException e )
176 {
177 result.setDependencyGraph( e.getResult().getRoot() );
178 result.setCollectionErrors( e.getResult().getExceptions() );
179
180 throw new DependencyResolutionException( result, "Could not resolve dependencies for project "
181 + project.getId() + ": " + e.getMessage(), e );
182 }
183
184 depRequest.setRoot( node );
185
186 if ( logger.isWarnEnabled() )
187 {
188 for ( DependencyNode child : node.getChildren() )
189 {
190 if ( !child.getRelocations().isEmpty() )
191 {
192 logger.warn( "The artifact " + child.getRelocations().get( 0 ) + " has been relocated to "
193 + child.getDependency().getArtifact() );
194 }
195 }
196 }
197
198 if ( logger.isDebugEnabled() )
199 {
200 node.accept( new GraphLogger( project ) );
201 }
202
203 try
204 {
205 process( result, repoSystem.resolveDependencies( session, depRequest ).getArtifactResults() );
206 }
207 catch ( org.eclipse.aether.resolution.DependencyResolutionException e )
208 {
209 process( result, e.getResult().getArtifactResults() );
210
211 throw new DependencyResolutionException( result, "Could not resolve dependencies for project "
212 + project.getId() + ": " + e.getMessage(), e );
213 }
214
215 return result;
216 }
217
218 private void process( DefaultDependencyResolutionResult result, Collection<ArtifactResult> results )
219 {
220 for ( ArtifactResult ar : results )
221 {
222 DependencyNode node = ar.getRequest().getDependencyNode();
223 if ( ar.isResolved() )
224 {
225 result.addResolvedDependency( node.getDependency() );
226 }
227 else
228 {
229 result.setResolutionErrors( node.getDependency(), ar.getExceptions() );
230 }
231 }
232 }
233
234 class GraphLogger
235 implements DependencyVisitor
236 {
237
238 private final MavenProject project;
239
240 private String indent = "";
241
242 private Map<String, Dependency> managed;
243
244 public GraphLogger( MavenProject project )
245 {
246 this.project = project;
247 }
248
249 public boolean visitEnter( DependencyNode node )
250 {
251 StringBuilder buffer = new StringBuilder( 128 );
252 buffer.append( indent );
253 org.eclipse.aether.graph.Dependency dep = node.getDependency();
254 if ( dep != null )
255 {
256 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
257
258 buffer.append( art );
259 buffer.append( ':' ).append( dep.getScope() );
260
261 String premanagedScope = DependencyManagerUtils.getPremanagedScope( node );
262 if ( premanagedScope != null && !premanagedScope.equals( dep.getScope() ) )
263 {
264 buffer.append( " (scope managed from " ).append( premanagedScope );
265 appendManagementSource( buffer, art, "scope" );
266 buffer.append( ')' );
267 }
268
269 String premanagedVersion = DependencyManagerUtils.getPremanagedVersion( node );
270 if ( premanagedVersion != null && !premanagedVersion.equals( art.getVersion() ) )
271 {
272 buffer.append( " (version managed from " ).append( premanagedVersion );
273 appendManagementSource( buffer, art, "version" );
274 buffer.append( ')' );
275 }
276 }
277 else
278 {
279 buffer.append( project.getGroupId() );
280 buffer.append( ':' ).append( project.getArtifactId() );
281 buffer.append( ':' ).append( project.getPackaging() );
282 buffer.append( ':' ).append( project.getVersion() );
283 }
284
285 logger.debug( buffer.toString() );
286 indent += " ";
287 return true;
288 }
289
290 public boolean visitLeave( DependencyNode node )
291 {
292 indent = indent.substring( 0, indent.length() - 3 );
293 return true;
294 }
295
296 private void appendManagementSource( StringBuilder buffer, org.eclipse.aether.artifact.Artifact artifact,
297 String field )
298 {
299 if ( managed == null )
300 {
301 managed = new HashMap<>();
302 if ( project.getDependencyManagement() != null )
303 {
304 for ( Dependency dep : project.getDependencyManagement().getDependencies() )
305 {
306 managed.put( dep.getManagementKey(), dep );
307 }
308 }
309 }
310
311 String key =
312 ArtifactIdUtils.toVersionlessId( artifact.getGroupId(), artifact.getArtifactId(),
313 artifact.getProperty( ArtifactProperties.TYPE, "jar" ),
314 artifact.getClassifier() );
315
316 Dependency dependency = managed.get( key );
317 if ( dependency != null )
318 {
319 InputLocation location = dependency.getLocation( field );
320 if ( location != null )
321 {
322 InputSource source = location.getSource();
323 if ( source != null )
324 {
325 buffer.append( " by " ).append( source.getModelId() );
326 }
327 }
328 }
329 }
330
331 }
332
333 }