How Maven's Legacy Repository Session Extension Works: Bridging Aether and Legacy APIs
Maven's LegacyRepositorySystemSessionExtender bridges the modern Eclipse Aether repository system with Maven's legacy ArtifactRepository API by copying mirror, proxy, and authentication selectors from the Aether session into legacy repository objects during session construction.
Apache Maven 4 uses the Eclipse Aether repository system internally, yet much of its core still depends on the older ArtifactRepository API. The legacy repository session extension mechanism ensures that modern Aether configuration—including mirrors, proxies, and credentials—flows seamlessly into these legacy objects that older plugins and core components expect.
Architecture and Integration Points
The extension sits at the intersection of Maven's modern Aether integration and its historical repository model. When Maven constructs a repository session, it must reconcile the modern selector-based configuration with the legacy object model that the rest of the codebase consumes.
The Aether-to-Legacy Bridge
Maven 4 maintains the ArtifactRepository interface for backward compatibility, but repository resolution now happens through Aether's RepositorySystem. The LegacyRepositorySystemSessionExtender (annotated with @Named and @Singleton in the apache/maven source) implements the RepositorySystemSessionExtender interface to transfer configuration data between these two worlds.
Session Construction Flow
The extension triggers during the session-building phase:
- Maven execution request – A
MavenExecutionRequestcontains the raw list of remote and plugin repositories defined in a POM or settings file. - Aether selectors –
MirrorSelector,ProxySelector, andAuthenticationSelectorare created by the AetherRepositorySystembased on current settings. - Extension invocation – The core session builder (such as
DefaultMavenRepositorySystemSession) looks for a bean implementingRepositorySystemSessionExtenderand invokes itsextendmethod. - Legacy population – After the extender runs, each
ArtifactRepositoryin the request has its mirror, proxy, and authentication fields populated with values derived from the Aether selectors.
The Extension Process: Mirror, Proxy, and Authentication Injection
The extend method in LegacyRepositorySystemSessionExtender.java serves as the central entry point for transforming legacy repository objects. The method signature processes both remote and plugin repositories:
public void extend(
MavenExecutionRequest request,
Map<String, Object> config,
MirrorSelector mirrorSelector,
ProxySelector proxySelector,
AuthenticationSelector authSelector) {
// remote repositories
injectMirror(request.getRemoteRepositories(), request.getMirrors());
injectProxy(proxySelector, request.getRemoteRepositories());
injectAuthentication(authSelector, request.getRemoteRepositories());
// plugin repositories
injectMirror(request.getPluginArtifactRepositories(), request.getMirrors());
injectProxy(proxySelector, request.getPluginArtifactRepositories());
injectAuthentication(authSelector, request.getPluginArtifactRepositories());
}
Mirror Injection via injectMirror
The injectMirror method iterates over each ArtifactRepository, finds the matching Aether Mirror using MavenRepositorySystem.getMirror, and replaces the repository's ID and URL with the mirror's data while preserving the original repository as a mirrored repository entry. This preserves a reference to the pre-mirrored repository for possible later use.
private void injectMirror(ArtifactRepository repo, Mirror mirror) {
if (mirror != null) {
ArtifactRepository original = MavenRepositorySystem.createArtifactRepository(
repo.getId(), repo.getUrl(), repo.getLayout(),
repo.getSnapshots(), repo.getReleases());
repo.setMirroredRepositories(Collections.singletonList(original));
repo.setId(mirror.getId());
repo.setUrl(mirror.getUrl());
repo.setBlocked(mirror.isBlocked());
}
}
Proxy Resolution and Conversion
For proxy configuration, the extender uses ProxySelector to obtain an Aether Proxy object, then converts it into Maven's legacy org.apache.maven.repository.Proxy format. The getProxy method extracts host, protocol, and port, and handles authentication extraction via AuthenticationContext when credentials are present.
private org.apache.maven.repository.Proxy getProxy(ProxySelector selector,
ArtifactRepository repository) {
RemoteRepository repo = RepositoryUtils.toRepo(repository);
org.eclipse.aether.repository.Proxy proxy = selector.getProxy(repo);
if (proxy != null) {
org.apache.maven.repository.Proxy p = new org.apache.maven.repository.Proxy();
p.setHost(proxy.getHost());
p.setProtocol(proxy.getType());
p.setPort(proxy.getPort());
return p;
}
return null;
}
Authentication Extraction
Similarly, AuthenticationSelector provides an Aether Authentication object. The extender converts this into Maven's own Authentication object through the getAuthentication method, extracting the username, password, and optional private-key credentials.
private Authentication getAuthentication(AuthenticationSelector selector,
ArtifactRepository repository) {
RemoteRepository repo = RepositoryUtils.toRepo(repository);
org.eclipse.aether.repository.Authentication auth = selector.getAuthentication(repo);
if (auth != null) {
AuthenticationContext ctx = AuthenticationContext.forRepository(null, repo);
Authentication result = new Authentication(
ctx.get(AuthenticationContext.USERNAME),
ctx.get(AuthenticationContext.PASSWORD));
result.setPrivateKey(ctx.get(AuthenticationContext.PRIVATE_KEY_PATH));
result.setPassphrase(ctx.get(AuthenticationContext.PRIVATE_KEY_PASSPHRASE));
ctx.close();
return result;
}
return null;
}
Key Source Files and Implementation Details
The legacy extension mechanism resides in the following critical files within the apache/maven repository:
impl/maven-core/src/main/java/org/apache/maven/internal/aether/LegacyRepositorySystemSessionExtender.java– The core implementation containingextend,injectMirror,getProxy, andgetAuthenticationmethods.impl/maven-core/src/main/java/org/apache/maven/internal/aether/RepositorySystemSessionExtender.java– The minimal interface defining theextendcontract that the core session builder invokes.impl/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java– Utility class used by the extender for mirror handling and legacy repository instantiation.
Why Maven Maintains This Compatibility Layer
Maven maintains the legacy repository session extension to ensure backward compatibility with plugins and extensions built against the legacy ArtifactRepository API. Rather than rewriting every consumer to understand Aether directly, Maven injects the modern configuration into the legacy objects once, letting existing code keep working while benefitting from the newer selector logic. This approach allows the core to migrate incrementally while preserving the ecosystem of existing plugins.
Summary
- LegacyRepositorySystemSessionExtender acts as the bridge between Eclipse Aether and Maven's legacy
ArtifactRepositoryAPI. - The extension copies mirror, proxy, and authentication configuration from Aether selectors into legacy repository objects during session construction.
- The process happens transparently in
DefaultMavenRepositorySystemSessionbefore artifact resolution begins. - Key methods include
extendfor orchestration,injectMirrorfor URL replacement, andgetAuthenticationfor credential transfer. - This mechanism preserves backward compatibility with thousands of existing Maven plugins while enabling modern Aether features.
Frequently Asked Questions
What is the purpose of LegacyRepositorySystemSessionExtender in Maven?
The LegacyRepositorySystemSessionExtender ensures that modern Eclipse Aether configuration (mirrors, proxies, and authentication) is available to Maven's legacy ArtifactRepository objects. It translates the modern selector-based repository system into the legacy object model that older Maven components and plugins expect, allowing Maven 4 to maintain backward compatibility while using Aether internally.
How does Maven map Aether mirrors to legacy ArtifactRepository objects?
The extender's injectMirror method uses MavenRepositorySystem.getMirror to find the matching Aether mirror for each repository. It then replaces the repository's ID and URL with the mirror's values while storing the original repository in the mirroredRepositories list. This allows the legacy system to resolve artifacts through the mirror while maintaining a reference to the original repository.
Where does the legacy repository session extension fit in Maven's startup sequence?
The extension occurs during session construction, specifically within DefaultMavenRepositorySystemSession or similar session builders. After the Aether RepositorySystem creates the MirrorSelector, ProxySelector, and AuthenticationSelector, the core invokes the RepositorySystemSessionExtender.extend() method to populate the MavenExecutionRequest's repository lists before artifact resolution begins.
Can plugins interact with the RepositorySystemSessionExtender directly?
No, plugins typically do not interact with the RepositorySystemSessionExtender directly. The interface is an internal SPI (Service Provider Interface) marked with @Named and @Singleton for dependency injection. Maven's core session builder automatically invokes the extender during initialization, ensuring that by the time plugin code executes, all ArtifactRepository objects already contain the correct mirror, proxy, and authentication configuration.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →