JERI is of course extensible, there are a number of layers:
1. Invocation Layer.
2. Object identification layer
3. Transport layer.
All proxy's that use JERI contain a java.lang.reflect.Proxy instance
that uses an InvocationHandler from an invocation layer factory.
Currently we have BasicILFactory, this uses standard java serialization
and Marshal streams from the net.jini.io package, which annotate streams
with codebase annotations.
The invocation layer provided by BasicILFactory allows you to download
any class from anywhere. Serialization was considered secure, at the
time when it was written. To be fair, serialization should have been
maintained secure. In this model, after you deserialized a proxy into
its downloaded code, then you ask the remote end to check it, and then
you apply constraints. The problem today is serialization is not
secure, and we can use a secure transport layer, however a proxy can
download another proxy that doesn't use a secure transport layer and the
constraints won't be applied to it. For example, Reggie provides a
lookup service, you can apply contraints against it, but it can still
download proxy's from other services and the constraints aren't applied
to those.
Enter AtomicILFactory, it utilises codebase annotations still, but in a
limited form. Instead of using codebase annotations for every class,
each endpoint is assigned a default ClassLoader that determines class
visibility and resolution. The service's server endpoint is assigned a
ClassLoader by AtomicILFactory, but how is its proxy ClassLoader
determined you ask? Ok, so we need to go back one step, proxy's are
marshalled independently of the stream, this means, unlike
BasicILFactory, Reggie cannot download proxy's from other services,
because their proxy classes won't be available via the default
ClassLoader. Instead, proxy's are marshalled by a ProxySerializer, that
contains a MarshalledInstance and a CodebaseAccessor bootstrap proxy,
which only utilises local classes. There's a new provider
net.jini.loader.ProxyCodebaseSpi, which the ProxySerializer passes the
MarshalledInstance and CodebaseAccess to as arguments. The bootstrap
proxy is used for authentication and codebase provisioning, the
provisioned ClassLoader is then used by the MarshalledInstance to
deserialize the proxy. So this is how the ClassLoader is established
for the proxy.
Now I was applying constraints to the proxy before it returns, but this
breaks a number of InvocationHandlers, that are expecting a proxy
without constraints, so for now, constraints are only applied to the
bootstrap proxy.
There are two ProxyCodebaseSpi implementations, one for preferred
classes, the other for OSGi.
Note the parent ClassLoader is the loader of the stream that
deserialized the proxy in it's marshalled form, at least for preferred
class loading, but not for OSGi. The reason is, a service proxy may
already contain proxy's for other services, which it utilises privately,
so it needs to be able to control the visibility of classes using
preferred class loading, the interfaces shared by the service proxy and
other proxy's it contains
This gives the client total control over who can download classes and
enforce constraints before deserialization occurs.
I haven't made this code publicly available yet.
Regards,
Peter.