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.isDebugEnabled() )
185 {
186 node.accept( new GraphLogger( project ) );
187 }
188
189 try
190 {
191 process( result, repoSystem.resolveDependencies( session, depRequest ).getArtifactResults() );
192 }
193 catch ( org.eclipse.aether.resolution.DependencyResolutionException e )
194 {
195 process( result, e.getResult().getArtifactResults() );
196
197 throw new DependencyResolutionException( result, "Could not resolve dependencies for project "
198 + project.getId() + ": " + e.getMessage(), e );
199 }
200
201 return result;
202 }
203
204 private void process( DefaultDependencyResolutionResult result, Collection<ArtifactResult> results )
205 {
206 for ( ArtifactResult ar : results )
207 {
208 DependencyNode node = ar.getRequest().getDependencyNode();
209 if ( ar.isResolved() )
210 {
211 result.addResolvedDependency( node.getDependency() );
212 }
213 else
214 {
215 result.setResolutionErrors( node.getDependency(), ar.getExceptions() );
216 }
217 }
218 }
219
220
221 class GraphLogger
222 implements DependencyVisitor
223 {
224
225 private final MavenProject project;
226
227 private String indent = "";
228
229 GraphLogger( MavenProject project )
230 {
231 this.project = project;
232 }
233
234 public boolean visitEnter( DependencyNode node )
235 {
236 StringBuilder buffer = new StringBuilder( 128 );
237 buffer.append( indent );
238 org.eclipse.aether.graph.Dependency dep = node.getDependency();
239 if ( dep != null )
240 {
241 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
242
243 buffer.append( art );
244 if ( StringUtils.isNotEmpty( dep.getScope() ) )
245 {
246 buffer.append( ':' ).append( dep.getScope() );
247 }
248
249 if ( dep.isOptional() )
250 {
251 buffer.append( " (optional)" );
252 }
253
254
255
256
257 if ( ( node.getManagedBits() & DependencyNode.MANAGED_SCOPE ) == DependencyNode.MANAGED_SCOPE )
258 {
259 final String premanagedScope = DependencyManagerUtils.getPremanagedScope( node );
260 buffer.append( " (scope managed from " );
261 buffer.append( Objects.toString( premanagedScope, "default" ) );
262 buffer.append( ')' );
263 }
264
265 if ( ( node.getManagedBits() & DependencyNode.MANAGED_VERSION ) == DependencyNode.MANAGED_VERSION )
266 {
267 final String premanagedVersion = DependencyManagerUtils.getPremanagedVersion( node );
268 buffer.append( " (version managed from " );
269 buffer.append( Objects.toString( premanagedVersion, "default" ) );
270 buffer.append( ')' );
271 }
272
273 if ( ( node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL ) == DependencyNode.MANAGED_OPTIONAL )
274 {
275 final Boolean premanagedOptional = DependencyManagerUtils.getPremanagedOptional( node );
276 buffer.append( " (optionality managed from " );
277 buffer.append( Objects.toString( premanagedOptional, "default" ) );
278 buffer.append( ')' );
279 }
280
281 if ( ( node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS )
282 == DependencyNode.MANAGED_EXCLUSIONS )
283 {
284 final Collection<org.eclipse.aether.graph.Exclusion> premanagedExclusions =
285 DependencyManagerUtils.getPremanagedExclusions( node );
286
287 buffer.append( " (exclusions managed from " );
288 buffer.append( Objects.toString( premanagedExclusions, "default" ) );
289 buffer.append( ')' );
290 }
291
292 if ( ( node.getManagedBits() & DependencyNode.MANAGED_PROPERTIES )
293 == DependencyNode.MANAGED_PROPERTIES )
294 {
295 final Map<String, String> premanagedProperties =
296 DependencyManagerUtils.getPremanagedProperties( node );
297
298 buffer.append( " (properties managed from " );
299 buffer.append( Objects.toString( premanagedProperties, "default" ) );
300 buffer.append( ')' );
301 }
302 }
303 else
304 {
305 buffer.append( project.getGroupId() );
306 buffer.append( ':' ).append( project.getArtifactId() );
307 buffer.append( ':' ).append( project.getPackaging() );
308 buffer.append( ':' ).append( project.getVersion() );
309 }
310
311 logger.debug( buffer.toString() );
312 indent += " ";
313 return true;
314 }
315
316 public boolean visitLeave( DependencyNode node )
317 {
318 indent = indent.substring( 0, indent.length() - 3 );
319 return true;
320 }
321
322 }
323
324 }