Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,32 @@ public void attachArtifact(@Nonnull Project project, @Nonnull ProducedArtifact a
artifact.getExtension(),
null);
}
if (!Objects.equals(project.getGroupId(), artifact.getGroupId())
|| !Objects.equals(project.getArtifactId(), artifact.getArtifactId())
|| !Objects.equals(
project.getVersion(), artifact.getBaseVersion().toString())) {
throw new IllegalArgumentException(
"The produced artifact must have the same groupId/artifactId/version than the project it is attached to. Expecting "
+ project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion()
+ " but received " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":"
+ artifact.getBaseVersion());
// Verify groupId and version, intentionally allow artifactId to differ as a project may be multi-module.
String g1 = project.getGroupId();
String a1 = project.getArtifactId();
String v1 = project.getVersion();
String g2 = artifact.getGroupId();
String a2 = artifact.getArtifactId();
String v2 = artifact.getBaseVersion().toString();

// ArtifactId may differ only for multi-module projects (source roots with module name)
boolean isMultiModule = false;
boolean artifactMatchesModule = false;
for (SourceRoot sr : getSourceRoots(project)) {
Optional<String> moduleName = sr.module();
if (moduleName.isPresent()) {
isMultiModule = true;
if (moduleName.get().equals(a2)) {
artifactMatchesModule = true;
break;
}
}
}
if (!(Objects.equals(g1, g2) && Objects.equals(v1, v2) && (artifactMatchesModule || Objects.equals(a1, a2)))) {
throw new IllegalArgumentException(String.format(
"The produced artifact must have the same groupId%s and version as the project it is attached to.%n"
+ "Expecting %s:%s:%s but received %s:%s:%s.",
isMultiModule ? "" : ", artifactID", g1, a1, v1, g2, a2, v2));
}
getMavenProject(project)
.addAttachedArtifact(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,94 @@

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Supplier;

import org.apache.maven.api.Language;
import org.apache.maven.api.ProducedArtifact;
import org.apache.maven.api.Project;
import org.apache.maven.api.ProjectScope;
import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.impl.DefaultModelVersionParser;
import org.apache.maven.impl.DefaultSourceRoot;
import org.apache.maven.impl.DefaultVersionParser;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.util.version.GenericVersionScheme;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

class DefaultProjectManagerTest {

private DefaultProjectManager projectManager;

private Project project;

private ProducedArtifact artifact;

private Path artifactPath;

@Test
void attachArtifact() {
InternalMavenSession session = Mockito.mock(InternalMavenSession.class);
ArtifactManager artifactManager = Mockito.mock(ArtifactManager.class);
MavenProject mavenProject = new MavenProject();
Project project = new DefaultProject(session, mavenProject);
ProducedArtifact artifact = Mockito.mock(ProducedArtifact.class);
Path path = Paths.get("");
project = new DefaultProject(session, mavenProject);
artifact = Mockito.mock(ProducedArtifact.class);
artifactPath = Paths.get("");
DefaultVersionParser versionParser =
new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme()));
DefaultProjectManager projectManager = new DefaultProjectManager(session, artifactManager);
projectManager = new DefaultProjectManager(session, artifactManager);

mavenProject.setGroupId("myGroup");
mavenProject.setArtifactId("myArtifact");
mavenProject.setVersion("1.0-SNAPSHOT");
when(artifact.getGroupId()).thenReturn("myGroup");
when(artifact.getArtifactId()).thenReturn("myArtifact");
when(artifact.getBaseVersion()).thenReturn(versionParser.parseVersion("1.0-SNAPSHOT"));
projectManager.attachArtifact(project, artifact, path);
projectManager.attachArtifact(project, artifact, artifactPath);

// Verify that an exception is thrown when the artifactId differs
when(artifact.getArtifactId()).thenReturn("anotherArtifact");
assertThrows(IllegalArgumentException.class, () -> projectManager.attachArtifact(project, artifact, path));
assertExceptionMessageContains("myGroup:anotherArtifact:1.0-SNAPSHOT");

// Add a Java module. It should relax the restriction on artifactId.
projectManager.addSourceRoot(
project,
new DefaultSourceRoot(
ProjectScope.MAIN,
Language.JAVA_FAMILY,
"org.foo.bar",
null,
Path.of("myProject"),
null,
null,
false,
null,
true));

// Verify that we get the same exception when the artifactId does not match the module name
assertExceptionMessageContains("myGroup:anotherArtifact:1.0-SNAPSHOT");

// Verify that no exception is thrown when the artifactId is the module name
when(artifact.getArtifactId()).thenReturn("org.foo.bar");
projectManager.attachArtifact(project, artifact, artifactPath);

// Verify that an exception is thrown when the groupId differs
when(artifact.getGroupId()).thenReturn("anotherGroup");
assertExceptionMessageContains("anotherGroup:org.foo.bar:1.0-SNAPSHOT");
}

private void assertExceptionMessageContains(String expectedGAV) {
String cause = assertThrows(
IllegalArgumentException.class,
() -> projectManager.attachArtifact(project, artifact, artifactPath))
.getMessage();
Supplier<String> message = () ->
String.format("The exception message does not contain the expected GAV. Message was:%n%s%n", cause);
assertTrue(cause.contains("myGroup:myArtifact:1.0-SNAPSHOT"), message);
assertTrue(cause.contains(expectedGAV), message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public DefaultSourceRoot(
@Nonnull Language language,
@Nullable String moduleName,
@Nullable Version targetVersionOrNull,
@Nullable Path directory,
@Nonnull Path directory,
@Nullable List<String> includes,
@Nullable List<String> excludes,
boolean stringFiltering,
Expand Down