This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/master by this push:
     new e34afc897a [MNG-7959] User controlled relocations (#1339)
e34afc897a is described below

commit e34afc897a7d7877f79207becc0a94ab001b024e
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Mon Dec 18 11:34:30 2023 +0100

    [MNG-7959] User controlled relocations (#1339)
    
    With some improvements. It accepts user property with CSV entries for 
relocations.
    
    To toy with it, use `-Dmaven.relocations.entries` user property, for 
example create `.mvn/maven.config` file with contents:
    ```
    -Dmaven.relocations.entries=entry1,entry2,...
    ```
    It accepts CSV (comma delimited) of entries, while entry form is as:
    ```
    GAV>GAV
    ```
    Where left GAV can contain `*` for any elem (so `*:*:*` would mean ALL, 
something you don't want). Right GAV is either fully specified, or also can 
contain `*`, then it behaves as "ordinary relocation": the coordinate is 
preserved from relocated artifact. Finally, if right hand GAV is absent (line 
looks like "GAV>"). the left hand matching GAV is banned fully (from resolving).
    
    Note: the ">" means project level, while ">>" means global (whole session 
level, so even plugins will get relocated artifacts) relocation.
    
    Examples:
    ```
    
-Dmaven.relocations.entries=org.foo:*:*>,org.here:*:*>org.there:*:*,javax.inject:javax.inject:1>>jakarta.inject:jakarta.inject:1.0.5
    ```
    
    Meaning: 3 entries, ban `org.foo` group (exactly, so `org.foo.bar` is 
allowed), relocate `org.here` to `org.there` and finally **globally relocate** 
(see ">>") `javax.inject:javax.inject:1` to 
`jakarta.inject:jakarta.inject:1.0.5`
    
    ---
    
    https://issues.apache.org/jira/browse/MNG-7959
---
 maven-resolver-provider/pom.xml                    |  30 +--
 .../internal/DefaultArtifactDescriptorReader.java  |  43 ++---
 .../internal/MavenArtifactRelocationSource.java    |  41 +++++
 .../repository/internal/RelocatedArtifact.java     |  59 ++++--
 ...ributionManagementArtifactRelocationSource.java |  75 ++++++++
 .../UserPropertiesArtifactRelocationSource.java    | 201 +++++++++++++++++++++
 6 files changed, 393 insertions(+), 56 deletions(-)

diff --git a/maven-resolver-provider/pom.xml b/maven-resolver-provider/pom.xml
index 15a63bd68e..8e3d4bf17d 100644
--- a/maven-resolver-provider/pom.xml
+++ b/maven-resolver-provider/pom.xml
@@ -78,6 +78,21 @@ under the License.
       <artifactId>javax.inject</artifactId>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.eclipse.sisu</groupId>
+      <artifactId>org.eclipse.sisu.plexus</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.sisu</groupId>
+      <artifactId>org.eclipse.sisu.inject</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <scope>provided</scope>
+    </dependency>
 
     <!-- Testing -->
     <dependency>
@@ -110,21 +125,6 @@ under the License.
       <artifactId>slf4j-simple</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.eclipse.sisu</groupId>
-      <artifactId>org.eclipse.sisu.plexus</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.sisu</groupId>
-      <artifactId>org.eclipse.sisu.inject</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>com.google.inject</groupId>
-      <artifactId>guice</artifactId>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <build>
diff --git 
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java
 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java
index 0d40d70d77..d45ebeba1d 100644
--- 
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java
+++ 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java
@@ -28,9 +28,7 @@ import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 
-import org.apache.maven.model.DistributionManagement;
 import org.apache.maven.model.Model;
-import org.apache.maven.model.Relocation;
 import org.apache.maven.model.building.ArtifactModelSource;
 import org.apache.maven.model.building.DefaultModelBuildingRequest;
 import org.apache.maven.model.building.ModelBuilder;
@@ -64,16 +62,13 @@ import org.eclipse.aether.resolution.VersionRequest;
 import org.eclipse.aether.resolution.VersionResolutionException;
 import org.eclipse.aether.resolution.VersionResult;
 import org.eclipse.aether.transfer.ArtifactNotFoundException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
+ * Default artifact descriptor reader.
  */
 @Named
 @Singleton
 public class DefaultArtifactDescriptorReader implements 
ArtifactDescriptorReader {
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(DefaultArtifactDescriptorReader.class);
-
     private final RemoteRepositoryManager remoteRepositoryManager;
     private final VersionResolver versionResolver;
     private final VersionRangeResolver versionRangeResolver;
@@ -81,6 +76,8 @@ public class DefaultArtifactDescriptorReader implements 
ArtifactDescriptorReader
     private final RepositoryEventDispatcher repositoryEventDispatcher;
     private final ModelBuilder modelBuilder;
     private final ModelCacheFactory modelCacheFactory;
+    private final Map<String, MavenArtifactRelocationSource> 
artifactRelocationSources;
+    private final ArtifactDescriptorReaderDelegate delegate;
 
     @Inject
     public DefaultArtifactDescriptorReader(
@@ -90,7 +87,8 @@ public class DefaultArtifactDescriptorReader implements 
ArtifactDescriptorReader
             ArtifactResolver artifactResolver,
             ModelBuilder modelBuilder,
             RepositoryEventDispatcher repositoryEventDispatcher,
-            ModelCacheFactory modelCacheFactory) {
+            ModelCacheFactory modelCacheFactory,
+            Map<String, MavenArtifactRelocationSource> 
artifactRelocationSources) {
         this.remoteRepositoryManager =
                 Objects.requireNonNull(remoteRepositoryManager, 
"remoteRepositoryManager cannot be null");
         this.versionResolver = Objects.requireNonNull(versionResolver, 
"versionResolver cannot be null");
@@ -100,6 +98,9 @@ public class DefaultArtifactDescriptorReader implements 
ArtifactDescriptorReader
         this.repositoryEventDispatcher =
                 Objects.requireNonNull(repositoryEventDispatcher, 
"repositoryEventDispatcher cannot be null");
         this.modelCacheFactory = Objects.requireNonNull(modelCacheFactory, 
"modelCacheFactory cannot be null");
+        this.artifactRelocationSources =
+                Objects.requireNonNull(artifactRelocationSources, 
"artifactRelocationSources cannot be null");
+        this.delegate = new ArtifactDescriptorReaderDelegate();
     }
 
     @Override
@@ -114,7 +115,7 @@ public class DefaultArtifactDescriptorReader implements 
ArtifactDescriptorReader
                     (ArtifactDescriptorReaderDelegate) 
config.get(ArtifactDescriptorReaderDelegate.class.getName());
 
             if (delegate == null) {
-                delegate = new ArtifactDescriptorReaderDelegate();
+                delegate = this.delegate;
             }
 
             delegate.populateResult(session, result, model);
@@ -236,16 +237,10 @@ public class DefaultArtifactDescriptorReader implements 
ArtifactDescriptorReader
                 throw new ArtifactDescriptorException(result);
             }
 
-            Relocation relocation = getRelocation(model);
-
-            if (relocation != null) {
+            Artifact relocatedArtifact = getRelocation(session, request, 
model);
+            if (relocatedArtifact != null) {
                 result.addRelocation(a);
-                a = new RelocatedArtifact(
-                        a,
-                        relocation.getGroupId(),
-                        relocation.getArtifactId(),
-                        relocation.getVersion(),
-                        relocation.getMessage());
+                a = relocatedArtifact;
                 result.setArtifact(a);
             } else {
                 return model;
@@ -264,13 +259,15 @@ public class DefaultArtifactDescriptorReader implements 
ArtifactDescriptorReader
         return props;
     }
 
-    private Relocation getRelocation(Model model) {
-        Relocation relocation = null;
-        DistributionManagement distMgmt = model.getDistributionManagement();
-        if (distMgmt != null) {
-            relocation = distMgmt.getRelocation();
+    private Artifact getRelocation(RepositorySystemSession session, 
ArtifactDescriptorRequest request, Model model) {
+        Artifact result = null;
+        for (MavenArtifactRelocationSource source : 
artifactRelocationSources.values()) {
+            result = source.relocatedTarget(session, request, model);
+            if (result != null) {
+                break;
+            }
         }
-        return relocation;
+        return result;
     }
 
     private void missingDescriptor(
diff --git 
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenArtifactRelocationSource.java
 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenArtifactRelocationSource.java
new file mode 100644
index 0000000000..1f6328f3f3
--- /dev/null
+++ 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenArtifactRelocationSource.java
@@ -0,0 +1,41 @@
+/*
+ * 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.repository.internal;
+
+import org.apache.maven.model.Model;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
+
+/**
+ * Maven relocation source.
+ *
+ * @since 4.0.0
+ */
+public interface MavenArtifactRelocationSource {
+    /**
+     * Returns {@link Artifact} instance where to relocate to, or {@code null}.
+     *
+     * @param session The session, never {@code null}.
+     * @param request The artifact descriptor request, never {@code null}.
+     * @param model The artifact model, never {@code null}.
+     * @return The {@link Artifact} to relocate to, or {@code null} if no 
relocation wanted.
+     */
+    Artifact relocatedTarget(RepositorySystemSession session, 
ArtifactDescriptorRequest request, Model model);
+}
diff --git 
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java
 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java
index 4f78f1a35e..bf1f97e294 100644
--- 
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java
+++ 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java
@@ -35,16 +35,29 @@ public final class RelocatedArtifact extends 
AbstractArtifact {
 
     private final String artifactId;
 
+    private final String classifier;
+
+    private final String extension;
+
     private final String version;
 
     private final String message;
 
-    RelocatedArtifact(Artifact artifact, String groupId, String artifactId, 
String version, String message) {
+    public RelocatedArtifact(
+            Artifact artifact,
+            String groupId,
+            String artifactId,
+            String classifier,
+            String extension,
+            String version,
+            String message) {
         this.artifact = Objects.requireNonNull(artifact, "artifact cannot be 
null");
-        this.groupId = (groupId != null && groupId.length() > 0) ? groupId : 
null;
-        this.artifactId = (artifactId != null && artifactId.length() > 0) ? 
artifactId : null;
-        this.version = (version != null && version.length() > 0) ? version : 
null;
-        this.message = (message != null && message.length() > 0) ? message : 
null;
+        this.groupId = (groupId != null && !groupId.isEmpty()) ? groupId : 
null;
+        this.artifactId = (artifactId != null && !artifactId.isEmpty()) ? 
artifactId : null;
+        this.classifier = (classifier != null && !classifier.isEmpty()) ? 
classifier : null;
+        this.extension = (extension != null && !extension.isEmpty()) ? 
extension : null;
+        this.version = (version != null && !version.isEmpty()) ? version : 
null;
+        this.message = (message != null && !message.isEmpty()) ? message : 
null;
     }
 
     @Override
@@ -65,6 +78,24 @@ public final class RelocatedArtifact extends 
AbstractArtifact {
         }
     }
 
+    @Override
+    public String getClassifier() {
+        if (classifier != null) {
+            return classifier;
+        } else {
+            return artifact.getClassifier();
+        }
+    }
+
+    @Override
+    public String getExtension() {
+        if (extension != null) {
+            return extension;
+        } else {
+            return artifact.getExtension();
+        }
+    }
+
     @Override
     public String getVersion() {
         if (version != null) {
@@ -81,7 +112,7 @@ public final class RelocatedArtifact extends 
AbstractArtifact {
         if (current.equals(version) || (version == null && current.length() <= 
0)) {
             return this;
         }
-        return new RelocatedArtifact(artifact, groupId, artifactId, version, 
message);
+        return new RelocatedArtifact(artifact, groupId, artifactId, 
classifier, extension, version, message);
     }
 
     @Override
@@ -90,7 +121,8 @@ public final class RelocatedArtifact extends 
AbstractArtifact {
         if (Objects.equals(current, file)) {
             return this;
         }
-        return new RelocatedArtifact(artifact.setFile(file), groupId, 
artifactId, version, message);
+        return new RelocatedArtifact(
+                artifact.setFile(file), groupId, artifactId, classifier, 
extension, version, message);
     }
 
     @Override
@@ -99,17 +131,8 @@ public final class RelocatedArtifact extends 
AbstractArtifact {
         if (current.equals(properties) || (properties == null && 
current.isEmpty())) {
             return this;
         }
-        return new RelocatedArtifact(artifact.setProperties(properties), 
groupId, artifactId, version, message);
-    }
-
-    @Override
-    public String getClassifier() {
-        return artifact.getClassifier();
-    }
-
-    @Override
-    public String getExtension() {
-        return artifact.getExtension();
+        return new RelocatedArtifact(
+                artifact.setProperties(properties), groupId, artifactId, 
classifier, extension, version, message);
     }
 
     @Override
diff --git 
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/relocation/DistributionManagementArtifactRelocationSource.java
 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/relocation/DistributionManagementArtifactRelocationSource.java
new file mode 100644
index 0000000000..e4033c9dec
--- /dev/null
+++ 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/relocation/DistributionManagementArtifactRelocationSource.java
@@ -0,0 +1,75 @@
+/*
+ * 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.repository.internal.relocation;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.apache.maven.model.DistributionManagement;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Relocation;
+import org.apache.maven.repository.internal.MavenArtifactRelocationSource;
+import org.apache.maven.repository.internal.RelocatedArtifact;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
+import org.eclipse.sisu.Priority;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Relocation source from standard distribution management. This is the "one 
and only" relocation implementation that
+ * existed in Maven 3 land, uses POM distributionManagement/relocation.
+ * <p>
+ * Note: this component should kick-in last regarding relocations.
+ *
+ * @since 4.0.0
+ */
+@Singleton
+@Named
+@Priority(5)
+@SuppressWarnings("checkstyle:MagicNumber")
+public final class DistributionManagementArtifactRelocationSource implements 
MavenArtifactRelocationSource {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(DistributionManagementArtifactRelocationSource.class);
+
+    @Override
+    public Artifact relocatedTarget(RepositorySystemSession session, 
ArtifactDescriptorRequest request, Model model) {
+        DistributionManagement distMgmt = model.getDistributionManagement();
+        if (distMgmt != null) {
+            Relocation relocation = distMgmt.getRelocation();
+            if (relocation != null) {
+                Artifact result = new RelocatedArtifact(
+                        request.getArtifact(),
+                        relocation.getGroupId(),
+                        relocation.getArtifactId(),
+                        null,
+                        null,
+                        relocation.getVersion(),
+                        relocation.getMessage());
+                LOGGER.debug(
+                        "The artifact {} has been relocated to {}: {}",
+                        request.getArtifact(),
+                        result,
+                        relocation.getMessage());
+                return result;
+            }
+        }
+        return null;
+    }
+}
diff --git 
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/relocation/UserPropertiesArtifactRelocationSource.java
 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/relocation/UserPropertiesArtifactRelocationSource.java
new file mode 100644
index 0000000000..fd3710b9e9
--- /dev/null
+++ 
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/relocation/UserPropertiesArtifactRelocationSource.java
@@ -0,0 +1,201 @@
+/*
+ * 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.repository.internal.relocation;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.repository.internal.MavenArtifactRelocationSource;
+import org.apache.maven.repository.internal.RelocatedArtifact;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
+import org.eclipse.sisu.Priority;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Relocation source from user properties.
+ *
+ * @since 4.0.0
+ */
+@Singleton
+@Named
+@Priority(50)
+@SuppressWarnings("checkstyle:MagicNumber")
+public final class UserPropertiesArtifactRelocationSource implements 
MavenArtifactRelocationSource {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(UserPropertiesArtifactRelocationSource.class);
+
+    private static final String CONFIG_PROP_RELOCATIONS_ENTRIES = 
"maven.relocations.entries";
+
+    @Override
+    public Artifact relocatedTarget(RepositorySystemSession session, 
ArtifactDescriptorRequest request, Model model) {
+        Relocations relocations = (Relocations) session.getData()
+                .computeIfAbsent(getClass().getName() + ".relocations", () -> 
parseRelocations(session));
+        if (relocations != null) {
+            Relocation relocation = 
relocations.getRelocation(request.getArtifact());
+            if (relocation != null && 
(isProjectContext(request.getRequestContext()) || relocation.global)) {
+                Artifact result = new RelocatedArtifact(
+                        request.getArtifact(),
+                        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 {}: {}",
+                        request.getArtifact(),
+                        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) {
+        String relocationsEntries = (String) 
session.getConfigProperties().get(CONFIG_PROP_RELOCATIONS_ENTRIES);
+        if (relocationsEntries == null) {
+            return null;
+        }
+        String[] entries = relocationsEntries.split(",");
+        try (Stream<String> lines = Arrays.stream(entries)) {
+            List<Relocation> relocationList = lines.filter(
+                            l -> l != null && !l.trim().isEmpty())
+                    .map(l -> {
+                        boolean global;
+                        String splitExpr;
+                        if (l.contains(">>")) {
+                            global = true;
+                            splitExpr = ">>";
+                        } else if (l.contains(">")) {
+                            global = false;
+                            splitExpr = ">";
+                        } else {
+                            throw new IllegalArgumentException("Unrecognized 
entry: " + l);
+                        }
+                        String[] parts = l.split(splitExpr);
+                        if (parts.length < 1) {
+                            throw new IllegalArgumentException("Unrecognized 
entry: " + l);
+                        }
+                        Artifact s = parseArtifact(parts[0]);
+                        Artifact t;
+                        if (parts.length > 1) {
+                            t = parseArtifact(parts[1]);
+                        } else {
+                            t = new 
DefaultArtifact("org.apache.maven.banned:user-relocation:1.0");
+                        }
+                        return new Relocation(global, s, t);
+                    })
+                    .collect(Collectors.toList());
+            LOGGER.info("Parsed {} user relocations", relocationList.size());
+            return new Relocations(relocationList);
+        }
+    }
+
+    private static Artifact parseArtifact(String coord) {
+        Artifact s;
+        String[] parts = coord.split(":");
+        switch (parts.length) {
+            case 3:
+                s = new DefaultArtifact(parts[0], parts[1], "*", "*", 
parts[2]);
+                break;
+            case 4:
+                s = new DefaultArtifact(parts[0], parts[1], "*", parts[2], 
parts[3]);
+                break;
+            case 5:
+                s = new DefaultArtifact(parts[0], parts[1], parts[2], 
parts[3], parts[4]);
+                break;
+            default:
+                throw new IllegalArgumentException("Bad artifact coordinates " 
+ coord
+                        + ", expected format is 
<groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>");
+        }
+        return s;
+    }
+}

Reply via email to