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