# How Maven's Legacy Repository Session Extension Works: Bridging Aether and Legacy APIs

> Understand how Maven's Legacy Repository Session Extension bridges Aether and legacy APIs. Learn how mirror, proxy, and authentication selectors are copied.

- Repository: [The Apache Software Foundation/maven](https://github.com/apache/maven)
- Tags: internals
- Published: 2026-07-05

---

**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:

1. **Maven execution request** – A `MavenExecutionRequest` contains the raw list of remote and plugin repositories defined in a POM or settings file.
2. **Aether selectors** – `MirrorSelector`, `ProxySelector`, and `AuthenticationSelector` are created by the Aether `RepositorySystem` based on current settings.
3. **Extension invocation** – The core session builder (such as `DefaultMavenRepositorySystemSession`) looks for a bean implementing `RepositorySystemSessionExtender` and invokes its `extend` method.
4. **Legacy population** – After the extender runs, each `ArtifactRepository` in 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`](https://github.com/apache/maven/blob/main/LegacyRepositorySystemSessionExtender.java) serves as the central entry point for transforming legacy repository objects. The method signature processes both remote and plugin repositories:

```java
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.

```java
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.

```java
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.

```java
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`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/internal/aether/LegacyRepositorySystemSessionExtender.java)** – The core implementation containing `extend`, `injectMirror`, `getProxy`, and `getAuthentication` methods.
- **[`impl/maven-core/src/main/java/org/apache/maven/internal/aether/RepositorySystemSessionExtender.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/internal/aether/RepositorySystemSessionExtender.java)** – The minimal interface defining the `extend` contract that the core session builder invokes.
- **[`impl/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java`](https://github.com/apache/maven/blob/main/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 `ArtifactRepository` API.
- The extension copies **mirror**, **proxy**, and **authentication** configuration from Aether selectors into legacy repository objects during session construction.
- The process happens transparently in `DefaultMavenRepositorySystemSession` before artifact resolution begins.
- Key methods include `extend` for orchestration, `injectMirror` for URL replacement, and `getAuthentication` for 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.