16
16
17
17
package org .springframework .boot .build .bom ;
18
18
19
+ import java .io .File ;
19
20
import java .util .ArrayList ;
20
21
import java .util .Arrays ;
21
22
import java .util .Collections ;
31
32
import java .util .regex .Pattern ;
32
33
import java .util .stream .Stream ;
33
34
35
+ import javax .xml .parsers .DocumentBuilder ;
36
+ import javax .xml .parsers .DocumentBuilderFactory ;
37
+ import javax .xml .xpath .XPath ;
38
+ import javax .xml .xpath .XPathFactory ;
39
+
34
40
import org .apache .maven .artifact .versioning .DefaultArtifactVersion ;
35
41
import org .apache .maven .artifact .versioning .VersionRange ;
36
42
import org .gradle .api .Project ;
37
43
import org .gradle .api .artifacts .Configuration ;
38
44
import org .gradle .api .artifacts .Dependency ;
39
45
import org .gradle .api .artifacts .result .DependencyResult ;
40
46
import org .gradle .api .artifacts .result .ResolutionResult ;
47
+ import org .w3c .dom .Document ;
41
48
42
49
import org .springframework .boot .build .bom .bomr .version .DependencyVersion ;
43
50
@@ -406,10 +413,16 @@ public String getArtifactId() {
406
413
407
414
}
408
415
416
+ public interface VersionAlignment {
417
+
418
+ Set <String > resolve ();
419
+
420
+ }
421
+
409
422
/**
410
- * Version alignment for a library.
423
+ * Version alignment for a library based on a dependency of another module .
411
424
*/
412
- public static class VersionAlignment {
425
+ public static class DependencyVersionAlignment implements VersionAlignment {
413
426
414
427
private final String from ;
415
428
@@ -423,14 +436,16 @@ public static class VersionAlignment {
423
436
424
437
private Set <String > alignedVersions ;
425
438
426
- VersionAlignment (String from , String managedBy , Project project , List <Library > libraries , List <Group > groups ) {
439
+ DependencyVersionAlignment (String from , String managedBy , Project project , List <Library > libraries ,
440
+ List <Group > groups ) {
427
441
this .from = from ;
428
442
this .managedBy = managedBy ;
429
443
this .project = project ;
430
444
this .libraries = libraries ;
431
445
this .groups = groups ;
432
446
}
433
447
448
+ @ Override
434
449
public Set <String > resolve () {
435
450
if (this .alignedVersions != null ) {
436
451
return this .alignedVersions ;
@@ -539,6 +554,100 @@ public String toString() {
539
554
540
555
}
541
556
557
+ /**
558
+ * Version alignment for a library based on a property in the pom of another module.
559
+ */
560
+ public static class PomPropertyVersionAlignment implements VersionAlignment {
561
+
562
+ private final String name ;
563
+
564
+ private final String from ;
565
+
566
+ private final String managedBy ;
567
+
568
+ private final Project project ;
569
+
570
+ private final List <Library > libraries ;
571
+
572
+ private Set <String > alignedVersions ;
573
+
574
+ PomPropertyVersionAlignment (String name , String from , String managedBy , Project project ,
575
+ List <Library > libraries ) {
576
+ this .name = name ;
577
+ this .from = from ;
578
+ this .managedBy = managedBy ;
579
+ this .project = project ;
580
+ this .libraries = libraries ;
581
+ }
582
+
583
+ @ Override
584
+ public Set <String > resolve () {
585
+ if (this .alignedVersions != null ) {
586
+ return this .alignedVersions ;
587
+ }
588
+ Configuration alignmentConfiguration = this .project .getConfigurations ()
589
+ .detachedConfiguration (getAligningDependencies ().toArray (new Dependency [0 ]));
590
+ Set <File > files = alignmentConfiguration .resolve ();
591
+ if (files .size () != 1 ) {
592
+ throw new IllegalStateException (
593
+ "Expected a single file when resolving the pom of " + this .from + " but found " + files .size ());
594
+ }
595
+ File pomFile = files .iterator ().next ();
596
+ return Set .of (propertyFrom (pomFile ));
597
+ }
598
+
599
+ private List <Dependency > getAligningDependencies () {
600
+ Library managingLibrary = findManagingLibrary ();
601
+ List <Dependency > boms = getBomDependencies (managingLibrary );
602
+ List <Dependency > dependencies = new ArrayList <>();
603
+ dependencies .addAll (boms );
604
+ dependencies .add (this .project .getDependencies ().create (this .from + "@pom" ));
605
+ return dependencies ;
606
+ }
607
+
608
+ private Library findManagingLibrary () {
609
+ if (this .managedBy == null ) {
610
+ return null ;
611
+ }
612
+ return this .libraries .stream ()
613
+ .filter ((candidate ) -> this .managedBy .equals (candidate .getName ()))
614
+ .findFirst ()
615
+ .orElseThrow (() -> new IllegalStateException ("Managing library '" + this .managedBy + "' not found." ));
616
+ }
617
+
618
+ private List <Dependency > getBomDependencies (Library manager ) {
619
+ return manager .getGroups ()
620
+ .stream ()
621
+ .flatMap ((group ) -> group .getBoms ()
622
+ .stream ()
623
+ .map ((bom ) -> this .project .getDependencies ()
624
+ .platform (group .getId () + ":" + bom .name () + ":" + manager .getVersion ().getVersion ())))
625
+ .toList ();
626
+ }
627
+
628
+ private String propertyFrom (File pomFile ) {
629
+ try {
630
+ DocumentBuilder documentBuilder = DocumentBuilderFactory .newInstance ().newDocumentBuilder ();
631
+ Document document = documentBuilder .parse (pomFile );
632
+ XPath xpath = XPathFactory .newInstance ().newXPath ();
633
+ return xpath .evaluate ("/project/properties/" + this .name + "/text()" , document );
634
+ }
635
+ catch (Exception ex ) {
636
+ throw new RuntimeException (ex );
637
+ }
638
+ }
639
+
640
+ @ Override
641
+ public String toString () {
642
+ String result = "version from properties of " + this .from ;
643
+ if (this .managedBy != null ) {
644
+ result += " that is managed by " + this .managedBy ;
645
+ }
646
+ return result ;
647
+ }
648
+
649
+ }
650
+
542
651
public record Link (String rootName , Function <LibraryVersion , String > factory , List <String > packages ) {
543
652
544
653
private static final Pattern PACKAGE_EXPAND = Pattern .compile ("^(.*)\\ [(.*)\\ ]$" );
0 commit comments