5959import  static  java .util .zip .ZipFile .OPEN_READ ;
6060import  static  org .elasticsearch .entitlement .bridge .Util .NO_CLASS ;
6161import  static  org .elasticsearch .entitlement .runtime .policy .PathLookup .BaseDir .TEMP ;
62+ import  static  org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .APM_AGENT ;
63+ import  static  org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .PLUGIN ;
64+ import  static  org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .SERVER ;
65+ import  static  org .elasticsearch .entitlement .runtime .policy .PolicyManager .ComponentKind .UNKNOWN ;
6266
6367/** 
6468 * This class is responsible for finding the <strong>component</strong> (system, server, plugin, agent) for a caller class to check, 
@@ -128,14 +132,55 @@ public class PolicyManager {
128132     */ 
129133    private  static  final  Logger  generalLogger  = LogManager .getLogger (PolicyManager .class );
130134
131-     static  final  String  UNKNOWN_COMPONENT_NAME  = "(unknown)" ;
132-     static  final  String  SERVER_COMPONENT_NAME  = "(server)" ;
133-     static  final  String  APM_AGENT_COMPONENT_NAME  = "(APM agent)" ;
134- 
135135    static  final  Class <?> DEFAULT_FILESYSTEM_CLASS  = PathUtils .getDefaultFileSystem ().getClass ();
136136
137137    static  final  Set <String > MODULES_EXCLUDED_FROM_SYSTEM_MODULES  = Set .of ("java.desktop" );
138138
139+     /** 
140+      * Identifies a particular entitlement {@link Scope} within a {@link Policy}. 
141+      */ 
142+     public  record  PolicyScope (ComponentKind  kind , String  componentName , String  moduleName ) {
143+         public  PolicyScope  {
144+             requireNonNull (kind );
145+             requireNonNull (componentName );
146+             requireNonNull (moduleName );
147+             assert  kind .componentName  == null  || kind .componentName .equals (componentName );
148+         }
149+ 
150+         public  static  PolicyScope  unknown (String  moduleName ) {
151+             return  new  PolicyScope (UNKNOWN , UNKNOWN .componentName , moduleName );
152+         }
153+ 
154+         public  static  PolicyScope  server (String  moduleName ) {
155+             return  new  PolicyScope (SERVER , SERVER .componentName , moduleName );
156+         }
157+ 
158+         public  static  PolicyScope  apmAgent (String  moduleName ) {
159+             return  new  PolicyScope (APM_AGENT , APM_AGENT .componentName , moduleName );
160+         }
161+ 
162+         public  static  PolicyScope  plugin (String  componentName , String  moduleName ) {
163+             return  new  PolicyScope (PLUGIN , componentName , moduleName );
164+         }
165+     }
166+ 
167+     public  enum  ComponentKind  {
168+         UNKNOWN ("(unknown)" ),
169+         SERVER ("(server)" ),
170+         APM_AGENT ("(APM agent)" ),
171+         PLUGIN (null );
172+ 
173+         /** 
174+          * If this kind corresponds to a single component, this is that component's name; 
175+          * otherwise null. 
176+          */ 
177+         final  String  componentName ;
178+ 
179+         ComponentKind (String  componentName ) {
180+             this .componentName  = componentName ;
181+         }
182+     }
183+ 
139184    /** 
140185     * This class contains all the entitlements by type, plus the {@link FileAccessTree} for the special case of filesystem entitlements. 
141186     * <p> 
@@ -209,7 +254,7 @@ ModuleEntitlements policyEntitlements(String componentName, Path componentPath,
209254    private  final  Map <String , List <Entitlement >> serverEntitlements ;
210255    private  final  List <Entitlement > apmAgentEntitlements ;
211256    private  final  Map <String , Map <String , List <Entitlement >>> pluginsEntitlements ;
212-     private  final  Function <Class <?>, String >  pluginResolver ;
257+     private  final  Function <Class <?>, PolicyScope >  scopeResolver ;
213258    private  final  PathLookup  pathLookup ;
214259    private  final  Set <Class <?>> mutedClasses ;
215260
@@ -245,10 +290,6 @@ private static Set<Module> findSystemLayerModules() {
245290        .collect (Collectors .toUnmodifiableSet ());
246291
247292    private  final  Map <String , Path > sourcePaths ;
248-     /** 
249-      * The package name containing classes from the APM agent. 
250-      */ 
251-     private  final  String  apmAgentPackageName ;
252293
253294    /** 
254295     * Frames originating from this module are ignored in the permission logic. 
@@ -266,9 +307,8 @@ public PolicyManager(
266307        Policy  serverPolicy ,
267308        List <Entitlement > apmAgentEntitlements ,
268309        Map <String , Policy > pluginPolicies ,
269-         Function <Class <?>, String >  pluginResolver ,
310+         Function <Class <?>, PolicyScope >  scopeResolver ,
270311        Map <String , Path > sourcePaths ,
271-         String  apmAgentPackageName ,
272312        Module  entitlementsModule ,
273313        PathLookup  pathLookup ,
274314        Set <Class <?>> suppressFailureLogClasses 
@@ -278,18 +318,17 @@ public PolicyManager(
278318        this .pluginsEntitlements  = requireNonNull (pluginPolicies ).entrySet ()
279319            .stream ()
280320            .collect (toUnmodifiableMap (Map .Entry ::getKey , e  -> buildScopeEntitlementsMap (e .getValue ())));
281-         this .pluginResolver  = pluginResolver ;
321+         this .scopeResolver  = scopeResolver ;
282322        this .sourcePaths  = sourcePaths ;
283-         this .apmAgentPackageName  = apmAgentPackageName ;
284323        this .entitlementsModule  = entitlementsModule ;
285324        this .pathLookup  = requireNonNull (pathLookup );
286325        this .mutedClasses  = suppressFailureLogClasses ;
287326
288327        List <ExclusiveFileEntitlement > exclusiveFileEntitlements  = new  ArrayList <>();
289328        for  (var  e  : serverEntitlements .entrySet ()) {
290-             validateEntitlementsPerModule (SERVER_COMPONENT_NAME , e .getKey (), e .getValue (), exclusiveFileEntitlements );
329+             validateEntitlementsPerModule (SERVER . componentName , e .getKey (), e .getValue (), exclusiveFileEntitlements );
291330        }
292-         validateEntitlementsPerModule (APM_AGENT_COMPONENT_NAME , ALL_UNNAMED , apmAgentEntitlements , exclusiveFileEntitlements );
331+         validateEntitlementsPerModule (APM_AGENT . componentName , ALL_UNNAMED , apmAgentEntitlements , exclusiveFileEntitlements );
293332        for  (var  p  : pluginsEntitlements .entrySet ()) {
294333            for  (var  m  : p .getValue ().entrySet ()) {
295334                validateEntitlementsPerModule (p .getKey (), m .getKey (), m .getValue (), exclusiveFileEntitlements );
@@ -684,50 +723,40 @@ ModuleEntitlements getEntitlements(Class<?> requestingClass) {
684723    }
685724
686725    private  ModuleEntitlements  computeEntitlements (Class <?> requestingClass ) {
687-         Module  requestingModule  = requestingClass .getModule ();
688-         if  (isServerModule (requestingModule )) {
689-             return  getModuleScopeEntitlements (
690-                 serverEntitlements ,
691-                 requestingModule .getName (),
692-                 SERVER_COMPONENT_NAME ,
693-                 getComponentPathFromClass (requestingClass )
694-             );
695-         }
726+         var  policyScope  = scopeResolver .apply (requestingClass );
727+         var  componentName  = policyScope .componentName ();
728+         var  moduleName  = policyScope .moduleName ();
696729
697-         // plugins 
698-         var  pluginName  = pluginResolver .apply (requestingClass );
699-         if  (pluginName  != null ) {
700-             var  pluginEntitlements  = pluginsEntitlements .get (pluginName );
701-             if  (pluginEntitlements  == null ) {
702-                 return  defaultEntitlements (pluginName , sourcePaths .get (pluginName ), requestingModule .getName ());
703-             } else  {
730+         switch  (policyScope .kind ()) {
731+             case  SERVER  -> {
704732                return  getModuleScopeEntitlements (
705-                     pluginEntitlements ,
706-                     getScopeName ( requestingModule ) ,
707-                     pluginName ,
708-                     sourcePaths . get ( pluginName )
733+                     serverEntitlements ,
734+                     moduleName ,
735+                     SERVER . componentName ,
736+                     getComponentPathFromClass ( requestingClass )
709737                );
710738            }
711-         }
712- 
713-         if  (requestingModule .isNamed () == false  && requestingClass .getPackageName ().startsWith (apmAgentPackageName )) {
714-             // The APM agent is the only thing running non-modular in the system classloader 
715-             return  policyEntitlements (
716-                 APM_AGENT_COMPONENT_NAME ,
717-                 getComponentPathFromClass (requestingClass ),
718-                 ALL_UNNAMED ,
719-                 apmAgentEntitlements 
720-             );
721-         }
722- 
723-         return  defaultEntitlements (UNKNOWN_COMPONENT_NAME , null , requestingModule .getName ());
724-     }
725- 
726-     private  static  String  getScopeName (Module  requestingModule ) {
727-         if  (requestingModule .isNamed () == false ) {
728-             return  ALL_UNNAMED ;
729-         } else  {
730-             return  requestingModule .getName ();
739+             case  APM_AGENT  -> {
740+                 // The APM agent is the only thing running non-modular in the system classloader 
741+                 return  policyEntitlements (
742+                     APM_AGENT .componentName ,
743+                     getComponentPathFromClass (requestingClass ),
744+                     ALL_UNNAMED ,
745+                     apmAgentEntitlements 
746+                 );
747+             }
748+             case  UNKNOWN  -> {
749+                 return  defaultEntitlements (UNKNOWN .componentName , null , moduleName );
750+             }
751+             default  -> {
752+                 assert  policyScope .kind () == PLUGIN ;
753+                 var  pluginEntitlements  = pluginsEntitlements .get (componentName );
754+                 if  (pluginEntitlements  == null ) {
755+                     return  defaultEntitlements (componentName , sourcePaths .get (componentName ), moduleName );
756+                 } else  {
757+                     return  getModuleScopeEntitlements (pluginEntitlements , moduleName , componentName , sourcePaths .get (componentName ));
758+                 }
759+             }
731760        }
732761    }
733762
@@ -763,10 +792,6 @@ private ModuleEntitlements getModuleScopeEntitlements(
763792        return  policyEntitlements (componentName , componentPath , scopeName , entitlements );
764793    }
765794
766-     private  static  boolean  isServerModule (Module  requestingModule ) {
767-         return  requestingModule .isNamed () && requestingModule .getLayer () == ModuleLayer .boot ();
768-     }
769- 
770795    /** 
771796     * Walks the stack to determine which class should be checked for entitlements. 
772797     * 
0 commit comments