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