View Javadoc
1   package org.apache.maven.shared.repository;
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.ArtifactUtils;
24  import org.apache.maven.artifact.factory.ArtifactFactory;
25  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
26  import org.apache.maven.artifact.repository.ArtifactRepository;
27  import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
28  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
29  import org.apache.maven.artifact.repository.DefaultArtifactRepository;
30  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
31  import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata;
32  import org.apache.maven.artifact.repository.metadata.Versioning;
33  import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
34  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
35  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
36  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
37  import org.apache.maven.artifact.resolver.ArtifactResolver;
38  import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
39  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
40  import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
41  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
42  import org.apache.maven.artifact.versioning.VersionRange;
43  import org.apache.maven.model.Dependency;
44  import org.apache.maven.model.DependencyManagement;
45  import org.apache.maven.model.Exclusion;
46  import org.apache.maven.project.DefaultMavenProjectBuilder;
47  import org.apache.maven.project.MavenProject;
48  import org.apache.maven.project.MavenProjectBuilder;
49  import org.apache.maven.project.ProjectBuildingException;
50  import org.apache.maven.shared.artifact.filter.PatternExcludesArtifactFilter;
51  import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter;
52  import org.apache.maven.shared.artifact.filter.ScopeArtifactFilter;
53  import org.apache.maven.shared.repository.model.GroupVersionAlignment;
54  import org.apache.maven.shared.repository.model.RepositoryInfo;
55  import org.apache.maven.shared.utils.io.FileUtils;
56  import org.apache.maven.shared.utils.io.IOUtil;
57  import org.codehaus.plexus.PlexusConstants;
58  import org.codehaus.plexus.PlexusContainer;
59  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
60  import org.codehaus.plexus.context.Context;
61  import org.codehaus.plexus.context.ContextException;
62  import org.codehaus.plexus.logging.AbstractLogEnabled;
63  import org.codehaus.plexus.logging.Logger;
64  import org.codehaus.plexus.logging.console.ConsoleLogger;
65  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
66  
67  import java.io.File;
68  import java.io.FileInputStream;
69  import java.io.FileWriter;
70  import java.io.IOException;
71  import java.io.Writer;
72  import java.lang.reflect.Field;
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.List;
81  import java.util.Map;
82  import java.util.Set;
83  import java.util.TimeZone;
84  
85  import static org.apache.commons.codec.digest.DigestUtils.md5Hex;
86  import static org.apache.commons.codec.digest.DigestUtils.shaHex;
87  
88  /**
89   * @author Jason van Zyl
90   * @plexus.component role="org.apache.maven.shared.repository.RepositoryAssembler" role-hint="default"
91   */
92  
93  // todo will need to pop the processed project cache using reflection
94  public class DefaultRepositoryAssembler
95      extends AbstractLogEnabled
96      implements RepositoryAssembler, Contextualizable
97  {
98      private static final String[] PREFERRED_RESOLVER_HINTS = { "project-cache-aware", // Provided in Maven 2.1-SNAPSHOT
99          "default" };
100 
101     protected static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
102 
103     protected static final String UTC_TIMESTAMP_PATTERN = "yyyyMMddHHmmss";
104 
105     /**
106      * @plexus.requirement
107      */
108     protected ArtifactFactory artifactFactory;
109 
110     // Replaced by Contextualizable code, to select the resolver in order of preference.
111     //
112     // @plexus.requirement
113     //
114     protected ArtifactResolver artifactResolver;
115 
116     /**
117      * @plexus.requirement
118      */
119     protected ArtifactRepositoryLayout repositoryLayout;
120 
121     /**
122      * @plexus.requirement
123      */
124     protected ArtifactRepositoryFactory artifactRepositoryFactory;
125 
126     /**
127      * @plexus.requirement
128      */
129     protected ArtifactMetadataSource metadataSource;
130 
131     /**
132      * @plexus.requirement
133      */
134     protected MavenProjectBuilder projectBuilder;
135 
136     public DefaultRepositoryAssembler()
137     {
138         // used for plexus init.
139     }
140 
141     public DefaultRepositoryAssembler( ArtifactFactory artifactFactory, ArtifactResolver artifactResolver,
142                                        ArtifactRepositoryLayout repositoryLayout,
143                                        ArtifactRepositoryFactory artifactRepositoryFactory,
144                                        ArtifactMetadataSource metadataSource, MavenProjectBuilder projectBuilder )
145     {
146         // used for testing, primarily.
147         this.artifactFactory = artifactFactory;
148         this.artifactResolver = artifactResolver;
149         this.repositoryLayout = repositoryLayout;
150         this.artifactRepositoryFactory = artifactRepositoryFactory;
151         this.metadataSource = metadataSource;
152         this.projectBuilder = projectBuilder;
153 
154         enableLogging( new ConsoleLogger( Logger.LEVEL_DEBUG, getClass().getName() + "::Internal" ) );
155     }
156 
157     public void buildRemoteRepository( File repositoryDirectory, RepositoryInfo repository,
158                                        RepositoryBuilderConfigSource configSource )
159         throws RepositoryAssemblyException
160     {
161         MavenProject project = configSource.getProject();
162         ArtifactRepository localRepository = configSource.getLocalRepository();
163 
164         Map groupVersionAlignments = createGroupVersionAlignments( repository.getGroupVersionAlignments() );
165 
166         ArtifactRepository targetRepository = createLocalRepository( repositoryDirectory );
167 
168         ArtifactResolutionResult result = null;
169 
170         Set dependencyArtifacts = project.getDependencyArtifacts();
171 
172         if ( dependencyArtifacts == null )
173         {
174             Logger logger = getLogger();
175 
176             if ( logger.isDebugEnabled() )
177             {
178                 logger.debug( "dependency-artifact set for project: " + project.getId()
179                                   + " is null. Skipping repository processing." );
180             }
181 
182             return;
183         }
184 
185         try
186         {
187             // i have to get everything first as a filter or transformation here
188             // doesn't seem to work
189             // to align everything. If I use a filter to change the version on
190             // the fly then I get the
191             // I get JARs but no POMs, and in some directories POMs with no
192             // JARs.
193 
194             // FIXME I'm not getting runtime dependencies here
195             result = artifactResolver.resolveTransitively( dependencyArtifacts, project.getArtifact(),
196                                                            getManagedVersionMap( project ), localRepository,
197                                                            project.getRemoteArtifactRepositories(), metadataSource );
198         }
199         catch ( ArtifactResolutionException e )
200         {
201             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
202         }
203         catch ( ArtifactNotFoundException e )
204         {
205             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
206         }
207         catch ( InvalidVersionSpecificationException e )
208         {
209             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
210         }
211 
212         try
213         {
214             // Blow the cache in the project builder so that we get POMs again
215             // on this next download
216             invalidateProccessedProjectCache();
217         }
218         catch ( Exception e )
219         {
220             throw new RepositoryAssemblyException( "Error invalidating the processed project cache.", e );
221         }
222 
223         ArtifactFilter filter = buildRepositoryFilter( repository, project );
224 
225         assembleRepositoryArtifacts( result, filter, project, localRepository, targetRepository, repositoryDirectory,
226                                      groupVersionAlignments );
227 
228         ArtifactRepository centralRepository = findCentralRepository( project );
229 
230         if ( repository.isIncludeMetadata() )
231         {
232             assembleRepositoryMetadata( result, filter, centralRepository, targetRepository );
233         }
234 
235         addPomWithAncestry( project.getArtifact(), project.getRemoteArtifactRepositories(), localRepository,
236                             targetRepository, groupVersionAlignments, project );
237     }
238 
239     private ArtifactFilter buildRepositoryFilter( RepositoryInfo repository, MavenProject project )
240     {
241         AndArtifactFilter filter = new AndArtifactFilter();
242 
243         ArtifactFilter scopeFilter = new ScopeArtifactFilter( repository.getScope() );
244         filter.add( scopeFilter );
245 
246         // ----------------------------------------------------------------------------
247         // Includes
248         //
249         // We'll take everything if no includes are specified to try and make
250         // this
251         // process more maintainable. Don't want to have to update the assembly
252         // descriptor everytime the POM is updated.
253         // ----------------------------------------------------------------------------
254 
255         List includes = repository.getIncludes();
256 
257         if ( ( includes == null ) || includes.isEmpty() )
258         {
259             List<String> patterns = new ArrayList<String>();
260 
261             Set projectArtifacts = project.getDependencyArtifacts();
262 
263             if ( projectArtifacts != null )
264             {
265                 for ( Object projectArtifact : projectArtifacts )
266                 {
267                     Artifact artifact = (Artifact) projectArtifact;
268 
269                     patterns.add( artifact.getDependencyConflictId() );
270                 }
271             }
272 
273             PatternIncludesArtifactFilter includeFilter = new PatternIncludesArtifactFilter( patterns, true );
274 
275             filter.add( includeFilter );
276         }
277         else
278         {
279             filter.add( new PatternIncludesArtifactFilter( repository.getIncludes(), true ) );
280         }
281 
282         // ----------------------------------------------------------------------------
283         // Excludes
284         //
285         // We still want to make it easy to exclude a few things even if we
286         // slurp
287         // up everything.
288         // ----------------------------------------------------------------------------
289 
290         List excludes = repository.getExcludes();
291 
292         if ( ( excludes != null ) && !excludes.isEmpty() )
293         {
294             filter.add( new PatternExcludesArtifactFilter( repository.getExcludes(), true ) );
295         }
296 
297         return filter;
298     }
299 
300     private void assembleRepositoryArtifacts( ArtifactResolutionResult result, ArtifactFilter filter,
301                                               MavenProject project, ArtifactRepository localRepository,
302                                               ArtifactRepository targetRepository, File repositoryDirectory,
303                                               Map groupVersionAlignments )
304         throws RepositoryAssemblyException
305     {
306         try
307         {
308             // Now that we have the graph, let's try to align it to versions
309             // that we want and remove
310             // the repository we previously populated.
311             FileUtils.deleteDirectory( repositoryDirectory );
312 
313             FileUtils.mkdir( repositoryDirectory.getAbsolutePath() );
314 
315             for ( Object o : result.getArtifacts() )
316             {
317                 Artifact a = (Artifact) o;
318 
319                 if ( filter.include( a ) )
320                 {
321                     getLogger().debug( "Re-resolving: " + a + " for repository assembly." );
322 
323                     setAlignment( a, groupVersionAlignments );
324 
325                     // We need to flip it back to not being resolved so we can
326                     // look for it again!
327                     a.setResolved( false );
328 
329                     artifactResolver.resolve( a, project.getRemoteArtifactRepositories(), localRepository );
330 
331                     a.setVersion( a.getBaseVersion() );
332 
333                     File targetFile = new File( targetRepository.getBasedir(), targetRepository.pathOf( a ) );
334                     FileUtils.copyFile( a.getFile(), targetFile );
335 
336                     writeChecksums( targetFile );
337 
338                     addPomWithAncestry( a, project.getRemoteArtifactRepositories(), localRepository, targetRepository,
339                                         groupVersionAlignments, project );
340                 }
341             }
342         }
343         catch ( ArtifactResolutionException e )
344         {
345             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
346         }
347         catch ( ArtifactNotFoundException e )
348         {
349             throw new RepositoryAssemblyException( "Error resolving artifacts: " + e.getMessage(), e );
350         }
351         catch ( IOException e )
352         {
353             throw new RepositoryAssemblyException( "Error writing artifact metdata.", e );
354         }
355     }
356 
357     private void addPomWithAncestry( final Artifact artifact, List remoteArtifactRepositories,
358                                      ArtifactRepository localRepository, ArtifactRepository targetRepository,
359                                      Map groupVersionAlignments, MavenProject masterProject )
360         throws RepositoryAssemblyException
361     {
362         String type = artifact.getType();
363         Map refs = masterProject.getProjectReferences();
364 
365         String projectKey = ArtifactUtils.versionlessKey( artifact );
366 
367         MavenProject p;
368         if ( artifact == masterProject.getArtifact() )
369         {
370             p = masterProject;
371         }
372         else if ( refs.containsKey( projectKey ) )
373         {
374             p = (MavenProject) refs.get( projectKey );
375         }
376         else
377         {
378             try
379             {
380                 artifact.isSnapshot();
381 
382                 Artifact pomArtifact =
383                     artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(),
384                                                            artifact.getBaseVersion() );
385 
386                 getLogger().debug( "Building MavenProject instance for: " + pomArtifact
387                                        + ". 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 =
406                 artifactFactory.createProjectArtifact( p.getGroupId(), p.getArtifactId(), p.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 =
417                     artifactFactory.createProjectArtifact( p.getGroupId(), p.getArtifactId(), p.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 ( Object o : project.getRemoteArtifactRepositories() )
455         {
456             ArtifactRepository r = (ArtifactRepository) o;
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 ( Object o : result.getArtifacts() )
471         {
472             Artifact a = (Artifact) o;
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(),
513                                                         targetRepository.pathOfRemoteRepositoryMetadata( metadata ) );
514 
515                     FileUtils.copyFile( metadataFile, metadataFileRemote );
516 
517                     FileUtils.copyFile( new File( metadataFile.getParentFile(), metadataFile.getName() + ".sha1" ),
518                                         new File( metadataFileRemote.getParentFile(),
519                                                   metadataFileRemote.getName() + ".sha1" ) );
520 
521                     FileUtils.copyFile( new File( metadataFile.getParentFile(), metadataFile.getName() + ".md5" ),
522                                         new File( metadataFileRemote.getParentFile(),
523                                                   metadataFileRemote.getName() + ".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         FileInputStream data = new FileInputStream( file );
537         String md5 = md5Hex( data ).toUpperCase();
538         data.close();
539         FileInputStream data1 = new FileInputStream( file );
540         String sha1 = shaHex( data1 ).toUpperCase();
541         data1.close();
542 
543         FileUtils.fileWrite( new File( file.getParentFile(), file.getName() + ".md5" ).getAbsolutePath(),
544                              md5.toLowerCase() );
545         FileUtils.fileWrite( new File( file.getParentFile(), file.getName() + ".sha1" ).getAbsolutePath(),
546                              sha1.toLowerCase() );
547     }
548 
549     protected Map createGroupVersionAlignments( List versionAlignments )
550     {
551         Map groupVersionAlignments = new HashMap();
552 
553         if ( versionAlignments != null )
554         {
555             for ( Object versionAlignment : versionAlignments )
556             {
557                 GroupVersionAlignment alignment = (GroupVersionAlignment) versionAlignment;
558 
559                 groupVersionAlignments.put( alignment.getId(), alignment );
560             }
561         }
562 
563         return groupVersionAlignments;
564     }
565 
566     protected static DateFormat getUtcDateFormatter()
567     {
568         DateFormat utcDateFormatter = new SimpleDateFormat( UTC_TIMESTAMP_PATTERN );
569         utcDateFormatter.setTimeZone( UTC_TIME_ZONE );
570         return utcDateFormatter;
571     }
572 
573     protected ArtifactRepository createLocalRepository( File directory )
574     {
575         String localRepositoryUrl = directory.getAbsolutePath();
576 
577         if ( !localRepositoryUrl.startsWith( "file:" ) )
578         {
579             localRepositoryUrl = "file://" + localRepositoryUrl;
580         }
581 
582         return createRepository( "local", localRepositoryUrl, false, true,
583                                  ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
584     }
585 
586     public ArtifactRepository createRepository( String repositoryId, String repositoryUrl, boolean offline,
587                                                 boolean updateSnapshots, String globalChecksumPolicy )
588     {
589         ArtifactRepository localRepository =
590             new DefaultArtifactRepository( repositoryId, repositoryUrl, repositoryLayout );
591 
592         boolean snapshotPolicySet = false;
593 
594         if ( offline )
595         {
596             snapshotPolicySet = true;
597         }
598 
599         if ( !snapshotPolicySet && updateSnapshots )
600         {
601             artifactRepositoryFactory.setGlobalUpdatePolicy( ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS );
602         }
603 
604         artifactRepositoryFactory.setGlobalChecksumPolicy( globalChecksumPolicy );
605 
606         return localRepository;
607     }
608 
609     private void invalidateProccessedProjectCache()
610         throws Exception
611     {
612         Class klass = DefaultMavenProjectBuilder.class;
613 
614         try
615         {
616             Field field = klass.getDeclaredField( "processedProjectCache" );
617 
618             field.setAccessible( true );
619 
620             Object cache = field.get( projectBuilder );
621 
622             cache.getClass().getDeclaredMethod( "clear", null ).invoke( cache, null );
623 
624             field.setAccessible( false );
625         }
626         catch ( NoSuchFieldException e )
627         {
628             // fine... no field, no cache. we'll ignore it.
629         }
630     }
631 
632     private void setAlignment( Artifact artifact, Map groupVersionAlignments )
633     {
634         GroupVersionAlignment alignment = (GroupVersionAlignment) groupVersionAlignments.get( artifact.getGroupId() );
635 
636         if ( alignment != null )
637         {
638             if ( !alignment.getExcludes().contains( artifact.getArtifactId() ) )
639             {
640                 artifact.setVersion( alignment.getVersion() );
641             }
642         }
643     }
644 
645     // TODO: Remove this, once we can depend on Maven 2.0.7 or later...in which
646     // MavenProject.getManagedVersionMap() exists. This is from MNG-1577.
647     private Map getManagedVersionMap( MavenProject project )
648         throws InvalidVersionSpecificationException
649     {
650         DependencyManagement dependencyManagement = project.getModel().getDependencyManagement();
651 
652         Map<String, Artifact> map;
653         List deps = ( dependencyManagement == null ) ? null : dependencyManagement.getDependencies();
654         if ( ( deps != null ) && ( deps.size() > 0 ) )
655         {
656             map = new HashMap<String, Artifact>();
657 
658             if ( getLogger().isDebugEnabled() )
659             {
660                 getLogger().debug( "Adding managed dependencies for " + project.getId() );
661             }
662 
663             for ( Object o1 : dependencyManagement.getDependencies() )
664             {
665                 Dependency d = (Dependency) o1;
666 
667                 VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
668                 Artifact artifact =
669                     artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange,
670                                                               d.getType(), d.getClassifier(), d.getScope(),
671                                                               d.isOptional() );
672                 if ( getLogger().isDebugEnabled() )
673                 {
674                     getLogger().debug( "  " + artifact );
675                 }
676 
677                 // If the dependencyManagement section listed exclusions,
678                 // add them to the managed artifacts here so that transitive
679                 // dependencies will be excluded if necessary.
680                 if ( ( null != d.getExclusions() ) && !d.getExclusions().isEmpty() )
681                 {
682                     List<String> exclusions = new ArrayList<String>();
683                     for ( Object o : d.getExclusions() )
684                     {
685                         Exclusion e = (Exclusion) o;
686                         exclusions.add( e.getGroupId() + ":" + e.getArtifactId() );
687                     }
688                     ExcludesArtifactFilter eaf = new ExcludesArtifactFilter( exclusions );
689                     artifact.setDependencyFilter( eaf );
690                 }
691                 else
692                 {
693                     artifact.setDependencyFilter( null );
694                 }
695                 map.put( d.getManagementKey(), artifact );
696             }
697         }
698         else
699         {
700             map = Collections.emptyMap();
701         }
702         return map;
703     }
704 
705     public void contextualize( Context context )
706         throws ContextException
707     {
708         PlexusContainer container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
709 
710         for ( String hint : PREFERRED_RESOLVER_HINTS )
711         {
712             if ( container.hasComponent( ArtifactResolver.ROLE, hint ) )
713             {
714                 try
715                 {
716                     artifactResolver = (ArtifactResolver) container.lookup( ArtifactResolver.ROLE, hint );
717                     break;
718                 }
719                 catch ( ComponentLookupException e )
720                 {
721                     getLogger().warn( "Cannot find ArtifactResolver with hint: " + hint, e );
722                 }
723             }
724             else
725             {
726                 getLogger().debug( "No ArtifactResolver with hint " + hint );
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(
745                 "Failed to lookup a valid ArtifactResolver implementation. Tried hints:\n" + Arrays.asList(
746                     PREFERRED_RESOLVER_HINTS ) );
747         }
748     }
749 }