In the previous section, we assumed objects were permanently associated with meta-objects. In this section, we are going to present a way that allows this association to be modified at run-time, while preserving security properties.
The basic principle we have adopted is that the meta-object associated with an object has total control over the object, so it can only be replaced by another meta-object if it agrees to leave.
We suggest a mechanism that allows a meta-object to be proposed as a replacement to the meta-object of an object. This mechanism will implicitly ask the existing meta-object whether it accepts to be replaced with the proposed one, and will abide by its decision. The identity of the existing meta-object is protected, and it is impossible to inconditionally replace it.
There are times in which a meta-object might wish to accept the suggested reconfiguration only in part. For example, being aware of its own properties, and being able to find out the properties of the suggested meta-object, it may name an existing meta-object, or create a new one, that somehow combines some selected properties of them. Therefore, the reconfiguration mechanism should allow a meta-object to reply more than just ``yes'' or ``no'': it may return (a reference to) the meta-object that will replace it.
Sometimes, the requester of the reconfiguration may wish to provide some hint for an existing meta-object about what it expects to take place during the reconfiguration. For example, it may indicate that it wishes meta-object N to become the meta-object of object O only if meta-object M is the current meta-object of O. Since the requester cannot find out which is the current meta-object of O, this hint must be part of the reconfiguration request, and the current meta-object can base its decision on it.
The semantics of not providing a hint meta-object M (for example, making it null) is a way to request the current meta-object, whatever it is, to be replaced with N. In any case, the current meta-object can overrule this request.
However, if object O is not reflective, there is no ``current meta-object'' to protect it from arbitrary reconfigurations. It would be nice to be able to specify global or per-class reconfiguration policies, to handle this case without having to make every single object reflective.
The mechanism we propose allows for such per-class policies. Whenever a meta-level reconfiguration request is issued on a non-reflective object, a message is created and presented to the meta-object associated with (the object that represents) the class of the object, if there is such a meta-object. This message, whose type is ``instance reconfiguration'', contains a reference to the object being reconfigured and a modifiable reference to the proposed meta-object, so that the class meta-object can change it. The message is also presented to meta-objects of base classes, and the reference that remains at the end of this process determines the meta-object to be installed as the object's meta-object. If the reference is nullified, the object remains non-reflective.
It is worth noting that, even if an object is reflective, its meta-object may hide and pretend it is not, by creating itself an ``instance reconfiguration'' message and using the messaging mechanism to send the message to the meta-objects of the classes of the object.
An important issue to be considered, when reconfiguration is possible, is how to ensure that meta-objects that have given up control over an object do not get privileged access to it any more. For example, the operation factory held by such a meta-object must be invalidated when it is replaced.
Note that a meta-object might create a stand-alone operation while its operation factory is still valid, and request it to be performed, i.e., submit it for interception, only after a reconfiguration. The operation may still be considered valid and delivered to the object, but it is up to the new meta-object to decide it.
Furthermore, if a meta-object is replaced while it handles an operation, its reply should be ignored and the operation should be handled by the new meta-object. So, even if a meta-object creates an operation, submits it for interception and holds its processing until after a reconfiguration, the operation will not be delivered at its choice: the new meta-object will be able handle the operation and approve it or reject it. In any case, the replaced meta-object should have an opportunity to reset any internal state, with a result that indicates the cancellation of the operation it had handled.
However, if an operation has already been delivered to the base-level object when a reconfiguration takes place, there is no way to cancel it without possibly creating inconsistencies in the base level, so the result should be handled by the same meta-object that handled the operation.
There is a possibility that, upon a reconfiguration request, a meta-object issues a new reconfiguration request. In this case, if the nested reconfiguration is successful, the pending reconfiguration should be ignored, otherwise a meta-object would be able to inconditionally re-take control on the object, by returning itself from the pending reconfiguration request. Concurrent reconfigurations, in multi-threaded systems, had better be serialized.