From 9ea3d7a05200378c914112b66e76319ae47c20a0 Mon Sep 17 00:00:00 2001
From: Guillaume Nodet
Date: Thu, 3 Apr 2025 10:31:08 +0200
Subject: [PATCH 1/3] [MNG-8637] Pull out Standalone API from UTs
This commit moves the Standalone API implementation from the test directory to the main source directory, making it available for reuse outside of tests.
The Standalone API provides a way to run Maven API in a standalone mode (without the full Maven environment), primarily for testing and specialized execution scenarios. This is now the proper way to utilize Maven 4 in MIMA-like scenarios.
Key changes:
- Moved ApiRunner and RepositorySystemSupplier from test to main source
- Added UnsupportedInStandaloneModeException for operations not supported in standalone mode
- Added package-info.java with documentation for the standalone package
---
impl/maven-impl/pom.xml | 36 ++++++-------
.../maven/impl/standalone/ApiRunner.java | 52 +++++++++++++++++--
.../standalone/RepositorySystemSupplier.java | 0
.../UnsupportedInStandaloneModeException.java | 47 +++++++++++++++++
.../maven/impl/standalone/package-info.java | 33 ++++++++++++
5 files changed, 144 insertions(+), 24 deletions(-)
rename impl/maven-impl/src/{test => main}/java/org/apache/maven/impl/standalone/ApiRunner.java (89%)
rename impl/maven-impl/src/{test => main}/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java (100%)
create mode 100644 impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/UnsupportedInStandaloneModeException.java
create mode 100644 impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java
diff --git a/impl/maven-impl/pom.xml b/impl/maven-impl/pom.xml
index e69f474c4a93..cb7dc7c6339c 100644
--- a/impl/maven-impl/pom.xml
+++ b/impl/maven-impl/pom.xml
@@ -112,6 +112,22 @@ under the License.
org.apache.maven.resolver
maven-resolver-impl
+
+ org.apache.maven.resolver
+ maven-resolver-named-locks
+
+
+ org.apache.maven.resolver
+ maven-resolver-connector-basic
+
+
+ org.apache.maven.resolver
+ maven-resolver-transport-file
+
+
+ org.apache.maven.resolver
+ maven-resolver-transport-apache
+
org.codehaus.plexus
plexus-sec-dispatcher
@@ -147,26 +163,6 @@ under the License.
assertj-core
test
-
- org.apache.maven.resolver
- maven-resolver-named-locks
- test
-
-
- org.apache.maven.resolver
- maven-resolver-connector-basic
- test
-
-
- org.apache.maven.resolver
- maven-resolver-transport-file
- test
-
-
- org.apache.maven.resolver
- maven-resolver-transport-apache
- test
-
com.google.jimfs
jimfs
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/ApiRunner.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/ApiRunner.java
similarity index 89%
rename from impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/ApiRunner.java
rename to impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/ApiRunner.java
index 9e7fbe9c383d..d8d1ac3f8577 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/ApiRunner.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/ApiRunner.java
@@ -74,22 +74,57 @@
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.LocalRepositoryManager;
+/**
+ * Provides functionality for running Maven API in a standalone mode.
+ *
+ * This class serves as the main entry point for executing Maven operations outside
+ * of the standard Maven build environment. It provides methods for creating and
+ * managing Maven sessions in a simplified context, primarily for testing and
+ * specialized execution scenarios.
+ *
+ *
+ * Example usage:
+ *
+ * Session session = ApiRunner.createSession();
+ * // Use session for Maven operations
+ *
+ *
+ *
+ * The standalone mode provides a subset of Maven's functionality, with some
+ * features being unavailable or simplified. Operations not supported in
+ * standalone mode will throw {@link UnsupportedInStandaloneModeException}.
+ *
+ *
+ * @since 4.0.0
+ */
public class ApiRunner {
/**
- * Create a new session.
+ * Creates a new Maven session with default configuration.
+ *
+ * @return a new {@link Session} instance
*/
public static Session createSession() {
return createSession(null);
}
/**
- * Create a new session.
+ * Creates a new Maven session with custom injector configuration.
+ *
+ * @param injectorConsumer consumer function to customize the injector
+ * @return a new {@link Session} instance
*/
public static Session createSession(Consumer injectorConsumer) {
return createSession(injectorConsumer, null);
}
+ /**
+ * Creates a new Maven session with custom injector configuration and local repository path.
+ *
+ * @param injectorConsumer consumer function to customize the injector
+ * @param localRepo path to the local repository
+ * @return a new {@link Session} instance
+ */
public static Session createSession(Consumer injectorConsumer, Path localRepo) {
Injector injector = Injector.create();
injector.bindInstance(Injector.class, injector);
@@ -108,10 +143,21 @@ public static Session createSession(Consumer injectorConsumer, Path lo
return session;
}
+ /**
+ * Interface for providing the local repository path.
+ */
interface LocalRepoProvider {
+ /**
+ * Gets the path to the local repository.
+ *
+ * @return the local repository path
+ */
Path getLocalRepo();
}
+ /**
+ * Default implementation of the Maven session for standalone mode.
+ */
static class DefaultSession extends AbstractSession {
private final Map systemProperties;
@@ -394,7 +440,5 @@ static Session newSession(RepositorySystem system, Lookup lookup, @Nullable Loca
// return defaultSession;
}
- static class UnsupportedInStandaloneModeException extends MavenException {}
-
record DumbPackaging(String id, Type type, Map plugins) implements Packaging {}
}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
similarity index 100%
rename from impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
rename to impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/UnsupportedInStandaloneModeException.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/UnsupportedInStandaloneModeException.java
new file mode 100644
index 000000000000..d90c56009bd4
--- /dev/null
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/UnsupportedInStandaloneModeException.java
@@ -0,0 +1,47 @@
+/*
+ * 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.impl.standalone;
+
+/**
+ * Exception thrown when attempting to use features that are not supported in standalone mode.
+ *
+ * This exception indicates that a requested operation is only available when running
+ * within a full Maven build context, not in the simplified standalone environment.
+ *
+ *
+ * @since 4.0.0
+ */
+public class UnsupportedInStandaloneModeException extends UnsupportedOperationException {
+
+ /**
+ * Constructs a new exception with a default message.
+ */
+ public UnsupportedInStandaloneModeException() {
+ super("This operation is not supported in standalone mode");
+ }
+
+ /**
+ * Constructs a new exception with a specific message.
+ *
+ * @param message the detail message
+ */
+ public UnsupportedInStandaloneModeException(String message) {
+ super(message);
+ }
+}
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java
new file mode 100644
index 000000000000..55a1e191fb5a
--- /dev/null
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ * Provides standalone implementation classes for Maven API execution outside of the standard Maven build environment.
+ *
+ * This package contains classes that enable running Maven API in a standalone mode, primarily for testing and
+ * specialized execution scenarios. The main components are:
+ *
+ * - {@link org.apache.maven.impl.standalone.ApiRunner} - Creates and manages Maven sessions for standalone execution
+ * - {@link org.apache.maven.impl.standalone.UnsupportedInStandaloneModeException} - Indicates operations not available in standalone mode
+ *
+ *
+ *
+ * @since 4.0.0
+ */
+package org.apache.maven.impl.standalone;
From 452365c9c7778f76373194260ca58497bb3d5dcb Mon Sep 17 00:00:00 2001
From: Guillaume Nodet
Date: Thu, 3 Apr 2025 13:01:40 +0200
Subject: [PATCH 2/3] [MNG-8637] Fix Javadoc HTML structure in
package-info.java
---
.../main/java/org/apache/maven/impl/standalone/package-info.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java
index 55a1e191fb5a..1bcaf8d10835 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/package-info.java
@@ -26,7 +26,6 @@
* {@link org.apache.maven.impl.standalone.ApiRunner} - Creates and manages Maven sessions for standalone execution
* {@link org.apache.maven.impl.standalone.UnsupportedInStandaloneModeException} - Indicates operations not available in standalone mode
*
- *
*
* @since 4.0.0
*/
From 761b2ccdcb4fee01ae12ba4defe1ceb0ae8c82ff Mon Sep 17 00:00:00 2001
From: Guillaume Nodet
Date: Thu, 3 Apr 2025 16:33:03 +0200
Subject: [PATCH 3/3] Move back transports to test scope
---
impl/maven-impl/pom.xml | 18 +++++++------
.../standalone/RepositorySystemSupplier.java | 19 ++------------
.../resolver/DefaultModelResolverTest.java | 25 ++++++++++++++++++-
.../impl/standalone/RequestTraceTest.java | 23 ++++++++++++++++-
.../impl/standalone/TestApiStandalone.java | 23 ++++++++++++++++-
5 files changed, 80 insertions(+), 28 deletions(-)
diff --git a/impl/maven-impl/pom.xml b/impl/maven-impl/pom.xml
index cb7dc7c6339c..026453c776a1 100644
--- a/impl/maven-impl/pom.xml
+++ b/impl/maven-impl/pom.xml
@@ -120,14 +120,6 @@ under the License.
org.apache.maven.resolver
maven-resolver-connector-basic
-
- org.apache.maven.resolver
- maven-resolver-transport-file
-
-
- org.apache.maven.resolver
- maven-resolver-transport-apache
-
org.codehaus.plexus
plexus-sec-dispatcher
@@ -163,6 +155,16 @@ under the License.
assertj-core
test
+
+ org.apache.maven.resolver
+ maven-resolver-transport-file
+ test
+
+
+ org.apache.maven.resolver
+ maven-resolver-transport-apache
+ test
+
com.google.jimfs
jimfs
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
index 14026145821d..50832df1d65d 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
@@ -121,8 +121,6 @@
import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor;
import org.eclipse.aether.spi.synccontext.SyncContextFactory;
-import org.eclipse.aether.transport.apache.ApacheTransporterFactory;
-import org.eclipse.aether.transport.file.FileTransporterFactory;
/**
* DI Bridge for Maven Resolver
@@ -488,21 +486,8 @@ static LocalPathPrefixComposerFactory newLocalPathPrefixComposerFactory() {
}
@Provides
- static TransporterProvider newTransportProvider(Map transporterFactories) {
- return new DefaultTransporterProvider(transporterFactories);
- }
-
- @Provides
- @Named(FileTransporterFactory.NAME)
- static FileTransporterFactory newFileTransporterFactory() {
- return new FileTransporterFactory();
- }
-
- @Provides
- @Named(ApacheTransporterFactory.NAME)
- static ApacheTransporterFactory newApacheTransporterFactory(
- ChecksumExtractor checksumExtractor, PathProcessor pathProcessor) {
- return new ApacheTransporterFactory(checksumExtractor, pathProcessor);
+ static TransporterProvider newTransportProvider(@Nullable Map transporterFactories) {
+ return new DefaultTransporterProvider(transporterFactories != null ? transporterFactories : Map.of());
}
@Provides
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/resolver/DefaultModelResolverTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/resolver/DefaultModelResolverTest.java
index e779e213d173..e680267895ad 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/resolver/DefaultModelResolverTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/resolver/DefaultModelResolverTest.java
@@ -25,11 +25,17 @@
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Provides;
import org.apache.maven.api.model.Dependency;
import org.apache.maven.api.model.Parent;
import org.apache.maven.api.services.model.ModelResolver;
import org.apache.maven.api.services.model.ModelResolverException;
import org.apache.maven.impl.standalone.ApiRunner;
+import org.eclipse.aether.spi.connector.transport.http.ChecksumExtractor;
+import org.eclipse.aether.spi.io.PathProcessor;
+import org.eclipse.aether.transport.apache.ApacheTransporterFactory;
+import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -51,7 +57,11 @@ void setup() {
Path basedir = Paths.get(System.getProperty("basedir", ""));
Path localRepoPath = basedir.resolve("target/local-repo");
Path remoteRepoPath = basedir.resolve("src/test/remote-repo");
- Session s = ApiRunner.createSession(null, localRepoPath);
+ Session s = ApiRunner.createSession(
+ injector -> {
+ injector.bindInstance(DefaultModelResolverTest.class, this);
+ },
+ localRepoPath);
RemoteRepository remoteRepository = s.createRemoteRepository(
RemoteRepository.CENTRAL_ID, remoteRepoPath.toUri().toString());
session = s.withRemoteRepositories(List.of(remoteRepository));
@@ -202,4 +212,17 @@ void testResolveDependencySuccessfullyResolvesExistingDependencyUsingHighestVers
private ModelResolver newModelResolver() throws Exception {
return new DefaultModelResolver();
}
+
+ @Provides
+ @Named(FileTransporterFactory.NAME)
+ static FileTransporterFactory newFileTransporterFactory() {
+ return new FileTransporterFactory();
+ }
+
+ @Provides
+ @Named(ApacheTransporterFactory.NAME)
+ static ApacheTransporterFactory newApacheTransporterFactory(
+ ChecksumExtractor checksumExtractor, PathProcessor pathProcessor) {
+ return new ApacheTransporterFactory(checksumExtractor, pathProcessor);
+ }
}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RequestTraceTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RequestTraceTest.java
index 1f6389c5dc1b..934350477018 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RequestTraceTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RequestTraceTest.java
@@ -28,6 +28,8 @@
import org.apache.maven.api.Node;
import org.apache.maven.api.PathScope;
import org.apache.maven.api.Session;
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Provides;
import org.apache.maven.api.services.DependencyResolver;
import org.apache.maven.api.services.DependencyResolverRequest;
import org.apache.maven.api.services.ModelBuilder;
@@ -40,6 +42,10 @@
import org.eclipse.aether.AbstractRepositoryListener;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositoryEvent;
+import org.eclipse.aether.spi.connector.transport.http.ChecksumExtractor;
+import org.eclipse.aether.spi.io.PathProcessor;
+import org.eclipse.aether.transport.apache.ApacheTransporterFactory;
+import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -50,7 +56,9 @@ class RequestTraceTest {
@Test
void testTraces() {
- Session session = ApiRunner.createSession();
+ Session session = ApiRunner.createSession(injector -> {
+ injector.bindInstance(RequestTraceTest.class, this);
+ });
ModelBuilder builder = session.getService(ModelBuilder.class);
ModelBuilderResult result = builder.newSession()
@@ -103,4 +111,17 @@ public void artifactResolved(RepositoryEvent event) {
assertNotNull(node);
assertEquals(6, node.getChildren().size());
}
+
+ @Provides
+ @Named(FileTransporterFactory.NAME)
+ static FileTransporterFactory newFileTransporterFactory() {
+ return new FileTransporterFactory();
+ }
+
+ @Provides
+ @Named(ApacheTransporterFactory.NAME)
+ static ApacheTransporterFactory newApacheTransporterFactory(
+ ChecksumExtractor checksumExtractor, PathProcessor pathProcessor) {
+ return new ApacheTransporterFactory(checksumExtractor, pathProcessor);
+ }
}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/TestApiStandalone.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/TestApiStandalone.java
index 40e18cace799..a0c519a9eaf5 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/TestApiStandalone.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/TestApiStandalone.java
@@ -26,10 +26,16 @@
import org.apache.maven.api.Node;
import org.apache.maven.api.PathScope;
import org.apache.maven.api.Session;
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Provides;
import org.apache.maven.api.services.ModelBuilder;
import org.apache.maven.api.services.ModelBuilderRequest;
import org.apache.maven.api.services.ModelBuilderResult;
import org.apache.maven.api.services.Sources;
+import org.eclipse.aether.spi.connector.transport.http.ChecksumExtractor;
+import org.eclipse.aether.spi.io.PathProcessor;
+import org.eclipse.aether.transport.apache.ApacheTransporterFactory;
+import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -40,7 +46,9 @@ class TestApiStandalone {
@Test
void testStandalone() {
- Session session = ApiRunner.createSession();
+ Session session = ApiRunner.createSession(injector -> {
+ injector.bindInstance(TestApiStandalone.class, this);
+ });
ModelBuilder builder = session.getService(ModelBuilder.class);
ModelBuilderResult result = builder.newSession()
@@ -63,4 +71,17 @@ void testStandalone() {
assertNotNull(node);
assertEquals(6, node.getChildren().size());
}
+
+ @Provides
+ @Named(FileTransporterFactory.NAME)
+ static FileTransporterFactory newFileTransporterFactory() {
+ return new FileTransporterFactory();
+ }
+
+ @Provides
+ @Named(ApacheTransporterFactory.NAME)
+ static ApacheTransporterFactory newApacheTransporterFactory(
+ ChecksumExtractor checksumExtractor, PathProcessor pathProcessor) {
+ return new ApacheTransporterFactory(checksumExtractor, pathProcessor);
+ }
}