View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.repository;
20  
21  import org.apache.maven.artifact.Artifact;
22  import org.apache.maven.artifact.ArtifactUtils;
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.repository.ArtifactRepositoryFactory;
27  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
28  import org.apache.maven.artifact.repository.DefaultArtifactRepository;
29  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
30  import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata;
31  import org.apache.maven.artifact.repository.metadata.Versioning;
32  import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
33  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
34  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
35  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
36  import org.apache.maven.artifact.resolver.ArtifactResolver;
37  import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
38  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
39  import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
40  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
41  import org.apache.maven.artifact.versioning.VersionRange;
42  import org.apache.maven.model.Dependency;
43  import org.apache.maven.model.DependencyManagement;
44  import org.apache.maven.model.Exclusion;
45  import org.apache.maven.project.DefaultMavenProjectBuilder;
46  import org.apache.maven.project.MavenProject;
47  import org.apache.maven.project.MavenProjectBuilder;
48  import org.apache.maven.project.ProjectBuildingException;
49  import org.apache.maven.shared.artifact.filter.PatternExcludesArtifactFilter;
50  import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter;
51  import org.apache.maven.shared.artifact.filter.ScopeArtifactFilter;
52  import org.apache.maven.shared.repository.model.GroupVersionAlignment;
53  import org.apache.maven.shared.repository.model.RepositoryInfo;
54  import org.apache.maven.shared.repository.utils.DigestUtils;
55  import org.codehaus.plexus.PlexusConstants;
56  import org.codehaus.plexus.PlexusContainer;
57  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
58  import org.codehaus.plexus.context.Context;
59  import org.codehaus.plexus.context.ContextException;
60  import org.codehaus.plexus.logging.AbstractLogEnabled;
61  import org.codehaus.plexus.logging.Logger;
62  import org.codehaus.plexus.logging.console.ConsoleLogger;
63  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
64  import org.codehaus.plexus.util.FileUtils;
65  import org.codehaus.plexus.util.IOUtil;
66  
67  import java.io.File;
68  import java.io.FileWriter;
69  import java.io.IOException;
70  import java.io.Writer;
71  import java.lang.reflect.Field;
72  import java.security.NoSuchAlgorithmException;
73  import java.text.DateFormat;
74  import java.text.SimpleDateFormat;
75  import java.util.ArrayList;
76  import java.util.Arrays;
77  import java.util.Collections;
78  import java.util.Date;
79  import java.util.HashMap;
80  import java.util.Iterator;
81  import java.util.List;
82  import java.util.Map;
83  import java.util.Set;
84  import java.util.TimeZone;
85  
86  /**
87   * @author Jason van Zyl
88   * @plexus.component role="org.apache.maven.shared.repository.RepositoryAssembler" role-hint="default"
89   */
90  
91  // todo will need to pop the processed project cache using reflection
92  public class DefaultRepositoryAssembler
93      extends AbstractLogEnabled
94      implements RepositoryAssembler, Contextualizable
95  {
96      private static final String[] PREFERRED_RESOLVER_HINTS = { "project-cache-aware", // Provided in Maven 2.1-SNAPSHOT
97                                                                "default" };
98  
99      protected static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
100 
101     protected static final String UTC_TIMESTAMP_PATTERN = "yyyyMMddHHmmss";
102 
103     /**
104      * @plexus.requirement
105      */
106     protected ArtifactFactory artifactFactory;
107 
108     // Replaced by Contextualizable code, to select the resolver in order of preference.
109     //
110     // @plexus.requirement
111     //
112     protected ArtifactResolver artifactResolver;
113 
114     /**
115      * @plexus.requirement
116      */
117     protected ArtifactRepositoryLayout repositoryLayout;
118 
119     /**
120      * @plexus.requirement
121      */
122     protected ArtifactRepositoryFactory artifactRepositoryFactory;
123 
124     /**
125      * @plexus.requirement
126      */
127     protected ArtifactMetadataSource metadataSource;
128 
129     /**
130      * @plexus.requirement
131      */
132     protected MavenProjectBuilder projectBuilder;
133 
134     public DefaultRepositoryAssembler()
135     {
136         // used for plexus init.
137     }
138 
139     public DefaultRepositoryAssembler( ArtifactFactory artifactFactory, ArtifactResolver artifactResolver,
140                                        ArtifactRepositoryLayout repositoryLayout,
141                                        ArtifactRepositoryFactory artifactRepositoryFactory,
142                                        ArtifactMetadataSource metadataSource, MavenProjectBuilder projectBuilder )
143     {
144         // used for testing, primarily.
145         this.artifactFactory = artifactFactory;
146         this.artifactResolver = artifactResolver;
147         this.repositoryLayout = repositoryLayout;
148         this.artifactRepositoryFactory = artifactRepositoryFactory;
149         this.metadataSource = metadataSource;
150         this.projectBuilder = projectBuilder;
151 
152         enableLogging( new ConsoleLogger( Logger.LEVEL_DEBUG, getClass().getName() + "::Internal" ) );
153     }
154 
155     public void buildRemoteRepository( File repositoryDirectory, RepositoryInfo repository,
156                                        RepositoryBuilderConfigSource configSource )
157         throws RepositoryAssemblyException
158     {
159         MavenProject project = configSource.getProject();
160         ArtifactRepository localRepository = configSource.getLocalRepository();
161 
162         Map groupVersionAlignments = createGroupVersionAlignments( repository.getGroupVersionAlignments() );
163 
164         ArtifactRepository targetRepository = createLocalRepository( repositoryDirectory );
165 
166         ArtifactResolutionResult result = null;
167 
168         Set dependencyArtifacts = project.getDependencyArtifacts();
169 
170         if ( dependencyArtifacts == null )
171         {
172             Logger logger = getLogger();
173 
174             if ( logger.isDebugEnabled() )
175             {
176                 logger.debug( "dependency-artifact set for project: " + project.getId()
177                     + " is null. Skipping repository processing." );
178             }
179 
180             return;
181         }
182 
183         try
184         {
185             // i have to get everything first as a filter or transformation here
186             // doesn't seem to work
187             // to align everything. If I use a filter to change the version on
188             // the fly then I get the
189             // I get JARs but no POMs, and in some directories POMs with no
190             // JARs.
191 
192             // FIXME I'm not getting runtime dependencies here
193             result = artifactResolver.resolveTransitively( dependencyArtifacts, project.getArtifact(),
194                                                            getManagedVersionMap( project ), localRepository,
195                                                            project.getRemoteArtifactRepositories(),
196                                                            metadataSource );
197         }
198         catch ( ArtifactResolutionException e )
199         {
200             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
201         }
202         catch ( ArtifactNotFoundException e )
203         {
204             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
205         }
206         catch ( InvalidVersionSpecificationException e )
207         {
208             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
209         }
210 
211         try
212         {
213             // Blow the cache in the project builder so that we get POMs again
214             // on this next download
215             invalidateProccessedProjectCache();
216         }
217         catch ( Exception e )
218         {
219             throw new RepositoryAssemblyException( "Error invalidating the processed project cache.", e );
220         }
221 
222         ArtifactFilter filter = buildRepositoryFilter( repository, project );
223 
224         assembleRepositoryArtifacts( result, filter, project, localRepository, targetRepository, repositoryDirectory,
225                                      groupVersionAlignments );
226 
227         ArtifactRepository centralRepository = findCentralRepository( project );
228 
229         if ( repository.isIncludeMetadata() )
230         {
231             assembleRepositoryMetadata( result, filter, centralRepository, targetRepository );
232         }
233 
234         addPomWithAncestry( project.getArtifact(), project.getRemoteArtifactRepositories(), localRepository,
235                             targetRepository, groupVersionAlignments, project );
236     }
237 
238     private ArtifactFilter buildRepositoryFilter( RepositoryInfo repository, MavenProject project )
239     {
240         AndArtifactFilter filter = new AndArtifactFilter();
241 
242         ArtifactFilter scopeFilter = new ScopeArtifactFilter( repository.getScope() );
243         filter.add( scopeFilter );
244 
245         // ----------------------------------------------------------------------------
246         // Includes
247         //
248         // We'll take everything if no includes are specified to try and make
249         // this
250         // process more maintainable. Don't want to have to update the assembly
251         // descriptor everytime the POM is updated.
252         // ----------------------------------------------------------------------------
253 
254         List includes = repository.getIncludes();
255 
256         if ( ( includes == null ) || includes.isEmpty() )
257         {
258             List patterns = new ArrayList();
259 
260             Set projectArtifacts = project.getDependencyArtifacts();
261 
262             if ( projectArtifacts != null )
263             {
264                 for ( Iterator it = projectArtifacts.iterator(); it.hasNext(); )
265                 {
266                     Artifact artifact = (Artifact) it.next();
267 
268                     patterns.add( artifact.getDependencyConflictId() );
269                 }
270             }
271 
272             PatternIncludesArtifactFilter includeFilter = new PatternIncludesArtifactFilter( patterns, true );
273 
274             filter.add( includeFilter );
275         }
276         else
277         {
278             filter.add( new PatternIncludesArtifactFilter( repository.getIncludes(), true ) );
279         }
280 
281         // ----------------------------------------------------------------------------
282         // Excludes
283         //
284         // We still want to make it easy to exclude a few things even if we
285         // slurp
286         // up everything.
287         // ----------------------------------------------------------------------------
288 
289         List excludes = repository.getExcludes();
290 
291         if ( ( excludes != null ) && !excludes.isEmpty() )
292         {
293             filter.add( new PatternExcludesArtifactFilter( repository.getExcludes(), true ) );
294         }
295 
296         return filter;
297     }
298 
299     private void assembleRepositoryArtifacts( ArtifactResolutionResult result, ArtifactFilter filter,
300                                               MavenProject project, ArtifactRepository localRepository,
301                                               ArtifactRepository targetRepository, File repositoryDirectory,
302                                               Map groupVersionAlignments )
303         throws RepositoryAssemblyException
304     {
305         try
306         {
307             // Now that we have the graph, let's try to align it to versions
308             // that we want and remove
309             // the repository we previously populated.
310             FileUtils.deleteDirectory( repositoryDirectory );
311 
312             FileUtils.mkdir( repositoryDirectory.getAbsolutePath() );
313 
314             for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
315             {
316                 Artifact a = (Artifact) i.next();
317 
318                 if ( filter.include( a ) )
319                 {
320                     getLogger().debug( "Re-resolving: " + a + " for repository assembly." );
321 
322                     setAlignment( a, groupVersionAlignments );
323 
324                     // We need to flip it back to not being resolved so we can
325                     // look for it again!
326                     a.setResolved( false );
327 
328                     artifactResolver.resolve( a, project.getRemoteArtifactRepositories(), localRepository );
329 
330                     a.setVersion( a.getBaseVersion() );
331 
332                     File targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( a ) );
333                     FileUtils.copyFile( a.getFile(), targetFile );
334 
335                     writeChecksums( targetFile );
336 
337                     addPomWithAncestry( a, project.getRemoteArtifactRepositories(), localRepository, targetRepository, groupVersionAlignments, project );
338                 }
339             }
340         }
341         catch ( ArtifactResolutionException e )
342         {
343             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
344         }
345         catch ( ArtifactNotFoundException e )
346         {
347             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
348         }
349         catch ( IOException e )
350         {
351             throw new RepositoryAssemblyException( "Error writing artifact metdata.", e );
352         }
353     }
354 
355     /**
356      *
357      * @param pomFileOverride This is used to allow injection of a POM's file directly, for
358      *         cases where the POM has not been installed into the repository yet.
359      */
360     private void addPomWithAncestry( final Artifact artifact, List remoteArtifactRepositories,
361                                      ArtifactRepository localRepository, ArtifactRepository targetRepository,
362                                      Map groupVersionAlignments, MavenProject masterProject )
363         throws RepositoryAssemblyException
364     {
365         String type = artifact.getType();
366         Map refs = masterProject.getProjectReferences();
367 
368         String projectKey = ArtifactUtils.versionlessKey( artifact );
369 
370         MavenProject p;
371         if ( artifact == masterProject.getArtifact() )
372         {
373             p = masterProject;
374         }
375         else if ( refs.containsKey( projectKey ) )
376         {
377             p = (MavenProject) refs.get( projectKey );
378         }
379         else
380         {
381             try
382             {
383                 artifact.isSnapshot();
384 
385                 Artifact pomArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion() );
386 
387                 getLogger().debug( "Building MavenProject instance for: " + pomArtifact + ". NOTE: This SHOULD BE available in the Artifact API! ...but it's not." );
388                 p = projectBuilder.buildFromRepository( pomArtifact, remoteArtifactRepositories, localRepository );
389             }
390             catch ( ProjectBuildingException e )
391             {
392                 throw new RepositoryAssemblyException( "Error reading POM for: " + artifact.getId(), e );
393             }
394         }
395 
396         // if we're dealing with a POM artifact, then we've already copied the POM itself; only process ancestry.
397         // NOTE: We need to preserve the original artifact for comparison here.
398         if ( "pom".equals( type ) )
399         {
400             p = p.getParent();
401         }
402 
403         while( p != null )
404         {
405             Artifact destArtifact = artifactFactory.createProjectArtifact( p.getGroupId(), p.getArtifactId(), p
406                 .getVersion() );
407 
408             setAlignment( destArtifact, groupVersionAlignments );
409 
410             File sourceFile = p.getFile();
411 
412             // try to use the POM file from the project instance itself first.
413             if ( ( sourceFile == null ) || !sourceFile.exists() )
414             {
415                 // something that hasn't been realigned yet...we want to read from the original location.
416                 Artifact srcArtifact = artifactFactory.createProjectArtifact( p.getGroupId(), p.getArtifactId(), p
417                                                                                .getVersion() );
418 
419                 sourceFile = new File( localRepository.getBasedir(), localRepository.pathOf( srcArtifact ) );
420             }
421 
422             if ( !sourceFile.exists() )
423             {
424                 break;
425             }
426 
427             File targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( destArtifact ) );
428 
429             try
430             {
431                 FileUtils.copyFile( sourceFile, targetFile );
432             }
433             catch ( IOException e )
434             {
435                 throw new RepositoryAssemblyException( "Error writing POM metdata: " + destArtifact.getId(), e );
436             }
437 
438             try
439             {
440                 writeChecksums( targetFile );
441             }
442             catch ( IOException e )
443             {
444                 throw new RepositoryAssemblyException( "Error writing checksums for POM: " + destArtifact.getId(), e );
445             }
446 
447             p = p.getParent();
448         }
449     }
450 
451     private ArtifactRepository findCentralRepository( MavenProject project )
452     {
453         ArtifactRepository centralRepository = null;
454         for ( Iterator i = project.getRemoteArtifactRepositories().iterator(); i.hasNext(); )
455         {
456             ArtifactRepository r = (ArtifactRepository) i.next();
457             if ( "central".equals( r.getId() ) )
458             {
459                 centralRepository = r;
460             }
461         }
462 
463         return centralRepository;
464     }
465 
466     private void assembleRepositoryMetadata( ArtifactResolutionResult result, ArtifactFilter filter,
467                                              ArtifactRepository centralRepository, ArtifactRepository targetRepository )
468         throws RepositoryAssemblyException
469     {
470         for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
471         {
472             Artifact a = (Artifact) i.next();
473 
474             if ( filter.include( a ) )
475             {
476                 Versioning v = new Versioning();
477 
478                 v.setRelease( a.getVersion() );
479 
480                 v.setLatest( a.getVersion() );
481 
482                 v.addVersion( a.getVersion() );
483 
484                 v.setLastUpdated( getUtcDateFormatter().format( new Date() ) );
485 
486                 ArtifactRepositoryMetadata metadata = new ArtifactRepositoryMetadata( a, v );
487                 String path = targetRepository.pathOfLocalRepositoryMetadata( metadata, centralRepository );
488                 File metadataFile = new File( targetRepository.getBasedir(), path );
489 
490                 MetadataXpp3Writer metadataWriter = new MetadataXpp3Writer();
491 
492                 Writer writer = null;
493                 try
494                 {
495                     writer = new FileWriter( metadataFile );
496 
497                     metadataWriter.write( writer, metadata.getMetadata() );
498                 }
499                 catch ( IOException e )
500                 {
501                     throw new RepositoryAssemblyException( "Error writing artifact metdata.", e );
502                 }
503                 finally
504                 {
505                     IOUtil.close( writer );
506                 }
507 
508                 try
509                 {
510                     writeChecksums( metadataFile );
511 
512                     File metadataFileRemote = new File( targetRepository.getBasedir(), targetRepository
513                         .pathOfRemoteRepositoryMetadata( metadata ) );
514 
515                     FileUtils.copyFile( metadataFile, metadataFileRemote );
516 
517                     FileUtils.copyFile( new File( metadataFile.getParentFile(), metadataFile.getName() + ".sha1" ),
518                                         new File( metadataFileRemote.getParentFile(), metadataFileRemote.getName()
519                                             + ".sha1" ) );
520 
521                     FileUtils.copyFile( new File( metadataFile.getParentFile(), metadataFile.getName() + ".md5" ),
522                                         new File( metadataFileRemote.getParentFile(), metadataFileRemote.getName()
523                                             + ".md5" ) );
524                 }
525                 catch ( IOException e )
526                 {
527                     throw new RepositoryAssemblyException( "Error writing artifact metdata.", e );
528                 }
529             }
530         }
531     }
532 
533     private void writeChecksums( File file )
534         throws IOException, RepositoryAssemblyException
535     {
536         try
537         {
538             String md5 = DigestUtils.createChecksum( file, "MD5" );
539             String sha1 = DigestUtils.createChecksum( file, "SHA-1" );
540 
541             FileUtils.fileWrite( new File( file.getParentFile(), file.getName() + ".md5" ).getAbsolutePath(), md5
542                 .toLowerCase() );
543             FileUtils.fileWrite( new File( file.getParentFile(), file.getName() + ".sha1" ).getAbsolutePath(), sha1
544                 .toLowerCase() );
545         }
546         catch ( NoSuchAlgorithmException e )
547         {
548             throw new RepositoryAssemblyException( "Unable to get write checksums: " + e.getMessage(), e );
549         }
550     }
551 
552     protected Map createGroupVersionAlignments( List versionAlignments )
553     {
554         Map groupVersionAlignments = new HashMap();
555 
556         if ( versionAlignments != null )
557         {
558             for ( Iterator i = versionAlignments.iterator(); i.hasNext(); )
559             {
560                 GroupVersionAlignment alignment = (GroupVersionAlignment) i.next();
561 
562                 groupVersionAlignments.put( alignment.getId(), alignment );
563             }
564         }
565 
566         return groupVersionAlignments;
567     }
568 
569     protected static DateFormat getUtcDateFormatter()
570     {
571         DateFormat utcDateFormatter = new SimpleDateFormat( UTC_TIMESTAMP_PATTERN );
572         utcDateFormatter.setTimeZone( UTC_TIME_ZONE );
573         return utcDateFormatter;
574     }
575 
576     protected ArtifactRepository createLocalRepository( File directory )
577     {
578         String localRepositoryUrl = directory.getAbsolutePath();
579 
580         if ( !localRepositoryUrl.startsWith( "file:" ) )
581         {
582             localRepositoryUrl = "file://" + localRepositoryUrl;
583         }
584 
585         return createRepository( "local", localRepositoryUrl, false, true,
586                                  ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
587     }
588 
589     public ArtifactRepository createRepository( String repositoryId, String repositoryUrl, boolean offline,
590                                                 boolean updateSnapshots, String globalChecksumPolicy )
591     {
592         ArtifactRepository localRepository = new DefaultArtifactRepository( repositoryId, repositoryUrl,
593                                                                             repositoryLayout );
594 
595         boolean snapshotPolicySet = false;
596 
597         if ( offline )
598         {
599             snapshotPolicySet = true;
600         }
601 
602         if ( !snapshotPolicySet && updateSnapshots )
603         {
604             artifactRepositoryFactory.setGlobalUpdatePolicy( ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS );
605         }
606 
607         artifactRepositoryFactory.setGlobalChecksumPolicy( globalChecksumPolicy );
608 
609         return localRepository;
610     }
611 
612     private void invalidateProccessedProjectCache()
613         throws Exception
614     {
615         Class klass = DefaultMavenProjectBuilder.class;
616 
617         try
618         {
619             Field field = klass.getDeclaredField( "processedProjectCache" );
620 
621             field.setAccessible( true );
622 
623             Object cache = field.get( projectBuilder );
624 
625             cache.getClass().getDeclaredMethod( "clear", null ).invoke( cache, null );
626 
627             field.setAccessible( false );
628         }
629         catch( NoSuchFieldException e )
630         {
631             // fine... no field, no cache. we'll ignore it.
632         }
633     }
634 
635     private void setAlignment( Artifact artifact, Map groupVersionAlignments )
636     {
637         GroupVersionAlignment alignment = (GroupVersionAlignment) groupVersionAlignments.get( artifact.getGroupId() );
638 
639         if ( alignment != null )
640         {
641             if ( !alignment.getExcludes().contains( artifact.getArtifactId() ) )
642             {
643                 artifact.setVersion( alignment.getVersion() );
644             }
645         }
646     }
647 
648     // TODO: Remove this, once we can depend on Maven 2.0.7 or later...in which
649     // MavenProject.getManagedVersionMap() exists. This is from MNG-1577.
650     private Map getManagedVersionMap( MavenProject project )
651         throws InvalidVersionSpecificationException
652     {
653         DependencyManagement dependencyManagement = project.getModel().getDependencyManagement();
654 
655         Map map = null;
656         List deps;
657         if ( ( dependencyManagement != null ) && ( ( deps = dependencyManagement.getDependencies() ) != null )
658              && ( deps.size() > 0 ) )
659         {
660             map = new HashMap();
661 
662             if ( getLogger().isDebugEnabled() )
663             {
664                 getLogger().debug( "Adding managed dependencies for " + project.getId() );
665             }
666 
667             for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); )
668             {
669                 Dependency d = (Dependency) i.next();
670 
671                 VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
672                 Artifact artifact = artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(),
673                                                                               versionRange, d.getType(),
674                                                                               d.getClassifier(), d.getScope(),
675                                                                               d.isOptional() );
676                 if ( getLogger().isDebugEnabled() )
677                 {
678                     getLogger().debug( "  " + artifact );
679                 }
680 
681                 // If the dependencyManagement section listed exclusions,
682                 // add them to the managed artifacts here so that transitive
683                 // dependencies will be excluded if necessary.
684                 if ( ( null != d.getExclusions() ) && !d.getExclusions().isEmpty() )
685                 {
686                     List exclusions = new ArrayList();
687                     Iterator exclItr = d.getExclusions().iterator();
688                     while ( exclItr.hasNext() )
689                     {
690                         Exclusion e = (Exclusion) exclItr.next();
691                         exclusions.add( e.getGroupId() + ":" + e.getArtifactId() );
692                     }
693                     ExcludesArtifactFilter eaf = new ExcludesArtifactFilter( exclusions );
694                     artifact.setDependencyFilter( eaf );
695                 }
696                 else
697                 {
698                     artifact.setDependencyFilter( null );
699                 }
700                 map.put( d.getManagementKey(), artifact );
701             }
702         }
703         else if ( map == null )
704         {
705             map = Collections.EMPTY_MAP;
706         }
707         return map;
708     }
709 
710     public void contextualize( Context context )
711         throws ContextException
712     {
713         PlexusContainer container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
714 
715         for ( int i = 0; i < PREFERRED_RESOLVER_HINTS.length; i++ )
716         {
717             String hint = PREFERRED_RESOLVER_HINTS[i];
718 
719             try
720             {
721                 artifactResolver = (ArtifactResolver) container.lookup( ArtifactResolver.ROLE, hint );
722                 break;
723             }
724             catch ( ComponentLookupException e )
725             {
726                 getLogger().debug( "Cannot find ArtifactResolver with hint: " + hint, e );
727             }
728         }
729 
730         if ( artifactResolver == null )
731         {
732             try
733             {
734                 artifactResolver = (ArtifactResolver) container.lookup( ArtifactResolver.ROLE );
735             }
736             catch ( ComponentLookupException e )
737             {
738                 getLogger().debug( "Cannot find ArtifactResolver with no hint.", e );
739             }
740         }
741 
742         if ( artifactResolver == null )
743         {
744             throw new ContextException( "Failed to lookup a valid ArtifactResolver implementation. Tried hints:\n"
745                                         + Arrays.asList( PREFERRED_RESOLVER_HINTS ) );
746         }
747     }
748 }