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
Original file line number Diff line number Diff line change
Expand Up @@ -489,37 +489,38 @@ protected List<CoreExtensions> readCoreExtensionsDescriptor(LocalContext context

// project
file = context.cwd.resolve(eff.get(Constants.MAVEN_PROJECT_EXTENSIONS));
loaded = readCoreExtensionsDescriptorFromFile(file);
loaded = readCoreExtensionsDescriptorFromFile(file, false);
if (!loaded.isEmpty()) {
result.add(new CoreExtensions(file, loaded));
}

// user
file = context.userHomeDirectory.resolve(eff.get(Constants.MAVEN_USER_EXTENSIONS));
loaded = readCoreExtensionsDescriptorFromFile(file);
loaded = readCoreExtensionsDescriptorFromFile(file, true);
if (!loaded.isEmpty()) {
result.add(new CoreExtensions(file, loaded));
}

// installation
file = context.installationDirectory.resolve(eff.get(Constants.MAVEN_INSTALLATION_EXTENSIONS));
loaded = readCoreExtensionsDescriptorFromFile(file);
loaded = readCoreExtensionsDescriptorFromFile(file, true);
if (!loaded.isEmpty()) {
result.add(new CoreExtensions(file, loaded));
}

return result.isEmpty() ? null : List.copyOf(result);
}

