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