Skip to content

Commit

Permalink
Restrict classloader for Maven 4 plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Dec 7, 2023
1 parent 2411c81 commit 9955de3
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,8 @@

import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
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.*;
import java.util.stream.Collectors;

import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.classrealm.ClassRealmRequest.RealmType;
Expand All @@ -58,6 +52,8 @@
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.
Expand All @@ -79,12 +75,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(
PlexusContainer container, List<ClassRealmManagerDelegate> delegates, CoreExports exports) {
Expand All @@ -102,7 +102,18 @@ public DefaultClassRealmManager(
foreignImports,
null /* artifacts */);

Map<String, ClassLoader> apiV4Imports = new HashMap<>();
apiV4Imports.put("org.apache.maven.api", containerRealm);
apiV4Imports.put("org.slf4j", containerRealm);
apiV4Imports.put("jakarta.inject.*", 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-") || ga.equals("jakarta.inject:jakarta.inject-api"))
.collect(Collectors.toSet());
}

private ClassRealm newRealm(String id) {
Expand All @@ -129,6 +140,11 @@ public ClassRealm getMavenApiRealm() {
return mavenApiRealm;
}

@Override
public ClassRealm getMaven4ApiRealm() {
return maven4ApiRealm;
}

/**
* Creates a new class realm with the specified parent and imports.
*
Expand All @@ -151,8 +167,9 @@ private ClassRealm createRealm(
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));
Expand Down Expand Up @@ -212,8 +229,9 @@ public ClassRealm createExtensionRealm(Plugin plugin, List<Artifact> artifacts)
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(
Expand Down
3 changes: 3 additions & 0 deletions maven-core/src/main/resources/META-INF/maven/extension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ under the License.
<exportedArtifact>org.apache.maven:maven-api-core</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-meta</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-model</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-plugin</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-settings</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-spi</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-toolchain</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-xml</exportedArtifact>

Expand Down Expand Up @@ -187,6 +189,7 @@ under the License.
<exportedArtifact>org.apache.maven.resolver:maven-resolver-util</exportedArtifact>
<exportedArtifact>org.apache.maven.resolver:maven-resolver-connector-basic</exportedArtifact>

<exportedArtifact>jakarta.inject:jakarta.inject-api</exportedArtifact>
<exportedArtifact>javax.inject:javax.inject</exportedArtifact>
<exportedArtifact>javax.annotation:javax.annotation-api</exportedArtifact>
<exportedArtifact>org.slf4j:slf4j-api</exportedArtifact>
Expand Down

0 comments on commit 9955de3

Please sign in to comment.