From 7c2842b12d6c9482dbdc81ff462e981bf53b9fdc Mon Sep 17 00:00:00 2001 From: Jerome Haltom Date: Thu, 14 Dec 2023 10:51:56 -0600 Subject: [PATCH] AuthenticationSelector isn't used for explicitely specified servers, but only for dynamically resolved servers from remote POMs. Instead, we have to merge in settings files directly to Repository.Builders. So, we do that. We also merge in policies defined in settings. We overlay these so ultimately MSBuild settings overwrite settings. --- .../MavenReferenceItemResolveTests.cs | 40 +++++++++++ .../Extensions/IterableExtensions.cs | 29 ++++++++ .../Extensions/IteratorExtensions.cs | 55 ++++++++++++++ .../Extensions/IteratorWrapper.cs | 72 +++++++++++++++++++ src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs | 69 ++++++++++++++++-- 5 files changed, 259 insertions(+), 6 deletions(-) create mode 100644 src/IKVM.Maven.Sdk.Tasks/Extensions/IterableExtensions.cs create mode 100644 src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorExtensions.cs create mode 100644 src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorWrapper.cs diff --git a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs index 1539b07..05127d0 100644 --- a/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs +++ b/src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs @@ -39,6 +39,17 @@ static ITaskItem GetLocalRepositoryItem() return item; } + /// + /// Creates a task item for the local repository. + /// + /// + static ITaskItem GetPrivateRepositoryItem() + { + var item = new TaskItem("github"); + item.SetMetadata("Url", "https://maven.pkg.github.com/ikvmnet/*"); + return item; + } + public TestContext TestContext { get; set; } [TestMethod] @@ -534,6 +545,35 @@ public void CanResolveFromLocalRepository() t.ResolvedReferences.Should().Contain(i => i.ItemSpec == "maven$hellotest:hellotest:1.0"); } + // TODO, need to set up some sort of local repository resolution or something to run this test + // + //[TestMethod] + //public void CanResolveFromPrivateRepository() + //{ + // 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(), GetPrivateRepositoryItem() }; + + // var i1 = new TaskItem("hellotest:hellotest:1.0"); + // i1.SetMetadata(MavenReferenceItemMetadata.GroupId, "hellotest"); + // i1.SetMetadata(MavenReferenceItemMetadata.ArtifactId, "hellotest"); + // i1.SetMetadata(MavenReferenceItemMetadata.Version, "1.0"); + // i1.SetMetadata(MavenReferenceItemMetadata.Scope, "compile"); + // t.References = new[] { i1 }; + + // t.Execute().Should().BeTrue(); + // errors.Should().BeEmpty(); + // t.ResolvedReferences.Should().Contain(i => i.ItemSpec == "maven$hellotest:hellotest:1.0"); + //} + } } diff --git a/src/IKVM.Maven.Sdk.Tasks/Extensions/IterableExtensions.cs b/src/IKVM.Maven.Sdk.Tasks/Extensions/IterableExtensions.cs new file mode 100644 index 0000000..2eb6eb8 --- /dev/null +++ b/src/IKVM.Maven.Sdk.Tasks/Extensions/IterableExtensions.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +using java.lang; + +namespace IKVM.Maven.Sdk.Tasks.Extensions +{ + + /// + /// Provides extension methods for working against Java instances. + /// + public static class IterableExtensions + { + + /// + /// Returns the appropriate wrapper type for the given . + /// + /// + /// + /// + public static IEnumerable AsEnumerable(this Iterable iterable) + { + var e = iterable.iterator().AsEnumerator(); + while (e.MoveNext()) + yield return e.Current; + } + + } + +} diff --git a/src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorExtensions.cs b/src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorExtensions.cs new file mode 100644 index 0000000..e03b7d8 --- /dev/null +++ b/src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorExtensions.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; + +using java.util; + +namespace IKVM.Maven.Sdk.Tasks.Extensions +{ + + /// + /// Provides extension methods for working against Java instances. + /// + public static class IteratorExtensions + { + + /// + /// Returns the appropriate wrapper type for the given . + /// + /// + /// + /// + public static IEnumerator AsEnumerator(this Iterator iterator) => iterator switch + { + IEnumerator i => i, + Iterator i => new IteratorWrapper(i), + }; + + /// + /// Iterators over the items in an iterator and produces an array. + /// + /// + /// + /// + public static List RemainingToList(this Iterator iterator) + { + var l = new List(); + while (iterator.hasNext()) + l.Add((T)iterator.next()); + + return l; + } + + /// + /// Returns an enumerable that iterators over the items in an iterator. + /// + /// + /// + /// + public static IEnumerable RemainingToEnumerable(this Iterator iterator) + { + while (iterator.hasNext()) + yield return (T)iterator.next(); + } + + } + +} diff --git a/src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorWrapper.cs b/src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorWrapper.cs new file mode 100644 index 0000000..868a826 --- /dev/null +++ b/src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorWrapper.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +using java.util; + +namespace IKVM.Maven.Sdk.Tasks.Extensions +{ + + class IteratorWrapper : IEnumerator + { + + readonly Iterator iterator; + T current; + int position = -1; + + /// + /// Initializes a new instance. + /// + /// + /// + public IteratorWrapper(Iterator iterator) + { + this.iterator = iterator ?? throw new ArgumentNullException(nameof(iterator)); + } + + /// + /// Gets the current element. + /// + public T Current => position > -1 ? current : throw new InvalidOperationException(); + + /// + /// Gets the current element. + /// + object IEnumerator.Current => current; + + /// + /// Moves to the next instance. + /// + /// + public bool MoveNext() + { + if (iterator.hasNext()) + { + current = (T)iterator.next(); + position++; + return true; + } + + return false; + } + + /// + /// Disposes of the instance. + /// + public void Dispose() + { + + } + + /// + /// Not supported. + /// + /// + public void Reset() + { + throw new NotSupportedException(); + } + + } + +} diff --git a/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs b/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs index cc975c4..c27d5b7 100644 --- a/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs +++ b/src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; +using IKVM.Maven.Sdk.Tasks.Extensions; + using java.io; using java.lang; using java.util; @@ -116,7 +118,7 @@ public IkvmMavenEnvironment(IList repositories, TaskLogging this.repositoryPath = DefaultRepositoryPath; this.settings = ReadSettings() ?? throw new NullReferenceException("Null result reading Settings."); this.repositorySystem = CreateRepositorySystem() ?? throw new NullReferenceException("Null result creating RepositorySystem."); - this.repositories = Arrays.asList(repositories.Select(i => CreateRepository(i)).ToArray()); + this.repositories = CreateRemoteRepositories(repositories, log); } /// @@ -244,9 +246,16 @@ AuthenticationSelector CreateAuthenticationSelector() foreach (Server server in (IEnumerable)settings.getServers()) { + // build authentication information from server record var builder = new AuthenticationBuilder(); - builder.addUsername(server.getUsername()).addPassword(server.getPassword()); - builder.addPrivateKey(server.getPrivateKey(), server.getPassphrase()); + if (server.getUsername() is string username) + builder.addUsername(username); + if (server.getPassword() is string password) + builder.addPassword(password); + if (server.getPrivateKey() is string privateKey) + builder.addPrivateKey(privateKey, server.getPassphrase()); + + // add server to selector selector.add(server.getId(), builder.build()); } @@ -273,12 +282,60 @@ public RepositorySystemSession CreateRepositorySystemSession(bool noError = fals } /// - /// Creates a new representing Maven Central. + /// Creates the set of remote repositories, along with any specified imported repositories. /// + /// + /// /// - ArtifactRepository CreateRepository(MavenRepositoryItem repository) + List CreateRemoteRepositories(IList import, TaskLoggingHelper log) { - return new RemoteRepository.Builder(repository.Id, DefaultRepositoryType, repository.Url).build(); + var map = new Dictionary(); + + // import user profile repositories + foreach (var repository in settings.getActiveProfiles().AsEnumerable().SelectMany(i => i.getRepositories().AsEnumerable())) + if (map.ContainsKey(repository.getId()) == false) + map[repository.getId()] = new RemoteRepository.Builder(repository.getId(), DefaultRepositoryType, repository.getUrl()); + + // override repository from imports + foreach (var repository in import) + map[repository.Id] = new RemoteRepository.Builder(repository.Id, DefaultRepositoryType, repository.Url); + + // merge profile settings + foreach (var repository in settings.getActiveProfiles().AsEnumerable().SelectMany(i => i.getRepositories().AsEnumerable())) + { + if (map.TryGetValue(repository.getId(), out var r) == false) + continue; + + var policy = repository.getReleases(); + if (policy != null) + r.setPolicy(new org.eclipse.aether.repository.RepositoryPolicy(policy.isEnabled(), policy.getUpdatePolicy(), policy.getChecksumPolicy())); + + var snapshots = repository.getSnapshots(); + if (snapshots != null) + r.setSnapshotPolicy(new org.eclipse.aether.repository.RepositoryPolicy(snapshots.isEnabled(), snapshots.getUpdatePolicy(), snapshots.getChecksumPolicy())); + } + + // merge server settings + foreach (var server in settings.getServers().AsEnumerable()) + { + if (map.TryGetValue(server.getId(), out var r) == false) + continue; + + // build authentication information from server record + var builder = new AuthenticationBuilder(); + if (server.getUsername() is string username) + builder.addUsername(username); + if (server.getPassword() is string password) + builder.addPassword(password); + if (server.getPrivateKey() is string privateKey) + builder.addPrivateKey(privateKey, server.getPassphrase()); + + // set authentication on repository + r.setAuthentication(builder.build()); + } + + // build final list of repositories + return Arrays.asList(map.Values.Select(i => i.build()).ToArray()); } }