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.

Reply via email to