From 69948fd83d7a2d99ac8c0f7d8e20d62b2a36cf8a Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Fri, 13 Feb 2026 13:52:06 +0100 Subject: [PATCH 1/5] Experiment: Maven 3.9.x + Resolver 2.x --- apache-maven/pom.xml | 2 +- .../repository/metadata/MetadataBridge.java | 9 +++ .../project/ClasspathArtifactResolver.java | 2 +- maven-embedder/pom.xml | 1 + maven-resolver-provider/pom.xml | 6 +- .../repository/internal/MavenMetadata.java | 8 ++ .../internal/MavenRepositorySystemUtils.java | 26 +------ .../internal/MavenResolverModule.java | 77 ------------------- .../MavenRepositorySystemUtilsTest.java | 11 ++- pom.xml | 10 ++- 10 files changed, 40 insertions(+), 112 deletions(-) delete mode 100644 maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenResolverModule.java diff --git a/apache-maven/pom.xml b/apache-maven/pom.xml index c576385affe2..5a444a75cd10 100644 --- a/apache-maven/pom.xml +++ b/apache-maven/pom.xml @@ -82,7 +82,7 @@ under the License. org.apache.maven.resolver - maven-resolver-transport-http + maven-resolver-transport-apache org.apache.maven.resolver diff --git a/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/MetadataBridge.java b/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/MetadataBridge.java index fbe682a05282..57ea0a2d9511 100644 --- a/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/MetadataBridge.java +++ b/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/MetadataBridge.java @@ -19,6 +19,7 @@ package org.apache.maven.artifact.repository.metadata; import java.io.File; +import java.nio.file.Path; import java.util.Collections; import java.util.Map; @@ -92,6 +93,14 @@ public MetadataBridge setFile(File file) { return this; } + public Path getPath() { + return null; + } + + public MetadataBridge setPath(Path file) { + return this; + } + public Nature getNature() { if (metadata instanceof RepositoryMetadata) { switch (((RepositoryMetadata) metadata).getNature()) { diff --git a/maven-compat/src/test/java/org/apache/maven/project/ClasspathArtifactResolver.java b/maven-compat/src/test/java/org/apache/maven/project/ClasspathArtifactResolver.java index 75bb6f17df06..54aa11984da9 100644 --- a/maven-compat/src/test/java/org/apache/maven/project/ClasspathArtifactResolver.java +++ b/maven-compat/src/test/java/org/apache/maven/project/ClasspathArtifactResolver.java @@ -61,7 +61,7 @@ public List resolveArtifacts( throw new IllegalStateException("Missing test POM for " + artifact, e); } } else { - result.addException(new ArtifactNotFoundException(artifact, null)); + result.addException(new ArtifactNotFoundException(artifact, "not found")); throw new ArtifactResolutionException(results); } } diff --git a/maven-embedder/pom.xml b/maven-embedder/pom.xml index 4a05e5641dca..323cce15fde3 100644 --- a/maven-embedder/pom.xml +++ b/maven-embedder/pom.xml @@ -139,6 +139,7 @@ under the License. logback-classic true + commons-cli diff --git a/maven-resolver-provider/pom.xml b/maven-resolver-provider/pom.xml index bc4a32412f3a..067128065a07 100644 --- a/maven-resolver-provider/pom.xml +++ b/maven-resolver-provider/pom.xml @@ -60,6 +60,10 @@ under the License. org.apache.maven.resolver maven-resolver-impl + + org.apache.maven.resolver + maven-resolver-supplier-mvn3 + org.codehaus.plexus plexus-utils @@ -107,7 +111,7 @@ under the License. org.apache.maven.resolver - maven-resolver-transport-http + maven-resolver-transport-apache test diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java index 63c49d5a399e..6588b32fa526 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.Reader; import java.io.Writer; +import java.nio.file.Path; import java.util.Collections; import java.util.Date; import java.util.Map; @@ -67,6 +68,13 @@ public File getFile() { return file; } + public Path getPath() { + if (file != null) { + return file.toPath(); + } + return null; + } + @Override public void merge(File existing, File result) throws RepositoryException { Metadata recessive = read(existing); diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java index 26fc96b68f9b..5d4c792f011b 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java @@ -24,11 +24,6 @@ import org.eclipse.aether.collection.DependencyManager; import org.eclipse.aether.collection.DependencySelector; import org.eclipse.aether.collection.DependencyTraverser; -import org.eclipse.aether.impl.ArtifactDescriptorReader; -import org.eclipse.aether.impl.DefaultServiceLocator; -import org.eclipse.aether.impl.MetadataGeneratorFactory; -import org.eclipse.aether.impl.VersionRangeResolver; -import org.eclipse.aether.impl.VersionResolver; import org.eclipse.aether.util.artifact.DefaultArtifactTypeRegistry; import org.eclipse.aether.util.graph.manager.ClassicDependencyManager; import org.eclipse.aether.util.graph.selector.AndDependencySelector; @@ -58,25 +53,6 @@ private MavenRepositorySystemUtils() { // hide constructor } - /** - * Creates a new service locator that already knows about all service implementations included in this library. To - * acquire a complete repository system, clients need to add some repository connectors for remote transfers. - * - * @return The new service locator, never {@code null}. - * @deprecated This method is deprecated along with {@link DefaultServiceLocator} (since Maven Resolver 1.7.0). - */ - @Deprecated - public static DefaultServiceLocator newServiceLocator() { - DefaultServiceLocator locator = new DefaultServiceLocator(); - locator.addService(ArtifactDescriptorReader.class, DefaultArtifactDescriptorReader.class); - locator.addService(VersionResolver.class, DefaultVersionResolver.class); - locator.addService(VersionRangeResolver.class, DefaultVersionRangeResolver.class); - locator.addService(MetadataGeneratorFactory.class, SnapshotMetadataGeneratorFactory.class); - locator.addService(MetadataGeneratorFactory.class, VersionsMetadataGeneratorFactory.class); - locator.addService(ModelCacheFactory.class, DefaultModelCacheFactory.class); - return locator; - } - /** * Creates a new Maven-like repository system session by initializing the session with values typical for * Maven-based resolution. In more detail, this method configures settings relevant for the processing of dependency @@ -84,7 +60,9 @@ public static DefaultServiceLocator newServiceLocator() { * the session with authentication, mirror, proxy and other information required for your environment. * * @return The new repository system session, never {@code null}. + * @deprecated Use {@link org.eclipse.aether.supplier.SessionBuilderSupplier} instead. */ + @Deprecated public static DefaultRepositorySystemSession newSession() { DefaultRepositorySystemSession session = new DefaultRepositorySystemSession(); diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenResolverModule.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenResolverModule.java deleted file mode 100644 index ec8caf6bc7f1..000000000000 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenResolverModule.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.maven.repository.internal; - -import javax.inject.Named; -import javax.inject.Singleton; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import com.google.inject.AbstractModule; -import com.google.inject.Provides; -import com.google.inject.name.Names; -import org.apache.maven.model.building.DefaultModelBuilderFactory; -import org.apache.maven.model.building.ModelBuilder; -import org.eclipse.aether.impl.ArtifactDescriptorReader; -import org.eclipse.aether.impl.MetadataGeneratorFactory; -import org.eclipse.aether.impl.VersionRangeResolver; -import org.eclipse.aether.impl.VersionResolver; -import org.eclipse.aether.impl.guice.AetherModule; - -/** - * MavenResolverModule - */ -@Deprecated -public final class MavenResolverModule extends AbstractModule { - - @Override - protected void configure() { - install(new AetherModule()); - bind(ArtifactDescriptorReader.class) - .to(DefaultArtifactDescriptorReader.class) - .in(Singleton.class); - bind(VersionResolver.class).to(DefaultVersionResolver.class).in(Singleton.class); - bind(VersionRangeResolver.class).to(DefaultVersionRangeResolver.class).in(Singleton.class); - bind(MetadataGeneratorFactory.class) - .annotatedWith(Names.named("snapshot")) - .to(SnapshotMetadataGeneratorFactory.class) - .in(Singleton.class); - - bind(MetadataGeneratorFactory.class) - .annotatedWith(Names.named("versions")) - .to(VersionsMetadataGeneratorFactory.class) - .in(Singleton.class); - - bind(ModelBuilder.class).toInstance(new DefaultModelBuilderFactory().newInstance()); - bind(ModelCacheFactory.class).to(DefaultModelCacheFactory.class).in(Singleton.class); - } - - @Provides - @Singleton - Set provideMetadataGeneratorFactories( - @Named("snapshot") MetadataGeneratorFactory snapshot, - @Named("versions") MetadataGeneratorFactory versions) { - Set factories = new HashSet<>(2); - factories.add(snapshot); - factories.add(versions); - return Collections.unmodifiableSet(factories); - } -} diff --git a/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/MavenRepositorySystemUtilsTest.java b/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/MavenRepositorySystemUtilsTest.java index f8ce8ee47724..f0d578cd115e 100644 --- a/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/MavenRepositorySystemUtilsTest.java +++ b/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/MavenRepositorySystemUtilsTest.java @@ -19,8 +19,7 @@ package org.apache.maven.repository.internal; import org.eclipse.aether.RepositorySystem; -import org.eclipse.aether.impl.MetadataGeneratorFactory; -import org.eclipse.aether.spi.locator.ServiceLocator; +import org.eclipse.aether.supplier.RepositorySystemSupplier; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -30,14 +29,14 @@ public class MavenRepositorySystemUtilsTest { @Test public void testGetRepositorySystem() { - ServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); - RepositorySystem repoSys = locator.getService(RepositorySystem.class); + RepositorySystem repoSys = new RepositorySystemSupplier().get(); assertNotNull(repoSys); } @Test public void testGetMetadataGeneratorFactories() { - ServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); - assertEquals(2, locator.getServices(MetadataGeneratorFactory.class).size()); + assertEquals( + 3, + new RepositorySystemSupplier().getMetadataGeneratorFactories().size()); } } diff --git a/pom.xml b/pom.xml index 1fc43f1c7a26..a040a01116c9 100644 --- a/pom.xml +++ b/pom.xml @@ -143,7 +143,7 @@ under the License. 2.0 2.0 1.4.0 - 1.9.25 + 2.0.15 1.7.36 2.11.0 2.0.9 @@ -404,6 +404,11 @@ under the License. maven-resolver-impl ${resolverVersion} + + org.apache.maven.resolver + maven-resolver-supplier-mvn3 + ${resolverVersion} + org.apache.maven.resolver maven-resolver-util @@ -421,7 +426,7 @@ under the License. org.apache.maven.resolver - maven-resolver-transport-http + maven-resolver-transport-apache ${resolverVersion} @@ -530,6 +535,7 @@ under the License. org.codehaus.modello modello-maven-plugin + 2.6.0 modello-site-docs From 010e967803dd2d95c349fddc018cde06ca7892ae Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Fri, 13 Feb 2026 16:27:38 +0100 Subject: [PATCH 2/5] Integrate proper Resolver 2.x --- .../java/org/apache/maven/DefaultMaven.java | 13 +- ...DefaultRepositorySystemSessionFactory.java | 131 ++++++++++-------- .../internal/aether/ResolverLifecycle.java | 2 +- .../java/org/apache/maven/cli/MavenCli.java | 84 +++++++++-- .../BootstrapCoreExtensionManager.java | 10 +- .../internal/MavenRepositorySystemUtils.java | 12 ++ 6 files changed, 169 insertions(+), 83 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java index f4e3559b52b1..f204586bebc0 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -162,15 +162,16 @@ private MavenExecutionResult doExecute(MavenExecutionRequest request) { // so that @SessionScoped components can be @Injected into AbstractLifecycleParticipants. // sessionScope.enter(); - try { - DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession(request); - MavenSession session = new MavenSession(container, repoSession, request, result); + try (RepositorySystemSession.CloseableSession repoSession = newRepositorySession(request)) { + DefaultRepositorySystemSession mutableSession = new DefaultRepositorySystemSession(repoSession); + MavenSession session = new MavenSession(container, mutableSession, request, result); + sessionScope.seed(RepositorySystemSession.class, mutableSession); sessionScope.seed(MavenSession.class, session); legacySupport.setSession(session); - return doExecute(request, session, result, repoSession); + return doExecute(request, session, result, mutableSession); } finally { sessionScope.exit(); } @@ -308,8 +309,8 @@ private void afterSessionEnd(Collection projects, MavenSession ses } } - public RepositorySystemSession newRepositorySession(MavenExecutionRequest request) { - return repositorySessionFactory.newRepositorySession(request); + public RepositorySystemSession.CloseableSession newRepositorySession(MavenExecutionRequest request) { + return repositorySessionFactory.newRepositorySession(request).build(); } private void validateLocalRepository(MavenExecutionRequest request) throws LocalRepositoryNotAccessibleException { diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index bcdf438db2ec..15d6ca5c6e6c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -21,6 +21,7 @@ import javax.inject.Inject; import javax.inject.Named; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -50,8 +51,8 @@ import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.eclipse.aether.ConfigurationProperties; -import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepositoryManager; import org.eclipse.aether.repository.RepositoryPolicy; @@ -115,15 +116,15 @@ public class DefaultRepositorySystemSessionFactory { private static final String MAVEN_RESOLVER_TRANSPORT_WAGON = "wagon"; - private static final String MAVEN_RESOLVER_TRANSPORT_NATIVE = "native"; + private static final String MAVEN_RESOLVER_TRANSPORT_APACHE = "native"; private static final String MAVEN_RESOLVER_TRANSPORT_AUTO = "auto"; private static final String WAGON_TRANSPORTER_PRIORITY_KEY = "aether.priority.WagonTransporterFactory"; - private static final String NATIVE_HTTP_TRANSPORTER_PRIORITY_KEY = "aether.priority.HttpTransporterFactory"; + private static final String APACHE_HTTP_TRANSPORTER_PRIORITY_KEY = "aether.priority.ApacheTransporterFactory"; - private static final String NATIVE_FILE_TRANSPORTER_PRIORITY_KEY = "aether.priority.FileTransporterFactory"; + private static final String FILE_TRANSPORTER_PRIORITY_KEY = "aether.priority.FileTransporterFactory"; private static final String RESOLVER_MAX_PRIORITY = String.valueOf(Float.MAX_VALUE); @@ -154,10 +155,9 @@ public class DefaultRepositorySystemSessionFactory { private RuntimeInformation runtimeInformation; @SuppressWarnings("checkstyle:methodlength") - public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest request) { - DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); - - session.setCache(request.getRepositoryCache()); + public RepositorySystemSession.SessionBuilder newRepositorySession(MavenExecutionRequest request) { + RepositorySystemSession.SessionBuilder mainSessionBuilder = MavenRepositorySystemUtils.newSession(repoSystem); + mainSessionBuilder.setCache(request.getRepositoryCache()); Map configProps = new LinkedHashMap<>(); configProps.put(ConfigurationProperties.USER_AGENT, getUserAgent()); @@ -169,14 +169,14 @@ public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest configProps.putAll(request.getSystemProperties()); configProps.putAll(request.getUserProperties()); - session.setOffline(request.isOffline()); - session.setChecksumPolicy(request.getGlobalChecksumPolicy()); + mainSessionBuilder.setOffline(request.isOffline()); + mainSessionBuilder.setChecksumPolicy(request.getGlobalChecksumPolicy()); if (request.isNoSnapshotUpdates()) { - session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_NEVER); + mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_NEVER); } else if (request.isUpdateSnapshots()) { - session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); } else { - session.setUpdatePolicy(null); + mainSessionBuilder.setUpdatePolicy(null); } int errorPolicy = 0; @@ -186,15 +186,15 @@ public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest errorPolicy |= request.isCacheTransferError() ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR : ResolutionErrorPolicy.CACHE_DISABLED; - session.setResolutionErrorPolicy( + mainSessionBuilder.setResolutionErrorPolicy( new SimpleResolutionErrorPolicy(errorPolicy, errorPolicy | ResolutionErrorPolicy.CACHE_NOT_FOUND)); - session.setArtifactTypeRegistry(RepositoryUtils.newArtifactTypeRegistry(artifactHandlerManager)); + mainSessionBuilder.setArtifactTypeRegistry(RepositoryUtils.newArtifactTypeRegistry(artifactHandlerManager)); if (request.getWorkspaceReader() != null) { - session.setWorkspaceReader(request.getWorkspaceReader()); + mainSessionBuilder.setWorkspaceReader(request.getWorkspaceReader()); } else { - session.setWorkspaceReader(workspaceRepository); + mainSessionBuilder.setWorkspaceReader(workspaceRepository); } DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest(); @@ -219,7 +219,7 @@ public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest mirror.getMirrorOf(), mirror.getMirrorOfLayouts()); } - session.setMirrorSelector(mirrorSelector); + mainSessionBuilder.setMirrorSelector(mirrorSelector); DefaultProxySelector proxySelector = new DefaultProxySelector(); for (Proxy proxy : decrypted.getProxies()) { @@ -230,7 +230,7 @@ public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest proxy.getProtocol(), proxy.getHost(), proxy.getPort(), authBuilder.build()), proxy.getNonProxyHosts()); } - session.setProxySelector(proxySelector); + mainSessionBuilder.setProxySelector(proxySelector); DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector(); for (Server server : decrypted.getServers()) { @@ -324,102 +324,111 @@ public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest configProps.put("aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions()); configProps.put("aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions()); } - session.setAuthenticationSelector(authSelector); + mainSessionBuilder.setAuthenticationSelector(authSelector); Object transport = configProps.getOrDefault(MAVEN_RESOLVER_TRANSPORT_KEY, MAVEN_RESOLVER_TRANSPORT_DEFAULT); if (MAVEN_RESOLVER_TRANSPORT_DEFAULT.equals(transport)) { // The "default" mode (user did not set anything) from now on defaults to AUTO - } else if (MAVEN_RESOLVER_TRANSPORT_NATIVE.equals(transport)) { + } else if (MAVEN_RESOLVER_TRANSPORT_APACHE.equals(transport)) { // Make sure (whatever extra priority is set) that resolver native is selected - configProps.put(NATIVE_FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); - configProps.put(NATIVE_HTTP_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); + configProps.put(FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); + configProps.put(APACHE_HTTP_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); } else if (MAVEN_RESOLVER_TRANSPORT_WAGON.equals(transport)) { // Make sure (whatever extra priority is set) that wagon is selected configProps.put(WAGON_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); } else if (!MAVEN_RESOLVER_TRANSPORT_AUTO.equals(transport)) { throw new IllegalArgumentException("Unknown resolver transport '" + transport + "'. Supported transports are: " + MAVEN_RESOLVER_TRANSPORT_WAGON + ", " - + MAVEN_RESOLVER_TRANSPORT_NATIVE + ", " + MAVEN_RESOLVER_TRANSPORT_AUTO); + + MAVEN_RESOLVER_TRANSPORT_APACHE + ", " + MAVEN_RESOLVER_TRANSPORT_AUTO); } - session.setUserProperties(request.getUserProperties()); - session.setSystemProperties(request.getSystemProperties()); - session.setConfigProperties(configProps); - - session.setTransferListener(request.getTransferListener()); + mainSessionBuilder.setUserProperties(request.getUserProperties()); + mainSessionBuilder.setSystemProperties(request.getSystemProperties()); + mainSessionBuilder.setConfigProperties(configProps); - session.setRepositoryListener(eventSpyDispatcher.chainListener(new LoggingRepositoryListener(logger))); + mainSessionBuilder.setTransferListener(request.getTransferListener()); - session.setIgnoreArtifactDescriptorRepositories(request.isIgnoreTransitiveRepositories()); + mainSessionBuilder.setRepositoryListener( + eventSpyDispatcher.chainListener(new LoggingRepositoryListener(logger))); - boolean recordReverseTree = ConfigUtils.getBoolean(session, false, MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE); - if (recordReverseTree) { - session.setRepositoryListener(new ChainedRepositoryListener( - session.getRepositoryListener(), new ReverseTreeRepositoryListener())); - } + mainSessionBuilder.setIgnoreArtifactDescriptorRepositories(request.isIgnoreTransitiveRepositories()); - mavenRepositorySystem.injectMirror(request.getRemoteRepositories(), request.getMirrors()); - mavenRepositorySystem.injectProxy(session, request.getRemoteRepositories()); - mavenRepositorySystem.injectAuthentication(session, request.getRemoteRepositories()); + try (RepositorySystemSession.CloseableSession protoSession = + setUpLocalRepositoryManager(request, mainSessionBuilder)) { + boolean recordReverseTree = + ConfigUtils.getBoolean(protoSession, false, MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE); + if (recordReverseTree) { + mainSessionBuilder.setRepositoryListener(new ChainedRepositoryListener( + protoSession.getRepositoryListener(), new ReverseTreeRepositoryListener())); + } - mavenRepositorySystem.injectMirror(request.getPluginArtifactRepositories(), request.getMirrors()); - mavenRepositorySystem.injectProxy(session, request.getPluginArtifactRepositories()); - mavenRepositorySystem.injectAuthentication(session, request.getPluginArtifactRepositories()); + mavenRepositorySystem.injectMirror(request.getRemoteRepositories(), request.getMirrors()); + mavenRepositorySystem.injectProxy(protoSession, request.getRemoteRepositories()); + mavenRepositorySystem.injectAuthentication(protoSession, request.getRemoteRepositories()); - setUpLocalRepositoryManager(request, session); + mavenRepositorySystem.injectMirror(request.getPluginArtifactRepositories(), request.getMirrors()); + mavenRepositorySystem.injectProxy(protoSession, request.getPluginArtifactRepositories()); + mavenRepositorySystem.injectAuthentication(protoSession, request.getPluginArtifactRepositories()); - return session; + return mainSessionBuilder; + } } - private void setUpLocalRepositoryManager(MavenExecutionRequest request, DefaultRepositorySystemSession session) { - List paths = new ArrayList<>(); - String localRepoHead = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_HEAD); + private RepositorySystemSession.CloseableSession setUpLocalRepositoryManager( + MavenExecutionRequest request, RepositorySystemSession.SessionBuilder sessionBuilder) { + Path requestLocalRepositoryPath = resolve(request.getLocalRepository().getBasedir()); + RepositorySystemSession.CloseableSession protoSession = sessionBuilder + .withLocalRepositoryBaseDirectories(requestLocalRepositoryPath) + .build(); + List paths = new ArrayList<>(); + String localRepoHead = ConfigUtils.getString(protoSession, null, MAVEN_REPO_LOCAL_HEAD); if (localRepoHead != null) { Arrays.stream(localRepoHead.split(",")) - .filter(p -> p != null && !p.trim().isEmpty()) + .filter(p -> !p.trim().isEmpty()) .map(this::resolve) .forEach(paths::add); } - paths.add(request.getLocalRepository().getBasedir()); + paths.add(resolve(request.getLocalRepository().getBasedir())); - String localRepoTail = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_TAIL); + String localRepoTail = ConfigUtils.getString(protoSession, null, MAVEN_REPO_LOCAL_TAIL); if (localRepoTail != null) { Arrays.stream(localRepoTail.split(",")) - .filter(p -> p != null && !p.trim().isEmpty()) + .filter(p -> !p.trim().isEmpty()) .map(this::resolve) .forEach(paths::add); } LocalRepository localRepo = new LocalRepository(paths.remove(0)); - LocalRepositoryManager lrm = repoSystem.newLocalRepositoryManager(session, localRepo); + LocalRepositoryManager lrm = repoSystem.newLocalRepositoryManager(protoSession, localRepo); if (paths.isEmpty()) { // we have only one local repo path - session.setLocalRepositoryManager(lrm); + sessionBuilder.setLocalRepositoryManager(lrm); } else { List tail = new ArrayList<>(); - for (String path : paths) { - tail.add(repoSystem.newLocalRepositoryManager(session, new LocalRepository(path))); + for (Path path : paths) { + tail.add(repoSystem.newLocalRepositoryManager(protoSession, new LocalRepository(path))); } boolean ignoreTailAvailability = - ConfigUtils.getBoolean(session, true, MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY); + ConfigUtils.getBoolean(protoSession, true, MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY); - session.setLocalRepositoryManager(new ChainedLocalRepositoryManager(lrm, tail, ignoreTailAvailability)); + sessionBuilder.setLocalRepositoryManager( + new ChainedLocalRepositoryManager(lrm, tail, ignoreTailAvailability)); } + return protoSession; } - private String resolve(String string) { + private Path resolve(String string) { if (string.startsWith("~/") || string.startsWith("~\\")) { // resolve based on $HOME return Paths.get(System.getProperty("user.home")) .resolve(string.substring(2)) .normalize() - .toAbsolutePath() - .toString(); + .toAbsolutePath(); } else { // resolve based on $CWD - return Paths.get(string).normalize().toAbsolutePath().toString(); + return Paths.get(string).normalize().toAbsolutePath(); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/ResolverLifecycle.java b/maven-core/src/main/java/org/apache/maven/internal/aether/ResolverLifecycle.java index 576e915a6dfa..ed5981b071bd 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/ResolverLifecycle.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/ResolverLifecycle.java @@ -18,13 +18,13 @@ */ package org.apache.maven.internal.aether; -import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import org.eclipse.aether.RepositorySystem; import org.eclipse.sisu.EagerSingleton; +import org.eclipse.sisu.PreDestroy; import static java.util.Objects.requireNonNull; diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index e0ed45c3a424..dacab208d4f4 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -18,14 +18,12 @@ */ package org.apache.maven.cli; -import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.Console; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -39,6 +37,7 @@ import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; @@ -152,7 +151,9 @@ public class MavenCli { private static final String UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE = "Unable to find the root directory. Create a " + DOT_MVN + " directory in the project root directory to identify it."; - private static final String EXTENSIONS_FILENAME = DOT_MVN + "/extensions.xml"; + private static final String PROJECT_EXTENSIONS_FILENAME = DOT_MVN + "/extensions.xml"; + + private static final File USER_EXTENSIONS_FILE = new File(USER_MAVEN_CONFIGURATION_HOME, "extensions.xml"); private static final String MVN_MAVEN_CONFIG = DOT_MVN + "/maven.config"; @@ -717,16 +718,37 @@ private List loadCoreExtensions( return Collections.emptyList(); } - File extensionsFile = new File(cliRequest.multiModuleProjectDirectory, EXTENSIONS_FILENAME); - if (!extensionsFile.isFile()) { + File projectExtensionsFile = new File(cliRequest.multiModuleProjectDirectory, PROJECT_EXTENSIONS_FILENAME); + if (!projectExtensionsFile.isFile() && !USER_EXTENSIONS_FILE.isFile()) { return Collections.emptyList(); } - List extensions = readCoreExtensionsDescriptor(extensionsFile); - if (extensions.isEmpty()) { + List projectExtensions = null; + List userExtensions = null; + if (projectExtensionsFile.isFile()) { + projectExtensions = readCoreExtensionsDescriptor(projectExtensionsFile.toPath()); + } + if (USER_EXTENSIONS_FILE.isFile()) { + userExtensions = readCoreExtensionsDescriptor(USER_EXTENSIONS_FILE.toPath()); + } + + if ((projectExtensions == null || projectExtensions.isEmpty()) + && (userExtensions == null || userExtensions.isEmpty())) { return Collections.emptyList(); } + Map> configuredCoreExtensions = new LinkedHashMap<>(); + if (projectExtensions != null && !projectExtensions.isEmpty()) { + configuredCoreExtensions.put(projectExtensionsFile.toPath(), projectExtensions); + } + if (userExtensions != null && !userExtensions.isEmpty()) { + configuredCoreExtensions.put(USER_EXTENSIONS_FILE.toPath(), userExtensions); + } + // TODO: maven installation extensions + List extensions = selectCoreExtensions(configuredCoreExtensions); + + // mediate versions + ContainerConfiguration cc = new DefaultContainerConfiguration() // .setClassWorld(cliRequest.classWorld) // .setRealm(containerRealm) // @@ -773,14 +795,54 @@ protected void configure() { } } - private List readCoreExtensionsDescriptor(File extensionsFile) + private List readCoreExtensionsDescriptor(Path extensionsFile) throws IOException, XmlPullParserException { CoreExtensionsXpp3Reader parser = new CoreExtensionsXpp3Reader(); + try (BufferedReader is = Files.newBufferedReader(extensionsFile, StandardCharsets.UTF_8)) { + return parser.read(is).getExtensions(); + } + } - try (InputStream is = new BufferedInputStream(new FileInputStream(extensionsFile))) { + private List selectCoreExtensions(Map> configuredCoreExtensions) { + slf4jLogger.debug("Configured core extensions (in precedence order):"); + for (Map.Entry> source : configuredCoreExtensions.entrySet()) { + slf4jLogger.debug("* Source file: {}", source.getKey()); + for (CoreExtension extension : source.getValue()) { + slf4jLogger.debug(" - {} -> {}", extension.getId(), source.getKey()); + } + } - return parser.read(is).getExtensions(); + LinkedHashMap selectedExtensions = new LinkedHashMap<>(); + List conflicts = new ArrayList<>(); + for (Map.Entry> coreExtensions : configuredCoreExtensions.entrySet()) { + for (CoreExtension coreExtension : coreExtensions.getValue()) { + String key = coreExtension.getGroupId() + ":" + coreExtension.getArtifactId(); + CoreExtension conflict = selectedExtensions.putIfAbsent(key, coreExtension); + if (conflict != null && !Objects.equals(coreExtension.getVersion(), conflict.getVersion())) { + conflicts.add(String.format( + "Conflicting extension %s: %s vs %s in %s", + key, coreExtension.getVersion(), conflict.getVersion(), coreExtensions.getKey())); + } + } + } + if (!conflicts.isEmpty()) { + slf4jLogger.warn("Found {} extension conflict(s):", conflicts.size()); + for (String conflict : conflicts) { + slf4jLogger.warn("* {}", conflict); + } + slf4jLogger.warn(""); + slf4jLogger.warn( + "Order of core extensions precedence is project > user > installation. Selected extensions are:"); + for (CoreExtension extension : selectedExtensions.values()) { + slf4jLogger.warn("* {}", extension.getId()); + } + } + + slf4jLogger.debug("Selected core extensions (in loading order):"); + for (CoreExtension source : selectedExtensions.values()) { + slf4jLogger.debug("* {}: ", source.getId()); } + return new ArrayList<>(selectedExtensions.values()); } private ClassRealm setupContainerRealm( diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java index bb903db6c18c..fabbeafd9db1 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java @@ -92,11 +92,13 @@ public BootstrapCoreExtensionManager( public List loadCoreExtensions( MavenExecutionRequest request, Set providedArtifacts, List extensions) throws Exception { - RepositorySystemSession repoSession = repositorySystemSessionFactory.newRepositorySession(request); - List repositories = RepositoryUtils.toRepos(request.getPluginArtifactRepositories()); - Interpolator interpolator = createInterpolator(request); + try (RepositorySystemSession.CloseableSession repoSession = + repositorySystemSessionFactory.newRepositorySession(request).build()) { + List repositories = RepositoryUtils.toRepos(request.getPluginArtifactRepositories()); + Interpolator interpolator = createInterpolator(request); - return resolveCoreExtensions(repoSession, repositories, providedArtifacts, extensions, interpolator); + return resolveCoreExtensions(repoSession, repositories, providedArtifacts, extensions, interpolator); + } } private List resolveCoreExtensions( diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java index 5d4c792f011b..501c241973cc 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java @@ -19,11 +19,14 @@ package org.apache.maven.repository.internal; import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.DefaultArtifactType; import org.eclipse.aether.collection.DependencyGraphTransformer; import org.eclipse.aether.collection.DependencyManager; import org.eclipse.aether.collection.DependencySelector; import org.eclipse.aether.collection.DependencyTraverser; +import org.eclipse.aether.supplier.SessionBuilderSupplier; import org.eclipse.aether.util.artifact.DefaultArtifactTypeRegistry; import org.eclipse.aether.util.graph.manager.ClassicDependencyManager; import org.eclipse.aether.util.graph.selector.AndDependencySelector; @@ -53,6 +56,15 @@ private MavenRepositorySystemUtils() { // hide constructor } + /** + * Creates a new Maven repository system session builder. + * + * @return The new repository system session builder, never {@code null}. + */ + public static RepositorySystemSession.SessionBuilder newSession(RepositorySystem repositorySystem) { + return new SessionBuilderSupplier(repositorySystem).get(); + } + /** * Creates a new Maven-like repository system session by initializing the session with values typical for * Maven-based resolution. In more detail, this method configures settings relevant for the processing of dependency From e752123d16e6f66c4e4d9340441d37b069ac4fcd Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Sat, 14 Feb 2026 13:08:11 +0100 Subject: [PATCH 3/5] Fix cycle --- maven-resolver-provider/pom.xml | 6 ++++++ pom.xml | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/maven-resolver-provider/pom.xml b/maven-resolver-provider/pom.xml index 067128065a07..d9ce5f6b8b31 100644 --- a/maven-resolver-provider/pom.xml +++ b/maven-resolver-provider/pom.xml @@ -63,6 +63,12 @@ under the License. org.apache.maven.resolver maven-resolver-supplier-mvn3 + + + * + * + + org.codehaus.plexus diff --git a/pom.xml b/pom.xml index a040a01116c9..e5d609cb5e7d 100644 --- a/pom.xml +++ b/pom.xml @@ -509,6 +509,16 @@ under the License. + + + + false + + maven-2404 + https://repository.apache.org/content/repositories/maven-2404/ + + + From 090d1eb2a21270491f3fc6dd5eb13c05212df968 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Sat, 7 Mar 2026 20:39:34 +0100 Subject: [PATCH 4/5] Last fixes --- .../LegacyLocalRepositoryManager.java | 24 +++++---- ...DefaultRepositorySystemSessionFactory.java | 50 +++++++++++-------- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/artifact/repository/LegacyLocalRepositoryManager.java b/maven-core/src/main/java/org/apache/maven/artifact/repository/LegacyLocalRepositoryManager.java index cd76c79d78d0..5ff846e7ff4f 100644 --- a/maven-core/src/main/java/org/apache/maven/artifact/repository/LegacyLocalRepositoryManager.java +++ b/maven-core/src/main/java/org/apache/maven/artifact/repository/LegacyLocalRepositoryManager.java @@ -28,6 +28,7 @@ import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout; import org.apache.maven.artifact.repository.metadata.RepositoryMetadataStoreException; +import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; import org.apache.maven.repository.Proxy; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; @@ -64,18 +65,21 @@ public static RepositorySystemSession overlay( return session; } - if (session != null) { - LocalRepositoryManager lrm = session.getLocalRepositoryManager(); - if (lrm != null && lrm.getRepository().getBasedir().equals(new File(repository.getBasedir()))) { - return session; - } + LocalRepositoryManager lrm = session.getLocalRepositoryManager(); + if (lrm != null + && lrm.getRepository() + .getBasePath() + .equals(DefaultRepositorySystemSessionFactory.resolve(repository.getBasedir()))) { + return session; + } + if (repository.getLayout() instanceof DefaultRepositoryLayout) { + return new DefaultRepositorySystemSession(session) + .setLocalRepositoryManager(DefaultRepositorySystemSessionFactory.setUpLocalRepositoryManager( + repository.getBasedir(), system, session)); } else { - session = new DefaultRepositorySystemSession(); + return new DefaultRepositorySystemSession(session) + .setLocalRepositoryManager(new LegacyLocalRepositoryManager(repository)); } - - final LocalRepositoryManager llrm = new LegacyLocalRepositoryManager(repository); - - return new DefaultRepositorySystemSession(session).setLocalRepositoryManager(llrm); } private LegacyLocalRepositoryManager(ArtifactRepository delegate) { diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index 15d6ca5c6e6c..568126c46d86 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -249,7 +249,7 @@ public RepositorySystemSession.SessionBuilder newRepositorySession(MavenExecutio } XmlPlexusConfiguration config = new XmlPlexusConfiguration(dom); - configProps.put("aether.connector.wagon.config." + server.getId(), config); + configProps.put("aether.transport.wagon.config." + server.getId(), config); // Translate to proper resolver configuration properties as well (as Plexus XML above is Wagon specific // only), but support only configuration/httpConfiguration/all, see @@ -321,8 +321,8 @@ public RepositorySystemSession.SessionBuilder newRepositorySession(MavenExecutio } } - configProps.put("aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions()); - configProps.put("aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions()); + configProps.put("aether.transport.wagon.perms.fileMode." + server.getId(), server.getFilePermissions()); + configProps.put("aether.transport.wagon.perms.dirMode." + server.getId(), server.getDirectoryPermissions()); } mainSessionBuilder.setAuthenticationSelector(authSelector); @@ -354,7 +354,7 @@ public RepositorySystemSession.SessionBuilder newRepositorySession(MavenExecutio mainSessionBuilder.setIgnoreArtifactDescriptorRepositories(request.isIgnoreTransitiveRepositories()); try (RepositorySystemSession.CloseableSession protoSession = - setUpLocalRepositoryManager(request, mainSessionBuilder)) { + setUpLocalRepositoryManager(request, repoSystem, mainSessionBuilder)) { boolean recordReverseTree = ConfigUtils.getBoolean(protoSession, false, MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE); if (recordReverseTree) { @@ -374,52 +374,58 @@ public RepositorySystemSession.SessionBuilder newRepositorySession(MavenExecutio } } - private RepositorySystemSession.CloseableSession setUpLocalRepositoryManager( - MavenExecutionRequest request, RepositorySystemSession.SessionBuilder sessionBuilder) { + private static RepositorySystemSession.CloseableSession setUpLocalRepositoryManager( + MavenExecutionRequest request, + RepositorySystem repoSystem, + RepositorySystemSession.SessionBuilder sessionBuilder) { Path requestLocalRepositoryPath = resolve(request.getLocalRepository().getBasedir()); RepositorySystemSession.CloseableSession protoSession = sessionBuilder .withLocalRepositoryBaseDirectories(requestLocalRepositoryPath) .build(); + LocalRepositoryManager lrm = + setUpLocalRepositoryManager(request.getLocalRepository().getBasedir(), repoSystem, protoSession); + sessionBuilder.setLocalRepositoryManager(lrm); + return protoSession; + } + + public static LocalRepositoryManager setUpLocalRepositoryManager( + String localRepository, RepositorySystem repoSystem, RepositorySystemSession session) { List paths = new ArrayList<>(); - String localRepoHead = ConfigUtils.getString(protoSession, null, MAVEN_REPO_LOCAL_HEAD); + String localRepoHead = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_HEAD); if (localRepoHead != null) { Arrays.stream(localRepoHead.split(",")) .filter(p -> !p.trim().isEmpty()) - .map(this::resolve) + .map(DefaultRepositorySystemSessionFactory::resolve) .forEach(paths::add); } - paths.add(resolve(request.getLocalRepository().getBasedir())); + paths.add(resolve(localRepository)); - String localRepoTail = ConfigUtils.getString(protoSession, null, MAVEN_REPO_LOCAL_TAIL); + String localRepoTail = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_TAIL); if (localRepoTail != null) { Arrays.stream(localRepoTail.split(",")) .filter(p -> !p.trim().isEmpty()) - .map(this::resolve) + .map(DefaultRepositorySystemSessionFactory::resolve) .forEach(paths::add); } LocalRepository localRepo = new LocalRepository(paths.remove(0)); - LocalRepositoryManager lrm = repoSystem.newLocalRepositoryManager(protoSession, localRepo); + LocalRepositoryManager lrm = repoSystem.newLocalRepositoryManager(session, localRepo); - if (paths.isEmpty()) { - // we have only one local repo path - sessionBuilder.setLocalRepositoryManager(lrm); - } else { + if (!paths.isEmpty()) { List tail = new ArrayList<>(); for (Path path : paths) { - tail.add(repoSystem.newLocalRepositoryManager(protoSession, new LocalRepository(path))); + tail.add(repoSystem.newLocalRepositoryManager(session, new LocalRepository(path))); } boolean ignoreTailAvailability = - ConfigUtils.getBoolean(protoSession, true, MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY); + ConfigUtils.getBoolean(session, true, MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY); - sessionBuilder.setLocalRepositoryManager( - new ChainedLocalRepositoryManager(lrm, tail, ignoreTailAvailability)); + lrm = new ChainedLocalRepositoryManager(lrm, tail, ignoreTailAvailability); } - return protoSession; + return lrm; } - private Path resolve(String string) { + public static Path resolve(String string) { if (string.startsWith("~/") || string.startsWith("~\\")) { // resolve based on $HOME return Paths.get(System.getProperty("user.home")) From 233af2b5107d7099d57ee0dc90b9931516792925 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 10 Mar 2026 14:12:05 +0100 Subject: [PATCH 5/5] Undo this partial change --- .../java/org/apache/maven/cli/MavenCli.java | 84 +++---------------- 1 file changed, 11 insertions(+), 73 deletions(-) diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index dacab208d4f4..e0ed45c3a424 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -18,12 +18,14 @@ */ package org.apache.maven.cli; -import java.io.BufferedReader; +import java.io.BufferedInputStream; import java.io.Console; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -37,7 +39,6 @@ import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; @@ -151,9 +152,7 @@ public class MavenCli { private static final String UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE = "Unable to find the root directory. Create a " + DOT_MVN + " directory in the project root directory to identify it."; - private static final String PROJECT_EXTENSIONS_FILENAME = DOT_MVN + "/extensions.xml"; - - private static final File USER_EXTENSIONS_FILE = new File(USER_MAVEN_CONFIGURATION_HOME, "extensions.xml"); + private static final String EXTENSIONS_FILENAME = DOT_MVN + "/extensions.xml"; private static final String MVN_MAVEN_CONFIG = DOT_MVN + "/maven.config"; @@ -718,37 +717,16 @@ private List loadCoreExtensions( return Collections.emptyList(); } - File projectExtensionsFile = new File(cliRequest.multiModuleProjectDirectory, PROJECT_EXTENSIONS_FILENAME); - if (!projectExtensionsFile.isFile() && !USER_EXTENSIONS_FILE.isFile()) { + File extensionsFile = new File(cliRequest.multiModuleProjectDirectory, EXTENSIONS_FILENAME); + if (!extensionsFile.isFile()) { return Collections.emptyList(); } - List projectExtensions = null; - List userExtensions = null; - if (projectExtensionsFile.isFile()) { - projectExtensions = readCoreExtensionsDescriptor(projectExtensionsFile.toPath()); - } - if (USER_EXTENSIONS_FILE.isFile()) { - userExtensions = readCoreExtensionsDescriptor(USER_EXTENSIONS_FILE.toPath()); - } - - if ((projectExtensions == null || projectExtensions.isEmpty()) - && (userExtensions == null || userExtensions.isEmpty())) { + List extensions = readCoreExtensionsDescriptor(extensionsFile); + if (extensions.isEmpty()) { return Collections.emptyList(); } - Map> configuredCoreExtensions = new LinkedHashMap<>(); - if (projectExtensions != null && !projectExtensions.isEmpty()) { - configuredCoreExtensions.put(projectExtensionsFile.toPath(), projectExtensions); - } - if (userExtensions != null && !userExtensions.isEmpty()) { - configuredCoreExtensions.put(USER_EXTENSIONS_FILE.toPath(), userExtensions); - } - // TODO: maven installation extensions - List extensions = selectCoreExtensions(configuredCoreExtensions); - - // mediate versions - ContainerConfiguration cc = new DefaultContainerConfiguration() // .setClassWorld(cliRequest.classWorld) // .setRealm(containerRealm) // @@ -795,54 +773,14 @@ protected void configure() { } } - private List readCoreExtensionsDescriptor(Path extensionsFile) + private List readCoreExtensionsDescriptor(File extensionsFile) throws IOException, XmlPullParserException { CoreExtensionsXpp3Reader parser = new CoreExtensionsXpp3Reader(); - try (BufferedReader is = Files.newBufferedReader(extensionsFile, StandardCharsets.UTF_8)) { - return parser.read(is).getExtensions(); - } - } - private List selectCoreExtensions(Map> configuredCoreExtensions) { - slf4jLogger.debug("Configured core extensions (in precedence order):"); - for (Map.Entry> source : configuredCoreExtensions.entrySet()) { - slf4jLogger.debug("* Source file: {}", source.getKey()); - for (CoreExtension extension : source.getValue()) { - slf4jLogger.debug(" - {} -> {}", extension.getId(), source.getKey()); - } - } + try (InputStream is = new BufferedInputStream(new FileInputStream(extensionsFile))) { - LinkedHashMap selectedExtensions = new LinkedHashMap<>(); - List conflicts = new ArrayList<>(); - for (Map.Entry> coreExtensions : configuredCoreExtensions.entrySet()) { - for (CoreExtension coreExtension : coreExtensions.getValue()) { - String key = coreExtension.getGroupId() + ":" + coreExtension.getArtifactId(); - CoreExtension conflict = selectedExtensions.putIfAbsent(key, coreExtension); - if (conflict != null && !Objects.equals(coreExtension.getVersion(), conflict.getVersion())) { - conflicts.add(String.format( - "Conflicting extension %s: %s vs %s in %s", - key, coreExtension.getVersion(), conflict.getVersion(), coreExtensions.getKey())); - } - } - } - if (!conflicts.isEmpty()) { - slf4jLogger.warn("Found {} extension conflict(s):", conflicts.size()); - for (String conflict : conflicts) { - slf4jLogger.warn("* {}", conflict); - } - slf4jLogger.warn(""); - slf4jLogger.warn( - "Order of core extensions precedence is project > user > installation. Selected extensions are:"); - for (CoreExtension extension : selectedExtensions.values()) { - slf4jLogger.warn("* {}", extension.getId()); - } - } - - slf4jLogger.debug("Selected core extensions (in loading order):"); - for (CoreExtension source : selectedExtensions.values()) { - slf4jLogger.debug("* {}: ", source.getId()); + return parser.read(is).getExtensions(); } - return new ArrayList<>(selectedExtensions.values()); } private ClassRealm setupContainerRealm(