1 package org.apache.maven.shared.dependency.graph.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.factory.ArtifactFactory;
24 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
25 import org.apache.maven.artifact.versioning.VersionRange;
26 import org.apache.maven.project.DefaultDependencyResolutionRequest;
27 import org.apache.maven.project.DependencyResolutionException;
28 import org.apache.maven.project.DependencyResolutionRequest;
29 import org.apache.maven.project.DependencyResolutionResult;
30 import org.apache.maven.project.MavenProject;
31 import org.apache.maven.project.ProjectBuildingRequest;
32 import org.apache.maven.project.ProjectDependenciesResolver;
33 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
34 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
35 import org.apache.maven.shared.dependency.graph.DependencyNode;
36 import org.codehaus.plexus.component.annotations.Component;
37 import org.codehaus.plexus.component.annotations.Requirement;
38 import org.codehaus.plexus.logging.AbstractLogEnabled;
39 import org.sonatype.aether.graph.Dependency;
40 import org.sonatype.aether.version.VersionConstraint;
41
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.HashSet;
46 import java.util.List;
47 import java.util.Set;
48
49
50
51
52
53
54
55
56 @Component( role = DependencyGraphBuilder.class, hint = "maven3" )
57 public class Maven3DependencyGraphBuilder
58 extends AbstractLogEnabled
59 implements DependencyGraphBuilder
60 {
61 @Requirement
62 private ProjectDependenciesResolver resolver;
63
64 @Requirement
65 private ArtifactFactory factory;
66
67
68
69
70
71
72
73
74
75 public DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter )
76 throws DependencyGraphBuilderException
77 {
78 return buildDependencyGraph( project, filter, null );
79 }
80
81
82
83
84
85
86
87
88
89
90
91 public DependencyNode buildDependencyGraph( MavenProject project, ArtifactFilter filter,
92 Collection<MavenProject> reactorProjects )
93 throws DependencyGraphBuilderException
94 {
95 ProjectBuildingRequest projectBuildingRequest =
96 (ProjectBuildingRequest) Invoker.invoke( project, "getProjectBuildingRequest" );
97
98 DependencyResolutionRequest request =
99 new DefaultDependencyResolutionRequest( project, projectBuildingRequest.getRepositorySession() );
100
101 DependencyResolutionResult result = resolveDependencies( request, reactorProjects );
102
103 return buildDependencyNode( null, result.getDependencyGraph(), project.getArtifact(), filter );
104 }
105
106 private DependencyResolutionResult resolveDependencies( DependencyResolutionRequest request,
107 Collection<MavenProject> reactorProjects )
108 throws DependencyGraphBuilderException
109 {
110 try
111 {
112 return resolver.resolve( request );
113 }
114 catch ( DependencyResolutionException e )
115 {
116 if ( reactorProjects == null )
117 {
118 throw new DependencyGraphBuilderException( "Could not resolve following dependencies: "
119 + e.getResult().getUnresolvedDependencies(), e );
120 }
121
122
123 return collectDependenciesFromReactor( e, reactorProjects );
124 }
125 }
126
127 private DependencyResolutionResult collectDependenciesFromReactor( DependencyResolutionException e,
128 Collection<MavenProject> reactorProjects )
129 throws DependencyGraphBuilderException
130 {
131 DependencyResolutionResult result = e.getResult();
132
133 List<Dependency> reactorDeps = getReactorDependencies( reactorProjects, result.getUnresolvedDependencies() );
134
135 result.getUnresolvedDependencies().removeAll( reactorDeps );
136 Invoker.invoke( result.getResolvedDependencies(), "addAll", Collection.class, reactorDeps );
137
138 if ( !result.getUnresolvedDependencies().isEmpty() )
139 {
140 throw new DependencyGraphBuilderException( "Could not resolve nor collect following dependencies: "
141 + result.getUnresolvedDependencies(), e );
142 }
143
144 return result;
145 }
146
147 private List<org.sonatype.aether.graph.Dependency> getReactorDependencies( Collection<MavenProject> reactorProjects,
148 List<?> dependencies )
149 {
150 Set<ArtifactKey> reactorProjectsIds = new HashSet<ArtifactKey>();
151 for ( MavenProject project : reactorProjects )
152 {
153 reactorProjectsIds.add( new ArtifactKey( project ) );
154 }
155
156 List<Dependency> reactorDeps = new ArrayList<Dependency>();
157 for ( Object untypedDependency : dependencies )
158 {
159 Dependency dependency = (Dependency) untypedDependency;
160 org.sonatype.aether.artifact.Artifact depArtifact = dependency.getArtifact();
161
162 ArtifactKey key =
163 new ArtifactKey( depArtifact.getGroupId(), depArtifact.getArtifactId(), depArtifact.getVersion() );
164
165 if ( reactorProjectsIds.contains( key ) )
166 {
167 reactorDeps.add( dependency );
168 }
169 }
170
171 return reactorDeps;
172 }
173
174 private Artifact getDependencyArtifact( Dependency dep )
175 {
176 org.sonatype.aether.artifact.Artifact artifact = dep.getArtifact();
177
178 return factory.createDependencyArtifact( artifact.getGroupId(), artifact.getArtifactId(),
179 VersionRange.createFromVersion( artifact.getVersion() ),
180 artifact.getProperty( "type", artifact.getExtension() ),
181 artifact.getClassifier(), dep.getScope(), dep.isOptional() );
182 }
183
184 private DependencyNode buildDependencyNode( DependencyNode parent, org.sonatype.aether.graph.DependencyNode node,
185 Artifact artifact, ArtifactFilter filter )
186 {
187 DefaultDependencyNode current =
188 new DefaultDependencyNode( parent, artifact,
189 null ,
190 null ,
191 getVersionSelectedFromRange( node.getVersionConstraint() ) );
192
193 List<DependencyNode> nodes = new ArrayList<DependencyNode>( node.getChildren().size() );
194 for ( org.sonatype.aether.graph.DependencyNode child : node.getChildren() )
195 {
196 Artifact childArtifact = getDependencyArtifact( child.getDependency() );
197
198 if ( ( filter == null ) || filter.include( childArtifact ) )
199 {
200 nodes.add( buildDependencyNode( current, child, childArtifact, filter ) );
201 }
202 }
203
204 current.setChildren( Collections.unmodifiableList( nodes ) );
205
206 return current;
207 }
208
209 private String getVersionSelectedFromRange( VersionConstraint constraint )
210 {
211 if ( ( constraint == null ) || ( constraint.getVersion() != null ) )
212 {
213 return null;
214 }
215
216 StringBuilder sb = new StringBuilder();
217 for ( org.sonatype.aether.version.VersionRange range : constraint.getRanges() )
218 {
219 if ( sb.length() > 0 )
220 {
221 sb.append( ',' );
222 }
223 sb.append( range );
224 }
225
226 return sb.toString();
227 }
228 }