[MNG-8402] System properties can take precedence over builtin expressions (#1947)

This commit is contained in:
Guillaume Nodet 2024-12-04 17:54:29 +01:00 committed by GitHub
parent 794efae428
commit 73e30c5d6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1059 additions and 950 deletions

View File

@ -176,7 +176,6 @@ under the License.
<dependency> <dependency>
<groupId>com.google.jimfs</groupId> <groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId> <artifactId>jimfs</artifactId>
<version>1.3.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -92,7 +92,6 @@ under the License.
<dependency> <dependency>
<groupId>com.google.jimfs</groupId> <groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId> <artifactId>jimfs</artifactId>
<version>1.3.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -164,6 +164,11 @@ under the License.
<artifactId>maven-resolver-transport-apache</artifactId> <artifactId>maven-resolver-transport-apache</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -184,8 +184,12 @@ public class DefaultModelInterpolator implements ModelInterpolator {
} }
} }
} }
// un-prefixed model reflection
String value = projectProperty(model, projectDir, expression, false);
// user properties // user properties
String value = request.getUserProperties().get(expression); if (value == null) {
value = request.getUserProperties().get(expression);
}
// model properties // model properties
if (value == null) { if (value == null) {
value = model.getProperties().get(expression); value = model.getProperties().get(expression);
@ -198,12 +202,8 @@ public class DefaultModelInterpolator implements ModelInterpolator {
if (value == null) { if (value == null) {
value = request.getSystemProperties().get("env." + expression); value = request.getSystemProperties().get("env." + expression);
} }
if (value != null) {
return value; return value;
} }
// model reflection
return projectProperty(model, projectDir, expression, false);
}
String projectProperty(Model model, Path projectDir, String subExpr, boolean prefixed) { String projectProperty(Model model, Path projectDir, String subExpr, boolean prefixed) {
if (projectDir != null) { if (projectDir != null) {
@ -223,7 +223,7 @@ public class DefaultModelInterpolator implements ModelInterpolator {
} else if (prefixed && subExpr.startsWith("baseUri.")) { } else if (prefixed && subExpr.startsWith("baseUri.")) {
try { try {
Object value = ReflectionValueExtractor.evaluate( Object value = ReflectionValueExtractor.evaluate(
subExpr, projectDir.toAbsolutePath().toUri(), false); subExpr, projectDir.toAbsolutePath().toUri(), true);
if (value != null) { if (value != null) {
return value.toString(); return value.toString();
} }
@ -234,8 +234,8 @@ public class DefaultModelInterpolator implements ModelInterpolator {
return rootLocator.findMandatoryRoot(projectDir).toString(); return rootLocator.findMandatoryRoot(projectDir).toString();
} else if (prefixed && subExpr.startsWith("rootDirectory.")) { } else if (prefixed && subExpr.startsWith("rootDirectory.")) {
try { try {
Object value = ReflectionValueExtractor.evaluate( Object value =
subExpr, projectDir.toAbsolutePath().toUri(), false); ReflectionValueExtractor.evaluate(subExpr, rootLocator.findMandatoryRoot(projectDir), true);
if (value != null) { if (value != null) {
return value.toString(); return value.toString();
} }

View File

@ -0,0 +1,606 @@
/*
* 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.internal.impl.model;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicReference;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import org.apache.maven.api.Session;
import org.apache.maven.api.di.Priority;
import org.apache.maven.api.di.Provides;
import org.apache.maven.api.model.Build;
import org.apache.maven.api.model.Dependency;
import org.apache.maven.api.model.Model;
import org.apache.maven.api.model.Organization;
import org.apache.maven.api.model.Repository;
import org.apache.maven.api.model.Resource;
import org.apache.maven.api.model.Scm;
import org.apache.maven.api.services.Lookup;
import org.apache.maven.api.services.ModelBuilderRequest;
import org.apache.maven.api.services.model.ModelInterpolator;
import org.apache.maven.api.services.model.RootLocator;
import org.apache.maven.internal.impl.model.profile.SimpleProblemCollector;
import org.apache.maven.internal.impl.standalone.ApiRunner;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
*/
class DefaultModelInterpolatorTest {
Map<String, String> context;
ModelInterpolator interpolator;
Session session;
AtomicReference<Path> rootDirectory; // used in TestRootLocator below
@BeforeEach
public void setUp() {
context = new HashMap<>();
context.put("basedir", "myBasedir");
context.put("anotherdir", "anotherBasedir");
context.put("project.baseUri", "myBaseUri");
session = ApiRunner.createSession(injector -> {
injector.bindInstance(DefaultModelInterpolatorTest.class, this);
});
interpolator = session.getService(Lookup.class).lookup(DefaultModelInterpolator.class);
}
protected void assertProblemFree(SimpleProblemCollector collector) {
assertEquals(0, collector.getErrors().size(), "Expected no errors");
assertEquals(0, collector.getWarnings().size(), "Expected no warnings");
assertEquals(0, collector.getFatals().size(), "Expected no fatals");
}
@SuppressWarnings("SameParameterValue")
protected void assertCollectorState(
int numFatals, int numErrors, int numWarnings, SimpleProblemCollector collector) {
assertEquals(numErrors, collector.getErrors().size(), "Errors");
assertEquals(numWarnings, collector.getWarnings().size(), "Warnings");
assertEquals(numFatals, collector.getFatals().size(), "Fatals");
}
private ModelBuilderRequest.ModelBuilderRequestBuilder createModelBuildingRequest(Map<String, String> p) {
ModelBuilderRequest.ModelBuilderRequestBuilder config = ModelBuilderRequest.builder()
.session(session)
.requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT);
if (p != null) {
config.systemProperties(p);
}
return config;
}
@Test
public void testDefaultBuildTimestampFormatShouldFormatTimeIn24HourFormat() {
Calendar cal = Calendar.getInstance();
cal.setTimeZone(MavenBuildTimestamp.DEFAULT_BUILD_TIME_ZONE);
cal.set(Calendar.HOUR, 12);
cal.set(Calendar.AM_PM, Calendar.AM);
// just to make sure all the bases are covered...
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 16);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.YEAR, 1976);
cal.set(Calendar.MONTH, Calendar.NOVEMBER);
cal.set(Calendar.DATE, 11);
Date firstTestDate = cal.getTime();
cal.set(Calendar.HOUR, 11);
cal.set(Calendar.AM_PM, Calendar.PM);
// just to make sure all the bases are covered...
cal.set(Calendar.HOUR_OF_DAY, 23);
Date secondTestDate = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat(MavenBuildTimestamp.DEFAULT_BUILD_TIMESTAMP_FORMAT);
format.setTimeZone(MavenBuildTimestamp.DEFAULT_BUILD_TIME_ZONE);
assertEquals("1976-11-11T00:16:00Z", format.format(firstTestDate));
assertEquals("1976-11-11T23:16:00Z", format.format(secondTestDate));
}
@Test
public void testDefaultBuildTimestampFormatWithLocalTimeZoneMidnightRollover() {
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
cal.set(Calendar.HOUR_OF_DAY, 1);
cal.set(Calendar.MINUTE, 16);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.YEAR, 2014);
cal.set(Calendar.MONTH, Calendar.JUNE);
cal.set(Calendar.DATE, 16);
Date firstTestDate = cal.getTime();
cal.set(Calendar.MONTH, Calendar.NOVEMBER);
Date secondTestDate = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat(MavenBuildTimestamp.DEFAULT_BUILD_TIMESTAMP_FORMAT);
format.setTimeZone(MavenBuildTimestamp.DEFAULT_BUILD_TIME_ZONE);
assertEquals("2014-06-15T23:16:00Z", format.format(firstTestDate));
assertEquals("2014-11-16T00:16:00Z", format.format(secondTestDate));
}
@Test
public void testShouldNotThrowExceptionOnReferenceToNonExistentValue() throws Exception {
Scm scm = Scm.newBuilder().connection("${test}/somepath").build();
Model model = Model.newBuilder().scm(scm).build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals("${test}/somepath", out.getScm().getConnection());
}
@Test
public void testShouldThrowExceptionOnRecursiveScmConnectionReference() throws Exception {
Scm scm = Scm.newBuilder()
.connection("${project.scm.connection}/somepath")
.build();
Model model = Model.newBuilder().scm(scm).build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
interpolator.interpolateModel(
model, (Path) null, createModelBuildingRequest(context).build(), collector);
assertCollectorState(0, 1, 0, collector);
}
@Test
public void testShouldNotThrowExceptionOnReferenceToValueContainingNakedExpression() throws Exception {
Scm scm = Scm.newBuilder().connection("${test}/somepath").build();
Map<String, String> props = new HashMap<>();
props.put("test", "test");
Model model = Model.newBuilder().scm(scm).properties(props).build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals("test/somepath", out.getScm().getConnection());
}
@Test
void shouldInterpolateOrganizationNameCorrectly() throws Exception {
String orgName = "MyCo";
Model model = Model.newBuilder()
.name("${project.organization.name} Tools")
.organization(Organization.newBuilder().name(orgName).build())
.build();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), new SimpleProblemCollector());
assertEquals(orgName + " Tools", out.getName());
}
@Test
public void shouldInterpolateDependencyVersionToSetSameAsProjectVersion() throws Exception {
Model model = Model.newBuilder()
.version("3.8.1")
.dependencies(Collections.singletonList(
Dependency.newBuilder().version("${project.version}").build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertCollectorState(0, 0, 0, collector);
assertEquals("3.8.1", (out.getDependencies().get(0)).getVersion());
}
@Test
public void testShouldNotInterpolateDependencyVersionWithInvalidReference() throws Exception {
Model model = Model.newBuilder()
.version("3.8.1")
.dependencies(Collections.singletonList(
Dependency.newBuilder().version("${something}").build()))
.build();
/*
// This is the desired behaviour, however there are too many crappy poms in the repo and an issue with the
// timing of executing the interpolation
try
{
new RegexBasedModelInterpolator().interpolate( model, context );
fail( "Should have failed to interpolate with invalid reference" );
}
catch ( ModelInterpolationException expected )
{
assertTrue( true );
}
*/
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals("${something}", (out.getDependencies().get(0)).getVersion());
}
@Test
public void testTwoReferences() throws Exception {
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.dependencies(Collections.singletonList(Dependency.newBuilder()
.version("${project.artifactId}-${project.version}")
.build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertCollectorState(0, 0, 0, collector);
assertEquals("foo-3.8.1", (out.getDependencies().get(0)).getVersion());
}
@Test
public void testProperty() throws Exception {
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.repositories(Collections.singletonList(Repository.newBuilder()
.url("file://localhost/${anotherdir}/temp-repo")
.build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model,
Paths.get("projectBasedir"),
createModelBuildingRequest(context).build(),
collector);
assertProblemFree(collector);
assertEquals(
"file://localhost/anotherBasedir/temp-repo",
(out.getRepositories().get(0)).getUrl());
}
@Test
public void testBasedirUnx() throws Exception {
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path projectBasedir = fs.getPath("projectBasedir");
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.repositories(Collections.singletonList(
Repository.newBuilder().url("${basedir}/temp-repo").build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, projectBasedir, createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals(
projectBasedir.toAbsolutePath() + "/temp-repo",
(out.getRepositories().get(0)).getUrl());
}
@Test
public void testBasedirWin() throws Exception {
FileSystem fs = Jimfs.newFileSystem(Configuration.windows());
Path projectBasedir = fs.getPath("projectBasedir");
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.repositories(Collections.singletonList(
Repository.newBuilder().url("${basedir}/temp-repo").build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, projectBasedir, createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals(
projectBasedir.toAbsolutePath() + "/temp-repo",
(out.getRepositories().get(0)).getUrl());
}
@Test
public void testBaseUri() throws Exception {
Path projectBasedir = Paths.get("projectBasedir");
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.repositories(Collections.singletonList(Repository.newBuilder()
.url("${project.baseUri}/temp-repo")
.build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, projectBasedir, createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals(
projectBasedir.resolve("temp-repo").toUri().toString(),
(out.getRepositories().get(0)).getUrl());
}
@Test
void testRootDirectory() throws Exception {
Path rootDirectory = Paths.get("myRootDirectory");
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.repositories(Collections.singletonList(Repository.newBuilder()
.url("file:${project.rootDirectory}/temp-repo")
.build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, rootDirectory, createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals("file:myRootDirectory/temp-repo", (out.getRepositories().get(0)).getUrl());
}
@Test
void testRootDirectoryWithUri() throws Exception {
Path rootDirectory = Paths.get("myRootDirectory");
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.repositories(Collections.singletonList(Repository.newBuilder()
.url("${project.rootDirectory.uri}/temp-repo")
.build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, rootDirectory, createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals(
rootDirectory.resolve("temp-repo").toUri().toString(),
(out.getRepositories().get(0)).getUrl());
}
@Test
void testRootDirectoryWithNull() throws Exception {
Path projectDirectory = Paths.get("myProjectDirectory");
this.rootDirectory = new AtomicReference<>(null);
Model model = Model.newBuilder()
.version("3.8.1")
.artifactId("foo")
.repositories(Collections.singletonList(Repository.newBuilder()
.url("file:///${project.rootDirectory}/temp-repo")
.build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
IllegalStateException e = assertThrows(
IllegalStateException.class,
() -> interpolator.interpolateModel(
model,
projectDirectory,
createModelBuildingRequest(context).build(),
collector));
assertEquals(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE, e.getMessage());
}
@Test
public void testEnvars() throws Exception {
context.put("env.HOME", "/path/to/home");
Map<String, String> modelProperties = new HashMap<>();
modelProperties.put("outputDirectory", "${env.HOME}");
Model model = Model.newBuilder().properties(modelProperties).build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals("/path/to/home", out.getProperties().get("outputDirectory"));
}
@Test
public void envarExpressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception {
Map<String, String> modelProperties = new HashMap<>();
modelProperties.put("outputDirectory", "${env.DOES_NOT_EXIST}");
Model model = Model.newBuilder().properties(modelProperties).build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals(out.getProperties().get("outputDirectory"), "${env.DOES_NOT_EXIST}");
}
@Test
public void expressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception {
Map<String, String> modelProperties = new HashMap<>();
modelProperties.put("outputDirectory", "${DOES_NOT_EXIST}");
Model model = Model.newBuilder().properties(modelProperties).build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, Paths.get("."), createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
assertEquals("${DOES_NOT_EXIST}", out.getProperties().get("outputDirectory"));
}
@Test
public void shouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorrectly() throws Exception {
Model model = Model.newBuilder()
.build(Build.newBuilder()
.sourceDirectory("correct")
.resources(List.of(Resource.newBuilder()
.directory("${project.build.sourceDirectory}")
.build()))
.build())
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model, (Path) null, createModelBuildingRequest(context).build(), collector);
assertCollectorState(0, 0, 0, collector);
List<Resource> outResources = out.getBuild().getResources();
Iterator<Resource> resIt = outResources.iterator();
assertEquals(model.getBuild().getSourceDirectory(), resIt.next().getDirectory());
}
@Test
public void shouldInterpolateUnprefixedBasedirExpression() throws Exception {
Path basedir = Paths.get("/test/path");
Model model = Model.newBuilder()
.dependencies(Collections.singletonList(Dependency.newBuilder()
.systemPath("${basedir}/artifact.jar")
.build()))
.build();
final SimpleProblemCollector collector = new SimpleProblemCollector();
Model result = interpolator.interpolateModel(
model, basedir, createModelBuildingRequest(context).build(), collector);
assertProblemFree(collector);
List<Dependency> rDeps = result.getDependencies();
assertNotNull(rDeps);
assertEquals(1, rDeps.size());
assertEquals(
basedir.resolve("artifact.jar").toAbsolutePath(),
Paths.get(rDeps.get(0).getSystemPath()).toAbsolutePath());
}
@Test
public void testRecursiveExpressionCycleNPE() throws Exception {
Map<String, String> props = new HashMap<>();
props.put("aa", "${bb}");
props.put("bb", "${aa}");
Model model = Model.newBuilder().properties(props).build();
SimpleProblemCollector collector = new SimpleProblemCollector();
ModelBuilderRequest request = createModelBuildingRequest(Map.of()).build();
interpolator.interpolateModel(model, null, request, collector);
assertCollectorState(0, 2, 0, collector);
assertTrue(collector.getErrors().get(0).contains("recursive variable reference"));
}
@Test
public void testRecursiveExpressionCycleBaseDir() throws Exception {
Map<String, String> props = new HashMap<>();
props.put("basedir", "${basedir}");
ModelBuilderRequest request = createModelBuildingRequest(Map.of()).build();
Model model = Model.newBuilder().properties(props).build();
SimpleProblemCollector collector = new SimpleProblemCollector();
ModelInterpolator interpolator = this.interpolator;
interpolator.interpolateModel(model, null, request, collector);
assertCollectorState(0, 1, 0, collector);
assertEquals(
"recursive variable reference: basedir", collector.getErrors().get(0));
}
@Test
void shouldIgnorePropertiesWithPomPrefix() throws Exception {
final String orgName = "MyCo";
final String uninterpolatedName = "${pom.organization.name} Tools";
Model model = Model.newBuilder()
.name(uninterpolatedName)
.organization(Organization.newBuilder().name(orgName).build())
.build();
SimpleProblemCollector collector = new SimpleProblemCollector();
Model out = interpolator.interpolateModel(
model,
null,
createModelBuildingRequest(context).build(),
// .validationLevel(ModelBuilderRequest.VALIDATION_LEVEL_MAVEN_4_0),
collector);
assertCollectorState(0, 0, 0, collector);
assertEquals(uninterpolatedName, out.getName());
}
@Provides
@Priority(10)
@SuppressWarnings("unused")
RootLocator testRootLocator() {
return new RootLocator() {
@Override
public Path findRoot(Path basedir) {
return rootDirectory != null ? rootDirectory.get() : basedir;
}
@Override
public Path findMandatoryRoot(Path basedir) {
return Optional.ofNullable(findRoot(basedir))
.orElseThrow(() -> new IllegalStateException(getNoRootMessage()));
}
};
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.internal.impl.model;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
class MavenBuildTimestampTest {
@Test
void testMavenBuildTimestampUsesUTC() {
Map<String, String> interpolationProperties = new HashMap<>();
interpolationProperties.put("maven.build.timestamp.format", "yyyyMMdd'T'HHmm'Z'");
MavenBuildTimestamp timestamp = new MavenBuildTimestamp(Instant.now(), interpolationProperties);
String formattedTimestamp = timestamp.formattedTimestamp();
assertTrue(formattedTimestamp.endsWith("Z"), "We expect the UTC marker at the end of the timestamp.");
}
}

View File

@ -105,17 +105,22 @@ public class SimpleProblemCollector implements ModelProblemCollector {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public List<String> getFatals() {
return getForLevel(ModelProblem.Severity.FATAL);
}
public List<String> getErrors() { public List<String> getErrors() {
return problems.stream() return getForLevel(ModelProblem.Severity.ERROR);
.filter(p -> p.getSeverity() == ModelProblem.Severity.ERROR)
.map(p -> p.getMessage())
.toList();
} }
public List<String> getWarnings() { public List<String> getWarnings() {
return getForLevel(ModelProblem.Severity.WARNING);
}
private List<String> getForLevel(BuilderProblem.Severity severity) {
return problems.stream() return problems.stream()
.filter(p -> p.getSeverity() == ModelProblem.Severity.WARNING) .filter(p -> p.getSeverity() == severity)
.map(p -> p.getMessage()) .map(BuilderProblem::getMessage)
.toList(); .toList();
} }
} }

View File

@ -29,6 +29,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.maven.api.Artifact; import org.apache.maven.api.Artifact;
@ -64,7 +65,6 @@ import org.apache.maven.internal.impl.resolver.scopes.Maven4ScopeManagerConfigur
import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.internal.impl.scope.ScopeManagerImpl; import org.eclipse.aether.internal.impl.scope.ScopeManagerImpl;
import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.LocalRepositoryManager; import org.eclipse.aether.repository.LocalRepositoryManager;
@ -75,10 +75,21 @@ public class ApiRunner {
* Create a new session. * Create a new session.
*/ */
public static Session createSession() { public static Session createSession() {
return createSession(null);
}
/**
* Create a new session.
*/
public static Session createSession(Consumer<Injector> injectorConsumer) {
Injector injector = Injector.create(); Injector injector = Injector.create();
injector.bindInstance(Injector.class, injector); injector.bindInstance(Injector.class, injector);
injector.bindImplicit(ApiRunner.class); injector.bindImplicit(ApiRunner.class);
injector.bindImplicit(RepositorySystemSupplier.class);
injector.discover(ApiRunner.class.getClassLoader()); injector.discover(ApiRunner.class.getClassLoader());
if (injectorConsumer != null) {
injectorConsumer.accept(injector);
}
Session session = injector.getInstance(Session.class); Session session = injector.getInstance(Session.class);
SessionScope scope = new SessionScope(); SessionScope scope = new SessionScope();
scope.enter(); scope.enter();
@ -286,24 +297,6 @@ public class ApiRunner {
}; };
} }
@Provides
@SuppressWarnings("unused")
static RepositorySystemSupplier newRepositorySystemSupplier() {
return new RepositorySystemSupplier();
}
@Provides
@SuppressWarnings("unused")
static RepositorySystem newRepositorySystem(RepositorySystemSupplier repositorySystemSupplier) {
return repositorySystemSupplier.getRepositorySystem();
}
@Provides
@SuppressWarnings("unused")
static RemoteRepositoryManager newRemoteRepositoryManager(RepositorySystemSupplier repositorySystemSupplier) {
return repositorySystemSupplier.getRemoteRepositoryManager();
}
@Provides @Provides
@SuppressWarnings("unused") @SuppressWarnings("unused")
static Session newSession(RepositorySystem system, Lookup lookup) { static Session newSession(RepositorySystem system, Lookup lookup) {
@ -313,6 +306,10 @@ public class ApiRunner {
// Java System properties // Java System properties
System.getProperties().forEach((k, v) -> properties.put(k.toString(), v.toString())); System.getProperties().forEach((k, v) -> properties.put(k.toString(), v.toString()));
// Do not allow user settings to interfere with our unit tests
// TODO: remove that when this go more public
properties.put("user.home", "target");
// SettingsDecrypter settingsDecrypter = // SettingsDecrypter settingsDecrypter =
// (SettingsDecrypter)Objects.requireNonNull(this.createSettingsDecrypter(preBoot)); // (SettingsDecrypter)Objects.requireNonNull(this.createSettingsDecrypter(preBoot));
// new DefaultProfileSelector(List.of( // new DefaultProfileSelector(List.of(

View File

@ -648,6 +648,11 @@ under the License.
<artifactId>byte-buddy</artifactId> <artifactId>byte-buddy</artifactId>
<version>${byteBuddyVersion}</version> <version>${byteBuddyVersion}</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies> </dependencies>
<!--bootstrap-start-comment--> <!--bootstrap-start-comment-->
</dependencyManagement> </dependencyManagement>