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 java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25
26 import org.apache.maven.RepositoryUtils;
27 import org.apache.maven.artifact.Artifact;
28 import org.apache.maven.artifact.repository.ArtifactRepository;
29 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
30 import org.apache.maven.model.Dependency;
31 import org.apache.maven.project.MavenProject;
32 import org.apache.maven.project.ProjectBuildingRequest;
33 import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder;
34 import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilderException;
35 import org.apache.maven.shared.dependency.graph.DependencyNode;
36 import org.apache.maven.shared.dependency.graph.internal.maven31.Maven31DirectScopeDependencySelector;
37 import org.apache.maven.shared.dependency.graph.internal.maven31.VerboseJavaScopeSelector;
38 import org.codehaus.plexus.component.annotations.Component;
39 import org.codehaus.plexus.component.annotations.Requirement;
40 import org.codehaus.plexus.logging.AbstractLogEnabled;
41 import org.eclipse.aether.DefaultRepositorySystemSession;
42 import org.eclipse.aether.RepositorySystem;
43 import org.eclipse.aether.artifact.ArtifactTypeRegistry;
44 import org.eclipse.aether.collection.CollectRequest;
45 import org.eclipse.aether.collection.CollectResult;
46 import org.eclipse.aether.collection.DependencyCollectionException;
47 import org.eclipse.aether.collection.DependencyGraphTransformer;
48 import org.eclipse.aether.collection.DependencySelector;
49 import org.eclipse.aether.graph.DependencyVisitor;
50 import org.eclipse.aether.graph.Exclusion;
51 import org.eclipse.aether.util.artifact.JavaScopes;
52 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
53 import org.eclipse.aether.util.graph.selector.AndDependencySelector;
54 import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
55 import org.eclipse.aether.util.graph.selector.OptionalDependencySelector;
56 import org.eclipse.aether.util.graph.transformer.ConflictResolver;
57 import org.eclipse.aether.util.graph.transformer.JavaScopeDeriver;
58 import org.eclipse.aether.util.graph.transformer.NearestVersionSelector;
59 import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector;
60 import org.eclipse.aether.util.graph.visitor.TreeDependencyVisitor;
61 import org.eclipse.aether.version.VersionConstraint;
62
63
64
65
66
67
68
69 @Component( role = DependencyCollectorBuilder.class, hint = "maven31" )
70 public class Maven31DependencyCollectorBuilder
71 extends AbstractLogEnabled
72 implements DependencyCollectorBuilder
73 {
74 @Requirement
75 private RepositorySystem repositorySystem;
76
77 private final ExceptionHandler<DependencyCollectorBuilderException> exceptionHandler;
78
79 public Maven31DependencyCollectorBuilder()
80 {
81 this.exceptionHandler = new ExceptionHandler<DependencyCollectorBuilderException>()
82 {
83 @Override
84 public DependencyCollectorBuilderException create( String message, Exception exception )
85 {
86 return new DependencyCollectorBuilderException( message, exception );
87 }
88 };
89 }
90
91 @Override
92 public DependencyNode collectDependencyGraph( ProjectBuildingRequest buildingRequest, ArtifactFilter filter )
93 throws DependencyCollectorBuilderException
94 {
95 DefaultRepositorySystemSession session = null;
96 try
97 {
98 MavenProject project = buildingRequest.getProject();
99
100 Artifact projectArtifact = project.getArtifact();
101 List<ArtifactRepository> remoteArtifactRepositories = project.getRemoteArtifactRepositories();
102
103 DefaultRepositorySystemSession repositorySession =
104 (DefaultRepositorySystemSession) Invoker.invoke( buildingRequest, "getRepositorySession",
105 exceptionHandler );
106
107 session = new DefaultRepositorySystemSession( repositorySession );
108
109 DependencyGraphTransformer transformer =
110 new ConflictResolver( new NearestVersionSelector(), new VerboseJavaScopeSelector(),
111 new SimpleOptionalitySelector(), new JavaScopeDeriver() );
112 session.setDependencyGraphTransformer( transformer );
113
114 DependencySelector depFilter =
115 new AndDependencySelector( new Maven31DirectScopeDependencySelector( JavaScopes.TEST ),
116 new OptionalDependencySelector(),
117 new ExclusionDependencySelector() );
118 session.setDependencySelector( depFilter );
119
120 session.setConfigProperty( ConflictResolver.CONFIG_PROP_VERBOSE, true );
121 session.setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, true );
122
123 org.eclipse.aether.artifact.Artifact aetherArtifact =
124 (org.eclipse.aether.artifact.Artifact) Invoker.invoke( RepositoryUtils.class, "toArtifact",
125 Artifact.class, projectArtifact,
126 exceptionHandler );
127
128 @SuppressWarnings( "unchecked" )
129 List<org.eclipse.aether.repository.RemoteRepository> aetherRepos =
130 (List<org.eclipse.aether.repository.RemoteRepository>) Invoker.invoke( RepositoryUtils.class, "toRepos",
131 List.class,
132 remoteArtifactRepositories,
133 exceptionHandler );
134
135 CollectRequest collectRequest = new CollectRequest();
136 collectRequest.setRoot( new org.eclipse.aether.graph.Dependency( aetherArtifact, "" ) );
137 collectRequest.setRepositories( aetherRepos );
138
139 org.eclipse.aether.artifact.ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry();
140 collectDependencyList( collectRequest, project, stereotypes );
141 collectManagedDependencyList( collectRequest, project, stereotypes );
142
143 CollectResult collectResult = repositorySystem.collectDependencies( session, collectRequest );
144
145 org.eclipse.aether.graph.DependencyNode rootNode = collectResult.getRoot();
146
147 if ( getLogger().isDebugEnabled() )
148 {
149 logTree( rootNode );
150 }
151
152 return buildDependencyNode( null, rootNode, projectArtifact, filter );
153 }
154 catch ( DependencyCollectionException e )
155 {
156 throw new DependencyCollectorBuilderException( "Could not collect dependencies: " + e.getResult(), e );
157 }
158 finally
159 {
160 if ( session != null )
161 {
162 session.setReadOnly();
163 }
164 }
165 }
166
167 private void logTree( org.eclipse.aether.graph.DependencyNode rootNode )
168 {
169
170 rootNode.accept( new TreeDependencyVisitor( new DependencyVisitor()
171 {
172 String indent = "";
173
174 @Override
175 public boolean visitEnter( org.eclipse.aether.graph.DependencyNode dependencyNode )
176 {
177 getLogger().debug( indent + "Aether node: " + dependencyNode + " data map: "
178 + dependencyNode.getData() );
179 indent += " ";
180 return true;
181 }
182
183 @Override
184 public boolean visitLeave( org.eclipse.aether.graph.DependencyNode dependencyNode )
185 {
186 indent = indent.substring( 0, indent.length() - 4 );
187 return true;
188 }
189 } ) );
190 }
191
192 private void collectManagedDependencyList( CollectRequest collectRequest, MavenProject project,
193 ArtifactTypeRegistry stereotypes )
194 throws DependencyCollectorBuilderException
195 {
196 if ( project.getDependencyManagement() != null )
197 {
198 for ( Dependency dependency : project.getDependencyManagement().getDependencies() )
199 {
200 org.eclipse.aether.graph.Dependency aetherDep = toAetherDependency( stereotypes, dependency );
201 collectRequest.addManagedDependency( aetherDep );
202 }
203 }
204 }
205
206 private void collectDependencyList( CollectRequest collectRequest, MavenProject project,
207 org.eclipse.aether.artifact.ArtifactTypeRegistry stereotypes )
208 throws DependencyCollectorBuilderException
209 {
210 for ( Dependency dependency : project.getDependencies() )
211 {
212 org.eclipse.aether.graph.Dependency aetherDep = toAetherDependency( stereotypes, dependency );
213 collectRequest.addDependency( aetherDep );
214 }
215 }
216
217
218 private org.eclipse.aether.graph.Dependency toAetherDependency( org.eclipse.aether.artifact.ArtifactTypeRegistry stereotypes,
219 Dependency dependency )
220 throws DependencyCollectorBuilderException
221 {
222 org.eclipse.aether.graph.Dependency aetherDep =
223 (org.eclipse.aether.graph.Dependency) Invoker.invoke( RepositoryUtils.class, "toDependency",
224 Dependency.class,
225 org.eclipse.aether.artifact.ArtifactTypeRegistry.class,
226 dependency, stereotypes, exceptionHandler );
227 return aetherDep;
228 }
229
230
231 private Artifact getDependencyArtifact( org.eclipse.aether.graph.Dependency dep )
232 {
233 org.eclipse.aether.artifact.Artifact artifact = dep.getArtifact();
234
235 try
236 {
237 Artifact mavenArtifact =
238 (Artifact) Invoker.invoke( RepositoryUtils.class, "toArtifact",
239 org.eclipse.aether.artifact.Artifact.class, artifact, exceptionHandler );
240
241 mavenArtifact.setScope( dep.getScope() );
242 mavenArtifact.setOptional( dep.isOptional() );
243
244 return mavenArtifact;
245 }
246 catch ( DependencyCollectorBuilderException e )
247 {
248
249 throw new RuntimeException( e.getMessage(), e );
250 }
251 }
252
253 private DependencyNode buildDependencyNode( DependencyNode parent, org.eclipse.aether.graph.DependencyNode node,
254 Artifact artifact, ArtifactFilter filter )
255 {
256 String premanagedVersion = DependencyManagerUtils.getPremanagedVersion( node );
257 String premanagedScope = DependencyManagerUtils.getPremanagedScope( node );
258
259 Boolean optional = null;
260 if ( node.getDependency() != null )
261 {
262 optional = node.getDependency().isOptional();
263 }
264
265 List<org.apache.maven.model.Exclusion> exclusions = null;
266 if ( node.getDependency() != null )
267 {
268 exclusions = new ArrayList<>( node.getDependency().getExclusions().size() );
269 for ( Exclusion exclusion : node.getDependency().getExclusions() )
270 {
271 org.apache.maven.model.Exclusion modelExclusion = new org.apache.maven.model.Exclusion();
272 modelExclusion.setGroupId( exclusion.getGroupId() );
273 modelExclusion.setArtifactId( exclusion.getArtifactId() );
274 exclusions.add( modelExclusion );
275 }
276 }
277
278 org.eclipse.aether.graph.DependencyNode winner =
279 (org.eclipse.aether.graph.DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER );
280 String winnerVersion = null;
281 String ignoredScope = null;
282 if ( winner != null )
283 {
284 winnerVersion = winner.getArtifact().getBaseVersion();
285 }
286 else
287 {
288 ignoredScope = (String) node.getData().get( VerboseJavaScopeSelector.REDUCED_SCOPE );
289 }
290
291 ConflictData data = new ConflictData( winnerVersion, ignoredScope );
292
293 VerboseDependencyNode current =
294 new VerboseDependencyNode( parent, artifact, premanagedVersion, premanagedScope,
295 getVersionSelectedFromRange( node.getVersionConstraint() ), optional,
296 exclusions, data );
297
298 List<DependencyNode> nodes = new ArrayList<DependencyNode>( node.getChildren().size() );
299 for ( org.eclipse.aether.graph.DependencyNode child : node.getChildren() )
300 {
301 Artifact childArtifact = getDependencyArtifact( child.getDependency() );
302
303 if ( ( filter == null ) || filter.include( childArtifact ) )
304 {
305 nodes.add( buildDependencyNode( current, child, childArtifact, filter ) );
306 }
307 }
308
309 current.setChildren( Collections.unmodifiableList( nodes ) );
310
311 return current;
312 }
313
314 private String getVersionSelectedFromRange( VersionConstraint constraint )
315 {
316 if ( ( constraint == null ) || ( constraint.getVersion() != null ) )
317 {
318 return null;
319 }
320
321 return constraint.getRange().toString();
322 }
323 }