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