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