Hi folks!
A small culprit I found in our proxy code yesterday night:
Consider the following (the 'protected' is important!)
public class User {
protected String getName() { return "Hans";}
}
User$Proxy extends User
private User delegate;
protected String getName {
return delegate.getName();
}
}
This code works perfect! But only as long as the User$Proxy and User classes
are loaded with the same ClassLoader. According to the JVM 2 classes are only
considered to be in the same package (and thus allows for protected access) if
they are loaded by the same ClassLoader.
This is what caused problems in Javassist as well, and there we had to do some
weird hacks with the ClassLoaderProvider factory.
The solution I did now is the following: I use the ClassLoader of the original
class to define the Proxy. This works perfectly fine, but only as long as we
don't proxy classes which are not meant to be 'shared'. Imagine a full-profile
EE server where you have e.g. MyFaces in the servers lib folder, which would
result in a ClassLoader hierarchy similar to:
SystemClassLoader
-> EE-server-internal (contains myfaces-*.jar)
-> EE-server-lib
-> EAR-A ->warA1, warA2, etc
-> EAR-B ->warB1, warB2, etc
But any proxies for e.g. javax.faces.context.FacesContext should not be loaded
with the EE-server-internal ClassLoader but maximum with EAR-A or EAR-B
ClassLoaders.
This means we should introduce an upper boundary ClassLoader detection somehow.
We might need the same for the HierarchicScannerService as well btw.
I already added a detection if proxyClassLoader != proxiedClassClassLoader and
in that case I skip the proxying of protected methods. We might also
automatically switch to using reflection in that case, but this is imo not
required by the specs.
Any objections? Any ideas?
LieGrue,
strub