View Javadoc
1   package org.apache.maven.shared.artifact.resolver;
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.ProjectDependenciesResolver;
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.artifact.factory.ArtifactFactory;
25  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
26  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
27  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
28  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
29  import org.apache.maven.artifact.resolver.ArtifactResolver;
30  import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException;
31  import org.apache.maven.execution.MavenSession;
32  import org.apache.maven.project.MavenProject;
33  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
34  
35  import java.util.Collection;
36  import java.util.Collections;
37  import java.util.HashSet;
38  import java.util.Iterator;
39  import java.util.LinkedHashSet;
40  import java.util.Set;
41  
42  /**
43   * Default implementation of {@link ProjectDependenciesResolver}. <strong>Warning:</strong> This is an internal utility
44   * class that is only public for technical reasons, it is not part of the public API. In particular, this class can
45   * be changed or deleted without prior notice.
46   * 
47   * @author jdcasey
48   * 
49   * @see ProjectDependenciesResolver
50   * @plexus.component role="org.apache.maven.ProjectDependenciesResolver" role-hint="default"
51   */
52  public final class DefaultProjectDependenciesResolver
53      implements ProjectDependenciesResolver
54  {
55  
56      /**
57       * @plexus.requirement
58       */
59      private ArtifactResolver resolver;
60  
61      /**
62       * @plexus.requirement
63       */
64      private ArtifactFactory artifactFactory;
65  
66      /**
67       * @plexus.requirement role-hint="maven"
68       */
69      private ArtifactMetadataSource metadataSource;
70      
71      // for plexus instantiation.
72      public DefaultProjectDependenciesResolver()
73      {
74      }
75  
76      // for testing.
77      DefaultProjectDependenciesResolver( ArtifactResolver resolver, ArtifactFactory artifactFactory,
78                                          ArtifactMetadataSource metadataSource )
79      {
80          this.resolver = resolver;
81          this.artifactFactory = artifactFactory;
82          this.metadataSource = metadataSource;
83      }
84  
85      /**
86       * {@inheritDoc}
87       */
88      @SuppressWarnings( "unchecked" )
89      public Set<Artifact> resolve( final Collection<? extends MavenProject> projects, final Collection<String> scopes,
90                                    final MavenSession session )
91          throws ArtifactResolutionException, ArtifactNotFoundException
92      {
93          Set<Artifact> resolved = new LinkedHashSet<Artifact>();
94  
95          if ( projects == null || projects.isEmpty() )
96          {
97              return resolved;
98          }
99  
100         CumulativeScopeArtifactFilter scopeFilter = new CumulativeScopeArtifactFilter( scopes );
101         
102         for ( MavenProject proj : projects )
103         {
104             Set<Artifact> depArtifacts = proj.getDependencyArtifacts();
105             if ( depArtifacts == null )
106             {
107                 try
108                 {
109                     depArtifacts = proj.createArtifacts( artifactFactory, null, scopeFilter );
110                 }
111                 catch ( InvalidDependencyVersionException e )
112                 {
113                     throw new ArtifactResolutionException( "Failed to create Artifact instances for project "
114                         + "dependencies: " + e.getMessage(), null, e );
115                 }
116             }
117             
118             if ( depArtifacts == null || depArtifacts.isEmpty() )
119             {
120                 continue;
121             }
122             
123             for ( Iterator<Artifact> it = depArtifacts.iterator(); it.hasNext(); )
124             {
125                 Artifact artifact = it.next();
126                 if ( resolved.contains( artifact ) )
127                 {
128                     // already resolved, don't do it again.
129                     it.remove();
130                 }
131             }
132             
133             Artifact projectArtifact = proj.getArtifact();
134             if ( projectArtifact == null )
135             {
136                 projectArtifact = artifactFactory.createProjectArtifact( proj.getGroupId(), proj.getArtifactId(),
137                                                                      proj.getVersion() );
138             }
139             
140             try
141             {
142                 ArtifactResolutionResult result = resolver.resolveTransitively( depArtifacts, projectArtifact,
143                                                                                 proj.getManagedVersionMap(),
144                                                                                 session.getLocalRepository(),
145                                                                                 proj.getRemoteArtifactRepositories(),
146                                                                                 metadataSource, scopeFilter );
147 
148                 if ( result.getArtifacts() != null && !result.getArtifacts().isEmpty() )
149                 {
150                     resolved.addAll( result.getArtifacts() );
151                 }
152             }
153             catch ( MultipleArtifactsNotFoundException me )
154             {
155                 Set<String> projectIds = getProjectIds( projects );
156                 Collection<Artifact> missing = new HashSet<Artifact>( me.getMissingArtifacts() );
157                 for ( Iterator<Artifact> it = missing.iterator(); it.hasNext(); )
158                 {
159                     Artifact artifact = it.next();
160                     if ( projectIds.contains( getProjectReferenceId( artifact.getGroupId(), artifact.getArtifactId(),
161                                                                      artifact.getVersion() ) ) )
162                     {
163                         it.remove();
164                     }
165                 }
166 
167                 if ( missing.isEmpty() )
168                 {
169                     resolved.addAll( me.getResolvedArtifacts() );
170                 }
171                 else
172                 {
173                     throw me;
174                 }
175             }
176         }
177         
178         return resolved;
179     }
180 
181     /**
182      * {@inheritDoc}
183      */
184     public Set<Artifact> resolve( final MavenProject project, final Collection<String> scopes,
185                                   final MavenSession session )
186         throws ArtifactResolutionException, ArtifactNotFoundException
187     {
188         Collection<MavenProject> projects = Collections.singleton( project );
189 
190         return resolve( projects, scopes, session );
191     }
192 
193     private Set<String> getProjectIds( final Collection<? extends MavenProject> projects )
194     {
195         Set<String> ids = new HashSet<String>();
196         if ( projects != null && !projects.isEmpty() )
197         {
198             for ( MavenProject project : projects )
199             {
200                 ids.add( getProjectReferenceId( project.getGroupId(), project.getArtifactId(), project.getVersion() ) );
201             }
202         }
203 
204         return ids;
205     }
206 
207     private static String getProjectReferenceId( String groupId, String artifactId, String version )
208     {
209         return groupId + ":" + artifactId + ":" + version;
210     }
211 
212 }