compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/relocation/UserPropertiesArtifactRelocationSource.java [59:158]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    private static final Artifact SENTINEL = new DefaultArtifact("org.apache.maven.banned:user-relocation:1.0");

    @Override
    public Artifact relocatedTarget(
            RepositorySystemSession session, ArtifactDescriptorResult artifactDescriptorResult, Model model)
            throws ArtifactDescriptorException {
        Relocations relocations = (Relocations) session.getData()
                .computeIfAbsent(getClass().getName() + ".relocations", () -> parseRelocations(session));
        if (relocations != null) {
            Artifact original = artifactDescriptorResult.getRequest().getArtifact();
            Relocation relocation = relocations.getRelocation(original);
            if (relocation != null
                    && (isProjectContext(artifactDescriptorResult.getRequest().getRequestContext())
                            || relocation.global)) {
                if (relocation.target == SENTINEL) {
                    String message = "The artifact " + original + " has been banned from resolution: "
                            + (relocation.global ? "User global ban" : "User project ban");
                    LOGGER.debug(message);
                    throw new ArtifactDescriptorException(artifactDescriptorResult, message);
                }
                Artifact result = new RelocatedArtifact(
                        original,
                        isAny(relocation.target.getGroupId()) ? null : relocation.target.getGroupId(),
                        isAny(relocation.target.getArtifactId()) ? null : relocation.target.getArtifactId(),
                        isAny(relocation.target.getClassifier()) ? null : relocation.target.getClassifier(),
                        isAny(relocation.target.getExtension()) ? null : relocation.target.getExtension(),
                        isAny(relocation.target.getVersion()) ? null : relocation.target.getVersion(),
                        relocation.global ? "User global relocation" : "User project relocation");
                LOGGER.debug(
                        "The artifact {} has been relocated to {}: {}",
                        original,
                        result,
                        relocation.global ? "User global relocation" : "User project relocation");
                return result;
            }
        }
        return null;
    }

    private boolean isProjectContext(String context) {
        return context != null && context.startsWith("project");
    }

    private static boolean isAny(String str) {
        return "*".equals(str);
    }

    private static boolean matches(String pattern, String str) {
        if (isAny(pattern)) {
            return true;
        } else if (pattern.endsWith("*")) {
            return str.startsWith(pattern.substring(0, pattern.length() - 1));
        } else {
            return Objects.equals(pattern, str);
        }
    }

    private static Predicate<Artifact> artifactPredicate(Artifact artifact) {
        return a -> matches(artifact.getGroupId(), a.getGroupId())
                && matches(artifact.getArtifactId(), a.getArtifactId())
                && matches(artifact.getBaseVersion(), a.getBaseVersion())
                && matches(artifact.getExtension(), a.getExtension())
                && matches(artifact.getClassifier(), a.getClassifier());
    }

    private static class Relocation {
        private final Predicate<Artifact> predicate;
        private final boolean global;
        private final Artifact source;
        private final Artifact target;

        private Relocation(boolean global, Artifact source, Artifact target) {
            this.predicate = artifactPredicate(source);
            this.global = global;
            this.source = source;
            this.target = target;
        }

        @Override
        public String toString() {
            return source + (global ? " >> " : " > ") + target;
        }
    }

    private static class Relocations {
        private final List<Relocation> relocations;

        private Relocations(List<Relocation> relocations) {
            this.relocations = relocations;
        }

        private Relocation getRelocation(Artifact artifact) {
            return relocations.stream()
                    .filter(r -> r.predicate.test(artifact))
                    .findFirst()
                    .orElse(null);
        }
    }

    private Relocations parseRelocations(RepositorySystemSession session) {
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/relocation/UserPropertiesArtifactRelocationSource.java [55:154]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    private static final Artifact SENTINEL = new DefaultArtifact("org.apache.maven.banned:user-relocation:1.0");

    @Override
    public Artifact relocatedTarget(
            RepositorySystemSession session, ArtifactDescriptorResult artifactDescriptorResult, Model model)
            throws ArtifactDescriptorException {
        Relocations relocations = (Relocations) session.getData()
                .computeIfAbsent(getClass().getName() + ".relocations", () -> parseRelocations(session));
        if (relocations != null) {
            Artifact original = artifactDescriptorResult.getRequest().getArtifact();
            Relocation relocation = relocations.getRelocation(original);
            if (relocation != null
                    && (isProjectContext(artifactDescriptorResult.getRequest().getRequestContext())
                            || relocation.global)) {
                if (relocation.target == SENTINEL) {
                    String message = "The artifact " + original + " has been banned from resolution: "
                            + (relocation.global ? "User global ban" : "User project ban");
                    LOGGER.debug(message);
                    throw new ArtifactDescriptorException(artifactDescriptorResult, message);
                }
                Artifact result = new RelocatedArtifact(
                        original,
                        isAny(relocation.target.getGroupId()) ? null : relocation.target.getGroupId(),
                        isAny(relocation.target.getArtifactId()) ? null : relocation.target.getArtifactId(),
                        isAny(relocation.target.getClassifier()) ? null : relocation.target.getClassifier(),
                        isAny(relocation.target.getExtension()) ? null : relocation.target.getExtension(),
                        isAny(relocation.target.getVersion()) ? null : relocation.target.getVersion(),
                        relocation.global ? "User global relocation" : "User project relocation");
                LOGGER.debug(
                        "The artifact {} has been relocated to {}: {}",
                        original,
                        result,
                        relocation.global ? "User global relocation" : "User project relocation");
                return result;
            }
        }
        return null;
    }

    private boolean isProjectContext(String context) {
        return context != null && context.startsWith("project");
    }

    private static boolean isAny(String str) {
        return "*".equals(str);
    }

    private static boolean matches(String pattern, String str) {
        if (isAny(pattern)) {
            return true;
        } else if (pattern.endsWith("*")) {
            return str.startsWith(pattern.substring(0, pattern.length() - 1));
        } else {
            return Objects.equals(pattern, str);
        }
    }

    private static Predicate<Artifact> artifactPredicate(Artifact artifact) {
        return a -> matches(artifact.getGroupId(), a.getGroupId())
                && matches(artifact.getArtifactId(), a.getArtifactId())
                && matches(artifact.getBaseVersion(), a.getBaseVersion())
                && matches(artifact.getExtension(), a.getExtension())
                && matches(artifact.getClassifier(), a.getClassifier());
    }

    private static class Relocation {
        private final Predicate<Artifact> predicate;
        private final boolean global;
        private final Artifact source;
        private final Artifact target;

        private Relocation(boolean global, Artifact source, Artifact target) {
            this.predicate = artifactPredicate(source);
            this.global = global;
            this.source = source;
            this.target = target;
        }

        @Override
        public String toString() {
            return source + (global ? " >> " : " > ") + target;
        }
    }

    private static class Relocations {
        private final List<Relocation> relocations;

        private Relocations(List<Relocation> relocations) {
            this.relocations = relocations;
        }

        private Relocation getRelocation(Artifact artifact) {
            return relocations.stream()
                    .filter(r -> r.predicate.test(artifact))
                    .findFirst()
                    .orElse(null);
        }
    }

    private Relocations parseRelocations(RepositorySystemSession session) {
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



