1111
1212import org .apache .logging .log4j .LogManager ;
1313import org .apache .logging .log4j .Logger ;
14+ import org .elasticsearch .common .Strings ;
1415import org .elasticsearch .core .PathUtils ;
1516import org .elasticsearch .core .SuppressForbidden ;
1617import org .elasticsearch .jdk .JarHell ;
1718import org .elasticsearch .jdk .ModuleQualifiedExportsService ;
19+ import org .elasticsearch .nativeaccess .NativeAccessUtil ;
1820
1921import java .io .IOException ;
2022import java .lang .ModuleLayer .Controller ;
@@ -173,21 +175,32 @@ public static Set<PluginBundle> loadPluginsBundles(Path pluginsDirectory) {
173175 /**
174176 * Constructs a new PluginsLoader
175177 *
176- * @param modules The set of module bundles present on the filesystem
177- * @param plugins The set of plugin bundles present on the filesystem
178+ * @param modules The set of module bundles present on the filesystem
179+ * @param plugins The set of plugin bundles present on the filesystem
180+ * @param pluginsWithNativeAccess A map plugin name -> set of module names for which we want to enable native access
178181 */
179- public static PluginsLoader createPluginsLoader (Set <PluginBundle > modules , Set <PluginBundle > plugins ) {
180- return createPluginsLoader (modules , plugins , true );
182+ public static PluginsLoader createPluginsLoader (
183+ Set <PluginBundle > modules ,
184+ Set <PluginBundle > plugins ,
185+ Map <String , Set <String >> pluginsWithNativeAccess
186+ ) {
187+ return createPluginsLoader (modules , plugins , pluginsWithNativeAccess , true );
181188 }
182189
183190 /**
184191 * Constructs a new PluginsLoader
185192 *
186- * @param modules The set of module bundles present on the filesystem
187- * @param plugins The set of plugin bundles present on the filesystem
193+ * @param modules The set of module bundles present on the filesystem
194+ * @param plugins The set of plugin bundles present on the filesystem
195+ * @param pluginsWithNativeAccess A map plugin name -> set of module names for which we want to enable native access
188196 * @param withServerExports {@code true} to add server module exports
189197 */
190- public static PluginsLoader createPluginsLoader (Set <PluginBundle > modules , Set <PluginBundle > plugins , boolean withServerExports ) {
198+ public static PluginsLoader createPluginsLoader (
199+ Set <PluginBundle > modules ,
200+ Set <PluginBundle > plugins ,
201+ Map <String , Set <String >> pluginsWithNativeAccess ,
202+ boolean withServerExports
203+ ) {
191204 Map <String , List <ModuleQualifiedExportsService >> qualifiedExports ;
192205 if (withServerExports ) {
193206 qualifiedExports = new HashMap <>(ModuleQualifiedExportsService .getBootServices ());
@@ -207,7 +220,8 @@ public static PluginsLoader createPluginsLoader(Set<PluginBundle> modules, Set<P
207220 Set <URL > systemLoaderURLs = JarHell .parseModulesAndClassPath ();
208221 for (PluginBundle bundle : sortedBundles ) {
209222 PluginsUtils .checkBundleJarHell (systemLoaderURLs , bundle , transitiveUrls );
210- loadPluginLayer (bundle , loadedPluginLayers , qualifiedExports );
223+ var modulesWithNativeAccess = pluginsWithNativeAccess .getOrDefault (bundle .plugin .getName (), Set .of ());
224+ loadPluginLayer (bundle , loadedPluginLayers , qualifiedExports , modulesWithNativeAccess );
211225 }
212226 }
213227
@@ -245,7 +259,8 @@ public Set<PluginBundle> pluginBundles() {
245259 private static void loadPluginLayer (
246260 PluginBundle bundle ,
247261 Map <String , LoadedPluginLayer > loaded ,
248- Map <String , List <ModuleQualifiedExportsService >> qualifiedExports
262+ Map <String , List <ModuleQualifiedExportsService >> qualifiedExports ,
263+ Set <String > modulesWithNativeAccess
249264 ) {
250265 String name = bundle .plugin .getName ();
251266 logger .debug (() -> "Loading bundle: " + name );
@@ -276,7 +291,8 @@ private static void loadPluginLayer(
276291 pluginParentLoader ,
277292 extendedPlugins ,
278293 spiLayerAndLoader ,
279- qualifiedExports
294+ qualifiedExports ,
295+ modulesWithNativeAccess
280296 );
281297 final ClassLoader pluginClassLoader = pluginLayerAndLoader .loader ();
282298
@@ -323,7 +339,8 @@ private static LayerAndLoader createPluginLayerAndLoader(
323339 ClassLoader pluginParentLoader ,
324340 List <LoadedPluginLayer > extendedPlugins ,
325341 LayerAndLoader spiLayerAndLoader ,
326- Map <String , List <ModuleQualifiedExportsService >> qualifiedExports
342+ Map <String , List <ModuleQualifiedExportsService >> qualifiedExports ,
343+ Set <String > modulesWithNativeAccess
327344 ) {
328345 final PluginDescriptor plugin = bundle .plugin ;
329346 if (plugin .getModuleName ().isPresent ()) {
@@ -332,7 +349,7 @@ private static LayerAndLoader createPluginLayerAndLoader(
332349 Stream .ofNullable (spiLayerAndLoader != null ? spiLayerAndLoader .layer () : null ),
333350 extendedPlugins .stream ().map (LoadedPluginLayer ::spiModuleLayer )
334351 ).toList ();
335- return createPluginModuleLayer (bundle , pluginParentLoader , parentLayers , qualifiedExports );
352+ return createPluginModuleLayer (bundle , pluginParentLoader , parentLayers , qualifiedExports , modulesWithNativeAccess );
336353 } else if (plugin .isStable ()) {
337354 logger .debug (() -> "Loading bundle: " + plugin .getName () + ", non-modular as synthetic module" );
338355 return LayerAndLoader .ofUberModuleLoader (
@@ -341,7 +358,8 @@ private static LayerAndLoader createPluginLayerAndLoader(
341358 ModuleLayer .boot (),
342359 "synthetic." + toModuleName (plugin .getName ()),
343360 bundle .allUrls ,
344- Set .of ("org.elasticsearch.server" ) // TODO: instead of denying server, allow only jvm + stable API modules
361+ Set .of ("org.elasticsearch.server" ), // TODO: instead of denying server, allow only jvm + stable API modules
362+ modulesWithNativeAccess
345363 )
346364 );
347365 } else {
@@ -363,15 +381,17 @@ static LayerAndLoader createSpiModuleLayer(
363381 urlsToPaths (urls ),
364382 parentLoader ,
365383 parentLayers ,
366- qualifiedExports
384+ qualifiedExports ,
385+ Set .of ()
367386 );
368387 }
369388
370389 static LayerAndLoader createPluginModuleLayer (
371390 PluginBundle bundle ,
372391 ClassLoader parentLoader ,
373392 List <ModuleLayer > parentLayers ,
374- Map <String , List <ModuleQualifiedExportsService >> qualifiedExports
393+ Map <String , List <ModuleQualifiedExportsService >> qualifiedExports ,
394+ Set <String > modulesWithNativeAccess
375395 ) {
376396 assert bundle .plugin .getModuleName ().isPresent ();
377397 return createModuleLayer (
@@ -380,7 +400,8 @@ static LayerAndLoader createPluginModuleLayer(
380400 urlsToPaths (bundle .urls ),
381401 parentLoader ,
382402 parentLayers ,
383- qualifiedExports
403+ qualifiedExports ,
404+ modulesWithNativeAccess
384405 );
385406 }
386407
@@ -390,7 +411,8 @@ static LayerAndLoader createModuleLayer(
390411 Path [] paths ,
391412 ClassLoader parentLoader ,
392413 List <ModuleLayer > parentLayers ,
393- Map <String , List <ModuleQualifiedExportsService >> qualifiedExports
414+ Map <String , List <ModuleQualifiedExportsService >> qualifiedExports ,
415+ Set <String > modulesWithNativeAccess
394416 ) {
395417 logger .debug (() -> "Loading bundle: creating module layer and loader for module " + moduleName );
396418 var finder = ModuleFinder .of (paths );
@@ -408,6 +430,7 @@ static LayerAndLoader createModuleLayer(
408430 exposeQualifiedExportsAndOpens (pluginModule , qualifiedExports );
409431 // configure qualified exports/opens to other modules/plugins
410432 addPluginExportsServices (qualifiedExports , controller );
433+ enableNativeAccess (moduleName , modulesWithNativeAccess , controller );
411434 logger .debug (() -> "Loading bundle: created module layer and loader for module " + moduleName );
412435 return new LayerAndLoader (controller .layer (), privilegedFindLoader (controller .layer (), moduleName ));
413436 }
@@ -518,4 +541,18 @@ protected void addOpens(String pkg, Module target) {
518541 addExportsService (qualifiedExports , exportsService , module .getName ());
519542 }
520543 }
544+
545+ private static void enableNativeAccess (String mainModuleName , Set <String > modulesWithNativeAccess , Controller controller ) {
546+ for (var moduleName : modulesWithNativeAccess ) {
547+ var module = controller .layer ().findModule (moduleName );
548+ module .ifPresentOrElse (m -> NativeAccessUtil .enableNativeAccess (controller , m ), () -> {
549+ assert false
550+ : Strings .format (
551+ "Native access not enabled for module [%s]: not a valid module name in layer [%s]" ,
552+ moduleName ,
553+ mainModuleName
554+ );
555+ });
556+ }
557+ }
521558}
0 commit comments