Introduce ValidationPackageOpener to relay open directives to validation providers (JPMS package opens -> validation provider)#340
Conversation
| } | ||
|
|
||
| @Override | ||
| public void openPackage(MethodHandles.Lookup providerLookup, Module targetModule, String packageName) { |
There was a problem hiding this comment.
Would it make sense to ensure this method is only ever called from the module of the provider?
We could use StackWalker to find all the stack frames until the provider module is reached and assert that there are no stack frames from other modules, which are not reflection related. That way, we'd ensure that only the provider can call this, as an additional safety net.
There was a problem hiding this comment.
Would it make sense to ensure this method is only ever called from the module of the provider
+1 , that definitely was the intention, yes! I thought that I got it addressed by:
if ( !providerLookup.lookupClass().getModule().equals( providerModule ) ) {the idea being that we pass the lookup created at a callsite opener.openPackage(MethodHandles.lookup(), ...) and as this carries the info of who called the lookup + it cannot be "faked" we get that safty net ? Or did you mean to add the stack walker as an extra check to this one?
There was a problem hiding this comment.
I was thinking about adding the StackWalker code as an extra safety, but it seems like your proposed solution is good enough, assuming safe usage from the provider.
yrodiere
left a comment
There was a problem hiding this comment.
This looks good to me overall, but the devil being in the details... it would be great to have the opinion of an expert such as @dmlloyd, who has been working extensively on using/hijacking the Java module system for Quarkus.
David, could you please tell us what you think of this? Of course this is outside of the context of Quarkus and I suppose native compilation will through a lot of it outside the window, but at least we'd want this to work / be safe in a generic "Java with modulepath" application.
Another question I have, but for @marko-bekhta: is the module opening transitive? I.e. once the provider got a module opened to it, can it open that module to another module (e.g. hibernate-validator opening user modules to a hypothetical hibernate-validator-extras module)?
yes, but one must do it "manually". At least, that's my understanding and what I've seen from my "experiments", if a package is opened to the current module, then this module can open that package to some other module. It would mean that we'd either have move package openers in our projects, or, for example, like with accessors, we could just open the package to us (HV core) and right away open that same package to the accessor lib, assuming that HV itslef won't be doing actual work and just delegate to the accessor lib, we need that inital "open" (form the package opener) to get the ability to pass it over. Also from the javadoc (https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Module.html#addOpens(java.lang.String,java.lang.Module)):
|
Following the idea described in https://in.relation.to/2018/03/21/spec-api-modularity-patterns/
Asking users to open packages with their constrained classes only to the Validation API module, without specifying the provider modules, and placing that responsibility on the API/provider to share the opened packages makes the applications more portable and not tied to a specific validation provider.
The idea is that the package opener is tied to a specific validation provider, and such an opener would only work from inside the provider module -- we require a lookup tied to the provider module. Since lookups are supposed to be caller sensitive, even if the opener "leaks" to another module, it will be useless, as the other module's lookup won't match the one from the provider (to which the opener is bound).
Opening this one to discuss the idea (and potentially include it in 4.0).
cc: @yrodiere @beikov