mirror of https://github.com/apache/maven.git
[MNG-8176] Restrict classloader for Maven 4 plugins (#1336)
This commit is contained in:
parent
9c1871fd22
commit
2a709dc038
|
@ -48,6 +48,13 @@ public interface ClassRealmManager {
|
||||||
*/
|
*/
|
||||||
ClassRealm getMavenApiRealm();
|
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.
|
* Creates a new class realm for the specified project and its build extensions.
|
||||||
*
|
*
|
||||||
|
|
|
@ -26,12 +26,14 @@ import java.io.File;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.maven.artifact.ArtifactUtils;
|
import org.apache.maven.artifact.ArtifactUtils;
|
||||||
import org.apache.maven.classrealm.ClassRealmRequest.RealmType;
|
import org.apache.maven.classrealm.ClassRealmRequest.RealmType;
|
||||||
|
@ -57,6 +59,8 @@ import org.slf4j.LoggerFactory;
|
||||||
public class DefaultClassRealmManager implements ClassRealmManager {
|
public class DefaultClassRealmManager implements ClassRealmManager {
|
||||||
public static final String API_REALMID = "maven.api";
|
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
|
* 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.
|
* 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 mavenApiRealm;
|
||||||
|
|
||||||
|
private final ClassRealm maven4ApiRealm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Patterns of artifacts provided by maven core and exported via maven api realm. These artifacts are filtered from
|
* 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.
|
* 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> providedArtifacts;
|
||||||
|
|
||||||
|
private final Set<String> providedArtifactsV4;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DefaultClassRealmManager(
|
public DefaultClassRealmManager(
|
||||||
CoreRealm coreRealm, List<ClassRealmManagerDelegate> delegates, CoreExports exports) {
|
CoreRealm coreRealm, List<ClassRealmManagerDelegate> delegates, CoreExports exports) {
|
||||||
|
@ -101,7 +109,16 @@ public class DefaultClassRealmManager implements ClassRealmManager {
|
||||||
foreignImports,
|
foreignImports,
|
||||||
null /* artifacts */);
|
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.providedArtifacts = exports.getExportedArtifacts();
|
||||||
|
|
||||||
|
this.providedArtifactsV4 = providedArtifacts.stream()
|
||||||
|
.filter(ga -> ga.startsWith("org.apache.maven:maven-api-"))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClassRealm newRealm(String id) {
|
private ClassRealm newRealm(String id) {
|
||||||
|
@ -128,6 +145,11 @@ public class DefaultClassRealmManager implements ClassRealmManager {
|
||||||
return mavenApiRealm;
|
return mavenApiRealm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassRealm getMaven4ApiRealm() {
|
||||||
|
return maven4ApiRealm;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new class realm with the specified parent and imports.
|
* 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());
|
List<ClassRealmConstituent> constituents = new ArrayList<>(artifacts == null ? 0 : artifacts.size());
|
||||||
|
|
||||||
if (artifacts != null && !artifacts.isEmpty()) {
|
if (artifacts != null && !artifacts.isEmpty()) {
|
||||||
|
boolean v4api = foreignImports != null && foreignImports.containsValue(maven4ApiRealm);
|
||||||
for (Artifact artifact : artifacts) {
|
for (Artifact artifact : artifacts) {
|
||||||
if (!isProvidedArtifact(artifact) && artifact.getFile() != null) {
|
if (!isProvidedArtifact(artifact, v4api) && artifact.getFile() != null) {
|
||||||
constituents.add(new ArtifactClassRealmConstituent(artifact));
|
constituents.add(new ArtifactClassRealmConstituent(artifact));
|
||||||
} else if (logger.isDebugEnabled()) {
|
} else if (logger.isDebugEnabled()) {
|
||||||
logger.debug(" Excluded: {}", getId(artifact));
|
logger.debug(" Excluded: {}", getId(artifact));
|
||||||
|
@ -211,8 +234,9 @@ public class DefaultClassRealmManager implements ClassRealmManager {
|
||||||
getKey(plugin, true), RealmType.Extension, PARENT_CLASSLOADER, null, foreignImports, artifacts);
|
getKey(plugin, true), RealmType.Extension, PARENT_CLASSLOADER, null, foreignImports, artifacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isProvidedArtifact(Artifact artifact) {
|
private boolean isProvidedArtifact(Artifact artifact, boolean v4api) {
|
||||||
return providedArtifacts.contains(artifact.getGroupId() + ":" + artifact.getArtifactId());
|
Set<String> provided = v4api ? providedArtifactsV4 : providedArtifacts;
|
||||||
|
return provided.contains(artifact.getGroupId() + ":" + artifact.getArtifactId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassRealm createPluginRealm(
|
public ClassRealm createPluginRealm(
|
||||||
|
|
|
@ -363,7 +363,8 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
|
||||||
pluginDescriptor.setClassRealm(pluginRealm);
|
pluginDescriptor.setClassRealm(pluginRealm);
|
||||||
pluginDescriptor.setArtifacts(pluginArtifacts);
|
pluginDescriptor.setArtifacts(pluginArtifacts);
|
||||||
} else {
|
} 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(
|
PluginRealmCache.Key cacheKey = pluginRealmCache.createKey(
|
||||||
plugin,
|
plugin,
|
||||||
|
@ -471,14 +472,16 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
|
||||||
return Collections.unmodifiableList(artifacts);
|
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<>();
|
Map<String, ClassLoader> foreignImports = new HashMap<>();
|
||||||
|
|
||||||
ClassLoader projectRealm = project.getClassRealm();
|
ClassLoader projectRealm = project.getClassRealm();
|
||||||
if (projectRealm != null) {
|
if (projectRealm != null) {
|
||||||
foreignImports.put("", projectRealm);
|
foreignImports.put("", projectRealm);
|
||||||
} else {
|
} else {
|
||||||
foreignImports.put("", classRealmManager.getMavenApiRealm());
|
foreignImports.put(
|
||||||
|
"", v4api ? classRealmManager.getMaven4ApiRealm() : classRealmManager.getMavenApiRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent != null && imports != null) {
|
if (parent != null && imports != null) {
|
||||||
|
|
Loading…
Reference in New Issue