View Javadoc

1   package org.apache.maven.plugin.assembly.artifact;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * @author jdcasey
61   * @version $Id: DefaultDependencyResolver.java 1163853 2011-08-31 22:42:32Z jdcasey $
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          // for plexus init
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                                 // TODO: such a call in MavenMetadataSource too - packaging not really the intention of
272                                 // type
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 }