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

gnodet 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 2a709dc038 [MNG-8176] Restrict classloader for Maven 4 plugins (#1336)
2a709dc038 is described below

commit 2a709dc03896d6b06a29819d1b969b408827916c
Author: Guillaume Nodet <[email protected]>
AuthorDate: Mon Aug 12 23:57:01 2024 +0200

    [MNG-8176] Restrict classloader for Maven 4 plugins (#1336)
---
 .../apache/maven/classrealm/ClassRealmManager.java |  7 +++++
 .../maven/classrealm/DefaultClassRealmManager.java | 30 +++++++++++++++++++---
 .../plugin/internal/DefaultMavenPluginManager.java |  9 ++++---
 3 files changed, 40 insertions(+), 6 deletions(-)

diff --git 
a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java 
b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java
index b0386f040b..689aa62003 100644
--- 
a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java
+++ 
b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java
@@ -48,6 +48,13 @@ public interface ClassRealmManager {
      */
     ClassRealm getMavenApiRealm();
 
+    /**
+     * Gets the class realm exposing the Maven 4 API. This is basically a 
restricted view on the Maven core realm.
+     *
+     * @return The class realm exposing the Maven API, never {@code null}.
+     */
+    ClassRealm getMaven4ApiRealm();
+
     /**
      * Creates a new class realm for the specified project and its build 
extensions.
      *
diff --git 
a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java
 
b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java
index 14bec0c1c0..7727693401 100644
--- 
a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java
+++ 
b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java
@@ -26,12 +26,14 @@ import java.io.File;
 import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Random;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.stream.Collectors;
 
 import org.apache.maven.artifact.ArtifactUtils;
 import org.apache.maven.classrealm.ClassRealmRequest.RealmType;
@@ -57,6 +59,8 @@ import org.slf4j.LoggerFactory;
 public class DefaultClassRealmManager implements ClassRealmManager {
     public static final String API_REALMID = "maven.api";
 
+    public static final String API_V4_REALMID = "maven.api.v4";
+
     /**
      * During normal command line build, ClassWorld is loaded by jvm system 
classloader, which only includes
      * plexus-classworlds jar and possibly javaagent classes, see 
https://issues.apache.org/jira/browse/MNG-4747.
@@ -78,12 +82,16 @@ public class DefaultClassRealmManager implements 
ClassRealmManager {
 
     private final ClassRealm mavenApiRealm;
 
+    private final ClassRealm maven4ApiRealm;
+
     /**
      * Patterns of artifacts provided by maven core and exported via maven api 
realm. These artifacts are filtered from
      * plugin and build extensions realms to avoid presence of duplicate and 
possibly conflicting classes on classpath.
      */
     private final Set<String> providedArtifacts;
 
+    private final Set<String> providedArtifactsV4;
+
     @Inject
     public DefaultClassRealmManager(
             CoreRealm coreRealm, List<ClassRealmManagerDelegate> delegates, 
CoreExports exports) {
@@ -101,7 +109,16 @@ public class DefaultClassRealmManager implements 
ClassRealmManager {
                 foreignImports,
                 null /* artifacts */);
 
+        Map<String, ClassLoader> apiV4Imports = new HashMap<>();
+        apiV4Imports.put("org.apache.maven.api", containerRealm);
+        apiV4Imports.put("org.slf4j", containerRealm);
+        this.maven4ApiRealm = createRealm(API_V4_REALMID, RealmType.Core, 
null, null, apiV4Imports, null);
+
         this.providedArtifacts = exports.getExportedArtifacts();
+
+        this.providedArtifactsV4 = providedArtifacts.stream()
+                .filter(ga -> ga.startsWith("org.apache.maven:maven-api-"))
+                .collect(Collectors.toSet());
     }
 
     private ClassRealm newRealm(String id) {
@@ -128,6 +145,11 @@ public class DefaultClassRealmManager implements 
ClassRealmManager {
         return mavenApiRealm;
     }
 
+    @Override
+    public ClassRealm getMaven4ApiRealm() {
+        return maven4ApiRealm;
+    }
+
     /**
      * Creates a new class realm with the specified parent and imports.
      *
@@ -150,8 +172,9 @@ public class DefaultClassRealmManager implements 
ClassRealmManager {
         List<ClassRealmConstituent> constituents = new ArrayList<>(artifacts 
== null ? 0 : artifacts.size());
 
         if (artifacts != null && !artifacts.isEmpty()) {
+            boolean v4api = foreignImports != null && 
foreignImports.containsValue(maven4ApiRealm);
             for (Artifact artifact : artifacts) {
-                if (!isProvidedArtifact(artifact) && artifact.getFile() != 
null) {
+                if (!isProvidedArtifact(artifact, v4api) && artifact.getFile() 
!= null) {
                     constituents.add(new 
ArtifactClassRealmConstituent(artifact));
                 } else if (logger.isDebugEnabled()) {
                     logger.debug("  Excluded: {}", getId(artifact));
@@ -211,8 +234,9 @@ public class DefaultClassRealmManager implements 
ClassRealmManager {
                 getKey(plugin, true), RealmType.Extension, PARENT_CLASSLOADER, 
null, foreignImports, artifacts);
     }
 
-    private boolean isProvidedArtifact(Artifact artifact) {
-        return providedArtifacts.contains(artifact.getGroupId() + ":" + 
artifact.getArtifactId());
+    private boolean isProvidedArtifact(Artifact artifact, boolean v4api) {
+        Set<String> provided = v4api ? providedArtifactsV4 : providedArtifacts;
+        return provided.contains(artifact.getGroupId() + ":" + 
artifact.getArtifactId());
     }
 
     public ClassRealm createPluginRealm(
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
index 908f608cd0..77d11a2706 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
@@ -363,7 +363,8 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
             pluginDescriptor.setClassRealm(pluginRealm);
             pluginDescriptor.setArtifacts(pluginArtifacts);
         } else {
-            Map<String, ClassLoader> foreignImports = calcImports(project, 
parent, imports);
+            boolean v4api = 
pluginDescriptor.getMojos().stream().anyMatch(MojoDescriptor::isV4Api);
+            Map<String, ClassLoader> foreignImports = calcImports(project, 
parent, imports, v4api);
 
             PluginRealmCache.Key cacheKey = pluginRealmCache.createKey(
                     plugin,
@@ -471,14 +472,16 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
         return Collections.unmodifiableList(artifacts);
     }
 
-    private Map<String, ClassLoader> calcImports(MavenProject project, 
ClassLoader parent, List<String> imports) {
+    private Map<String, ClassLoader> calcImports(
+            MavenProject project, ClassLoader parent, List<String> imports, 
boolean v4api) {
         Map<String, ClassLoader> foreignImports = new HashMap<>();
 
         ClassLoader projectRealm = project.getClassRealm();
         if (projectRealm != null) {
             foreignImports.put("", projectRealm);
         } else {
-            foreignImports.put("", classRealmManager.getMavenApiRealm());
+            foreignImports.put(
+                    "", v4api ? classRealmManager.getMaven4ApiRealm() : 
classRealmManager.getMavenApiRealm());
         }
 
         if (parent != null && imports != null) {

Reply via email to