|
|
|
|
@ -16,6 +16,7 @@
@@ -16,6 +16,7 @@
|
|
|
|
|
|
|
|
|
|
package org.springframework.boot.build.bom; |
|
|
|
|
|
|
|
|
|
import java.io.File; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
@ -31,6 +32,11 @@ import java.util.regex.Matcher;
@@ -31,6 +32,11 @@ import java.util.regex.Matcher;
|
|
|
|
|
import java.util.regex.Pattern; |
|
|
|
|
import java.util.stream.Stream; |
|
|
|
|
|
|
|
|
|
import javax.xml.parsers.DocumentBuilder; |
|
|
|
|
import javax.xml.parsers.DocumentBuilderFactory; |
|
|
|
|
import javax.xml.xpath.XPath; |
|
|
|
|
import javax.xml.xpath.XPathFactory; |
|
|
|
|
|
|
|
|
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion; |
|
|
|
|
import org.apache.maven.artifact.versioning.VersionRange; |
|
|
|
|
import org.gradle.api.Project; |
|
|
|
|
@ -38,6 +44,7 @@ import org.gradle.api.artifacts.Configuration;
@@ -38,6 +44,7 @@ import org.gradle.api.artifacts.Configuration;
|
|
|
|
|
import org.gradle.api.artifacts.Dependency; |
|
|
|
|
import org.gradle.api.artifacts.result.DependencyResult; |
|
|
|
|
import org.gradle.api.artifacts.result.ResolutionResult; |
|
|
|
|
import org.w3c.dom.Document; |
|
|
|
|
|
|
|
|
|
import org.springframework.boot.build.bom.bomr.version.DependencyVersion; |
|
|
|
|
|
|
|
|
|
@ -406,10 +413,16 @@ public class Library {
@@ -406,10 +413,16 @@ public class Library {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public interface VersionAlignment { |
|
|
|
|
|
|
|
|
|
Set<String> resolve(); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Version alignment for a library. |
|
|
|
|
* Version alignment for a library based on a dependency of another module. |
|
|
|
|
*/ |
|
|
|
|
public static class VersionAlignment { |
|
|
|
|
public static class DependencyVersionAlignment implements VersionAlignment { |
|
|
|
|
|
|
|
|
|
private final String from; |
|
|
|
|
|
|
|
|
|
@ -423,7 +436,8 @@ public class Library {
@@ -423,7 +436,8 @@ public class Library {
|
|
|
|
|
|
|
|
|
|
private Set<String> alignedVersions; |
|
|
|
|
|
|
|
|
|
VersionAlignment(String from, String managedBy, Project project, List<Library> libraries, List<Group> groups) { |
|
|
|
|
DependencyVersionAlignment(String from, String managedBy, Project project, List<Library> libraries, |
|
|
|
|
List<Group> groups) { |
|
|
|
|
this.from = from; |
|
|
|
|
this.managedBy = managedBy; |
|
|
|
|
this.project = project; |
|
|
|
|
@ -431,6 +445,7 @@ public class Library {
@@ -431,6 +445,7 @@ public class Library {
|
|
|
|
|
this.groups = groups; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Set<String> resolve() { |
|
|
|
|
if (this.alignedVersions != null) { |
|
|
|
|
return this.alignedVersions; |
|
|
|
|
@ -539,6 +554,100 @@ public class Library {
@@ -539,6 +554,100 @@ public class Library {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Version alignment for a library based on a property in the pom of another module. |
|
|
|
|
*/ |
|
|
|
|
public static class PomPropertyVersionAlignment implements VersionAlignment { |
|
|
|
|
|
|
|
|
|
private final String name; |
|
|
|
|
|
|
|
|
|
private final String from; |
|
|
|
|
|
|
|
|
|
private final String managedBy; |
|
|
|
|
|
|
|
|
|
private final Project project; |
|
|
|
|
|
|
|
|
|
private final List<Library> libraries; |
|
|
|
|
|
|
|
|
|
private Set<String> alignedVersions; |
|
|
|
|
|
|
|
|
|
PomPropertyVersionAlignment(String name, String from, String managedBy, Project project, |
|
|
|
|
List<Library> libraries) { |
|
|
|
|
this.name = name; |
|
|
|
|
this.from = from; |
|
|
|
|
this.managedBy = managedBy; |
|
|
|
|
this.project = project; |
|
|
|
|
this.libraries = libraries; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Set<String> resolve() { |
|
|
|
|
if (this.alignedVersions != null) { |
|
|
|
|
return this.alignedVersions; |
|
|
|
|
} |
|
|
|
|
Configuration alignmentConfiguration = this.project.getConfigurations() |
|
|
|
|
.detachedConfiguration(getAligningDependencies().toArray(new Dependency[0])); |
|
|
|
|
Set<File> files = alignmentConfiguration.resolve(); |
|
|
|
|
if (files.size() != 1) { |
|
|
|
|
throw new IllegalStateException( |
|
|
|
|
"Expected a single file when resolving the pom of " + this.from + " but found " + files.size()); |
|
|
|
|
} |
|
|
|
|
File pomFile = files.iterator().next(); |
|
|
|
|
return Set.of(propertyFrom(pomFile)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private List<Dependency> getAligningDependencies() { |
|
|
|
|
Library managingLibrary = findManagingLibrary(); |
|
|
|
|
List<Dependency> boms = getBomDependencies(managingLibrary); |
|
|
|
|
List<Dependency> dependencies = new ArrayList<>(); |
|
|
|
|
dependencies.addAll(boms); |
|
|
|
|
dependencies.add(this.project.getDependencies().create(this.from + "@pom")); |
|
|
|
|
return dependencies; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Library findManagingLibrary() { |
|
|
|
|
if (this.managedBy == null) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
return this.libraries.stream() |
|
|
|
|
.filter((candidate) -> this.managedBy.equals(candidate.getName())) |
|
|
|
|
.findFirst() |
|
|
|
|
.orElseThrow(() -> new IllegalStateException("Managing library '" + this.managedBy + "' not found.")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private List<Dependency> getBomDependencies(Library manager) { |
|
|
|
|
return manager.getGroups() |
|
|
|
|
.stream() |
|
|
|
|
.flatMap((group) -> group.getBoms() |
|
|
|
|
.stream() |
|
|
|
|
.map((bom) -> this.project.getDependencies() |
|
|
|
|
.platform(group.getId() + ":" + bom.name() + ":" + manager.getVersion().getVersion()))) |
|
|
|
|
.toList(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String propertyFrom(File pomFile) { |
|
|
|
|
try { |
|
|
|
|
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); |
|
|
|
|
Document document = documentBuilder.parse(pomFile); |
|
|
|
|
XPath xpath = XPathFactory.newInstance().newXPath(); |
|
|
|
|
return xpath.evaluate("/project/properties/" + this.name + "/text()", document); |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
throw new RuntimeException(ex); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public String toString() { |
|
|
|
|
String result = "version from properties of " + this.from; |
|
|
|
|
if (this.managedBy != null) { |
|
|
|
|
result += " that is managed by " + this.managedBy; |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public record Link(String rootName, Function<LibraryVersion, String> factory, List<String> packages) { |
|
|
|
|
|
|
|
|
|
private static final Pattern PACKAGE_EXPAND = Pattern.compile("^(.*)\\[(.*)\\]$"); |
|
|
|
|
|