1 package org.apache.maven.plugins.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.LinkedHashMap;
26 import java.util.LinkedHashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30
31 import org.apache.maven.artifact.Artifact;
32 import org.apache.maven.artifact.repository.ArtifactRepository;
33 import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
34 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
35 import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException;
36 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
37 import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
38 import org.apache.maven.plugins.assembly.archive.ArchiveCreationException;
39 import org.apache.maven.plugins.assembly.archive.phase.ModuleSetAssemblyPhase;
40 import org.apache.maven.plugins.assembly.model.Assembly;
41 import org.apache.maven.plugins.assembly.model.DependencySet;
42 import org.apache.maven.plugins.assembly.model.ModuleBinaries;
43 import org.apache.maven.plugins.assembly.model.ModuleSet;
44 import org.apache.maven.plugins.assembly.model.Repository;
45 import org.apache.maven.plugins.assembly.resolved.AssemblyId;
46 import org.apache.maven.plugins.assembly.utils.FilterUtils;
47 import org.apache.maven.project.MavenProject;
48 import org.apache.maven.project.ProjectBuildingRequest;
49 import org.apache.maven.repository.RepositorySystem;
50 import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
51 import org.apache.maven.shared.artifact.filter.resolve.transform.ArtifactIncludeFilterTransformer;
52 import org.apache.maven.shared.artifact.resolve.ArtifactResult;
53 import org.apache.maven.shared.dependencies.resolve.DependencyResolverException;
54 import org.codehaus.plexus.component.annotations.Component;
55 import org.codehaus.plexus.component.annotations.Requirement;
56 import org.codehaus.plexus.logging.AbstractLogEnabled;
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 @Requirement
69 private RepositorySystem resolver;
70
71 @Requirement
72 private org.apache.maven.shared.dependencies.resolve.DependencyResolver dependencyResolver;
73
74 @Override
75 public Map<DependencySet, Set<Artifact>> resolveDependencySets( final Assembly assembly, ModuleSet moduleSet,
76 final AssemblerConfigurationSource configSource,
77 List<DependencySet> dependencySets )
78 throws DependencyResolutionException
79 {
80 Map<DependencySet, Set<Artifact>> result = new LinkedHashMap<DependencySet, Set<Artifact>>();
81
82 for ( DependencySet dependencySet : dependencySets )
83 {
84
85 final MavenProject currentProject = configSource.getProject();
86
87 final ResolutionManagementInfo info = new ResolutionManagementInfo( currentProject );
88 updateRepositoryResolutionRequirements( assembly, info );
89 final AssemblyId assemblyId = AssemblyId.createAssemblyId( assembly );
90 updateDependencySetResolutionRequirements( dependencySet, info, assemblyId,
91 configSource.getMavenSession().getProjectBuildingRequest(),
92 currentProject );
93 updateModuleSetResolutionRequirements( assemblyId, moduleSet, dependencySet, info, configSource );
94
95 resolve( assembly, configSource, result, dependencySet, info );
96
97 }
98 return result;
99 }
100
101 private void resolve( Assembly assembly, AssemblerConfigurationSource configSource,
102 Map<DependencySet, Set<Artifact>> result, DependencySet dependencySet,
103 ResolutionManagementInfo info )
104 throws DependencyResolutionException
105 {
106 Set<Artifact> artifacts;
107 if ( info.isResolutionRequired() )
108 {
109 final List<ArtifactRepository> repos =
110 aggregateRemoteArtifactRepositories( configSource.getRemoteRepositories(), info.getEnabledProjects() );
111
112 artifacts = info.getArtifacts();
113 if ( info.isResolvedTransitively() )
114 {
115 getLogger().debug( "Resolving project dependencies transitively." );
116
117 ArtifactFilter filter = new ArtifactIncludeFilterTransformer().transform( info.getScopeFilter() );
118 artifacts = resolveTransitively( artifacts, repos, filter, configSource );
119 }
120 else
121 {
122 getLogger().debug( "Resolving project dependencies ONLY. "
123 + "Transitive dependencies WILL NOT be included in the results." );
124 artifacts = resolveNonTransitively( assembly, artifacts, configSource, repos );
125 }
126 }
127 else
128 {
129 artifacts = new HashSet<Artifact>();
130 }
131 result.put( dependencySet, artifacts );
132 }
133
134 @Override
135 public Map<DependencySet, Set<Artifact>> resolveDependencySets( final Assembly assembly,
136 final AssemblerConfigurationSource configSource,
137 List<DependencySet> dependencySets )
138 throws DependencyResolutionException
139 {
140 Map<DependencySet, Set<Artifact>> result = new LinkedHashMap<DependencySet, Set<Artifact>>();
141
142 for ( DependencySet dependencySet : dependencySets )
143 {
144
145 final MavenProject currentProject = configSource.getProject();
146
147 final ResolutionManagementInfo info = new ResolutionManagementInfo( currentProject );
148 updateRepositoryResolutionRequirements( assembly, info );
149 final AssemblyId assemblyId = AssemblyId.createAssemblyId( assembly );
150 updateDependencySetResolutionRequirements( dependencySet, info, assemblyId,
151 configSource.getMavenSession().getProjectBuildingRequest(),
152 currentProject );
153
154 resolve( assembly, configSource, result, dependencySet, info );
155
156 }
157 return result;
158 }
159
160 Set<Artifact> resolveNonTransitively( final Assembly assembly, final Set<Artifact> dependencyArtifacts,
161 final AssemblerConfigurationSource configSource,
162 final List<ArtifactRepository> repos )
163 throws DependencyResolutionException
164 {
165
166 final List<Artifact> missing = new ArrayList<Artifact>();
167 final Set<Artifact> resolved = new LinkedHashSet<Artifact>();
168 for ( final Artifact depArtifact : dependencyArtifacts )
169 {
170 ArtifactResolutionRequest req = new ArtifactResolutionRequest();
171 req.setLocalRepository( configSource.getLocalRepository() );
172 req.setRemoteRepositories( repos );
173 req.setArtifact( depArtifact );
174
175 ArtifactResolutionResult resolve = resolver.resolve( req );
176 if ( resolve.hasExceptions() )
177 {
178 if ( getLogger().isDebugEnabled() )
179 {
180 getLogger().debug(
181 "Failed to resolve: " + depArtifact.getId() + " for assembly: " + assembly.getId() );
182 }
183 missing.add( depArtifact );
184 }
185 else
186 {
187 resolved.add( depArtifact );
188 }
189 }
190
191 if ( !missing.isEmpty() )
192
193 {
194 final MavenProject project = configSource.getProject();
195 final Artifact rootArtifact = project.getArtifact();
196
197 final Throwable error =
198 new MultipleArtifactsNotFoundException( rootArtifact, new ArrayList<Artifact>( resolved ), missing,
199 repos );
200
201 throw new DependencyResolutionException( "Failed to resolve dependencies for: " + assembly.getId(), error );
202 }
203
204 return resolved;
205 }
206
207 private Set<Artifact> resolveTransitively( final Set<Artifact> dependencyArtifacts,
208 final List<ArtifactRepository> repos,
209 final ArtifactFilter filter,
210 final AssemblerConfigurationSource configSource )
211 throws DependencyResolutionException
212 {
213 final MavenProject project = configSource.getProject();
214
215 ArtifactResolutionRequest req = new ArtifactResolutionRequest();
216 req.setLocalRepository( configSource.getLocalRepository() );
217 req.setResolveRoot( false );
218 req.setRemoteRepositories( repos );
219 req.setResolveTransitively( true );
220 req.setArtifact( project.getArtifact() );
221 req.setArtifactDependencies( dependencyArtifacts );
222 req.setManagedVersionMap( project.getManagedVersionMap() );
223 req.setCollectionFilter( filter );
224 req.setOffline( configSource.getMavenSession().isOffline() );
225 req.setForceUpdate( configSource.getMavenSession().getRequest().isUpdateSnapshots() );
226 req.setServers( configSource.getMavenSession().getRequest().getServers() );
227 req.setMirrors( configSource.getMavenSession().getRequest().getMirrors() );
228 req.setProxies( configSource.getMavenSession().getRequest().getProxies() );
229
230 ArtifactResolutionResult result;
231
232 result = resolver.resolve( req );
233 if ( result.hasExceptions() )
234 {
235 throw new DependencyResolutionException( "Failed to resolve dependencies for assembly: ",
236 result.getExceptions().get( 0 ) );
237 }
238
239 getLogger().debug( "While resolving dependencies of " + project.getId() + ":" );
240
241 FilterUtils.reportFilteringStatistics( Collections.singleton( filter ), getLogger() );
242
243 return result.getArtifacts();
244 }
245
246 void updateRepositoryResolutionRequirements( final Assembly assembly, final ResolutionManagementInfo requirements )
247 {
248 final List<Repository> repositories = assembly.getRepositories();
249
250 Set<String> rootScopes = new HashSet<String>();
251
252 if ( repositories != null && !repositories.isEmpty() )
253 {
254
255 requirements.setResolutionRequired( true );
256 for ( final Repository repo : repositories )
257 {
258 rootScopes.add( repo.getScope() );
259 }
260 }
261
262 requirements.setScopeFilter( FilterUtils.newScopeFilter( rootScopes ) );
263 }
264
265
266 void updateModuleSetResolutionRequirements( AssemblyId assemblyId, ModuleSet set, DependencySet dependencySet,
267 final ResolutionManagementInfo requirements,
268 final AssemblerConfigurationSource configSource )
269 throws DependencyResolutionException
270 {
271 final ModuleBinaries binaries = set.getBinaries();
272 if ( binaries != null )
273 {
274 Set<MavenProject> projects;
275 try
276 {
277 projects = ModuleSetAssemblyPhase.getModuleProjects( set, configSource, getLogger() );
278 }
279 catch ( final ArchiveCreationException e )
280 {
281 throw new DependencyResolutionException( "Error determining project-set for moduleSet with binaries.",
282 e );
283 }
284
285 if ( !projects.isEmpty() )
286 {
287 for ( final MavenProject p : projects )
288 {
289 requirements.enableProjectResolution( p );
290
291 if ( p.getArtifact() == null )
292 {
293
294
295 final Artifact artifact =
296 resolver.createArtifact( p.getGroupId(), p.getArtifactId(), p.getVersion(),
297 p.getPackaging() );
298 p.setArtifact( artifact );
299 }
300 }
301 }
302
303 if ( binaries.isIncludeDependencies() )
304 {
305 updateDependencySetResolutionRequirements( dependencySet, requirements, assemblyId,
306 configSource.getMavenSession().getProjectBuildingRequest(),
307 projects.toArray( new MavenProject[projects.size()] ) );
308 }
309 }
310 }
311
312 void updateDependencySetResolutionRequirements( final DependencySet set,
313 final ResolutionManagementInfo requirements, AssemblyId assemblyId,
314 ProjectBuildingRequest buildingRequest,
315 final MavenProject... projects )
316 throws DependencyResolutionException
317 {
318 requirements.setResolutionRequired( true );
319
320 requirements.setResolvedTransitively( set.isUseTransitiveDependencies() );
321
322 ScopeFilter scopeFilter = FilterUtils.newScopeFilter( set.getScope() );
323
324 requirements.setScopeFilter( scopeFilter );
325
326 for ( final MavenProject project : projects )
327 {
328 if ( project == null )
329 {
330 continue;
331 }
332
333 Set<Artifact> dependencyArtifacts = project.getDependencyArtifacts();
334 if ( dependencyArtifacts == null )
335 {
336 try
337 {
338 Iterable<ArtifactResult> artifactResults =
339 dependencyResolver.resolveDependencies( buildingRequest, project.getModel(), scopeFilter );
340
341 dependencyArtifacts = new HashSet<Artifact>();
342
343 for ( ArtifactResult artifactResult : artifactResults )
344 {
345 dependencyArtifacts.add( artifactResult.getArtifact() );
346 }
347
348 project.setDependencyArtifacts( dependencyArtifacts );
349 }
350 catch ( final DependencyResolverException e )
351 {
352 throw new DependencyResolutionException(
353 "Failed to create dependency artifacts for resolution. Assembly: " + assemblyId, e );
354 }
355 }
356
357 requirements.addArtifacts( dependencyArtifacts );
358 getLogger().debug( "Dependencies for project: " + project.getId() + " are:\n" + StringUtils.join(
359 dependencyArtifacts.iterator(), "\n" ) );
360 }
361 }
362
363 List<ArtifactRepository> aggregateRemoteArtifactRepositories( final List<ArtifactRepository> remoteRepositories,
364 final Set<MavenProject> projects )
365 {
366 final List<List<ArtifactRepository>> repoLists = new ArrayList<List<ArtifactRepository>>();
367
368 repoLists.add( remoteRepositories );
369 for ( final MavenProject project : projects )
370 {
371 repoLists.add( project.getRemoteArtifactRepositories() );
372 }
373
374 final List<ArtifactRepository> remoteRepos = new ArrayList<ArtifactRepository>();
375 final Set<String> encounteredUrls = new HashSet<String>();
376
377 for ( final List<ArtifactRepository> repositoryList : repoLists )
378 {
379 if ( ( repositoryList != null ) && !repositoryList.isEmpty() )
380 {
381 for ( final ArtifactRepository repo : repositoryList )
382 {
383 if ( !encounteredUrls.contains( repo.getUrl() ) )
384 {
385 remoteRepos.add( repo );
386 encounteredUrls.add( repo.getUrl() );
387 }
388 }
389 }
390 }
391
392 return remoteRepos;
393 }
394
395 }