View Javadoc

1   package org.apache.maven.project;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Collection;
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.apache.maven.RepositoryUtils;
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.model.Dependency;
29  import org.apache.maven.model.DependencyManagement;
30  import org.apache.maven.model.Exclusion;
31  import org.codehaus.plexus.component.annotations.Component;
32  import org.codehaus.plexus.component.annotations.Requirement;
33  import org.codehaus.plexus.logging.Logger;
34  import org.sonatype.aether.RepositorySystem;
35  import org.sonatype.aether.RepositorySystemSession;
36  import org.sonatype.aether.artifact.ArtifactTypeRegistry;
37  import org.sonatype.aether.collection.CollectRequest;
38  import org.sonatype.aether.collection.DependencyCollectionException;
39  import org.sonatype.aether.graph.DependencyFilter;
40  import org.sonatype.aether.graph.DependencyNode;
41  import org.sonatype.aether.graph.DependencyVisitor;
42  import org.sonatype.aether.resolution.ArtifactResolutionException;
43  import org.sonatype.aether.resolution.ArtifactResult;
44  import org.sonatype.aether.util.artifact.JavaScopes;
45  
46  /**
47   * @author Benjamin Bentmann
48   */
49  @Component( role = ProjectDependenciesResolver.class )
50  public class DefaultProjectDependenciesResolver
51      implements ProjectDependenciesResolver
52  {
53  
54      @Requirement
55      private Logger logger;
56  
57      @Requirement
58      private RepositorySystem repoSystem;
59  
60      public DependencyResolutionResult resolve( DependencyResolutionRequest request )
61          throws DependencyResolutionException
62      {
63          DefaultDependencyResolutionResult result = new DefaultDependencyResolutionResult();
64  
65          MavenProject project = request.getMavenProject();
66          RepositorySystemSession session = request.getRepositorySession();
67          DependencyFilter filter = request.getResolutionFilter();
68  
69          ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry();
70  
71          CollectRequest collect = new CollectRequest();
72          collect.setRequestContext( "project" );
73          collect.setRepositories( project.getRemoteProjectRepositories() );
74  
75          if ( project.getDependencyArtifacts() == null )
76          {
77              for ( Dependency dependency : project.getDependencies() )
78              {
79                  collect.addDependency( RepositoryUtils.toDependency( dependency, stereotypes ) );
80              }
81          }
82          else
83          {
84              Map<String, Dependency> dependencies = new HashMap<String, Dependency>();
85              for ( Dependency dependency : project.getDependencies() )
86              {
87                  String key = dependency.getManagementKey();
88                  dependencies.put( key, dependency );
89              }
90              for ( Artifact artifact : project.getDependencyArtifacts() )
91              {
92                  String key = artifact.getDependencyConflictId();
93                  Dependency dependency = dependencies.get( key );
94                  Collection<Exclusion> exclusions = dependency != null ? dependency.getExclusions() : null;
95                  org.sonatype.aether.graph.Dependency dep = RepositoryUtils.toDependency( artifact, exclusions );
96                  if ( !JavaScopes.SYSTEM.equals( dep.getScope() ) && dep.getArtifact().getFile() != null )
97                  {
98                      // enable re-resolution
99                      org.sonatype.aether.artifact.Artifact art = dep.getArtifact();
100                     art = art.setFile( null ).setVersion( art.getBaseVersion() );
101                     dep = dep.setArtifact( art );
102                 }
103                 collect.addDependency( dep );
104             }
105         }
106 
107         DependencyManagement depMngt = project.getDependencyManagement();
108         if ( depMngt != null )
109         {
110             for ( Dependency dependency : depMngt.getDependencies() )
111             {
112                 collect.addManagedDependency( RepositoryUtils.toDependency( dependency, stereotypes ) );
113             }
114         }
115 
116         DependencyNode node;
117         try
118         {
119             node = repoSystem.collectDependencies( session, collect ).getRoot();
120             result.setDependencyGraph( node );
121         }
122         catch ( DependencyCollectionException e )
123         {
124             result.setDependencyGraph( e.getResult().getRoot() );
125             result.setCollectionErrors( e.getResult().getExceptions() );
126 
127             throw new DependencyResolutionException( result, "Could not resolve dependencies for project "
128                 + project.getId() + ": " + e.getMessage(), e );
129         }
130 
131         if ( logger.isWarnEnabled() )
132         {
133             for ( DependencyNode child : node.getChildren() )
134             {
135                 if ( !child.getRelocations().isEmpty() )
136                 {
137                     logger.warn( "The artifact " + child.getRelocations().get( 0 ) + " has been relocated to "
138                         + child.getDependency().getArtifact() );
139                 }
140             }
141         }
142 
143         if ( logger.isDebugEnabled() )
144         {
145             node.accept( new GraphLogger( project ) );
146         }
147 
148         try
149         {
150             process( result, repoSystem.resolveDependencies( session, node, filter ) );
151         }
152         catch ( ArtifactResolutionException e )
153         {
154             process( result, e.getResults() );
155 
156             throw new DependencyResolutionException( result, "Could not resolve dependencies for project "
157                 + project.getId() + ": " + e.getMessage(), e );
158         }
159 
160         return result;
161     }
162 
163     private void process( DefaultDependencyResolutionResult result, Collection<ArtifactResult> results )
164     {
165         for ( ArtifactResult ar : results )
166         {
167             DependencyNode node = ar.getRequest().getDependencyNode();
168             if ( ar.isResolved() )
169             {
170                 node.setArtifact( ar.getArtifact() );
171                 result.addResolvedDependency( node.getDependency() );
172             }
173             else
174             {
175                 result.setResolutionErrors( node.getDependency(), ar.getExceptions() );
176             }
177         }
178     }
179 
180     class GraphLogger
181         implements DependencyVisitor
182     {
183 
184         private final MavenProject project;
185 
186         private String indent = "";
187 
188         public GraphLogger( MavenProject project )
189         {
190             this.project = project;
191         }
192 
193         public boolean visitEnter( DependencyNode node )
194         {
195             StringBuilder buffer = new StringBuilder( 128 );
196             buffer.append( indent );
197             org.sonatype.aether.graph.Dependency dep = node.getDependency();
198             if ( dep != null )
199             {
200                 org.sonatype.aether.artifact.Artifact art = dep.getArtifact();
201 
202                 buffer.append( art );
203                 buffer.append( ':' ).append( dep.getScope() );
204 
205                 if ( node.getPremanagedScope() != null && !node.getPremanagedScope().equals( dep.getScope() ) )
206                 {
207                     buffer.append( " (scope managed from " ).append( node.getPremanagedScope() ).append( ")" );
208                 }
209 
210                 if ( node.getPremanagedVersion() != null && !node.getPremanagedVersion().equals( art.getVersion() ) )
211                 {
212                     buffer.append( " (version managed from " ).append( node.getPremanagedVersion() ).append( ")" );
213                 }
214             }
215             else
216             {
217                 buffer.append( project.getGroupId() );
218                 buffer.append( ':' ).append( project.getArtifactId() );
219                 buffer.append( ':' ).append( project.getPackaging() );
220                 buffer.append( ':' ).append( project.getVersion() );
221             }
222 
223             logger.debug( buffer.toString() );
224             indent += "   ";
225             return true;
226         }
227 
228         public boolean visitLeave( DependencyNode node )
229         {
230             indent = indent.substring( 0, indent.length() - 3 );
231             return true;
232         }
233 
234     }
235 
236 }