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) {