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