1 package org.apache.maven.shared.dependency.tree;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.IdentityHashMap;
26 import java.util.Map;
27 import java.util.Stack;
28
29 import org.apache.maven.artifact.Artifact;
30 import org.apache.maven.artifact.resolver.ResolutionListener;
31 import org.apache.maven.artifact.resolver.ResolutionListenerForDepMgmt;
32 import org.apache.maven.artifact.versioning.VersionRange;
33 import org.apache.maven.shared.dependency.tree.traversal.CollectingDependencyNodeVisitor;
34 import org.codehaus.plexus.logging.Logger;
35
36
37
38
39
40
41
42
43 public class DependencyTreeResolutionListener
44 implements ResolutionListener, ResolutionListenerForDepMgmt
45 {
46
47
48
49
50
51 private final Logger logger;
52
53
54
55
56 private final Stack<DependencyNode> parentNodes;
57
58
59
60
61 private final Map<Artifact, DependencyNode> nodesByArtifact;
62
63
64
65
66 private DependencyNode rootNode;
67
68
69
70
71 private DependencyNode currentNode;
72
73
74
75
76 private Map<String, String> managedVersions = new HashMap<String, String>();
77
78
79
80
81 private Map<String, String> managedScopes = new HashMap<String, String>();
82
83
84
85
86
87
88
89
90
91 public DependencyTreeResolutionListener( Logger logger )
92 {
93 this.logger = logger;
94
95 parentNodes = new Stack<DependencyNode>();
96 nodesByArtifact = new IdentityHashMap<Artifact, DependencyNode>();
97 rootNode = null;
98 currentNode = null;
99 }
100
101
102
103
104
105
106 public void testArtifact( Artifact artifact )
107 {
108 log( "testArtifact: artifact=" + artifact );
109 }
110
111
112
113
114 public void startProcessChildren( Artifact artifact )
115 {
116 log( "startProcessChildren: artifact=" + artifact );
117
118 if ( !currentNode.getArtifact().equals( artifact ) )
119 {
120 throw new IllegalStateException( "Artifact was expected to be " + currentNode.getArtifact() + " but was "
121 + artifact );
122 }
123
124 parentNodes.push( currentNode );
125 }
126
127
128
129
130 public void endProcessChildren( Artifact artifact )
131 {
132 DependencyNode node = parentNodes.pop();
133
134 log( "endProcessChildren: artifact=" + artifact );
135
136 if ( node == null )
137 {
138 throw new IllegalStateException( "Parent dependency node was null" );
139 }
140
141 if ( !node.getArtifact().equals( artifact ) )
142 {
143 throw new IllegalStateException( "Parent dependency node artifact was expected to be " + node.getArtifact()
144 + " but was " + artifact );
145 }
146 }
147
148
149
150
151 public void includeArtifact( Artifact artifact )
152 {
153 log( "includeArtifact: artifact=" + artifact );
154
155 DependencyNode existingNode = getNode( artifact );
156
157
158
159
160
161 if ( existingNode == null && isCurrentNodeIncluded() )
162 {
163 DependencyNode node = addNode( artifact );
164
165
166
167
168
169 flushDependencyManagement( node );
170 }
171 }
172
173
174
175
176 public void omitForNearer( Artifact omitted, Artifact kept )
177 {
178 log( "omitForNearer: omitted=" + omitted + " kept=" + kept );
179
180 if ( !omitted.getDependencyConflictId().equals( kept.getDependencyConflictId() ) )
181 {
182 throw new IllegalArgumentException( "Omitted artifact dependency conflict id "
183 + omitted.getDependencyConflictId() + " differs from kept artifact dependency conflict id "
184 + kept.getDependencyConflictId() );
185 }
186
187 if ( isCurrentNodeIncluded() )
188 {
189 DependencyNode omittedNode = getNode( omitted );
190
191 if ( omittedNode != null )
192 {
193 removeNode( omitted );
194 }
195 else
196 {
197 omittedNode = createNode( omitted );
198
199 currentNode = omittedNode;
200 }
201
202 omittedNode.omitForConflict( kept );
203
204
205
206
207
208 flushDependencyManagement( omittedNode );
209
210 DependencyNode keptNode = getNode( kept );
211
212 if ( keptNode == null )
213 {
214 addNode( kept );
215 }
216 }
217 }
218
219
220
221
222 public void updateScope( Artifact artifact, String scope )
223 {
224 log( "updateScope: artifact=" + artifact + ", scope=" + scope );
225
226 DependencyNode node = getNode( artifact );
227
228 if ( node == null )
229 {
230
231 node = addNode( artifact );
232 }
233
234 node.setOriginalScope( artifact.getScope() );
235 }
236
237
238
239
240 public void manageArtifact( Artifact artifact, Artifact replacement )
241 {
242
243
244 log( "manageArtifact: artifact=" + artifact + ", replacement=" + replacement );
245
246 if ( replacement.getVersion() != null )
247 {
248 manageArtifactVersion( artifact, replacement );
249 }
250
251 if ( replacement.getScope() != null )
252 {
253 manageArtifactScope( artifact, replacement );
254 }
255 }
256
257
258
259
260 public void omitForCycle( Artifact artifact )
261 {
262 log( "omitForCycle: artifact=" + artifact );
263
264 if ( isCurrentNodeIncluded() )
265 {
266 DependencyNode node = createNode( artifact );
267
268 node.omitForCycle();
269 }
270 }
271
272
273
274
275 public void updateScopeCurrentPom( Artifact artifact, String scopeIgnored )
276 {
277 log( "updateScopeCurrentPom: artifact=" + artifact + ", scopeIgnored=" + scopeIgnored );
278
279 DependencyNode node = getNode( artifact );
280
281 if ( node == null )
282 {
283
284 node = addNode( artifact );
285
286 }
287
288 node.setFailedUpdateScope( scopeIgnored );
289 }
290
291
292
293
294 public void selectVersionFromRange( Artifact artifact )
295 {
296 log( "selectVersionFromRange: artifact=" + artifact );
297
298 DependencyNode node = getNode( artifact );
299
300
301
302
303 if ( node == null && isCurrentNodeIncluded() )
304 {
305 node = addNode( artifact );
306 }
307
308 node.setVersionSelectedFromRange( artifact.getVersionRange() );
309 node.setAvailableVersions( artifact.getAvailableVersions() );
310 }
311
312
313
314
315 public void restrictRange( Artifact artifact, Artifact replacement, VersionRange versionRange )
316 {
317 log( "restrictRange: artifact=" + artifact + ", replacement=" + replacement + ", versionRange=" + versionRange );
318
319
320 }
321
322
323
324
325
326
327 public void manageArtifactVersion( Artifact artifact, Artifact replacement )
328 {
329 log( "manageArtifactVersion: artifact=" + artifact + ", replacement=" + replacement );
330
331
332
333
334
335 if ( isCurrentNodeIncluded() && !replacement.getVersion().equals( artifact.getVersion() ) )
336 {
337
338
339
340
341 managedVersions.put( replacement.getId(), artifact.getVersion() );
342 }
343 }
344
345
346
347
348 public void manageArtifactScope( Artifact artifact, Artifact replacement )
349 {
350 log( "manageArtifactScope: artifact=" + artifact + ", replacement=" + replacement );
351
352
353
354
355
356 if ( isCurrentNodeIncluded() && !replacement.getScope().equals( artifact.getScope() ) )
357 {
358
359
360
361
362 managedScopes.put( replacement.getId(), artifact.getScope() );
363 }
364 }
365
366
367
368
369
370
371
372
373
374 public Collection<DependencyNode> getNodes()
375 {
376 return Collections.unmodifiableCollection( nodesByArtifact.values() );
377 }
378
379
380
381
382
383
384 public DependencyNode getRootNode()
385 {
386 return rootNode;
387 }
388
389
390
391
392
393
394
395
396
397 private void log( String message )
398 {
399 int depth = parentNodes.size();
400
401 StringBuffer buffer = new StringBuffer();
402
403 for ( int i = 0; i < depth; i++ )
404 {
405 buffer.append( " " );
406 }
407
408 buffer.append( message );
409
410 logger.debug( buffer.toString() );
411 }
412
413
414
415
416
417
418
419
420 private DependencyNode createNode( Artifact artifact )
421 {
422 DependencyNode node = new DependencyNode( artifact );
423
424 if ( !parentNodes.isEmpty() )
425 {
426 DependencyNode parent = parentNodes.peek();
427
428 parent.addChild( node );
429 }
430
431 return node;
432 }
433
434
435
436
437
438
439
440
441
442
443 DependencyNode addNode( Artifact artifact )
444 {
445 DependencyNode node = createNode( artifact );
446
447 DependencyNode previousNode = nodesByArtifact.put( node.getArtifact(), node );
448
449 if ( previousNode != null )
450 {
451 throw new IllegalStateException( "Duplicate node registered for artifact: " + node.getArtifact() );
452 }
453
454 if ( rootNode == null )
455 {
456 rootNode = node;
457 }
458
459 currentNode = node;
460
461 return node;
462 }
463
464
465
466
467
468
469
470
471
472 private DependencyNode getNode( Artifact artifact )
473 {
474 return nodesByArtifact.get( artifact );
475 }
476
477
478
479
480
481
482
483 private void removeNode( Artifact artifact )
484 {
485 DependencyNode node = nodesByArtifact.remove( artifact );
486
487 if ( !artifact.equals( node.getArtifact() ) )
488 {
489 throw new IllegalStateException( "Removed dependency node artifact was expected to be " + artifact
490 + " but was " + node.getArtifact() );
491 }
492 }
493
494
495
496
497
498
499
500
501 private boolean isCurrentNodeIncluded()
502 {
503 for ( DependencyNode node : parentNodes )
504 {
505 if ( node.getState() != DependencyNode.INCLUDED )
506 {
507 return false;
508 }
509 }
510
511 return true;
512 }
513
514
515
516
517
518
519
520
521 private void flushDependencyManagement( DependencyNode node )
522 {
523 Artifact artifact = node.getArtifact();
524 String premanagedVersion = managedVersions.get( artifact.getId() );
525 String premanagedScope = managedScopes.get( artifact.getId() );
526
527 if ( premanagedVersion != null || premanagedScope != null )
528 {
529 if ( premanagedVersion != null )
530 {
531 node.setPremanagedVersion( premanagedVersion );
532 }
533
534 if ( premanagedScope != null )
535 {
536 node.setPremanagedScope( premanagedScope );
537 }
538
539 premanagedVersion = null;
540 premanagedScope = null;
541 }
542 }
543 }