Skip to content

Commit

Permalink
AuthenticationSelector isn't used for explicitely specified servers, …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
wasabii committed Dec 14, 2023
1 parent 649e763 commit 7c2842b
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 6 deletions.
40 changes: 40 additions & 0 deletions src/IKVM.Maven.Sdk.Tasks.Tests/MavenReferenceItemResolveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ static ITaskItem GetLocalRepositoryItem()
return item;
}

/// <summary>
/// Creates a task item for the local repository.
/// </summary>
/// <returns></returns>
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]
Expand Down Expand Up @@ -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<IBuildEngine>();
// var errors = new List<BuildErrorEventArgs>();
// engine.Setup(x => x.LogErrorEvent(It.IsAny<BuildErrorEventArgs>())).Callback((BuildErrorEventArgs e) => { errors.Add(e); TestContext.WriteLine("ERROR: " + e.Message); });
// engine.Setup(x => x.LogWarningEvent(It.IsAny<BuildWarningEventArgs>())).Callback((BuildWarningEventArgs e) => TestContext.WriteLine("WARNING: " + e.Message));
// engine.Setup(x => x.LogMessageEvent(It.IsAny<BuildMessageEventArgs>())).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");
//}

}

}
29 changes: 29 additions & 0 deletions src/IKVM.Maven.Sdk.Tasks/Extensions/IterableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Collections.Generic;

using java.lang;

namespace IKVM.Maven.Sdk.Tasks.Extensions
{

/// <summary>
/// Provides extension methods for working against Java <see cref="Iterable"/> instances.
/// </summary>
public static class IterableExtensions
{

/// <summary>
/// Returns the appropriate wrapper type for the given <see cref="Iterable"/>.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="iterable"></param>
/// <returns></returns>
public static IEnumerable<T> AsEnumerable<T>(this Iterable iterable)
{
var e = iterable.iterator().AsEnumerator<T>();
while (e.MoveNext())
yield return e.Current;
}

}

}
55 changes: 55 additions & 0 deletions src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Collections.Generic;

using java.util;

namespace IKVM.Maven.Sdk.Tasks.Extensions
{

/// <summary>
/// Provides extension methods for working against Java <see cref="Iterator"/> instances.
/// </summary>
public static class IteratorExtensions
{

/// <summary>
/// Returns the appropriate wrapper type for the given <see cref="Iterator"/>.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="iterator"></param>
/// <returns></returns>
public static IEnumerator<T> AsEnumerator<T>(this Iterator iterator) => iterator switch
{
IEnumerator<T> i => i,
Iterator i => new IteratorWrapper<T>(i),
};

/// <summary>
/// Iterators over the items in an iterator and produces an array.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="iterator"></param>
/// <returns></returns>
public static List<T> RemainingToList<T>(this Iterator iterator)
{
var l = new List<T>();
while (iterator.hasNext())
l.Add((T)iterator.next());

return l;
}

/// <summary>
/// Returns an enumerable that iterators over the items in an iterator.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="iterator"></param>
/// <returns></returns>
public static IEnumerable<T> RemainingToEnumerable<T>(this Iterator iterator)
{
while (iterator.hasNext())
yield return (T)iterator.next();
}

}

}
72 changes: 72 additions & 0 deletions src/IKVM.Maven.Sdk.Tasks/Extensions/IteratorWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections;
using System.Collections.Generic;

using java.util;

namespace IKVM.Maven.Sdk.Tasks.Extensions
{

class IteratorWrapper<T> : IEnumerator<T>
{

readonly Iterator iterator;
T current;
int position = -1;

/// <summary>
/// Initializes a new instance.
/// </summary>
/// <param name="iterator"></param>
/// <exception cref="ArgumentNullException"></exception>
public IteratorWrapper(Iterator iterator)
{
this.iterator = iterator ?? throw new ArgumentNullException(nameof(iterator));
}

/// <summary>
/// Gets the current element.
/// </summary>
public T Current => position > -1 ? current : throw new InvalidOperationException();

/// <summary>
/// Gets the current element.
/// </summary>
object IEnumerator.Current => current;

/// <summary>
/// Moves to the next instance.
/// </summary>
/// <returns></returns>
public bool MoveNext()
{
if (iterator.hasNext())
{
current = (T)iterator.next();
position++;
return true;
}

return false;
}

/// <summary>
/// Disposes of the instance.
/// </summary>
public void Dispose()
{

}

/// <summary>
/// Not supported.
/// </summary>
/// <exception cref="NotSupportedException"></exception>
public void Reset()
{
throw new NotSupportedException();
}

}

}
69 changes: 63 additions & 6 deletions src/IKVM.Maven.Sdk.Tasks/MavenEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -116,7 +118,7 @@ public IkvmMavenEnvironment(IList<MavenRepositoryItem> 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);
}

/// <summary>
Expand Down Expand Up @@ -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());
}

Expand All @@ -273,12 +282,60 @@ public RepositorySystemSession CreateRepositorySystemSession(bool noError = fals
}

/// <summary>
/// Creates a new <see cref="ArtifactRepository"/> representing Maven Central.
/// Creates the set of remote repositories, along with any specified imported repositories.
/// </summary>
/// <param name="import"></param>
/// <param name="log"></param>
/// <returns></returns>
ArtifactRepository CreateRepository(MavenRepositoryItem repository)
List CreateRemoteRepositories(IList<MavenRepositoryItem> import, TaskLoggingHelper log)
{
return new RemoteRepository.Builder(repository.Id, DefaultRepositoryType, repository.Url).build();
var map = new Dictionary<string, RemoteRepository.Builder>();

// import user profile repositories
foreach (var repository in settings.getActiveProfiles().AsEnumerable<Profile>().SelectMany(i => i.getRepositories().AsEnumerable<Repository>()))
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<Profile>().SelectMany(i => i.getRepositories().AsEnumerable<Repository>()))
{
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<Server>())
{
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());
}

}
Expand Down

0 comments on commit 7c2842b

Please sign in to comment.