1 package org.apache.maven.plugin.assembly.artifact;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.LinkedHashSet;
27 import java.util.List;
28 import java.util.Set;
29
30 import org.apache.maven.artifact.Artifact;
31 import org.apache.maven.artifact.factory.ArtifactFactory;
32 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
33 import org.apache.maven.artifact.repository.ArtifactRepository;
34 import org.apache.maven.artifact.resolver.ArtifactCollector;
35 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
36 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
37 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
38 import org.apache.maven.artifact.resolver.ArtifactResolver;
39 import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException;
40 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
41 import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
42 import org.apache.maven.plugin.assembly.AssemblyContext;
43 import org.apache.maven.plugin.assembly.archive.ArchiveCreationException;
44 import org.apache.maven.plugin.assembly.archive.phase.ModuleSetAssemblyPhase;
45 import org.apache.maven.plugin.assembly.model.Assembly;
46 import org.apache.maven.plugin.assembly.model.DependencySet;
47 import org.apache.maven.plugin.assembly.model.ModuleBinaries;
48 import org.apache.maven.plugin.assembly.model.ModuleSet;
49 import org.apache.maven.plugin.assembly.model.Repository;
50 import org.apache.maven.plugin.assembly.utils.FilterUtils;
51 import org.apache.maven.project.MavenProject;
52 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
53 import org.codehaus.plexus.component.annotations.Component;
54 import org.codehaus.plexus.component.annotations.Requirement;
55 import org.codehaus.plexus.logging.AbstractLogEnabled;
56 import org.codehaus.plexus.logging.Logger;
57 import org.codehaus.plexus.util.StringUtils;
58
59
60
61
62
63 @Component( role = DependencyResolver.class )
64 public class DefaultDependencyResolver
65 extends AbstractLogEnabled
66 implements DependencyResolver
67 {
68
69 @Requirement
70 private ArtifactResolver resolver;
71
72 @Requirement
73 private ArtifactMetadataSource metadataSource;
74
75 @Requirement
76 private ArtifactFactory factory;
77
78 @Requirement
79 private ArtifactCollector collector;
80
81 public DefaultDependencyResolver()
82 {
83
84 }
85
86 protected DefaultDependencyResolver( final ArtifactResolver resolver, final ArtifactMetadataSource metadataSource,
87 final ArtifactFactory factory, final ArtifactCollector collector,
88 final Logger logger )
89 {
90 this.resolver = resolver;
91 this.metadataSource = metadataSource;
92 this.factory = factory;
93 this.collector = collector;
94
95 enableLogging( logger );
96 }
97
98 public void resolve( final Assembly assembly, final AssemblerConfigurationSource configSource,
99 final AssemblyContext context )
100 throws DependencyResolutionException
101 {
102 final MavenProject currentProject = configSource.getProject();
103
104 final ResolutionManagementInfo info = new ResolutionManagementInfo( currentProject );
105 getRepositoryResolutionRequirements( assembly, info, currentProject );
106 getDependencySetResolutionRequirements( assembly, assembly.getDependencySets(), info, currentProject );
107 getModuleSetResolutionRequirements( assembly, info, configSource );
108
109 if ( !info.isResolutionRequired() )
110 {
111 context.setResolvedArtifacts( new HashSet<Artifact>() );
112 return;
113 }
114
115 final List<ArtifactRepository> repos =
116 aggregateRemoteArtifactRepositories( configSource.getRemoteRepositories(), info.getEnabledProjects() );
117
118 Set<Artifact> artifacts = info.getArtifacts();
119 if ( info.isResolvedTransitively() )
120 {
121 getLogger().debug( "Resolving project dependencies transitively." );
122 artifacts = resolveTransitively( artifacts, repos, info, configSource );
123 }
124 else
125 {
126 getLogger().debug( "Resolving project dependencies ONLY. Transitive dependencies WILL NOT be included in the results." );
127 artifacts = resolveNonTransitively( assembly, artifacts, configSource, repos );
128 }
129
130 context.setResolvedArtifacts( artifacts );
131 }
132
133 protected Set<Artifact> resolveNonTransitively( final Assembly assembly, final Set<Artifact> dependencyArtifacts,
134 final AssemblerConfigurationSource configSource,
135 final List<ArtifactRepository> repos )
136 throws DependencyResolutionException
137 {
138
139 final List<Artifact> missing = new ArrayList<Artifact>();
140 final Set<Artifact> resolved = new LinkedHashSet<Artifact>();
141 for ( final Iterator<Artifact> it = dependencyArtifacts.iterator(); it.hasNext(); )
142 {
143 final Artifact depArtifact = it.next();
144
145 try
146 {
147 resolver.resolve( depArtifact, repos, configSource.getLocalRepository() );
148 resolved.add( depArtifact );
149 }
150 catch ( final ArtifactResolutionException e )
151 {
152 if ( getLogger().isDebugEnabled() )
153 {
154 getLogger().debug( "Failed to resolve: " + depArtifact.getId() + " for assembly: "
155 + assembly.getId() );
156 }
157 missing.add( depArtifact );
158 }
159 catch ( final ArtifactNotFoundException e )
160 {
161 if ( getLogger().isDebugEnabled() )
162 {
163 getLogger().debug( "Failed to resolve: " + depArtifact.getId() + " for assembly: "
164 + assembly.getId() );
165 }
166 missing.add( depArtifact );
167 }
168 }
169
170 if ( !missing.isEmpty() )
171 {
172 final MavenProject project = configSource.getProject();
173 final Artifact rootArtifact = project.getArtifact();
174
175 final Throwable error =
176 new MultipleArtifactsNotFoundException( rootArtifact, new ArrayList<Artifact>( resolved ), missing,
177 repos );
178
179 throw new DependencyResolutionException( "Failed to resolve dependencies for: " + assembly.getId(), error );
180 }
181
182 return resolved;
183 }
184
185 @SuppressWarnings( "unchecked" )
186 private Set<Artifact> resolveTransitively( final Set<Artifact> dependencyArtifacts,
187 final List<ArtifactRepository> repos,
188 final ResolutionManagementInfo info,
189 final AssemblerConfigurationSource configSource )
190 throws DependencyResolutionException
191 {
192 final MavenProject project = configSource.getProject();
193
194 final ArtifactFilter filter = info.getScopeFilter();
195 final ArtifactRepository localRepository = configSource.getLocalRepository();
196
197 ArtifactResolutionResult result;
198 try
199 {
200 result =
201 resolver.resolveTransitively( dependencyArtifacts, project.getArtifact(),
202 project.getManagedVersionMap(), localRepository, repos, metadataSource,
203 filter );
204 }
205 catch ( final ArtifactResolutionException e )
206 {
207 throw new DependencyResolutionException( "Failed to resolve dependencies for assembly: ", e );
208 }
209 catch ( final ArtifactNotFoundException e )
210 {
211 throw new DependencyResolutionException( "Failed to resolve dependencies for assembly: ", e );
212 }
213
214 getLogger().debug( "While resolving dependencies of " + project.getId() + ":" );
215
216 FilterUtils.reportFilteringStatistics( Collections.singleton( filter ), getLogger() );
217
218 return result.getArtifacts();
219 }
220
221 protected void getRepositoryResolutionRequirements( final Assembly assembly,
222 final ResolutionManagementInfo requirements,
223 final MavenProject... project )
224 {
225 final List<Repository> repositories = assembly.getRepositories();
226
227 if ( repositories != null && !repositories.isEmpty() )
228 {
229 requirements.setResolutionRequired( true );
230 for ( final Repository repo : repositories )
231 {
232 enableScope( repo.getScope(), requirements );
233 }
234 }
235 }
236
237 protected void getModuleSetResolutionRequirements( final Assembly assembly,
238 final ResolutionManagementInfo requirements,
239 final AssemblerConfigurationSource configSource )
240 throws DependencyResolutionException
241 {
242 final List<ModuleSet> moduleSets = assembly.getModuleSets();
243
244 if ( moduleSets != null && !moduleSets.isEmpty() )
245 {
246 for ( final ModuleSet set : moduleSets )
247 {
248 final ModuleBinaries binaries = set.getBinaries();
249 if ( binaries != null )
250 {
251 Set<MavenProject> projects;
252 try
253 {
254 projects = ModuleSetAssemblyPhase.getModuleProjects( set, configSource, getLogger() );
255 }
256 catch ( final ArchiveCreationException e )
257 {
258 throw new DependencyResolutionException(
259 "Error determining project-set for moduleSet with binaries.",
260 e );
261 }
262
263 if ( projects != null && !projects.isEmpty() )
264 {
265 for ( final MavenProject p : projects )
266 {
267 requirements.enableProjectResolution( p );
268
269 if ( p.getArtifact() == null )
270 {
271
272
273 final Artifact artifact =
274 factory.createBuildArtifact( p.getGroupId(), p.getArtifactId(), p.getVersion(),
275 p.getPackaging() );
276 p.setArtifact( artifact );
277 }
278 }
279 }
280
281 if ( binaries.isIncludeDependencies() )
282 {
283 getDependencySetResolutionRequirements( assembly,
284 ModuleSetAssemblyPhase.getDependencySets( binaries ),
285 requirements, projects.toArray( new MavenProject[] {} ) );
286 }
287 }
288 }
289 }
290 }
291
292 @SuppressWarnings( "unchecked" )
293 protected void getDependencySetResolutionRequirements( final Assembly assembly, final List<DependencySet> depSets,
294 final ResolutionManagementInfo requirements,
295 final MavenProject... projects )
296 throws DependencyResolutionException
297 {
298 if ( depSets != null && !depSets.isEmpty() )
299 {
300 requirements.setResolutionRequired( true );
301
302 for ( final DependencySet set : depSets )
303 {
304 requirements.setResolvedTransitively( set.isUseTransitiveDependencies() );
305
306 enableScope( set.getScope(), requirements );
307 }
308
309 for ( final MavenProject project : projects )
310 {
311 if ( project == null )
312 {
313 continue;
314 }
315
316 Set<Artifact> dependencyArtifacts = project.getDependencyArtifacts();
317 if ( dependencyArtifacts == null )
318 {
319 try
320 {
321 dependencyArtifacts = project.createArtifacts( factory, null, requirements.getScopeFilter() );
322 project.setDependencyArtifacts( dependencyArtifacts );
323 }
324 catch ( final InvalidDependencyVersionException e )
325 {
326 throw new DependencyResolutionException(
327 "Failed to create dependency artifacts for resolution. Assembly: "
328 + assembly.getId(), e );
329 }
330 }
331
332 requirements.addArtifacts( dependencyArtifacts );
333 getLogger().debug( "Dependencies for project: " + project.getId() + " are:\n"
334 + StringUtils.join( dependencyArtifacts.iterator(), "\n" ) );
335 }
336 }
337 }
338
339 private void enableScope( final String scope, final ResolutionManagementInfo requirements )
340 {
341 if ( Artifact.SCOPE_COMPILE.equals( scope ) )
342 {
343 requirements.enableCompileScope();
344 }
345 else if ( Artifact.SCOPE_PROVIDED.equals( scope ) )
346 {
347 requirements.enableProvidedScope();
348 }
349 else if ( Artifact.SCOPE_RUNTIME.equals( scope ) )
350 {
351 requirements.enableRuntimeScope();
352 }
353 else if ( Artifact.SCOPE_SYSTEM.equals( scope ) )
354 {
355 requirements.enableSystemScope();
356 }
357 else if ( Artifact.SCOPE_TEST.equals( scope ) )
358 {
359 requirements.enableTestScope();
360 }
361 }
362
363 @SuppressWarnings( "unchecked" )
364 protected List<ArtifactRepository> aggregateRemoteArtifactRepositories( final List<ArtifactRepository> remoteRepositories,
365 final Set<MavenProject> projects )
366 {
367 final List<List<ArtifactRepository>> repoLists = new ArrayList<List<ArtifactRepository>>();
368
369 repoLists.add( remoteRepositories );
370 for ( final MavenProject project : projects )
371 {
372 repoLists.add( project.getRemoteArtifactRepositories() );
373 }
374
375 final List<ArtifactRepository> remoteRepos = new ArrayList<ArtifactRepository>();
376 final Set<String> encounteredUrls = new HashSet<String>();
377
378 for ( final Iterator<List<ArtifactRepository>> listIterator = repoLists.iterator(); listIterator.hasNext(); )
379 {
380 final List<ArtifactRepository> repositoryList = listIterator.next();
381
382 if ( ( repositoryList != null ) && !repositoryList.isEmpty() )
383 {
384 for ( final Iterator<ArtifactRepository> it = repositoryList.iterator(); it.hasNext(); )
385 {
386 final ArtifactRepository repo = it.next();
387
388 if ( !encounteredUrls.contains( repo.getUrl() ) )
389 {
390 remoteRepos.add( repo );
391 encounteredUrls.add( repo.getUrl() );
392 }
393 }
394 }
395 }
396
397 return remoteRepos;
398 }
399
400 protected ArtifactResolver getArtifactResolver()
401 {
402 return resolver;
403 }
404
405 protected DefaultDependencyResolver setArtifactResolver( final ArtifactResolver resolver )
406 {
407 this.resolver = resolver;
408
409 return this;
410 }
411
412 protected ArtifactMetadataSource getArtifactMetadataSource()
413 {
414 return metadataSource;
415 }
416
417 protected DefaultDependencyResolver setArtifactMetadataSource( final ArtifactMetadataSource metadataSource )
418 {
419 this.metadataSource = metadataSource;
420
421 return this;
422 }
423
424 protected ArtifactFactory getArtifactFactory()
425 {
426 return factory;
427 }
428
429 protected DefaultDependencyResolver setArtifactFactory( final ArtifactFactory factory )
430 {
431 this.factory = factory;
432
433 return this;
434 }
435
436 protected ArtifactCollector getArtifactCollector()
437 {
438 return collector;
439 }
440
441 protected DefaultDependencyResolver setArtifactCollector( final ArtifactCollector collector )
442 {
443 this.collector = collector;
444
445 return this;
446 }
447
448 protected DefaultDependencyResolver setLogger( final Logger logger )
449 {
450 enableLogging( logger );
451
452 return this;
453 }
454
455 }