Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions impl/maven-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ under the License.
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId>
</dependency>
<dependency>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

am unsure are these deps really needed here, maybe only for test?

As if you make them required, you make apache transport or basic connector "mandatory". I'd rather put back these into test scope of maven-impl and let "mima-like use case" user pick deps he needs instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved out the transports and kept named locks and connectors, as they are really the only implementation. If needed, we can revisit later.

<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-named-locks</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-sec-dispatcher</artifactId>
Expand Down Expand Up @@ -147,16 +155,6 @@ under the License.
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-named-locks</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-file</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
* 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.
* </p>
*
* <p>Example usage:</p>
* <pre>
* Session session = ApiRunner.createSession();
* // Use session for Maven operations
* </pre>
*
* <p>
* 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}.
* </p>
*
* @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<Injector> 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<Injector> injectorConsumer, Path localRepo) {
Injector injector = Injector.create();
injector.bindInstance(Injector.class, injector);
Expand All @@ -108,10 +143,21 @@ public static Session createSession(Consumer<Injector> 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<String, String> systemProperties;
Expand Down Expand Up @@ -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<String, PluginContainer> plugins) implements Packaging {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -488,21 +486,8 @@ static LocalPathPrefixComposerFactory newLocalPathPrefixComposerFactory() {
}

@Provides
static TransporterProvider newTransportProvider(Map<String, TransporterFactory> 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<String, TransporterFactory> transporterFactories) {
return new DefaultTransporterProvider(transporterFactories != null ? transporterFactories : Map.of());
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
* <p>
* This exception indicates that a requested operation is only available when running
* within a full Maven build context, not in the simplified standalone environment.
* </p>
*
* @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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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.
* <p>
* This package contains classes that enable running Maven API in a standalone mode, primarily for testing and
* specialized execution scenarios. The main components are:
* <ul>
* <li>{@link org.apache.maven.impl.standalone.ApiRunner} - Creates and manages Maven sessions for standalone execution</li>
* <li>{@link org.apache.maven.impl.standalone.UnsupportedInStandaloneModeException} - Indicates operations not available in standalone mode</li>
* </ul>
*
* @since 4.0.0
*/
package org.apache.maven.impl.standalone;
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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));
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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()
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()
Expand All @@ -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);
}
}