1 package org.apache.maven.lifecycle.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import org.apache.maven.RepositoryUtils;
19 import org.apache.maven.artifact.Artifact;
20 import org.apache.maven.artifact.ArtifactUtils;
21 import org.apache.maven.artifact.factory.ArtifactFactory;
22 import org.apache.maven.execution.MavenSession;
23 import org.apache.maven.lifecycle.LifecycleExecutionException;
24 import org.apache.maven.project.DefaultDependencyResolutionRequest;
25 import org.apache.maven.project.DependencyResolutionException;
26 import org.apache.maven.project.DependencyResolutionResult;
27 import org.apache.maven.project.MavenProject;
28 import org.apache.maven.project.ProjectDependenciesResolver;
29 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
30 import org.codehaus.plexus.component.annotations.Component;
31 import org.codehaus.plexus.component.annotations.Requirement;
32 import org.codehaus.plexus.logging.Logger;
33 import org.sonatype.aether.graph.Dependency;
34 import org.sonatype.aether.graph.DependencyFilter;
35 import org.sonatype.aether.graph.DependencyNode;
36 import org.sonatype.aether.util.filter.AndDependencyFilter;
37 import org.sonatype.aether.util.filter.ScopeDependencyFilter;
38
39 import java.util.*;
40
41
42
43
44
45
46
47
48
49
50
51 @Component(role = LifecycleDependencyResolver.class)
52 public class LifecycleDependencyResolver
53 {
54
55 @Requirement
56 private ProjectDependenciesResolver dependenciesResolver;
57
58 @Requirement
59 private Logger logger;
60
61 @Requirement
62 private ArtifactFactory artifactFactory;
63
64 @SuppressWarnings({"UnusedDeclaration"})
65 public LifecycleDependencyResolver()
66 {
67 }
68
69 public LifecycleDependencyResolver( ProjectDependenciesResolver projectDependenciesResolver, Logger logger )
70 {
71 this.dependenciesResolver = projectDependenciesResolver;
72 this.logger = logger;
73 }
74
75 public static List<MavenProject> getProjects( MavenProject project, MavenSession session, boolean aggregator )
76 {
77 if ( aggregator )
78 {
79 return session.getProjects();
80 }
81 else
82 {
83 return Collections.singletonList( project );
84 }
85 }
86
87 public void resolveProjectDependencies( MavenProject project, Collection<String> scopesToCollect,
88 Collection<String> scopesToResolve, MavenSession session,
89 boolean aggregating, Set<Artifact> projectArtifacts )
90 throws LifecycleExecutionException
91 {
92 if ( project.getDependencyArtifacts() == null )
93 {
94 try
95 {
96 project.setDependencyArtifacts( project.createArtifacts( artifactFactory, null, null ) );
97 }
98 catch ( InvalidDependencyVersionException e )
99 {
100 throw new LifecycleExecutionException( e );
101 }
102 }
103
104 Set<Artifact> artifacts =
105 getDependencies( project, scopesToCollect, scopesToResolve, session, aggregating, projectArtifacts );
106
107 project.setResolvedArtifacts( artifacts );
108
109 Map<String, Artifact> map = new HashMap<String, Artifact>();
110 for ( Artifact artifact : artifacts )
111 {
112 map.put( artifact.getDependencyConflictId(), artifact );
113 }
114 for ( Artifact artifact : project.getDependencyArtifacts() )
115 {
116 if ( artifact.getFile() == null )
117 {
118 Artifact resolved = map.get( artifact.getDependencyConflictId() );
119 if ( resolved != null )
120 {
121 artifact.setFile( resolved.getFile() );
122 artifact.setDependencyTrail( resolved.getDependencyTrail() );
123 artifact.setResolvedVersion( resolved.getVersion() );
124 artifact.setResolved( true );
125 }
126 }
127 }
128 }
129
130 private Set<Artifact> getDependencies( MavenProject project, Collection<String> scopesToCollect,
131 Collection<String> scopesToResolve, MavenSession session,
132 boolean aggregating, Set<Artifact> projectArtifacts )
133 throws LifecycleExecutionException
134 {
135 if ( scopesToCollect == null )
136 {
137 scopesToCollect = Collections.emptySet();
138 }
139 if ( scopesToResolve == null )
140 {
141 scopesToResolve = Collections.emptySet();
142 }
143
144 if ( scopesToCollect.isEmpty() && scopesToResolve.isEmpty() )
145 {
146 return new LinkedHashSet<Artifact>();
147 }
148
149 scopesToCollect = new HashSet<String>( scopesToCollect );
150 scopesToCollect.addAll( scopesToResolve );
151
152 DependencyFilter collectionFilter = new ScopeDependencyFilter( null, negate( scopesToCollect ) );
153 DependencyFilter resolutionFilter = new ScopeDependencyFilter( null, negate( scopesToResolve ) );
154 resolutionFilter = AndDependencyFilter.newInstance( collectionFilter, resolutionFilter );
155 resolutionFilter =
156 AndDependencyFilter.newInstance( resolutionFilter, new ReactorDependencyFilter( projectArtifacts ) );
157
158 DependencyResolutionResult result;
159 try
160 {
161 DefaultDependencyResolutionRequest request =
162 new DefaultDependencyResolutionRequest( project, session.getRepositorySession() );
163 request.setResolutionFilter( resolutionFilter );
164
165 result = dependenciesResolver.resolve( request );
166 }
167 catch ( DependencyResolutionException e )
168 {
169 result = e.getResult();
170
171
172
173
174
175
176 if ( aggregating && areAllDependenciesInReactor( session.getProjects(), result.getUnresolvedDependencies() ) )
177 {
178 logger.warn( "The following dependencies could not be resolved at this point of the build"
179 + " but seem to be part of the reactor:" );
180
181 for ( Dependency dependency : result.getUnresolvedDependencies() )
182 {
183 logger.warn( "o " + dependency );
184 }
185
186 logger.warn( "Try running the build up to the lifecycle phase \"package\"" );
187 }
188 else
189 {
190 throw new LifecycleExecutionException( null, project, e );
191 }
192 }
193
194 Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
195 if ( result.getDependencyGraph() != null && !result.getDependencyGraph().getChildren().isEmpty() )
196 {
197 RepositoryUtils.toArtifacts( artifacts, result.getDependencyGraph().getChildren(),
198 Collections.singletonList( project.getArtifact().getId() ), collectionFilter );
199 }
200 return artifacts;
201 }
202
203 private boolean areAllDependenciesInReactor( Collection<MavenProject> projects, Collection<Dependency> dependencies )
204 {
205 Set<String> projectKeys = getReactorProjectKeys( projects );
206
207 for ( Dependency dependency : dependencies )
208 {
209 org.sonatype.aether.artifact.Artifact a = dependency.getArtifact();
210 String key = ArtifactUtils.key( a.getGroupId(), a.getArtifactId(), a.getVersion() );
211 if ( !projectKeys.contains( key ) )
212 {
213 return false;
214 }
215 }
216
217 return true;
218 }
219
220 private Set<String> getReactorProjectKeys( Collection<MavenProject> projects )
221 {
222 Set<String> projectKeys = new HashSet<String>( projects.size() * 2 );
223 for ( MavenProject project : projects )
224 {
225 String key = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
226 projectKeys.add( key );
227 }
228 return projectKeys;
229 }
230
231 private Collection<String> negate( Collection<String> scopes )
232 {
233 Collection<String> result = new HashSet<String>();
234 Collections.addAll( result, "system", "compile", "provided", "runtime", "test" );
235
236 for ( String scope : scopes )
237 {
238 if ( "compile".equals( scope ) )
239 {
240 result.remove( "compile" );
241 result.remove( "system" );
242 result.remove( "provided" );
243 }
244 else if ( "runtime".equals( scope ) )
245 {
246 result.remove( "compile" );
247 result.remove( "runtime" );
248 }
249 else if ( "compile+runtime".equals( scope ) )
250 {
251 result.remove( "compile" );
252 result.remove( "system" );
253 result.remove( "provided" );
254 result.remove( "runtime" );
255 }
256 else if ( "runtime+system".equals( scope ) )
257 {
258 result.remove( "compile" );
259 result.remove( "system" );
260 result.remove( "runtime" );
261 }
262 else if ( "test".equals( scope ) )
263 {
264 result.clear();
265 }
266 }
267
268 return result;
269 }
270
271 private static class ReactorDependencyFilter
272 implements DependencyFilter
273 {
274
275 private Set<String> keys = new HashSet<String>();
276
277 public ReactorDependencyFilter( Collection<Artifact> artifacts )
278 {
279 for ( Artifact artifact : artifacts )
280 {
281 String key = ArtifactUtils.key( artifact );
282 keys.add( key );
283 }
284 }
285
286 public boolean accept( DependencyNode node, List<DependencyNode> parents )
287 {
288 Dependency dependency = node.getDependency();
289 if ( dependency != null )
290 {
291 org.sonatype.aether.artifact.Artifact a = dependency.getArtifact();
292 String key = ArtifactUtils.key( a.getGroupId(), a.getArtifactId(), a.getVersion() );
293 return !keys.contains( key );
294 }
295 return false;
296 }
297
298 }
299
300 }