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