mirror of https://github.com/apache/maven.git
Merge remote-tracking branch 'upstream/master' into MNG-8451
This commit is contained in:
commit
99f5cab86e
|
@ -18,10 +18,6 @@
|
|||
*/
|
||||
package org.apache.maven.api.services;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
|
||||
/**
|
||||
|
@ -32,14 +28,14 @@ import org.apache.maven.api.annotations.Experimental;
|
|||
@Experimental
|
||||
public abstract class MavenBuilderException extends MavenException {
|
||||
|
||||
private final List<BuilderProblem> problems;
|
||||
private final ProblemCollector<BuilderProblem> problems;
|
||||
|
||||
public MavenBuilderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
problems = List.of();
|
||||
problems = ProblemCollector.empty();
|
||||
}
|
||||
|
||||
public MavenBuilderException(String message, List<BuilderProblem> problems) {
|
||||
public MavenBuilderException(String message, ProblemCollector<BuilderProblem> problems) {
|
||||
super(buildMessage(message, problems), null);
|
||||
this.problems = problems;
|
||||
}
|
||||
|
@ -49,20 +45,16 @@ public abstract class MavenBuilderException extends MavenException {
|
|||
* and then a list is built. These exceptions are usually thrown in "fatal" cases (and usually prevent Maven
|
||||
* from starting), and these exceptions may end up very early on output.
|
||||
*/
|
||||
protected static String buildMessage(String message, List<BuilderProblem> problems) {
|
||||
protected static String buildMessage(String message, ProblemCollector<BuilderProblem> problems) {
|
||||
StringBuilder msg = new StringBuilder(message);
|
||||
ArrayList<BuilderProblem> sorted = new ArrayList<>(problems);
|
||||
sorted.sort(Comparator.comparing(BuilderProblem::getSeverity));
|
||||
for (BuilderProblem problem : sorted) {
|
||||
msg.append("\n * ")
|
||||
.append(problem.getSeverity().name())
|
||||
.append(": ")
|
||||
.append(problem.getMessage());
|
||||
}
|
||||
problems.problems().forEach(problem -> msg.append("\n * ")
|
||||
.append(problem.getSeverity().name())
|
||||
.append(": ")
|
||||
.append(problem.getMessage()));
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
public List<BuilderProblem> getProblems() {
|
||||
public ProblemCollector<BuilderProblem> getProblemCollector() {
|
||||
return problems;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
package org.apache.maven.api.services;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
|
||||
|
@ -82,10 +80,10 @@ public class ModelBuilderException extends MavenException {
|
|||
*
|
||||
* @return The problems that caused this exception, never {@code null}.
|
||||
*/
|
||||
public List<ModelProblem> getProblems() {
|
||||
public ProblemCollector<ModelProblem> getProblemCollector() {
|
||||
if (result == null) {
|
||||
return Collections.emptyList();
|
||||
return ProblemCollector.empty();
|
||||
}
|
||||
return Collections.unmodifiableList(result.getProblems());
|
||||
return result.getProblemCollector();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,12 +91,12 @@ public interface ModelBuilderResult {
|
|||
List<Profile> getActiveExternalProfiles();
|
||||
|
||||
/**
|
||||
* Gets the problems that were encountered during the project building.
|
||||
* Gets the problem collector that collected problems encountered during the project building.
|
||||
*
|
||||
* @return the problems that were encountered during the project building, can be empty but never {@code null}
|
||||
* @return the problem collector that collected problems encountered during the project building
|
||||
*/
|
||||
@Nonnull
|
||||
List<ModelProblem> getProblems();
|
||||
ProblemCollector<ModelProblem> getProblemCollector();
|
||||
|
||||
/**
|
||||
* Gets the children of this result.
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
package org.apache.maven.api.services;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.model.InputLocation;
|
||||
import org.apache.maven.api.model.Model;
|
||||
|
||||
|
@ -33,15 +31,15 @@ import org.apache.maven.api.model.Model;
|
|||
*/
|
||||
public interface ModelProblemCollector {
|
||||
|
||||
/**
|
||||
* The collected problems.
|
||||
* @return a list of model problems encountered, never {@code null}
|
||||
*/
|
||||
List<ModelProblem> getProblems();
|
||||
ProblemCollector<ModelProblem> getProblemCollector();
|
||||
|
||||
boolean hasErrors();
|
||||
default boolean hasErrors() {
|
||||
return getProblemCollector().hasErrorProblems();
|
||||
}
|
||||
|
||||
boolean hasFatalErrors();
|
||||
default boolean hasFatalErrors() {
|
||||
return getProblemCollector().hasFatalProblems();
|
||||
}
|
||||
|
||||
default void add(BuilderProblem.Severity severity, ModelProblem.Version version, String message) {
|
||||
add(severity, version, message, null, null);
|
||||
|
@ -64,7 +62,9 @@ public interface ModelProblemCollector {
|
|||
InputLocation location,
|
||||
Exception exception);
|
||||
|
||||
void add(ModelProblem problem);
|
||||
default void add(ModelProblem problem) {
|
||||
getProblemCollector().reportProblem(problem);
|
||||
}
|
||||
|
||||
ModelBuilderException newModelBuilderException();
|
||||
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* 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.api.services;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.api.Constants;
|
||||
import org.apache.maven.api.ProtoSession;
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.annotations.Nullable;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Collects problems that were encountered during project building.
|
||||
*
|
||||
* @param <P> The type of the problem.
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface ProblemCollector<P extends BuilderProblem> {
|
||||
/**
|
||||
* Returns {@code true} if there is at least one problem collected with severity equal or more severe than
|
||||
* {@link org.apache.maven.api.services.BuilderProblem.Severity#WARNING}. This check is logically equivalent
|
||||
* to "is there any problem reported?", given warning is the lowest severity.
|
||||
*/
|
||||
default boolean hasWarningProblems() {
|
||||
return hasProblemsFor(BuilderProblem.Severity.WARNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if there is at least one problem collected with severity equal or more severe than
|
||||
* {@link org.apache.maven.api.services.BuilderProblem.Severity#ERROR}.
|
||||
*/
|
||||
default boolean hasErrorProblems() {
|
||||
return hasProblemsFor(BuilderProblem.Severity.ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if there is at least one problem collected with severity equal or more severe than
|
||||
* {@link org.apache.maven.api.services.BuilderProblem.Severity#FATAL}.
|
||||
*/
|
||||
default boolean hasFatalProblems() {
|
||||
return hasProblemsFor(BuilderProblem.Severity.FATAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if there is at least one problem collected with severity equal or more severe than
|
||||
* passed in severity.
|
||||
*/
|
||||
default boolean hasProblemsFor(BuilderProblem.Severity severity) {
|
||||
requireNonNull(severity, "severity");
|
||||
for (BuilderProblem.Severity s : BuilderProblem.Severity.values()) {
|
||||
if (s.ordinal() <= severity.ordinal() && problemsReportedFor(s) > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns total count of problems reported.
|
||||
*/
|
||||
default int totalProblemsReported() {
|
||||
return problemsReportedFor(BuilderProblem.Severity.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns count of problems reported for given severities.
|
||||
*/
|
||||
int problemsReportedFor(BuilderProblem.Severity... severities);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if reported problem count exceeded allowed count, and issues were lost. When this
|
||||
* method returns {@code true}, it means that element count of stream returned by method {@link #problems()}
|
||||
* and the counter returned by {@link #totalProblemsReported()} are not equal (latter is bigger than former).
|
||||
*/
|
||||
boolean problemsOverflow();
|
||||
|
||||
/**
|
||||
* Reports a problem: always maintains the counters, but whether problem is preserved in memory, depends on
|
||||
* implementation and its configuration.
|
||||
*
|
||||
* @return {@code true} if passed problem is preserved by this call.
|
||||
*/
|
||||
boolean reportProblem(P problem);
|
||||
|
||||
/**
|
||||
* Returns all reported and preserved problems ordered by severity in decreasing order. Note: counters and
|
||||
* element count in this stream does not have to be equal.
|
||||
*/
|
||||
@Nonnull
|
||||
default Stream<P> problems() {
|
||||
Stream<P> result = Stream.empty();
|
||||
for (BuilderProblem.Severity severity : BuilderProblem.Severity.values()) {
|
||||
result = Stream.concat(result, problems(severity));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all reported and preserved problems for given severity. Note: counters and element count in this
|
||||
* stream does not have to be equal.
|
||||
*/
|
||||
@Nonnull
|
||||
Stream<P> problems(BuilderProblem.Severity severity);
|
||||
|
||||
/**
|
||||
* Creates "empty" problem collector.
|
||||
*/
|
||||
@Nonnull
|
||||
static <P extends BuilderProblem> ProblemCollector<P> empty() {
|
||||
return new ProblemCollector<>() {
|
||||
@Override
|
||||
public boolean problemsOverflow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int problemsReportedFor(BuilderProblem.Severity... severities) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reportProblem(P problem) {
|
||||
throw new IllegalStateException("empty problem collector");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<P> problems(BuilderProblem.Severity severity) {
|
||||
return Stream.empty();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new instance of problem collector.
|
||||
*/
|
||||
@Nonnull
|
||||
static <P extends BuilderProblem> ProblemCollector<P> create(@Nullable ProtoSession protoSession) {
|
||||
if (protoSession != null
|
||||
&& protoSession.getUserProperties().containsKey(Constants.MAVEN_BUILDER_MAX_PROBLEMS)) {
|
||||
return new Impl<>(
|
||||
Integer.parseInt(protoSession.getUserProperties().get(Constants.MAVEN_BUILDER_MAX_PROBLEMS)));
|
||||
} else {
|
||||
return create(100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new instance of problem collector. Visible for testing only.
|
||||
*/
|
||||
@Nonnull
|
||||
static <P extends BuilderProblem> ProblemCollector<P> create(int maxCountLimit) {
|
||||
return new Impl<>(maxCountLimit);
|
||||
}
|
||||
|
||||
class Impl<P extends BuilderProblem> implements ProblemCollector<P> {
|
||||
|
||||
private final int maxCountLimit;
|
||||
private final AtomicInteger totalCount;
|
||||
private final ConcurrentMap<BuilderProblem.Severity, LongAdder> counters;
|
||||
private final ConcurrentMap<BuilderProblem.Severity, List<P>> problems;
|
||||
|
||||
private static final List<BuilderProblem.Severity> REVERSED_ORDER = Arrays.stream(
|
||||
BuilderProblem.Severity.values())
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.toList();
|
||||
|
||||
private Impl(int maxCountLimit) {
|
||||
if (maxCountLimit < 0) {
|
||||
throw new IllegalArgumentException("maxCountLimit must be non-negative");
|
||||
}
|
||||
this.maxCountLimit = maxCountLimit;
|
||||
this.totalCount = new AtomicInteger();
|
||||
this.counters = new ConcurrentHashMap<>();
|
||||
this.problems = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int problemsReportedFor(BuilderProblem.Severity... severity) {
|
||||
int result = 0;
|
||||
for (BuilderProblem.Severity s : severity) {
|
||||
result += getCounter(s).intValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean problemsOverflow() {
|
||||
return totalCount.get() > maxCountLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reportProblem(P problem) {
|
||||
requireNonNull(problem, "problem");
|
||||
int currentCount = totalCount.incrementAndGet();
|
||||
getCounter(problem.getSeverity()).increment();
|
||||
if (currentCount <= maxCountLimit || dropProblemWithLowerSeverity(problem.getSeverity())) {
|
||||
getProblems(problem.getSeverity()).add(problem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<P> problems(BuilderProblem.Severity severity) {
|
||||
requireNonNull(severity, "severity");
|
||||
return getProblems(severity).stream();
|
||||
}
|
||||
|
||||
private LongAdder getCounter(BuilderProblem.Severity severity) {
|
||||
return counters.computeIfAbsent(severity, k -> new LongAdder());
|
||||
}
|
||||
|
||||
private List<P> getProblems(BuilderProblem.Severity severity) {
|
||||
return problems.computeIfAbsent(severity, k -> new CopyOnWriteArrayList<>());
|
||||
}
|
||||
|
||||
private boolean dropProblemWithLowerSeverity(BuilderProblem.Severity severity) {
|
||||
for (BuilderProblem.Severity s : REVERSED_ORDER) {
|
||||
if (s.ordinal() > severity.ordinal()) {
|
||||
List<P> problems = getProblems(s);
|
||||
while (!problems.isEmpty()) {
|
||||
try {
|
||||
return problems.remove(0) != null;
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// empty, continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
package org.apache.maven.api.services;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.Service;
|
||||
import org.apache.maven.api.Session;
|
||||
|
@ -108,7 +107,7 @@ public interface SettingsBuilder extends Service {
|
|||
* @return The list of problems that were encountered, must not be {@code null}.
|
||||
*/
|
||||
@Nonnull
|
||||
default List<BuilderProblem> validate(@Nonnull Settings settings) {
|
||||
default ProblemCollector<BuilderProblem> validate(@Nonnull Settings settings) {
|
||||
return validate(settings, false);
|
||||
}
|
||||
|
||||
|
@ -120,7 +119,7 @@ public interface SettingsBuilder extends Service {
|
|||
* @return The list of problems that were encountered, must not be {@code null}.
|
||||
*/
|
||||
@Nonnull
|
||||
List<BuilderProblem> validate(@Nonnull Settings settings, boolean isProjectSettings);
|
||||
ProblemCollector<BuilderProblem> validate(@Nonnull Settings settings, boolean isProjectSettings);
|
||||
|
||||
/**
|
||||
* Convert a model profile to a settings profile.
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
package org.apache.maven.api.services;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
|
||||
|
@ -42,7 +41,7 @@ public class SettingsBuilderException extends MavenBuilderException {
|
|||
super(message, e);
|
||||
}
|
||||
|
||||
public SettingsBuilderException(String message, List<BuilderProblem> problems) {
|
||||
public SettingsBuilderException(String message, ProblemCollector<BuilderProblem> problems) {
|
||||
super(message, problems);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
package org.apache.maven.api.services;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.settings.Settings;
|
||||
|
@ -47,5 +45,5 @@ public interface SettingsBuilderResult {
|
|||
* @return the problems that were encountered during the settings building, can be empty but never {@code null}
|
||||
*/
|
||||
@Nonnull
|
||||
List<BuilderProblem> getProblems();
|
||||
ProblemCollector<BuilderProblem> getProblems();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
package org.apache.maven.api.services;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
|
||||
|
@ -42,7 +41,7 @@ public class ToolchainsBuilderException extends MavenBuilderException {
|
|||
super(message, e);
|
||||
}
|
||||
|
||||
public ToolchainsBuilderException(String message, List<BuilderProblem> problems) {
|
||||
public ToolchainsBuilderException(String message, ProblemCollector<BuilderProblem> problems) {
|
||||
super(message, problems);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
package org.apache.maven.api.services;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.toolchain.PersistedToolchains;
|
||||
|
@ -46,5 +44,5 @@ public interface ToolchainsBuilderResult {
|
|||
* @return the problems that were encountered during the settings building, can be empty but never {@code null}
|
||||
*/
|
||||
@Nonnull
|
||||
List<BuilderProblem> getProblems();
|
||||
ProblemCollector<BuilderProblem> getProblems();
|
||||
}
|
||||
|
|
|
@ -95,9 +95,11 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
.build());
|
||||
|
||||
return new DefaultSettingsBuildingResult(
|
||||
new Settings(result.getEffectiveSettings()), convert(result.getProblems()));
|
||||
new Settings(result.getEffectiveSettings()),
|
||||
convert(result.getProblems().problems().toList()));
|
||||
} catch (SettingsBuilderException e) {
|
||||
throw new SettingsBuildingException(convert(e.getProblems()));
|
||||
throw new SettingsBuildingException(
|
||||
convert(e.getProblemCollector().problems().toList()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ import javax.inject.Inject;
|
|||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.services.SettingsBuilder;
|
||||
import org.apache.maven.settings.Settings;
|
||||
import org.apache.maven.settings.building.SettingsProblem.Severity;
|
||||
|
@ -56,8 +56,8 @@ public class DefaultSettingsValidator implements SettingsValidator {
|
|||
|
||||
@Override
|
||||
public void validate(Settings settings, boolean isProjectSettings, SettingsProblemCollector problems) {
|
||||
List<BuilderProblem> list = settingsBuilder.validate(settings.getDelegate(), isProjectSettings);
|
||||
for (BuilderProblem problem : list) {
|
||||
ProblemCollector<BuilderProblem> list = settingsBuilder.validate(settings.getDelegate(), isProjectSettings);
|
||||
for (BuilderProblem problem : list.problems().toList()) {
|
||||
addViolation(problems, Severity.valueOf(problem.getSeverity().name()), problem.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,9 +99,10 @@ class DefaultSettingsValidatorTest {
|
|||
SimpleProblemCollector problems = new SimpleProblemCollector();
|
||||
validator.validate(settings, problems);
|
||||
assertEquals(4, problems.messages.size());
|
||||
assertContains(problems.messages.get(0), "'mirrors.mirror.id' must not be 'local'");
|
||||
assertContains(problems.messages.get(1), "'mirrors.mirror.url' for local is missing");
|
||||
assertContains(problems.messages.get(2), "'mirrors.mirror.mirrorOf' for local is missing");
|
||||
// errors are now by severity descending
|
||||
assertContains(problems.messages.get(0), "'mirrors.mirror.url' for local is missing");
|
||||
assertContains(problems.messages.get(1), "'mirrors.mirror.mirrorOf' for local is missing");
|
||||
assertContains(problems.messages.get(2), "'mirrors.mirror.id' must not be 'local'");
|
||||
assertContains(problems.messages.get(3), "'mirrors.mirror.id' must not contain any of these characters");
|
||||
}
|
||||
|
||||
|
@ -121,11 +122,12 @@ class DefaultSettingsValidatorTest {
|
|||
SimpleProblemCollector problems = new SimpleProblemCollector();
|
||||
validator.validate(settings, problems);
|
||||
assertEquals(3, problems.messages.size());
|
||||
// errors are now by severity descending
|
||||
assertContains(
|
||||
problems.messages.get(0), "'profiles.profile[default].repositories.repository.id' must not be 'local'");
|
||||
assertContains(
|
||||
problems.messages.get(1),
|
||||
problems.messages.get(0),
|
||||
"'profiles.profile[default].repositories.repository.url' for local is missing");
|
||||
assertContains(
|
||||
problems.messages.get(1), "'profiles.profile[default].repositories.repository.id' must not be 'local'");
|
||||
assertContains(
|
||||
problems.messages.get(2),
|
||||
"'profiles.profile[default].repositories.repository.id' must not contain any of these characters");
|
||||
|
|
|
@ -92,9 +92,11 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
.build());
|
||||
|
||||
return new DefaultToolchainsBuildingResult(
|
||||
new PersistedToolchains(result.getEffectiveToolchains()), convert(result.getProblems()));
|
||||
new PersistedToolchains(result.getEffectiveToolchains()),
|
||||
convert(result.getProblems().problems().toList()));
|
||||
} catch (ToolchainsBuilderException e) {
|
||||
throw new ToolchainsBuildingException(convert(e.getProblems()));
|
||||
throw new ToolchainsBuildingException(
|
||||
convert(e.getProblemCollector().problems().toList()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -597,13 +597,16 @@ public abstract class LookupInvoker<C extends LookupContext> implements Invoker
|
|||
context.interactive = mayDisableInteractiveMode(context, context.effectiveSettings.isInteractiveMode());
|
||||
context.localRepositoryPath = localRepositoryPath(context);
|
||||
|
||||
if (emitSettingsWarnings && !settingsResult.getProblems().isEmpty()) {
|
||||
if (emitSettingsWarnings && settingsResult.getProblems().hasWarningProblems()) {
|
||||
int totalProblems = settingsResult.getProblems().totalProblemsReported();
|
||||
context.logger.info("");
|
||||
context.logger.info(
|
||||
"Some problems were encountered while building the effective settings (use -X to see details)");
|
||||
context.logger.info(String.format(
|
||||
"%s %s encountered while building the effective settings (use -e to see details)",
|
||||
totalProblems, (totalProblems == 1) ? "problem was" : "problems were"));
|
||||
|
||||
if (context.invokerRequest.options().verbose().orElse(false)) {
|
||||
for (BuilderProblem problem : settingsResult.getProblems()) {
|
||||
if (context.invokerRequest.options().showErrors().orElse(false)) {
|
||||
for (BuilderProblem problem :
|
||||
settingsResult.getProblems().problems().toList()) {
|
||||
context.logger.warn(problem.getMessage() + " @ " + problem.getLocation());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,15 +205,21 @@ public class MavenInvoker extends LookupInvoker<MavenContext> {
|
|||
new org.apache.maven.toolchain.model.PersistedToolchains(
|
||||
toolchainsResult.getEffectiveToolchains()));
|
||||
|
||||
if (!toolchainsResult.getProblems().isEmpty()) {
|
||||
context.logger.warn("");
|
||||
context.logger.warn("Some problems were encountered while building the effective toolchains");
|
||||
if (toolchainsResult.getProblems().hasWarningProblems()) {
|
||||
int totalProblems = toolchainsResult.getProblems().totalProblemsReported();
|
||||
context.logger.info("");
|
||||
context.logger.info(String.format(
|
||||
"%s %s encountered while building the effective toolchains (use -e to see details)",
|
||||
totalProblems, (totalProblems == 1) ? "problem was" : "problems were"));
|
||||
|
||||
for (BuilderProblem problem : toolchainsResult.getProblems()) {
|
||||
context.logger.warn(problem.getMessage() + " @ " + problem.getLocation());
|
||||
if (context.invokerRequest.options().showErrors().orElse(false)) {
|
||||
for (BuilderProblem problem :
|
||||
toolchainsResult.getProblems().problems().toList()) {
|
||||
context.logger.warn(problem.getMessage() + " @ " + problem.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
context.logger.warn("");
|
||||
context.logger.info("");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ import org.apache.maven.api.services.ModelProblem.Version;
|
|||
import org.apache.maven.api.services.ModelProblemCollector;
|
||||
import org.apache.maven.api.services.ModelSource;
|
||||
import org.apache.maven.api.services.ModelTransformer;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.services.Source;
|
||||
import org.apache.maven.api.services.model.LifecycleBindingsInjector;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
|
@ -340,7 +341,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
try {
|
||||
MavenProject project = request.getProject();
|
||||
|
||||
List<ModelProblem> modelProblems = null;
|
||||
ProblemCollector<ModelProblem> problemCollector = null;
|
||||
Throwable error = null;
|
||||
|
||||
if (project == null) {
|
||||
|
@ -378,7 +379,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
error = e;
|
||||
}
|
||||
|
||||
modelProblems = result.getProblems();
|
||||
problemCollector = result.getProblemCollector();
|
||||
|
||||
initProject(project, result);
|
||||
}
|
||||
|
@ -391,7 +392,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
}
|
||||
|
||||
ProjectBuildingResult result =
|
||||
new DefaultProjectBuildingResult(project, convert(modelProblems), resolutionResult);
|
||||
new DefaultProjectBuildingResult(project, convert(problemCollector), resolutionResult);
|
||||
|
||||
if (error != null) {
|
||||
ProjectBuildingException e = new ProjectBuildingException(List.of(result));
|
||||
|
@ -498,18 +499,14 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
} catch (ModelBuilderException e) {
|
||||
result = e.getResult();
|
||||
if (result == null || result.getEffectiveModel() == null) {
|
||||
return List.of(new DefaultProjectBuildingResult(e.getModelId(), pomFile, convert(e.getProblems())));
|
||||
return List.of(new DefaultProjectBuildingResult(
|
||||
e.getModelId(), pomFile, convert(e.getProblemCollector())));
|
||||
}
|
||||
}
|
||||
|
||||
List<ProjectBuildingResult> results = new ArrayList<>();
|
||||
List<ModelBuilderResult> allModels = results(result).toList();
|
||||
for (ModelBuilderResult r : allModels) {
|
||||
List<ModelProblem> problems = new ArrayList<>(r.getProblems());
|
||||
results(r)
|
||||
.filter(c -> c != r)
|
||||
.flatMap(c -> c.getProblems().stream())
|
||||
.forEach(problems::remove);
|
||||
if (r.getEffectiveModel() != null) {
|
||||
File pom = r.getSource().getPath().toFile();
|
||||
MavenProject project =
|
||||
|
@ -529,9 +526,10 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
if (request.isResolveDependencies()) {
|
||||
resolutionResult = resolveDependencies(project);
|
||||
}
|
||||
results.add(new DefaultProjectBuildingResult(project, convert(problems), resolutionResult));
|
||||
results.add(new DefaultProjectBuildingResult(
|
||||
project, convert(r.getProblemCollector()), resolutionResult));
|
||||
} else {
|
||||
results.add(new DefaultProjectBuildingResult(null, convert(problems), null));
|
||||
results.add(new DefaultProjectBuildingResult(null, convert(r.getProblemCollector()), null));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
|
@ -541,11 +539,34 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
return Stream.concat(result.getChildren().stream().flatMap(this::results), Stream.of(result));
|
||||
}
|
||||
|
||||
private List<org.apache.maven.model.building.ModelProblem> convert(List<ModelProblem> problems) {
|
||||
if (problems == null) {
|
||||
private List<org.apache.maven.model.building.ModelProblem> convert(
|
||||
ProblemCollector<ModelProblem> problemCollector) {
|
||||
if (problemCollector == null) {
|
||||
return null;
|
||||
}
|
||||
return problems.stream().map(p -> convert(p)).toList();
|
||||
ArrayList<org.apache.maven.model.building.ModelProblem> problems = new ArrayList<>();
|
||||
problemCollector.problems().map(BuildSession::convert).forEach(problems::add);
|
||||
if (problemCollector.problemsOverflow()) {
|
||||
problems.add(
|
||||
0,
|
||||
new DefaultModelProblem(
|
||||
"Too many model problems reported (listed problems are just a subset of reported problems)",
|
||||
org.apache.maven.model.building.ModelProblem.Severity.WARNING,
|
||||
null,
|
||||
null,
|
||||
-1,
|
||||
-1,
|
||||
null,
|
||||
null));
|
||||
return new ArrayList<>(problems) {
|
||||
@Override
|
||||
public int size() {
|
||||
return problemCollector.totalProblemsReported();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return problems;
|
||||
}
|
||||
}
|
||||
|
||||
private static org.apache.maven.model.building.ModelProblem convert(ModelProblem p) {
|
||||
|
|
|
@ -62,27 +62,33 @@ public class DefaultProjectsSelector implements ProjectsSelector {
|
|||
|
||||
List<MavenProject> projects = new ArrayList<>(results.size());
|
||||
|
||||
boolean problems = false;
|
||||
long totalProblemsCount = 0;
|
||||
|
||||
for (ProjectBuildingResult result : results) {
|
||||
projects.add(result.getProject());
|
||||
|
||||
if (!result.getProblems().isEmpty() && LOGGER.isWarnEnabled()) {
|
||||
int problemsCount = result.getProblems().size();
|
||||
totalProblemsCount += problemsCount;
|
||||
if (problemsCount != 0 && LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn("");
|
||||
LOGGER.warn(
|
||||
"Some problems were encountered while building the effective model for '{}'",
|
||||
"{} {} encountered while building the effective model for '{}' (use -e to see details)",
|
||||
problemsCount,
|
||||
(problemsCount == 1) ? "problem was" : "problems were",
|
||||
result.getProject().getId());
|
||||
|
||||
for (ModelProblem problem : result.getProblems()) {
|
||||
String loc = ModelProblemUtils.formatLocation(problem, result.getProjectId());
|
||||
LOGGER.warn("{}{}", problem.getMessage(), ((loc != null && !loc.isEmpty()) ? " @ " + loc : ""));
|
||||
if (request.isShowErrors()) { // this means -e or -X (as -X enables -e as well)
|
||||
for (ModelProblem problem : result.getProblems()) {
|
||||
String loc = ModelProblemUtils.formatLocation(problem, result.getProjectId());
|
||||
LOGGER.warn("{}{}", problem.getMessage(), ((loc != null && !loc.isEmpty()) ? " @ " + loc : ""));
|
||||
}
|
||||
}
|
||||
|
||||
problems = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (problems) {
|
||||
if (totalProblemsCount > 0) {
|
||||
LOGGER.warn("");
|
||||
LOGGER.warn("Total model problems reported: {}", totalProblemsCount);
|
||||
LOGGER.warn("");
|
||||
LOGGER.warn("It is highly recommended to fix these problems"
|
||||
+ " because they threaten the stability of your build.");
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -39,6 +38,7 @@ import org.apache.maven.api.di.Inject;
|
|||
import org.apache.maven.api.di.Named;
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.Interpolator;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.services.SettingsBuilder;
|
||||
import org.apache.maven.api.services.SettingsBuilderException;
|
||||
import org.apache.maven.api.services.SettingsBuilderRequest;
|
||||
|
@ -97,7 +97,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
|
||||
@Override
|
||||
public SettingsBuilderResult build(SettingsBuilderRequest request) throws SettingsBuilderException {
|
||||
List<BuilderProblem> problems = new ArrayList<>();
|
||||
ProblemCollector<BuilderProblem> problems = ProblemCollector.create(request.getSession());
|
||||
|
||||
Source installationSource = request.getInstallationSettingsSource().orElse(null);
|
||||
Settings installation = readSettings(installationSource, false, request, problems);
|
||||
|
@ -139,30 +139,18 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
if (hasErrors(problems)) {
|
||||
if (problems.hasErrorProblems()) {
|
||||
throw new SettingsBuilderException("Error building settings", problems);
|
||||
}
|
||||
|
||||
return new DefaultSettingsBuilderResult(effective, problems);
|
||||
}
|
||||
|
||||
private boolean hasErrors(List<BuilderProblem> problems) {
|
||||
if (problems != null) {
|
||||
for (BuilderProblem problem : problems) {
|
||||
if (BuilderProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Settings readSettings(
|
||||
Source settingsSource,
|
||||
boolean isProjectSettings,
|
||||
SettingsBuilderRequest request,
|
||||
List<BuilderProblem> problems) {
|
||||
ProblemCollector<BuilderProblem> problems) {
|
||||
if (settingsSource == null) {
|
||||
return Settings.newInstance();
|
||||
}
|
||||
|
@ -184,7 +172,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
.strict(false)
|
||||
.build());
|
||||
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
settingsSource.getLocation(),
|
||||
loc != null ? loc.getLineNumber() : -1,
|
||||
loc != null ? loc.getColumnNumber() : -1,
|
||||
|
@ -195,7 +183,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
}
|
||||
} catch (XmlReaderException e) {
|
||||
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
settingsSource.getLocation(),
|
||||
loc != null ? loc.getLineNumber() : -1,
|
||||
loc != null ? loc.getColumnNumber() : -1,
|
||||
|
@ -204,7 +192,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
BuilderProblem.Severity.FATAL));
|
||||
return Settings.newInstance();
|
||||
} catch (IOException e) {
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
settingsSource.getLocation(),
|
||||
-1,
|
||||
-1,
|
||||
|
@ -242,7 +230,8 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
return settings;
|
||||
}
|
||||
|
||||
private Settings interpolate(Settings settings, SettingsBuilderRequest request, List<BuilderProblem> problems) {
|
||||
private Settings interpolate(
|
||||
Settings settings, SettingsBuilderRequest request, ProblemCollector<BuilderProblem> problems) {
|
||||
Function<String, String> src;
|
||||
if (request.getInterpolationSource().isPresent()) {
|
||||
src = request.getInterpolationSource().get();
|
||||
|
@ -269,7 +258,10 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
}
|
||||
|
||||
private Settings decrypt(
|
||||
Source settingsSource, Settings settings, SettingsBuilderRequest request, List<BuilderProblem> problems) {
|
||||
Source settingsSource,
|
||||
Settings settings,
|
||||
SettingsBuilderRequest request,
|
||||
ProblemCollector<BuilderProblem> problems) {
|
||||
if (dispatchers.isEmpty()) {
|
||||
return settings;
|
||||
}
|
||||
|
@ -284,7 +276,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
try {
|
||||
return secDispatcher.decrypt(str);
|
||||
} catch (Exception e) {
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
settingsSource.getLocation(),
|
||||
-1,
|
||||
-1,
|
||||
|
@ -297,7 +289,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
};
|
||||
Settings result = new SettingsTransformer(decryptFunction).visit(settings);
|
||||
if (preMaven4Passwords.get() > 0) {
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
settingsSource.getLocation(),
|
||||
-1,
|
||||
-1,
|
||||
|
@ -323,8 +315,9 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<BuilderProblem> validate(Settings settings, boolean isProjectSettings) {
|
||||
ArrayList<BuilderProblem> problems = new ArrayList<>();
|
||||
public ProblemCollector<BuilderProblem> validate(Settings settings, boolean isProjectSettings) {
|
||||
// TODO: any way to get ProtoSession here?
|
||||
ProblemCollector<BuilderProblem> problems = ProblemCollector.create(null);
|
||||
settingsValidator.validate(settings, isProjectSettings, problems);
|
||||
return problems;
|
||||
}
|
||||
|
@ -347,11 +340,11 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
|
||||
private final Settings effectiveSettings;
|
||||
|
||||
private final List<BuilderProblem> problems;
|
||||
private final ProblemCollector<BuilderProblem> problems;
|
||||
|
||||
DefaultSettingsBuilderResult(Settings effectiveSettings, List<BuilderProblem> problems) {
|
||||
DefaultSettingsBuilderResult(Settings effectiveSettings, ProblemCollector<BuilderProblem> problems) {
|
||||
this.effectiveSettings = effectiveSettings;
|
||||
this.problems = (problems != null) ? problems : new ArrayList<>();
|
||||
this.problems = (problems != null) ? problems : ProblemCollector.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -360,7 +353,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<BuilderProblem> getProblems() {
|
||||
public ProblemCollector<BuilderProblem> getProblems() {
|
||||
return problems;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Set;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.settings.Mirror;
|
||||
import org.apache.maven.api.settings.Profile;
|
||||
import org.apache.maven.api.settings.Proxy;
|
||||
|
@ -41,7 +42,7 @@ public class DefaultSettingsValidator {
|
|||
private static final String ILLEGAL_REPO_ID_CHARS = "\\/:\"<>|?*"; // ILLEGAL_FS_CHARS
|
||||
|
||||
@SuppressWarnings("checkstyle:MethodLength")
|
||||
public void validate(Settings settings, boolean isProjectSettings, List<BuilderProblem> problems) {
|
||||
public void validate(Settings settings, boolean isProjectSettings, ProblemCollector<BuilderProblem> problems) {
|
||||
if (isProjectSettings) {
|
||||
String msgS = "is not supported on project settings.";
|
||||
String msgP = "are not supported on project settings.";
|
||||
|
@ -208,7 +209,8 @@ public class DefaultSettingsValidator {
|
|||
}
|
||||
}
|
||||
|
||||
private void validateRepositories(List<BuilderProblem> problems, List<Repository> repositories, String prefix) {
|
||||
private void validateRepositories(
|
||||
ProblemCollector<BuilderProblem> problems, List<Repository> repositories, String prefix) {
|
||||
Set<String> repoIds = new HashSet<>();
|
||||
|
||||
for (Repository repository : repositories) {
|
||||
|
@ -268,7 +270,7 @@ public class DefaultSettingsValidator {
|
|||
* </ul>
|
||||
*/
|
||||
private static boolean validateStringEmpty(
|
||||
List<BuilderProblem> problems, String fieldName, String string, String message) {
|
||||
ProblemCollector<BuilderProblem> problems, String fieldName, String string, String message) {
|
||||
if (string == null || string.length() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
@ -287,7 +289,7 @@ public class DefaultSettingsValidator {
|
|||
* </ul>
|
||||
*/
|
||||
private static boolean validateStringNotEmpty(
|
||||
List<BuilderProblem> problems, String fieldName, String string, String sourceHint) {
|
||||
ProblemCollector<BuilderProblem> problems, String fieldName, String string, String sourceHint) {
|
||||
if (!validateNotNull(problems, fieldName, string, sourceHint)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -309,7 +311,7 @@ public class DefaultSettingsValidator {
|
|||
* </ul>
|
||||
*/
|
||||
private static boolean validateNotNull(
|
||||
List<BuilderProblem> problems, String fieldName, Object object, String sourceHint) {
|
||||
ProblemCollector<BuilderProblem> problems, String fieldName, Object object, String sourceHint) {
|
||||
if (object != null) {
|
||||
return true;
|
||||
}
|
||||
|
@ -320,7 +322,7 @@ public class DefaultSettingsValidator {
|
|||
}
|
||||
|
||||
private static boolean validateBannedCharacters(
|
||||
List<BuilderProblem> problems,
|
||||
ProblemCollector<BuilderProblem> problems,
|
||||
String fieldName,
|
||||
BuilderProblem.Severity severity,
|
||||
String string,
|
||||
|
@ -344,7 +346,7 @@ public class DefaultSettingsValidator {
|
|||
}
|
||||
|
||||
private static void addViolation(
|
||||
List<BuilderProblem> problems,
|
||||
ProblemCollector<BuilderProblem> problems,
|
||||
BuilderProblem.Severity severity,
|
||||
String fieldName,
|
||||
String sourceHint,
|
||||
|
@ -358,6 +360,6 @@ public class DefaultSettingsValidator {
|
|||
|
||||
buffer.append(' ').append(message);
|
||||
|
||||
problems.add(new DefaultBuilderProblem(null, -1, -1, null, buffer.toString(), severity));
|
||||
problems.reportProblem(new DefaultBuilderProblem(null, -1, -1, null, buffer.toString(), severity));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ import javax.xml.stream.XMLStreamException;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -32,6 +30,7 @@ import org.apache.maven.api.di.Inject;
|
|||
import org.apache.maven.api.di.Named;
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.Interpolator;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.services.Source;
|
||||
import org.apache.maven.api.services.ToolchainsBuilder;
|
||||
import org.apache.maven.api.services.ToolchainsBuilderException;
|
||||
|
@ -70,7 +69,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
|
||||
@Override
|
||||
public ToolchainsBuilderResult build(ToolchainsBuilderRequest request) throws ToolchainsBuilderException {
|
||||
List<BuilderProblem> problems = new ArrayList<>();
|
||||
ProblemCollector<BuilderProblem> problems = ProblemCollector.create(request.getSession());
|
||||
|
||||
Source installationSource = request.getInstallationToolchainsSource().orElse(null);
|
||||
PersistedToolchains installation = readToolchains(installationSource, request, problems);
|
||||
|
@ -80,27 +79,15 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
|
||||
PersistedToolchains effective = toolchainsMerger.merge(user, installation, false, null);
|
||||
|
||||
if (hasErrors(problems)) {
|
||||
if (problems.hasErrorProblems()) {
|
||||
throw new ToolchainsBuilderException("Error building toolchains", problems);
|
||||
}
|
||||
|
||||
return new DefaultToolchainsBuilderResult(effective, problems);
|
||||
}
|
||||
|
||||
private boolean hasErrors(List<BuilderProblem> problems) {
|
||||
if (problems != null) {
|
||||
for (BuilderProblem problem : problems) {
|
||||
if (BuilderProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private PersistedToolchains readToolchains(
|
||||
Source toolchainsSource, ToolchainsBuilderRequest request, List<BuilderProblem> problems) {
|
||||
Source toolchainsSource, ToolchainsBuilderRequest request, ProblemCollector<BuilderProblem> problems) {
|
||||
if (toolchainsSource == null) {
|
||||
return PersistedToolchains.newInstance();
|
||||
}
|
||||
|
@ -129,7 +116,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
.strict(false)
|
||||
.build());
|
||||
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
toolchainsSource.getLocation(),
|
||||
loc != null ? loc.getLineNumber() : -1,
|
||||
loc != null ? loc.getColumnNumber() : -1,
|
||||
|
@ -139,7 +126,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
}
|
||||
} catch (XmlReaderException e) {
|
||||
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
toolchainsSource.getLocation(),
|
||||
loc != null ? loc.getLineNumber() : -1,
|
||||
loc != null ? loc.getColumnNumber() : -1,
|
||||
|
@ -148,7 +135,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
BuilderProblem.Severity.FATAL));
|
||||
return PersistedToolchains.newInstance();
|
||||
} catch (IOException e) {
|
||||
problems.add(new DefaultBuilderProblem(
|
||||
problems.reportProblem(new DefaultBuilderProblem(
|
||||
toolchainsSource.getLocation(),
|
||||
-1,
|
||||
-1,
|
||||
|
@ -164,7 +151,9 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
}
|
||||
|
||||
private PersistedToolchains interpolate(
|
||||
PersistedToolchains toolchains, ToolchainsBuilderRequest request, List<BuilderProblem> problems) {
|
||||
PersistedToolchains toolchains,
|
||||
ToolchainsBuilderRequest request,
|
||||
ProblemCollector<BuilderProblem> problems) {
|
||||
Map<String, String> userProperties = request.getSession().getUserProperties();
|
||||
Map<String, String> systemProperties = request.getSession().getSystemProperties();
|
||||
Function<String, String> src = Interpolator.chain(userProperties::get, systemProperties::get);
|
||||
|
@ -180,11 +169,12 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
|
||||
private final PersistedToolchains effectiveToolchains;
|
||||
|
||||
private final List<BuilderProblem> problems;
|
||||
private final ProblemCollector<BuilderProblem> problems;
|
||||
|
||||
DefaultToolchainsBuilderResult(PersistedToolchains effectiveToolchains, List<BuilderProblem> problems) {
|
||||
DefaultToolchainsBuilderResult(
|
||||
PersistedToolchains effectiveToolchains, ProblemCollector<BuilderProblem> problems) {
|
||||
this.effectiveToolchains = effectiveToolchains;
|
||||
this.problems = (problems != null) ? problems : new ArrayList<>();
|
||||
this.problems = (problems != null) ? problems : ProblemCollector.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -193,7 +183,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<BuilderProblem> getProblems() {
|
||||
public ProblemCollector<BuilderProblem> getProblems() {
|
||||
return problems;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ import org.apache.maven.api.services.ModelProblem;
|
|||
import org.apache.maven.api.services.ModelProblem.Version;
|
||||
import org.apache.maven.api.services.ModelProblemCollector;
|
||||
import org.apache.maven.api.services.ModelSource;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.services.RepositoryFactory;
|
||||
import org.apache.maven.api.services.Source;
|
||||
import org.apache.maven.api.services.SuperPomProvider;
|
||||
|
@ -205,10 +206,6 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
return new ModelBuilderSessionImpl();
|
||||
}
|
||||
|
||||
static int getMaxProblems(Session session) {
|
||||
return Integer.parseInt(session.getUserProperties().getOrDefault(Constants.MAVEN_BUILDER_MAX_PROBLEMS, "100"));
|
||||
}
|
||||
|
||||
protected class ModelBuilderSessionImpl implements ModelBuilderSession {
|
||||
ModelBuilderSessionState mainSession;
|
||||
|
||||
|
@ -227,8 +224,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
mainSession = new ModelBuilderSessionState(request);
|
||||
session = mainSession;
|
||||
} else {
|
||||
session =
|
||||
mainSession.derive(request, new DefaultModelBuilderResult(getMaxProblems(mainSession.session)));
|
||||
session = mainSession.derive(
|
||||
request, new DefaultModelBuilderResult(ProblemCollector.create(mainSession.session)));
|
||||
}
|
||||
// Build the request
|
||||
if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_PROJECT) {
|
||||
|
@ -264,7 +261,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
this(
|
||||
request.getSession(),
|
||||
request,
|
||||
new DefaultModelBuilderResult(DefaultModelBuilder.getMaxProblems(request.getSession())),
|
||||
new DefaultModelBuilderResult(ProblemCollector.create(request.getSession())),
|
||||
request.getSession()
|
||||
.getData()
|
||||
.computeIfAbsent(SessionData.key(ModelCache.class), modelCacheFactory::newInstance),
|
||||
|
@ -305,12 +302,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
this.result.setSource(this.request.getSource());
|
||||
}
|
||||
|
||||
int getMaxProblems() {
|
||||
return DefaultModelBuilder.getMaxProblems(session);
|
||||
}
|
||||
|
||||
ModelBuilderSessionState derive(ModelSource source) {
|
||||
return derive(source, new DefaultModelBuilderResult(result, getMaxProblems()));
|
||||
return derive(source, new DefaultModelBuilderResult(ProblemCollector.create(session)));
|
||||
}
|
||||
|
||||
ModelBuilderSessionState derive(ModelSource source, DefaultModelBuilderResult result) {
|
||||
|
@ -321,7 +314,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
* Creates a new session, sharing cached datas and propagating errors.
|
||||
*/
|
||||
ModelBuilderSessionState derive(ModelBuilderRequest request) {
|
||||
return derive(request, new DefaultModelBuilderResult(result, getMaxProblems()));
|
||||
return derive(request, new DefaultModelBuilderResult(ProblemCollector.create(session)));
|
||||
}
|
||||
|
||||
ModelBuilderSessionState derive(ModelBuilderRequest request, DefaultModelBuilderResult result) {
|
||||
|
@ -433,18 +426,9 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean hasFatalErrors() {
|
||||
return result.getProblems().stream().anyMatch(p -> p.getSeverity() == Severity.FATAL);
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
return result.getProblems().stream()
|
||||
.anyMatch(p -> p.getSeverity() == Severity.FATAL || p.getSeverity() == Severity.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ModelProblem> getProblems() {
|
||||
return result.getProblems();
|
||||
public ProblemCollector<ModelProblem> getProblemCollector() {
|
||||
return result.getProblemCollector();
|
||||
}
|
||||
|
||||
public void setSource(String source) {
|
||||
|
@ -481,30 +465,6 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void add(ModelProblem problem) {
|
||||
result.addProblem(problem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(BuilderProblem.Severity severity, ModelProblem.Version version, String message) {
|
||||
add(severity, version, message, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(
|
||||
BuilderProblem.Severity severity,
|
||||
ModelProblem.Version version,
|
||||
String message,
|
||||
InputLocation location) {
|
||||
add(severity, version, message, location, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(
|
||||
BuilderProblem.Severity severity, ModelProblem.Version version, String message, Exception exception) {
|
||||
add(severity, version, message, null, exception);
|
||||
}
|
||||
|
||||
public void add(
|
||||
BuilderProblem.Severity severity,
|
||||
ModelProblem.Version version,
|
||||
|
@ -720,8 +680,9 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
|
||||
private void loadFromRoot(Path root, Path top) {
|
||||
try (PhasingExecutor executor = createExecutor()) {
|
||||
DefaultModelBuilderResult r =
|
||||
Objects.equals(top, root) ? result : new DefaultModelBuilderResult(getMaxProblems());
|
||||
DefaultModelBuilderResult r = Objects.equals(top, root)
|
||||
? result
|
||||
: new DefaultModelBuilderResult(ProblemCollector.create(session));
|
||||
loadFilePom(executor, top, root, Set.of(), r);
|
||||
}
|
||||
if (result.getFileModel() == null && !Objects.equals(top, root)) {
|
||||
|
@ -767,7 +728,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
-1,
|
||||
-1,
|
||||
null);
|
||||
r.addProblem(problem);
|
||||
r.getProblemCollector().reportProblem(problem);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -789,13 +750,13 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
-1,
|
||||
-1,
|
||||
null);
|
||||
r.addProblem(problem);
|
||||
r.getProblemCollector().reportProblem(problem);
|
||||
continue;
|
||||
}
|
||||
|
||||
DefaultModelBuilderResult cr = Objects.equals(top, subprojectFile)
|
||||
? result
|
||||
: new DefaultModelBuilderResult(r, getMaxProblems());
|
||||
: new DefaultModelBuilderResult(ProblemCollector.create(session));
|
||||
if (request.isRecursive()) {
|
||||
r.getChildren().add(cr);
|
||||
}
|
||||
|
@ -806,9 +767,6 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
// gathered with problem collector
|
||||
add(Severity.ERROR, Version.V40, "Failed to load project " + pom, e);
|
||||
}
|
||||
if (r != result) {
|
||||
r.getProblems().forEach(result::addProblem);
|
||||
}
|
||||
}
|
||||
|
||||
static <T> Set<T> concat(Set<T> a, T b) {
|
||||
|
@ -1731,12 +1689,9 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
modelBuilderSession.buildEffectiveModel(importIds);
|
||||
importResult = modelBuilderSession.result;
|
||||
} catch (ModelBuilderException e) {
|
||||
e.getResult().getProblems().forEach(this::add);
|
||||
return null;
|
||||
}
|
||||
|
||||
importResult.getProblems().forEach(this::add);
|
||||
|
||||
importModel = importResult.getEffectiveModel();
|
||||
|
||||
return importModel;
|
||||
|
@ -1858,6 +1813,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
return subprojects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model buildRawModel(ModelBuilderRequest request) throws ModelBuilderException {
|
||||
ModelBuilderSessionState build = new ModelBuilderSessionState(request);
|
||||
Model model = build.readRawModel();
|
||||
|
|
|
@ -20,20 +20,15 @@ package org.apache.maven.internal.impl.model;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.api.model.Model;
|
||||
import org.apache.maven.api.model.Profile;
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.ModelBuilderResult;
|
||||
import org.apache.maven.api.services.ModelProblem;
|
||||
import org.apache.maven.api.services.ModelSource;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
|
||||
/**
|
||||
* Collects the output of the model builder.
|
||||
|
@ -46,23 +41,14 @@ class DefaultModelBuilderResult implements ModelBuilderResult {
|
|||
private Model effectiveModel;
|
||||
private List<Profile> activePomProfiles;
|
||||
private List<Profile> activeExternalProfiles;
|
||||
private final Queue<ModelProblem> problems = new ConcurrentLinkedQueue<>();
|
||||
private final DefaultModelBuilderResult problemHolder;
|
||||
|
||||
private final ProblemCollector<ModelProblem> problemCollector;
|
||||
private final List<DefaultModelBuilderResult> children = new ArrayList<>();
|
||||
|
||||
private int maxProblems;
|
||||
private Map<BuilderProblem.Severity, AtomicInteger> problemCount = new ConcurrentHashMap<>();
|
||||
|
||||
DefaultModelBuilderResult(int maxProblems) {
|
||||
this(null, maxProblems);
|
||||
}
|
||||
|
||||
DefaultModelBuilderResult(DefaultModelBuilderResult problemHolder, int maxProblems) {
|
||||
this.problemHolder = problemHolder;
|
||||
this.maxProblems = maxProblems;
|
||||
DefaultModelBuilderResult(ProblemCollector<ModelProblem> problemCollector) {
|
||||
this.problemCollector = problemCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
@ -132,39 +118,8 @@ class DefaultModelBuilderResult implements ModelBuilderResult {
|
|||
* guaranteed to be non-null but possibly empty.
|
||||
*/
|
||||
@Override
|
||||
public List<ModelProblem> getProblems() {
|
||||
List<ModelProblem> additionalProblems = new ArrayList<>();
|
||||
problemCount.forEach((s, i) -> {
|
||||
if (i.get() > maxProblems) {
|
||||
additionalProblems.add(new DefaultModelProblem(
|
||||
String.format("Too many problems %d of severity %s", i.get(), s.name()),
|
||||
s,
|
||||
ModelProblem.Version.BASE,
|
||||
null,
|
||||
-1,
|
||||
-1,
|
||||
null,
|
||||
null));
|
||||
}
|
||||
});
|
||||
return Stream.concat(problems.stream(), additionalProblems.stream()).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a given problem to the list of problems and propagates it to the parent result if present.
|
||||
*
|
||||
* @param problem The problem to be added. It must be an instance of ModelProblem.
|
||||
*/
|
||||
public void addProblem(ModelProblem problem) {
|
||||
int problemCount = this.problemCount
|
||||
.computeIfAbsent(problem.getSeverity(), s -> new AtomicInteger())
|
||||
.incrementAndGet();
|
||||
if (problemCount < maxProblems) {
|
||||
problems.add(problem);
|
||||
}
|
||||
if (problemHolder != null) {
|
||||
problemHolder.addProblem(problem);
|
||||
}
|
||||
public ProblemCollector<ModelProblem> getProblemCollector() {
|
||||
return problemCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -183,18 +138,19 @@ class DefaultModelBuilderResult implements ModelBuilderResult {
|
|||
} else {
|
||||
modelId = null;
|
||||
}
|
||||
if (!problems.isEmpty()) {
|
||||
if (problemCollector.hasWarningProblems()) {
|
||||
int totalProblems = problemCollector.totalProblemsReported();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(problems.size())
|
||||
sb.append(totalProblems)
|
||||
.append(
|
||||
(problems.size() == 1)
|
||||
(totalProblems == 1)
|
||||
? " problem was "
|
||||
: " problems were encountered while building the effective model");
|
||||
if (modelId != null && !modelId.isEmpty()) {
|
||||
sb.append(" for ");
|
||||
sb.append(modelId);
|
||||
}
|
||||
for (ModelProblem problem : problems) {
|
||||
for (ModelProblem problem : problemCollector.problems().toList()) {
|
||||
sb.append(System.lineSeparator());
|
||||
sb.append(" - [");
|
||||
sb.append(problem.getSeverity());
|
||||
|
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.services.BuilderProblem.Severity;
|
||||
import org.apache.maven.api.services.ModelProblem;
|
||||
|
||||
/**
|
||||
* There are various forms of results that are represented by this class:
|
||||
* <ol>
|
||||
* <li>success - in which case only the model field is set
|
||||
* <li>success with warnings - model field + non-error model problems
|
||||
* <li>error - no model, but diagnostics
|
||||
* <li>error - (partial) model and diagnostics
|
||||
* </ol>
|
||||
* Could encode these variants as subclasses, but kept in one for now
|
||||
*
|
||||
* @param <T> the model type
|
||||
*/
|
||||
public class Result<T> {
|
||||
|
||||
/**
|
||||
* Success without warnings
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
public static <T> Result<T> success(T model) {
|
||||
return success(model, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Success with warnings
|
||||
*
|
||||
* @param model
|
||||
* @param problems
|
||||
*/
|
||||
public static <T> Result<T> success(T model, Iterable<? extends ModelProblem> problems) {
|
||||
assert !hasErrors(problems);
|
||||
return new Result<>(false, model, problems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Success with warnings
|
||||
*
|
||||
* @param model
|
||||
* @param results
|
||||
*/
|
||||
public static <T> Result<T> success(T model, Result<?>... results) {
|
||||
final List<ModelProblem> problemsList = new ArrayList<>();
|
||||
|
||||
for (Result<?> result1 : results) {
|
||||
for (ModelProblem modelProblem : result1.getProblems()) {
|
||||
problemsList.add(modelProblem);
|
||||
}
|
||||
}
|
||||
|
||||
return success(model, problemsList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error with problems describing the cause
|
||||
*
|
||||
* @param problems
|
||||
*/
|
||||
public static <T> Result<T> error(Iterable<? extends ModelProblem> problems) {
|
||||
return error(null, problems);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(T model) {
|
||||
return error(model, Collections.emptyList());
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(Result<?> result) {
|
||||
return error(result.getProblems());
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(Result<?>... results) {
|
||||
final List<ModelProblem> problemsList = new ArrayList<>();
|
||||
|
||||
for (Result<?> result1 : results) {
|
||||
for (ModelProblem modelProblem : result1.getProblems()) {
|
||||
problemsList.add(modelProblem);
|
||||
}
|
||||
}
|
||||
|
||||
return error(problemsList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error with partial result and problems describing the cause
|
||||
*
|
||||
* @param model
|
||||
* @param problems
|
||||
*/
|
||||
public static <T> Result<T> error(T model, Iterable<? extends ModelProblem> problems) {
|
||||
return new Result<>(true, model, problems);
|
||||
}
|
||||
|
||||
/**
|
||||
* New result - determine whether error or success by checking problems for errors
|
||||
*
|
||||
* @param model
|
||||
* @param problems
|
||||
*/
|
||||
public static <T> Result<T> newResult(T model, Iterable<? extends ModelProblem> problems) {
|
||||
return new Result<>(hasErrors(problems), model, problems);
|
||||
}
|
||||
|
||||
/**
|
||||
* New result consisting of given result and new problem. Convenience for newResult(result.get(),
|
||||
* concat(result.getProblems(),problems)).
|
||||
*
|
||||
* @param result
|
||||
* @param problem
|
||||
*/
|
||||
public static <T> Result<T> addProblem(Result<T> result, ModelProblem problem) {
|
||||
return addProblems(result, Collections.singleton(problem));
|
||||
}
|
||||
|
||||
/**
|
||||
* New result that includes the given
|
||||
*
|
||||
* @param result
|
||||
* @param problems
|
||||
*/
|
||||
public static <T> Result<T> addProblems(Result<T> result, Iterable<? extends ModelProblem> problems) {
|
||||
Collection<ModelProblem> list = new ArrayList<>();
|
||||
for (ModelProblem item : problems) {
|
||||
list.add(item);
|
||||
}
|
||||
for (ModelProblem item : result.getProblems()) {
|
||||
list.add(item);
|
||||
}
|
||||
return new Result<>(result.hasErrors() || hasErrors(problems), result.get(), list);
|
||||
}
|
||||
|
||||
public static <T> Result<T> addProblems(Result<T> result, Result<?>... results) {
|
||||
final List<ModelProblem> problemsList = new ArrayList<>();
|
||||
|
||||
for (Result<?> result1 : results) {
|
||||
for (ModelProblem modelProblem : result1.getProblems()) {
|
||||
problemsList.add(modelProblem);
|
||||
}
|
||||
}
|
||||
return addProblems(result, problemsList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the given results into a single result by combining problems and models into single collection.
|
||||
*
|
||||
* @param results
|
||||
*/
|
||||
public static <T> Result<Iterable<T>> newResultSet(Iterable<? extends Result<? extends T>> results) {
|
||||
boolean hasErrors = false;
|
||||
List<T> modelsList = new ArrayList<>();
|
||||
List<ModelProblem> problemsList = new ArrayList<>();
|
||||
|
||||
for (Result<? extends T> result : results) {
|
||||
modelsList.add(result.get());
|
||||
|
||||
for (ModelProblem modelProblem : result.getProblems()) {
|
||||
problemsList.add(modelProblem);
|
||||
}
|
||||
|
||||
if (result.hasErrors()) {
|
||||
hasErrors = true;
|
||||
}
|
||||
}
|
||||
return new Result<>(hasErrors, (Iterable<T>) modelsList, problemsList);
|
||||
}
|
||||
|
||||
// helper to determine if problems contain error
|
||||
private static boolean hasErrors(Iterable<? extends ModelProblem> problems) {
|
||||
for (ModelProblem input : problems) {
|
||||
if (input.getSeverity().equals(Severity.ERROR)
|
||||
|| input.getSeverity().equals(Severity.FATAL)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
private final boolean errors;
|
||||
|
||||
private final T value;
|
||||
|
||||
private final Iterable<? extends ModelProblem> problems;
|
||||
|
||||
private Result(boolean errors, T model, Iterable<? extends ModelProblem> problems) {
|
||||
this.errors = errors;
|
||||
this.value = model;
|
||||
this.problems = problems;
|
||||
}
|
||||
|
||||
public Iterable<? extends ModelProblem> getProblems() {
|
||||
return problems;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
return errors;
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ import org.apache.maven.api.services.ModelBuilderRequest;
|
|||
import org.apache.maven.api.services.ModelBuilderResult;
|
||||
import org.apache.maven.api.services.ModelProblem;
|
||||
import org.apache.maven.api.services.ModelSource;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.services.model.ModelResolverException;
|
||||
import org.apache.maven.internal.impl.InternalSession;
|
||||
import org.apache.maven.internal.impl.model.ModelProblemUtils;
|
||||
|
@ -207,20 +208,22 @@ public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader
|
|||
ModelBuilderResult modelResult = modelBuilder.newSession().build(modelRequest);
|
||||
// ModelBuildingEx is thrown only on FATAL and ERROR severities, but we still can have WARNs
|
||||
// that may lead to unexpected build failure, log them
|
||||
if (!modelResult.getProblems().isEmpty()) {
|
||||
List<ModelProblem> problems = modelResult.getProblems();
|
||||
if (modelResult.getProblemCollector().hasWarningProblems()) {
|
||||
ProblemCollector<ModelProblem> problemCollector = modelResult.getProblemCollector();
|
||||
int totalProblems = problemCollector.totalProblemsReported();
|
||||
if (logger.isDebugEnabled()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(problems.size())
|
||||
sb.append(totalProblems)
|
||||
.append(" ")
|
||||
.append((problems.size() == 1) ? "problem was" : "problems were")
|
||||
.append(" encountered while building the effective model for ")
|
||||
.append((totalProblems == 1) ? "problem was" : "problems were")
|
||||
.append(" encountered while building the effective model for '")
|
||||
.append(request.getArtifact())
|
||||
.append(" during ")
|
||||
.append("' during ")
|
||||
.append(RequestTraceHelper.interpretTrace(true, request.getTrace()))
|
||||
.append("\n")
|
||||
.append((problems.size() == 1) ? "Problem" : "Problems");
|
||||
for (ModelProblem modelProblem : problems) {
|
||||
.append((totalProblems == 1) ? "Problem" : "Problems");
|
||||
for (ModelProblem modelProblem :
|
||||
problemCollector.problems().toList()) {
|
||||
sb.append("\n* ")
|
||||
.append(modelProblem.getMessage())
|
||||
.append(" @ ")
|
||||
|
@ -229,16 +232,17 @@ public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader
|
|||
logger.warn(sb.toString());
|
||||
} else {
|
||||
logger.warn(
|
||||
"{} {} encountered while building the effective model for {} during {} (use -X to see details)",
|
||||
problems.size(),
|
||||
(problems.size() == 1) ? "problem was" : "problems were",
|
||||
"{} {} encountered while building the effective model for '{}' during {} (use -X to see details)",
|
||||
totalProblems,
|
||||
(totalProblems == 1) ? "problem was" : "problems were",
|
||||
request.getArtifact(),
|
||||
RequestTraceHelper.interpretTrace(false, request.getTrace()));
|
||||
}
|
||||
}
|
||||
model = modelResult.getEffectiveModel();
|
||||
} catch (ModelBuilderException e) {
|
||||
for (ModelProblem problem : e.getResult().getProblems()) {
|
||||
for (ModelProblem problem :
|
||||
e.getResult().getProblemCollector().problems().toList()) {
|
||||
if (problem.getException() instanceof ModelResolverException) {
|
||||
result.addException(problem.getException());
|
||||
throw new ArtifactDescriptorException(result);
|
||||
|
|
|
@ -109,8 +109,7 @@ public class DefaultVersionResolver implements VersionResolver {
|
|||
cacheKey = new Key(session, request);
|
||||
|
||||
Object obj = cache.get(session, cacheKey);
|
||||
if (obj instanceof Record) {
|
||||
Record record = (Record) obj;
|
||||
if (obj instanceof Record record) {
|
||||
result.setVersion(record.version);
|
||||
result.setRepository(
|
||||
getRepository(session, request.getRepositories(), record.repoClass, record.repoId));
|
||||
|
@ -189,8 +188,7 @@ public class DefaultVersionResolver implements VersionResolver {
|
|||
if (result.getVersion() != null && result.getVersion().endsWith(SNAPSHOT)) {
|
||||
VersionRequest subRequest = new VersionRequest();
|
||||
subRequest.setArtifact(artifact.setVersion(result.getVersion()));
|
||||
if (result.getRepository() instanceof RemoteRepository) {
|
||||
RemoteRepository r = (RemoteRepository) result.getRepository();
|
||||
if (result.getRepository() instanceof RemoteRepository r) {
|
||||
subRequest.setRepositories(Collections.singletonList(r));
|
||||
} else {
|
||||
subRequest.setRepositories(request.getRepositories());
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* This UT is for {@link ProblemCollector} but here we have implementations for problems.
|
||||
*/
|
||||
class DefaultProblemCollectorTest {
|
||||
@Test
|
||||
void severityFatalDetection() {
|
||||
ProblemCollector<BuilderProblem> collector = ProblemCollector.create(5);
|
||||
|
||||
assertFalse(collector.hasProblemsFor(BuilderProblem.Severity.WARNING));
|
||||
assertFalse(collector.hasErrorProblems());
|
||||
assertFalse(collector.hasFatalProblems());
|
||||
|
||||
collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.FATAL));
|
||||
|
||||
// fatal triggers all
|
||||
assertTrue(collector.hasProblemsFor(BuilderProblem.Severity.WARNING));
|
||||
assertTrue(collector.hasErrorProblems());
|
||||
assertTrue(collector.hasFatalProblems());
|
||||
}
|
||||
|
||||
@Test
|
||||
void severityErrorDetection() {
|
||||
ProblemCollector<BuilderProblem> collector = ProblemCollector.create(5);
|
||||
|
||||
assertFalse(collector.hasProblemsFor(BuilderProblem.Severity.WARNING));
|
||||
assertFalse(collector.hasErrorProblems());
|
||||
assertFalse(collector.hasFatalProblems());
|
||||
|
||||
collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.ERROR));
|
||||
|
||||
// error triggers error + warning
|
||||
assertTrue(collector.hasProblemsFor(BuilderProblem.Severity.WARNING));
|
||||
assertTrue(collector.hasErrorProblems());
|
||||
assertFalse(collector.hasFatalProblems());
|
||||
}
|
||||
|
||||
@Test
|
||||
void severityWarningDetection() {
|
||||
ProblemCollector<BuilderProblem> collector = ProblemCollector.create(5);
|
||||
|
||||
assertFalse(collector.hasProblemsFor(BuilderProblem.Severity.WARNING));
|
||||
assertFalse(collector.hasErrorProblems());
|
||||
assertFalse(collector.hasFatalProblems());
|
||||
|
||||
collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.WARNING));
|
||||
|
||||
// warning triggers warning only
|
||||
assertTrue(collector.hasProblemsFor(BuilderProblem.Severity.WARNING));
|
||||
assertFalse(collector.hasErrorProblems());
|
||||
assertFalse(collector.hasFatalProblems());
|
||||
}
|
||||
|
||||
@Test
|
||||
void lossy() {
|
||||
ProblemCollector<BuilderProblem> collector = ProblemCollector.create(5);
|
||||
IntStream.range(0, 5)
|
||||
.forEach(i -> collector.reportProblem(new DefaultBuilderProblem(
|
||||
"source", 0, 0, null, "message " + i, BuilderProblem.Severity.WARNING)));
|
||||
|
||||
// collector is "full" of warnings
|
||||
assertFalse(collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.WARNING)));
|
||||
|
||||
// but collector will drop warning for more severe issues
|
||||
assertTrue(collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.ERROR)));
|
||||
assertTrue(collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.FATAL)));
|
||||
|
||||
// collector is full of warnings, errors and fatal (mixed)
|
||||
assertFalse(collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.WARNING)));
|
||||
|
||||
// fill it up with fatal ones
|
||||
IntStream.range(0, 5)
|
||||
.forEach(i -> collector.reportProblem(new DefaultBuilderProblem(
|
||||
"source", 0, 0, null, "message " + i, BuilderProblem.Severity.FATAL)));
|
||||
|
||||
// from now on, only counters work, problems are lost
|
||||
assertFalse(collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.WARNING)));
|
||||
assertFalse(collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.ERROR)));
|
||||
assertFalse(collector.reportProblem(
|
||||
new DefaultBuilderProblem("source", 0, 0, null, "message", BuilderProblem.Severity.FATAL)));
|
||||
|
||||
assertEquals(17, collector.totalProblemsReported());
|
||||
assertEquals(8, collector.problemsReportedFor(BuilderProblem.Severity.WARNING));
|
||||
assertEquals(2, collector.problemsReportedFor(BuilderProblem.Severity.ERROR));
|
||||
assertEquals(7, collector.problemsReportedFor(BuilderProblem.Severity.FATAL));
|
||||
|
||||
// but preserved problems count == capacity
|
||||
assertEquals(5, collector.problems().count());
|
||||
}
|
||||
|
||||
@Test
|
||||
void moreSeverePushOutLeastSevere() {
|
||||
ProblemCollector<BuilderProblem> collector = ProblemCollector.create(5);
|
||||
|
||||
assertEquals(0, collector.totalProblemsReported());
|
||||
assertEquals(0, collector.problems().count());
|
||||
|
||||
IntStream.range(0, 5)
|
||||
.forEach(i -> collector.reportProblem(new DefaultBuilderProblem(
|
||||
"source", 0, 0, null, "message " + i, BuilderProblem.Severity.WARNING)));
|
||||
assertEquals(5, collector.totalProblemsReported());
|
||||
assertEquals(5, collector.problems().count());
|
||||
|
||||
IntStream.range(0, 5)
|
||||
.forEach(i -> collector.reportProblem(new DefaultBuilderProblem(
|
||||
"source", 0, 0, null, "message " + i, BuilderProblem.Severity.ERROR)));
|
||||
assertEquals(10, collector.totalProblemsReported());
|
||||
assertEquals(5, collector.problems().count());
|
||||
|
||||
IntStream.range(0, 4)
|
||||
.forEach(i -> collector.reportProblem(new DefaultBuilderProblem(
|
||||
"source", 0, 0, null, "message " + i, BuilderProblem.Severity.FATAL)));
|
||||
assertEquals(14, collector.totalProblemsReported());
|
||||
assertEquals(5, collector.problems().count());
|
||||
|
||||
assertEquals(5, collector.problemsReportedFor(BuilderProblem.Severity.WARNING));
|
||||
assertEquals(5, collector.problemsReportedFor(BuilderProblem.Severity.ERROR));
|
||||
assertEquals(4, collector.problemsReportedFor(BuilderProblem.Severity.FATAL));
|
||||
|
||||
assertEquals(0, collector.problems(BuilderProblem.Severity.WARNING).count());
|
||||
assertEquals(1, collector.problems(BuilderProblem.Severity.ERROR).count());
|
||||
assertEquals(4, collector.problems(BuilderProblem.Severity.FATAL).count());
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ package org.apache.maven.internal.impl;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.api.services.SettingsBuilder;
|
||||
import org.apache.maven.api.settings.Profile;
|
||||
import org.apache.maven.api.settings.Repository;
|
||||
|
@ -56,32 +57,29 @@ class DefaultSettingsValidatorTest {
|
|||
void testValidate() {
|
||||
Profile prof = Profile.newBuilder().id("xxx").build();
|
||||
Settings model = Settings.newBuilder().profiles(List.of(prof)).build();
|
||||
List<BuilderProblem> problems = validator.validate(model);
|
||||
assertEquals(0, problems.size());
|
||||
ProblemCollector<BuilderProblem> problems = validator.validate(model);
|
||||
assertEquals(0, problems.totalProblemsReported());
|
||||
|
||||
Repository repo = org.apache.maven.api.settings.Repository.newInstance(false);
|
||||
Settings model2 = Settings.newBuilder()
|
||||
.profiles(List.of(prof.withRepositories(List.of(repo))))
|
||||
.build();
|
||||
problems.clear();
|
||||
problems = validator.validate(model2);
|
||||
assertEquals(2, problems.size());
|
||||
assertEquals(2, problems.totalProblemsReported());
|
||||
|
||||
repo = repo.withUrl("http://xxx.xxx.com");
|
||||
model2 = Settings.newBuilder()
|
||||
.profiles(List.of(prof.withRepositories(List.of(repo))))
|
||||
.build();
|
||||
problems.clear();
|
||||
problems = validator.validate(model2);
|
||||
assertEquals(1, problems.size());
|
||||
assertEquals(1, problems.totalProblemsReported());
|
||||
|
||||
repo = repo.withId("xxx");
|
||||
model2 = Settings.newBuilder()
|
||||
.profiles(List.of(prof.withRepositories(List.of(repo))))
|
||||
.build();
|
||||
problems.clear();
|
||||
problems = validator.validate(model2);
|
||||
assertEquals(0, problems.size());
|
||||
assertEquals(0, problems.totalProblemsReported());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -76,7 +76,8 @@ class ComplexActivationTest {
|
|||
.build();
|
||||
ModelBuilderResult result = builder.newSession().build(request);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getProblems().stream()
|
||||
assertTrue(result.getProblemCollector()
|
||||
.problems()
|
||||
.anyMatch(p -> p.getSeverity() == BuilderProblem.Severity.WARNING
|
||||
&& p.getMessage().contains("The 'missing' assertion will be ignored.")));
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
package org.apache.maven.internal.impl.model.profile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.model.InputLocation;
|
||||
|
@ -27,6 +26,7 @@ import org.apache.maven.api.services.BuilderProblem;
|
|||
import org.apache.maven.api.services.ModelBuilderException;
|
||||
import org.apache.maven.api.services.ModelProblem;
|
||||
import org.apache.maven.api.services.ModelProblemCollector;
|
||||
import org.apache.maven.api.services.ProblemCollector;
|
||||
import org.apache.maven.internal.impl.model.DefaultModelProblem;
|
||||
|
||||
/**
|
||||
|
@ -34,23 +34,11 @@ import org.apache.maven.internal.impl.model.DefaultModelProblem;
|
|||
*/
|
||||
public class SimpleProblemCollector implements ModelProblemCollector {
|
||||
|
||||
final List<ModelProblem> problems = new ArrayList<>();
|
||||
final ProblemCollector<ModelProblem> problemCollector = ProblemCollector.create(100);
|
||||
|
||||
@Override
|
||||
public List<ModelProblem> getProblems() {
|
||||
return problems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasErrors() {
|
||||
return problems.stream()
|
||||
.anyMatch(p -> p.getSeverity() == ModelProblem.Severity.FATAL
|
||||
|| p.getSeverity() == ModelProblem.Severity.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFatalErrors() {
|
||||
return problems.stream().anyMatch(p -> p.getSeverity() == ModelProblem.Severity.FATAL);
|
||||
public ProblemCollector<ModelProblem> getProblemCollector() {
|
||||
return problemCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,11 +58,6 @@ public class SimpleProblemCollector implements ModelProblemCollector {
|
|||
exception));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(ModelProblem problem) {
|
||||
this.problems.add(problem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuilderException newModelBuilderException() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
@ -118,8 +101,8 @@ public class SimpleProblemCollector implements ModelProblemCollector {
|
|||
}
|
||||
|
||||
private List<String> getForLevel(BuilderProblem.Severity severity) {
|
||||
return problems.stream()
|
||||
.filter(p -> p.getSeverity() == severity)
|
||||
return problemCollector
|
||||
.problems(severity)
|
||||
.map(BuilderProblem::getMessage)
|
||||
.toList();
|
||||
}
|
||||
|
|
|
@ -47,8 +47,7 @@ class MavenITmng8379SettingsDecryptTest extends AbstractMavenIntegrationTestCase
|
|||
verifier.verifyErrorFreeLog();
|
||||
|
||||
// there is a warning and all fields decrypted
|
||||
verifier.verifyTextInLog(
|
||||
"[INFO] Some problems were encountered while building the effective settings (use -X to see details)");
|
||||
verifier.verifyTextInLog(" encountered while building the effective settings (use -e to see details)");
|
||||
verifier.verifyTextInLog("<password>testtest</password>");
|
||||
verifier.verifyTextInLog("<value>testtest</value>");
|
||||
}
|
||||
|
@ -71,8 +70,7 @@ class MavenITmng8379SettingsDecryptTest extends AbstractMavenIntegrationTestCase
|
|||
|
||||
// there is no warning and all fields decrypted
|
||||
verifier.verifyTextNotInLog("[WARNING]");
|
||||
verifier.verifyTextNotInLog(
|
||||
"[INFO] Some problems were encountered while building the effective settings (use -X to see details)");
|
||||
verifier.verifyTextNotInLog(" encountered while building the effective settings (use -e to see details)");
|
||||
verifier.verifyTextInLog("<password>testtest</password>");
|
||||
verifier.verifyTextInLog("<value>secretHeader</value>");
|
||||
}
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -156,7 +156,7 @@ under the License.
|
|||
<jlineVersion>3.28.0</jlineVersion>
|
||||
<junitVersion>5.11.4</junitVersion>
|
||||
<jxpathVersion>1.3</jxpathVersion>
|
||||
<logbackClassicVersion>1.5.12</logbackClassicVersion>
|
||||
<logbackClassicVersion>1.5.13</logbackClassicVersion>
|
||||
<mockitoVersion>5.14.2</mockitoVersion>
|
||||
<plexusInteractivityVersion>1.3</plexusInteractivityVersion>
|
||||
<plexusInterpolationVersion>1.27</plexusInterpolationVersion>
|
||||
|
|
Loading…
Reference in New Issue