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
2 changes: 1 addition & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:

- name: Set up Maven
shell: bash
run: mvn --errors --batch-mode --show-version org.apache.maven.plugins:maven-wrapper-plugin:3.3.2:wrapper "-Dmaven=4.0.0-rc-1"
run: mvn --errors --batch-mode --show-version org.apache.maven.plugins:maven-wrapper-plugin:3.3.2:wrapper "-Dmaven=4.0.0-rc-2"

- name: Build Maven distributions
shell: bash
Expand Down
5 changes: 5 additions & 0 deletions api/maven-api-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ static ModelBuilderRequest build(@Nonnull Session session, @Nonnull ModelSource
static ModelBuilderRequest build(@Nonnull Session session, @Nonnull Path path) {
return builder()
.session(requireNonNull(session, "session cannot be null"))
.source(ModelSource.fromPath(path))
.source(Sources.buildSource(path))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,72 @@
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;

import static java.util.Objects.requireNonNull;

/**
* A Source specific to load POMs. The {@link #resolve(ModelLocator, String)} method
* will be used to find POMs for subprojects.
* Represents a source for loading Maven Project Object Model (POM) files. This interface
* extends the basic {@link Source} interface with specific functionality for handling
* Maven POM files and resolving related project POMs.
*
* <p>The interface provides two types of sources:</p>
* <ul>
* <li>Build sources: Used for POM files of projects being built by Maven in the filesystem.
* These sources support resolving related POMs using the {@link ModelLocator}.</li>
* <li>Resolved sources: Used for artifacts that have been resolved by Maven from repositories
* (using groupId:artifactId:version coordinates) and downloaded to the local repository.
* These sources do not support resolving other sources.</li>
* </ul>
*
* @since 4.0.0
* @see Source
*/
public interface ModelSource extends Source {

/**
* Interface for locating POM files within a project structure.
* Implementations of this interface provide the ability to find POM files
* in various project contexts.
*
* @since 4.0.0
*/
interface ModelLocator {
/**
* Returns the file containing the pom or null if a pom can not be
* found at the given file or in the given directory.
* Attempts to locate an existing POM file at or within the specified project path.
*
* @since 4.0.0
* <p>This method is used to find POM files in various contexts, such as:</p>
* <ul>
* <li>Directly at the specified path</li>
* <li>Within a directory at the specified path</li>
* <li>In standard Maven project locations relative to the specified path</li>
* </ul>
*
* @param project the path to search for a POM file
* @return the path to the located POM file, or null if no POM can be found
* @throws NullPointerException if project is null
*/
@Nullable
Path locateExistingPom(@Nonnull Path project);
}

/**
* Resolves a relative path to another POM file using the provided model locator.
* This method is specifically used to locate POM files for subprojects or related
* projects referenced from the current POM.
*
* <p>The resolution process typically involves:</p>
* <ul>
* <li>Normalizing the relative path for the current platform</li>
* <li>Resolving the path against the current POM's location</li>
* <li>Using the model locator to find an existing POM at the resolved location</li>
* </ul>
*
* @param modelLocator the locator to use for finding the related POM file
* @param relative the relative path to resolve
* @return a new ModelSource for the resolved POM, or null if:
* <ul>
* <li>This is not a build source</li>
* <li>No POM can be found at the resolved location</li>
* </ul>
* @throws NullPointerException if modelLocator or relative is null
*/
@Nullable
ModelSource resolve(@Nonnull ModelLocator modelLocator, @Nonnull String relative);

@Nonnull
static ModelSource fromPath(@Nonnull Path path) {
return fromPath(path, null);
}

@Nonnull
static ModelSource fromPath(@Nonnull Path path, @Nullable String location) {
return new PathSource(requireNonNull(path, "path cannot be null"), location);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ static SettingsBuilderRequest build(
@Nonnull
static SettingsBuilderRequest build(
@Nonnull ProtoSession session, @Nonnull Path installationSettingsPath, @Nonnull Path userSettingsPath) {
return build(session, Source.fromPath(installationSettingsPath), null, Source.fromPath(userSettingsPath));
return build(session, Sources.fromPath(installationSettingsPath), null, Sources.fromPath(userSettingsPath));
}

@Nonnull
Expand All @@ -112,15 +112,15 @@ static SettingsBuilderRequest build(
.session(requireNonNull(session, "session cannot be null"))
.installationSettingsSource(
installationSettingsPath != null && Files.exists(installationSettingsPath)
? Source.fromPath(installationSettingsPath)
? Sources.fromPath(installationSettingsPath)
: null)
.projectSettingsSource(
projectSettingsPath != null && Files.exists(projectSettingsPath)
? Source.fromPath(projectSettingsPath)
? Sources.fromPath(projectSettingsPath)
: null)
.userSettingsSource(
userSettingsPath != null && Files.exists(userSettingsPath)
? Source.fromPath(userSettingsPath)
? Sources.fromPath(userSettingsPath)
: null)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,74 +27,88 @@
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;

import static java.util.Objects.requireNonNull;

/**
* Provides access to the contents of a source independently of the
* backing store (e.g. file system, database, memory).
* <p>
* This is mainly used to parse files into objects such as
* {@link org.apache.maven.api.Project},
* {@link org.apache.maven.api.model.Model},
* {@link org.apache.maven.api.settings.Settings}, or
* {@link org.apache.maven.api.toolchain.PersistedToolchains}.
* This is mainly used to parse files into objects such as Maven projects,
* models, settings, or toolchains. The source implementation handles
* all the details of accessing the underlying content while providing
* a uniform API to consumers.
* <p>
* Sources can represent:
* <ul>
* <li>Local filesystem files</li>
* <li>In-memory content</li>
* <li>Database entries</li>
* <li>Network resources</li>
* </ul>
*
* @since 4.0.0
* @see org.apache.maven.api.services.ProjectBuilder#build(Session, Source)
* @see org.apache.maven.api.services.SettingsBuilder#build(Session, Source, Source, Source)
* @see org.apache.maven.api.services.ToolchainsBuilder#build(Session, Source, Source)
*/
@Experimental
public interface Source {

/**
* Provides access the file to be parsed, if this source is backed by a file.
* Provides access to the file backing this source, if available.
* Not all sources are backed by files - for example, in-memory sources
* or database-backed sources will return null.
*
* @return the underlying {@code Path}, or {@code null} if this source is not backed by a file
* @return the underlying {@code Path} if this source is file-backed,
* or {@code null} if this source has no associated file
*/
@Nullable
Path getPath();

/**
* Creates a new byte stream to the source contents.
* Closing the returned stream is the responsibility of the caller.
* Creates a new input stream to read the source contents.
* Each call creates a fresh stream starting from the beginning.
* The caller is responsible for closing the returned stream.
*
* @return a byte stream to the source contents, never {@code null}
* @throws IOException in case of IO issue
* @return a new input stream positioned at the start of the content
* @throws IOException if the stream cannot be created or opened
*/
@Nonnull
InputStream openStream() throws IOException;

/**
* Provides a user-friendly hint about the location of the source.
* This could be a local file path, a URI or just an empty string.
* The intention is to assist users during error reporting.
* Returns a human-readable description of where this source came from,
* used primarily for error messages and debugging.
* <p>
* Examples of locations:
* <ul>
* <li>Absolute file path: {@code /path/to/pom.xml}</li>
* <li>Relative file path: {@code ../parent/pom.xml}</li>
* <li>URL: {@code https://repo.maven.org/.../pom.xml}</li>
* <li>Description: {@code <memory>} or {@code <database>}</li>
* </ul>
*
* @return a user-friendly hint about the location of the source, never {@code null}
* @return a non-null string describing the source location
*/
@Nonnull
String getLocation();

/**
* Returns a new source identified by a relative path. Implementation <strong>MUST</strong>
* be able to accept <code>relative</code> parameter values that
* Resolves a new source relative to this one.
* <p>
* The resolution strategy depends on the source type:
* <ul>
* <li>use either / or \ file path separator,</li>
* <li>have .. parent directory references,</li>
* <li>point either at file or directory.</li>
* <li>File sources resolve against their parent directory</li>
* <li>URL sources resolve against their base URL</li>
* <li>Other sources may not support resolution and return null</li>
* </ul>
* <p>
* The implementation must handle:
* <ul>
* <li>Both forward and back slashes as path separators</li>
* <li>Parent directory references (..)</li>
* <li>Both file and directory targets</li>
* </ul>
*
* @param relative is the path of the requested source relative to this source
* @return related source or <code>null</code> if no such source
* @param relative path to resolve relative to this source
* @return the resolved source, or null if resolution not possible
* @throws NullPointerException if relative is null
*/
@Nullable
Source resolve(@Nonnull String relative);

/**
* Creates a Source for the following Path
*/
@Nonnull
static Source fromPath(@Nonnull Path path) {
return new PathSource(requireNonNull(path, "path cannot be null"));
}
}
Loading