protected List<CoreExtension> readCoreExtensionsDescriptorFromFile(Path extensionsFile) {
protected List<CoreExtension> readCoreExtensionsDescriptorFromFile(Path extensionsFile, boolean allowMetaVersions) {
try {
if (extensionsFile != null && Files.exists(extensionsFile)) {
try (InputStream is = Files.newInputStream(extensionsFile)) {
return validateCoreExtensionsDescriptorFromFile(
extensionsFile,
List.copyOf(new CoreExtensionsStaxReader()
.read(is, true, new InputSource(extensionsFile.toString()))
.getExtensions()));
.getExtensions()),
allowMetaVersions);
}
}
return List.of();
Expand All @@ -529,23 +530,37 @@ protected List<CoreExtension> readCoreExtensionsDescriptorFromFile(Path extensio
}

protected List<CoreExtension> validateCoreExtensionsDescriptorFromFile(
Path extensionFile, List<CoreExtension> coreExtensions) {
Path extensionFile, List<CoreExtension> coreExtensions, boolean allowMetaVersions) {
Map<String, List<InputLocation>> gasLocations = new HashMap<>();
Map<String, List<InputLocation>> metaVersionLocations = new HashMap<>();
for (CoreExtension coreExtension : coreExtensions) {
String ga = coreExtension.getGroupId() + ":" + coreExtension.getArtifactId();
InputLocation location = coreExtension.getLocation("");
gasLocations.computeIfAbsent(ga, k -> new ArrayList<>()).add(location);
// TODO: metaversions could be extensible enum with these two values out of the box
if ("LATEST".equals(coreExtension.getVersion()) || "RELEASE".equals(coreExtension.getVersion())) {
metaVersionLocations.computeIfAbsent(ga, k -> new ArrayList<>()).add(location);
}
}
if (gasLocations.values().stream().noneMatch(l -> l.size() > 1)) {
return coreExtensions;
}
throw new IllegalStateException("Extension conflicts in file " + extensionFile + ": "
+ gasLocations.entrySet().stream()
.map(e -> e.getKey() + " defined on lines "
+ e.getValue().stream()
.map(l -> String.valueOf(l.getLineNumber()))
.collect(Collectors.joining(", ")))
.collect(Collectors.joining("; ")));
if (gasLocations.values().stream().anyMatch(l -> l.size() > 1)) {
throw new IllegalStateException("Extension conflicts in file " + extensionFile + ": "
+ gasLocations.entrySet().stream()
.map(e -> e.getKey() + " defined on lines "
+ e.getValue().stream()
.map(l -> String.valueOf(l.getLineNumber()))
.collect(Collectors.joining(", ")))
.collect(Collectors.joining("; ")));
}
if (!allowMetaVersions && !metaVersionLocations.isEmpty()) {
throw new IllegalStateException("Extension with illegal version in file " + extensionFile + ": "
+ metaVersionLocations.entrySet().stream()
.map(e -> e.getKey() + " defined on lines "
+ e.getValue().stream()
.map(l -> String.valueOf(l.getLineNumber()))
.collect(Collectors.joining(", ")))
.collect(Collectors.joining("; ")));
}
return coreExtensions;
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import org.apache.maven.api.cli.CoreExtensions;
Expand Down Expand Up @@ -60,7 +61,7 @@ protected List<CoreExtension> selectCoreExtensions(C context, List<CoreExtension
for (CoreExtension coreExtension : coreExtensions.coreExtensions()) {
String key = coreExtension.getGroupId() + ":" + coreExtension.getArtifactId();
CoreExtension conflict = selectedExtensions.putIfAbsent(key, coreExtension);
if (conflict != null) {
if (conflict != null && !Objects.equals(coreExtension.getVersion(), conflict.getVersion())) {
conflicts.add(String.format(
"Conflicting extension %s: %s vs %s",
key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,38 @@ public DependencyResult resolveCoreExtension(
List<RemoteRepository> repositories,
RepositorySystemSession session)
throws PluginResolutionException {
return resolveInternal(plugin, null /* pluginArtifact */, dependencyFilter, repositories, session);
RequestTrace trace = RequestTrace.newChild(null, plugin);

Artifact pluginArtifact = toArtifact(plugin, session);

try {
DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession(session);
pluginSession.setArtifactDescriptorPolicy(new SimpleArtifactDescriptorPolicy(true, false));

ArtifactDescriptorRequest request =
new ArtifactDescriptorRequest(pluginArtifact, repositories, REPOSITORY_CONTEXT);
request.setTrace(trace);
ArtifactDescriptorResult result = repoSystem.readArtifactDescriptor(pluginSession, request);

for (MavenPluginDependenciesValidator dependenciesValidator : dependenciesValidators) {
dependenciesValidator.validate(session, pluginArtifact, result);
}

pluginArtifact = result.getArtifact();

if (logger.isWarnEnabled() && !result.getRelocations().isEmpty()) {
String message =
pluginArtifact instanceof RelocatedArtifact relocated ? ": " + relocated.getMessage() : "";
logger.warn(
"The extension {} has been relocated to {}{}",
result.getRelocations().get(0),
pluginArtifact,
message);
}
return resolveInternal(plugin, pluginArtifact, dependencyFilter, repositories, session);
} catch (ArtifactDescriptorException e) {
throw new PluginResolutionException(plugin, e.getResult().getExceptions(), e);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* 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.it;

import java.nio.file.Path;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* This is a test set for GH-11181.
*/
class MavenITgh11181CoreExtensionsMetaVersionsTest extends AbstractMavenIntegrationTestCase {
MavenITgh11181CoreExtensionsMetaVersionsTest() {
super("[4.1.0-SNAPSHOT,)");
}

/**
* Project wide extensions: use of meta versions is invalid.
*/
@Test
void pwMetaVersionIsInvalid() throws Exception {
Path testDir = extractResources("/gh-11181-core-extensions-meta-versions")
.toPath()
.toAbsolutePath()
.resolve("pw-metaversion-is-invalid");
Verifier verifier = newVerifier(testDir.toString());
verifier.setUserHomeDirectory(testDir.resolve("HOME"));
verifier.setAutoclean(false);
verifier.addCliArgument("validate");
try {
verifier.execute();
fail("Expected VerificationException");
} catch (VerificationException e) {
// there is not even a log; this is very early failure
assertTrue(e.getMessage().contains("Error executing Maven."));
}
}

/**
* User wide extensions: use of meta versions is valid.
*/
@Test
void uwMetaVersionIsValid() throws Exception {
Path testDir = extractResources("/gh-11181-core-extensions-meta-versions")
.toPath()
.toAbsolutePath()
.resolve("uw-metaversion-is-valid");
Verifier verifier = newVerifier(testDir.toString());
verifier.setUserHomeDirectory(testDir.resolve("HOME"));
verifier.setHandleLocalRepoTail(false);
verifier.setAutoclean(false);
verifier.addCliArgument("validate");
verifier.execute();

verifier.verifyErrorFreeLog();
}

/**
* Same GA different V extensions in project-wide and user-wide: warn for conflict.
*/
@Test
void uwPwDifferentVersionIsConflict() throws Exception {
Path testDir = extractResources("/gh-11181-core-extensions-meta-versions")
.toPath()
.toAbsolutePath()
.resolve("uw-pw-different-version-is-conflict");
Verifier verifier = newVerifier(testDir.toString());
verifier.setUserHomeDirectory(testDir.resolve("HOME"));
verifier.setHandleLocalRepoTail(false);
verifier.setAutoclean(false);
verifier.addCliArgument("validate");
verifier.execute();

verifier.verifyErrorFreeLog();
verifier.verifyTextInLog("WARNING");
verifier.verifyTextInLog("Conflicting extension io.takari.maven:takari-smart-builder");
}

/**
* Same GAV extensions in project-wide and user-wide: do not warn for conflict.
*/
@Test
void uwPwSameVersionIsNotConflict() throws Exception {
Path testDir = extractResources("/gh-11181-core-extensions-meta-versions")
.toPath()
.toAbsolutePath()
.resolve("uw-pw-same-version-is-not-conflict");
Verifier verifier = newVerifier(testDir.toString());
verifier.setUserHomeDirectory(testDir.resolve("HOME"));
verifier.setHandleLocalRepoTail(false);
verifier.setAutoclean(false);
verifier.addCliArgument("validate");
verifier.execute();

verifier.verifyErrorFreeLog();
verifier.verifyTextNotInLog("WARNING");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public TestSuiteOrdering() {
* the tests are to finishing. Newer tests are also more likely to fail, so this is
* a fail fast technique as well.
*/
suite.addTestSuite(MavenITgh11181CoreExtensionsMetaVersionsTest.class);
suite.addTestSuite(MavenITgh11055DIServiceInjectionTest.class);
suite.addTestSuite(MavenITgh11084ReactorReaderPreferConsumerPomTest.class);
suite.addTestSuite(MavenITgh10210SettingsXmlDecryptTest.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
<extension>
<groupId>io.takari.maven</groupId>
<artifactId>takari-smart-builder</artifactId>
<version>RELEASE</version>
</extension>
</extensions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>org.apache.maven.its.gh11181</groupId>
<artifactId>pw-metaversion-is-invalid</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.13.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
<extension>
<groupId>io.takari.maven</groupId>
<artifactId>takari-smart-builder</artifactId>
<version>RELEASE</version>
</extension>
</extensions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>org.apache.maven.its.gh11181</groupId>
<artifactId>uw-metaversion-is-valid</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.13.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
<extension>
<groupId>io.takari.maven</groupId>
<artifactId>takari-smart-builder</artifactId>
<version>1.1.0</version>
</extension>
</extensions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
<extension>
<groupId>io.takari.maven</groupId>
<artifactId>takari-smart-builder</artifactId>
<version>1.0.2</version>
</extension>
</extensions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>org.apache.maven.its.gh11181</groupId>
<artifactId>uw-metaversion-is-valid</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.13.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
<extension>
<groupId>io.takari.maven</groupId>
<artifactId>takari-smart-builder</artifactId>
<version>1.1.0</version>
</extension>
</extensions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
<extension>
<groupId>io.takari.maven</groupId>
<artifactId>takari-smart-builder</artifactId>
<version>1.1.0</version>
</extension>
</extensions>
Loading
Loading