From b428aea229fc2733d5a68f4fa905faffa63c6f12 Mon Sep 17 00:00:00 2001 From: Jerome Haltom Date: Wed, 17 Jan 2024 13:30:08 -0600 Subject: [PATCH] Upgrade Maven to 3.9. Upgrade Maven Resolver to 1.9. Added support for Exclusions metadata. Takes an artifact ID pattern. New resolver code made some parsing methods private. Go after them with reflection. --- .../ikvm-maven-sdk-tasks-java.pom | 20 ++--- .../MavenReferenceItemResolveTests.cs | 29 +++++++ .../IKVM.Maven.Sdk.Tasks.csproj | 1 + .../Json/VersionConstraintJsonConverter.cs | 12 ++- .../Json/VersionJsonConverter.cs | 11 ++- src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs | 2 + .../MavenReferenceItem.cs | 20 +++-- .../MavenReferenceItemExclusion.cs | 75 +++++++++++++++++++ .../MavenReferenceItemMetadata.cs | 24 ++++++ .../MavenReferenceItemPrepare.cs | 48 ++++++------ .../MavenReferenceItemResolve.cs | 5 +- 11 files changed, 199 insertions(+), 48 deletions(-) create mode 100644 src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemExclusion.cs diff --git a/src/IKVM.Maven.Sdk.Tasks.Java/ikvm-maven-sdk-tasks-java.pom b/src/IKVM.Maven.Sdk.Tasks.Java/ikvm-maven-sdk-tasks-java.pom index b663caf..6b76eda 100644 --- a/src/IKVM.Maven.Sdk.Tasks.Java/ikvm-maven-sdk-tasks-java.pom +++ b/src/IKVM.Maven.Sdk.Tasks.Java/ikvm-maven-sdk-tasks-java.pom @@ -10,52 +10,52 @@ org.apache.maven maven-model - 3.8.7 + 3.9.6 org.apache.maven maven-core - 3.8.7 + 3.9.6 org.apache.maven maven-resolver-provider - 3.8.7 + 3.9.6 org.apache.maven maven-settings-builder - 3.8.7 + 3.9.6 org.apache.maven.resolver maven-resolver-api - 1.6.3 + 1.9.18 org.apache.maven.resolver maven-resolver-spi - 1.6.3 + 1.9.18 org.apache.maven.resolver maven-resolver-impl - 1.6.3 + 1.9.18 org.apache.maven.resolver maven-resolver-connector-basic - 1.6.3 + 1.9.18 org.apache.maven.resolver maven-resolver-transport-file - 1.6.3 + 1.9.18 org.apache.maven.resolver maven-resolver-transport-http - 1.6.3 + 1.9.18 \ No newline at end of file diff --git a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs index 774ea20..b779d88 100644 --- a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs +++ b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs @@ -572,6 +572,35 @@ public void CanResolveFromPrivateRepository() t.ResolvedReferences.Should().Contain(i => i.ItemSpec == "maven$org.apache.xmlgraphics:fop:2.8"); } + [TestMethod] + public void ExclusionsShouldExcludeSystemDependency() + { + var cacheFile = Path.GetTempFileName(); + + var engine = new Mock(); + var errors = new List(); + engine.Setup(x => x.LogErrorEvent(It.IsAny())).Callback((BuildErrorEventArgs e) => { errors.Add(e); TestContext.WriteLine("ERROR: " + e.Message); }); + engine.Setup(x => x.LogWarningEvent(It.IsAny())).Callback((BuildWarningEventArgs e) => TestContext.WriteLine("WARNING: " + e.Message)); + engine.Setup(x => x.LogMessageEvent(It.IsAny())).Callback((BuildMessageEventArgs e) => TestContext.WriteLine(e.Message)); + var t = new MavenReferenceItemResolve(); + t.BuildEngine = engine.Object; + t.CacheFile = cacheFile; + t.Repositories = new[] { GetCentralRepositoryItem() }; + + var i1 = new TaskItem("net.sf.jt400:jt400:20.0.6"); + i1.SetMetadata(MavenReferenceItemMetadata.GroupId, "net.sf.jt400"); + i1.SetMetadata(MavenReferenceItemMetadata.ArtifactId, "jt400"); + i1.SetMetadata(MavenReferenceItemMetadata.Version, "20.0.6"); + i1.SetMetadata(MavenReferenceItemMetadata.Exclusions, "com.sun:tools"); + + t.References = new[] { i1 }; + + t.Execute().Should().BeTrue(); + errors.Should().BeEmpty(); + + t.ResolvedReferences.Should().NotContain(i => i.ItemSpec == "maven$com.sun:tools:jar:1.8.0"); + } + } } diff --git a/src/IKVM.Maven.Sdk.Tasks/IKVM.Maven.Sdk.Tasks.csproj b/src/IKVM.Maven.Sdk.Tasks/IKVM.Maven.Sdk.Tasks.csproj index d0ae67a..ff0d3f7 100644 --- a/src/IKVM.Maven.Sdk.Tasks/IKVM.Maven.Sdk.Tasks.csproj +++ b/src/IKVM.Maven.Sdk.Tasks/IKVM.Maven.Sdk.Tasks.csproj @@ -9,6 +9,7 @@ + diff --git a/src/IKVM.Maven.Sdk.Tasks/Json/VersionConstraintJsonConverter.cs b/src/IKVM.Maven.Sdk.Tasks/Json/VersionConstraintJsonConverter.cs index bdb9321..4146739 100644 --- a/src/IKVM.Maven.Sdk.Tasks/Json/VersionConstraintJsonConverter.cs +++ b/src/IKVM.Maven.Sdk.Tasks/Json/VersionConstraintJsonConverter.cs @@ -1,4 +1,6 @@ using System; +using System.Linq; +using System.Reflection; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; @@ -13,12 +15,20 @@ namespace IKVM.Maven.Sdk.Tasks.Json /// class VersionConstraintJsonConverter : JsonConverter { + + static readonly MethodInfo parseVersionConstraintMethod = typeof(GenericVersionScheme) + .GetMethods() + .Where(i => i.Name == "parseVersionConstraint") + .Where(i => i.GetParameters().Length == 1 && i.GetParameters()[0].ParameterType == typeof(string)) + .Where(i => i.ReturnType == typeof(GenericVersionScheme).Assembly.GetType("org.eclipse.aether.util.version.GenericVersionConstraint")) + .First(); + public override org.eclipse.aether.version.VersionConstraint Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) return null; else - return new GenericVersionScheme().parseVersionConstraint(reader.GetString()); + return (org.eclipse.aether.version.VersionConstraint)parseVersionConstraintMethod.Invoke(new GenericVersionScheme(), new[] { reader.GetString() }); } public override void Write(Utf8JsonWriter writer, org.eclipse.aether.version.VersionConstraint value, JsonSerializerOptions options) diff --git a/src/IKVM.Maven.Sdk.Tasks/Json/VersionJsonConverter.cs b/src/IKVM.Maven.Sdk.Tasks/Json/VersionJsonConverter.cs index 7206690..5ad2636 100644 --- a/src/IKVM.Maven.Sdk.Tasks/Json/VersionJsonConverter.cs +++ b/src/IKVM.Maven.Sdk.Tasks/Json/VersionJsonConverter.cs @@ -1,4 +1,6 @@ using System; +using System.Linq; +using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; @@ -13,12 +15,19 @@ namespace IKVM.Maven.Sdk.Tasks.Json class VersionJsonConverter : JsonConverter { + static readonly MethodInfo parseVersionMethod = typeof(GenericVersionScheme) + .GetMethods() + .Where(i => i.Name == "parseVersion") + .Where(i => i.GetParameters().Length == 1 && i.GetParameters()[0].ParameterType == typeof(string)) + .Where(i => i.ReturnType == typeof(GenericVersionScheme).Assembly.GetType("org.eclipse.aether.util.version.GenericVersion")) + .First(); + public override org.eclipse.aether.version.Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) return null; else - return new GenericVersionScheme().parseVersion(reader.GetString()); + return (org.eclipse.aether.version.Version)parseVersionMethod.Invoke(new GenericVersionScheme(), new[] { reader.GetString() }); } public override void Write(Utf8JsonWriter writer, org.eclipse.aether.version.Version value, JsonSerializerOptions options) diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs b/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs index 478d438..b67df9d 100644 --- a/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs +++ b/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs @@ -287,6 +287,8 @@ public RepositorySystemSession CreateRepositorySystemSession(bool noError = fals session.setTransferListener(new MavenTransferListener(log, noError)); session.setRepositoryListener(new MavenRepositoryListener(log)); session.setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, "true"); + session.setSystemProperty("java.version", java.lang.System.getProperty("java.version") ?? "1.8"); + session.setOffline(settings.isOffline()); return session; } diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItem.cs b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItem.cs index 1252c02..d8c8c53 100644 --- a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItem.cs +++ b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItem.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using System.Linq; using org.eclipse.aether.util.artifact; @@ -47,11 +47,17 @@ class MavenReferenceItem : IEquatable /// public string Scope { get; set; } = JavaScopes.COMPILE; + /// + /// Gets the exclusions of this reference. + /// + public MavenReferenceItemExclusion[] Exclusions { get; set; } + /// /// Originator of the reference item. /// public string ReferenceSource { get; set; } + /// public override bool Equals(object obj) { return Equals(obj as MavenReferenceItem); @@ -72,6 +78,7 @@ public bool Equals(MavenReferenceItem other) Version == other.Version && Optional == other.Optional && Scope == other.Scope && + Enumerable.SequenceEqual(Exclusions, Exclusions) && ReferenceSource == other.ReferenceSource; } @@ -81,16 +88,7 @@ public bool Equals(MavenReferenceItem other) /// public override int GetHashCode() { - int hashCode = 1928079503; - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(ItemSpec); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(GroupId); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(ArtifactId); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Classifier); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Version); - hashCode = hashCode * -1521134295 + Optional.GetHashCode(); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Scope); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(ReferenceSource); - return hashCode; + return HashCode.Combine(HashCode.Combine(ItemSpec, GroupId, ArtifactId, Classifier, Version, Optional, Scope, Exclusions), ReferenceSource); } /// diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemExclusion.cs b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemExclusion.cs new file mode 100644 index 0000000..6e9b2fc --- /dev/null +++ b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemExclusion.cs @@ -0,0 +1,75 @@ +using System; + +namespace IKVM.Maven.Sdk.Tasks +{ + + public class MavenReferenceItemExclusion : IEquatable + { + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public MavenReferenceItemExclusion(string groupId, string artifactId, string classifier, string extension) + { + GroupId = groupId ?? throw new ArgumentNullException(nameof(groupId)); + ArtifactId = artifactId ?? throw new ArgumentNullException(nameof(artifactId)); + Classifier = classifier; + Extension = extension; + } + + /// + /// The Maven group ID. Required. + /// + public string GroupId { get; set; } + + /// + /// The Maven artifact ID. Required. + /// + public string ArtifactId { get; set; } + + /// + /// Gets the classifier of the exclusion. + /// + public string Classifier { get; set; } + + /// + /// Gets the extension ID of the exclusion. + /// + public string Extension { get; set; } + + /// + public override bool Equals(object obj) + { + return Equals(obj as MavenReferenceItemExclusion); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(GroupId, ArtifactId, Classifier, Extension); + } + + /// + /// Returns true if the this item is equal to the other item. + /// + /// + /// + public bool Equals(MavenReferenceItemExclusion other) + { + return other is not null && GroupId == other.GroupId && ArtifactId == other.ArtifactId && Classifier == other.Classifier && Extension == other.Extension; + } + + + /// + public override string ToString() + { + return $"{GroupId}:{ArtifactId}"; + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemMetadata.cs b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemMetadata.cs index 54d18e7..856828d 100644 --- a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemMetadata.cs +++ b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemMetadata.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.Build.Framework; @@ -19,6 +20,7 @@ static class MavenReferenceItemMetadata public static readonly string Dependencies = "Dependencies"; public static readonly string Scope = "Scope"; public static readonly string Optional = "Optional"; + public static readonly string Exclusions = "Exclusions"; public static readonly string Debug = "Debug"; public static readonly string ReferenceSource = "ReferenceSource"; @@ -39,6 +41,7 @@ public static void Save(MavenReferenceItem item, ITaskItem task) task.SetMetadata(MavenReferenceItemMetadata.Version, item.Version); task.SetMetadata(MavenReferenceItemMetadata.Optional, item.Optional ? "true" : "false"); task.SetMetadata(MavenReferenceItemMetadata.Scope, item.Scope); + task.SetMetadata(MavenReferenceItemMetadata.Exclusions, string.Join(";", item.Exclusions.Select(i => i.ToString()))); task.SetMetadata(MavenReferenceItemMetadata.ReferenceSource, item.ReferenceSource); } @@ -65,6 +68,7 @@ public static MavenReferenceItem[] Import(IEnumerable tasks) item.Version = task.GetMetadata(MavenReferenceItemMetadata.Version); item.Optional = string.Equals(task.GetMetadata(MavenReferenceItemMetadata.Optional), "true", StringComparison.OrdinalIgnoreCase); item.Scope = task.GetMetadata(MavenReferenceItemMetadata.Scope); + item.Exclusions = task.GetMetadata(MavenReferenceItemMetadata.Exclusions).Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(i => ParseExclusion(i)).Where(i => i != null).ToArray(); item.ReferenceSource = task.GetMetadata(MavenReferenceItemMetadata.ReferenceSource); list.Add(item); } @@ -73,6 +77,26 @@ public static MavenReferenceItem[] Import(IEnumerable tasks) return list.ToArray(); } + /// + /// Parses a compressed exclusion string. + /// + /// + /// + /// + static MavenReferenceItemExclusion ParseExclusion(string value) + { + var a = value.Split(':'); + if (a.Length is 2 or 3 or 4) + { + var groupId = a[0]; + var artifactId = a[1]; + var classifier = a.Length >= 3 ? a[2] : null; + var extension = a.Length >= 4 ? a[3] : null; + return new MavenReferenceItemExclusion(groupId, artifactId, classifier, extension); + } + + return null; + } } } diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemPrepare.cs b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemPrepare.cs index 1959fe0..80360af 100644 --- a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemPrepare.cs +++ b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemPrepare.cs @@ -75,31 +75,31 @@ ITaskItem ToTaskItem(MavenReferenceItem item) void AssignMetadata(MavenReferenceItem item) { if (string.IsNullOrWhiteSpace(item.ItemSpec) == false) - { - var a = item.ItemSpec.Split(':'); - if (a.Length is 2 or 3) { - // itemspec may set various properties - var groupId = a[0]; - var artifactId = a[1]; - var version = a.Length >= 3 ? a[2] : null; - - // if the itemspec is parsable as coordinates, we should attempt to apply or validate metadata - if (string.IsNullOrWhiteSpace(item.GroupId)) - item.GroupId = groupId; - else if (item.GroupId != groupId) - throw new MavenTaskMessageException("Error.MavenInvalidGroupId", item.ItemSpec); - - if (string.IsNullOrWhiteSpace(item.ArtifactId)) - item.ArtifactId = artifactId; - else if (item.ArtifactId != artifactId) - throw new MavenTaskMessageException("Error.MavenInvalidArtifactId", item.ItemSpec); - - if (string.IsNullOrWhiteSpace(item.Version)) - item.Version = version; - else if (version != null && item.Version != version) - throw new MavenTaskMessageException("Error.MavenInvalidVersion", item.ItemSpec); - } + var a = item.ItemSpec.Split(':'); + if (a.Length is 2 or 3) + { + // itemspec may set various properties + var groupId = a[0]; + var artifactId = a[1]; + var version = a.Length >= 3 ? a[2] : null; + + // if the itemspec is parsable as coordinates, we should attempt to apply or validate metadata + if (string.IsNullOrWhiteSpace(item.GroupId)) + item.GroupId = groupId; + else if (item.GroupId != groupId) + throw new MavenTaskMessageException("Error.MavenInvalidGroupId", item.ItemSpec); + + if (string.IsNullOrWhiteSpace(item.ArtifactId)) + item.ArtifactId = artifactId; + else if (item.ArtifactId != artifactId) + throw new MavenTaskMessageException("Error.MavenInvalidArtifactId", item.ItemSpec); + + if (string.IsNullOrWhiteSpace(item.Version)) + item.Version = version; + else if (version != null && item.Version != version) + throw new MavenTaskMessageException("Error.MavenInvalidVersion", item.ItemSpec); + } } if (string.IsNullOrWhiteSpace(item.GroupId)) diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs index 110858c..5924da2 100644 --- a/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs +++ b/src/IKVM.Maven.Sdk.Tasks/MavenReferenceItemResolve.cs @@ -246,7 +246,10 @@ DependencyNode ResolveCompileDependencyGraph(IkvmMavenEnvironment maven, Reposit // convert set of incoming items into a dependency list var dependencies = new Dependency[items.Count]; for (int i = 0; i < items.Count; i++) - dependencies[i] = new Dependency(new DefaultArtifact(items[i].GroupId, items[i].ArtifactId, items[i].Classifier, "jar", items[i].Version), items[i].Scope, items[i].Optional ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE, new java.util.ArrayList()); + { + var exclusions = Arrays.asList(items[i].Exclusions.Select(j => new Exclusion(j.GroupId, j.ArtifactId, j.Classifier, j.Extension)).ToArray()); + dependencies[i] = new Dependency(new DefaultArtifact(items[i].GroupId, items[i].ArtifactId, items[i].Classifier, "jar", items[i].Version), items[i].Scope, items[i].Optional ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE, exclusions); + } // check the cache var root = ResolveCompileDependencyGraphFromCache(maven, dependencies);