directory-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Emmanuel Lecharny <elecha...@gmail.com>
Subject Re: Implementing Interceptor Extendibility, another way of doing things...
Date Thu, 03 Nov 2011 13:16:39 GMT
On 11/3/11 12:54 PM, Alex Karasulu wrote:
> Hi all,
>
> Forgive the prepost here: need to report on a off list conversation I just
> had with Emmanuel. We generated some very nice ideas on these matters. I'm
> going to be very direct with implementation details rather than being high
> level and general with these ideas to directly dump the thoughts:
>
> (1)  For each intercepted operation (add, delete, modify etc), the server
> maintains an ordered list of core aspect descriptors out of the box
> (normalization, access-control, authorization etc) which must be applied in
> order to an invocation of an intercepted operation.
>
> To do this we can have an operation expose aspect ordering:
>
> add.getAspects() ... returns order list or array of Aspects like
> {Normalization, AccessControl, Authorization, ...}.
>
> Dynamic configuration should allow us to change this ordered list on the
> fly to introduce new aspects or remove old ones. Meaning if we like we can
> define a new logical aspect like craptastic aspect and have it participate
> in various operation invocations in the order we like it to participate.
>
> This is our logical aspect ordering model and exposed as a dynamic
> configuration point in the server.
>
> (2) Each Interceptor must publish one and only one aspect it participates
> in. The aspect must be in the set of aspects configured in the server via
> dynamic configuration so we have a list of aspects managed by the server
> without the need for ordering since ordering is operation specific.
>
> normalization
> craptastic
> authentication
> access-control
> foobar
>
> ...
>
> Interceptor.getAspect()  should return an aspect within this set, and if it
> does not then it simply is not considered for injection into the chains
> created.
>
> In the configuration area we also manage operation aspects with order:
>
> bind: normalization, authentication
> add: normalization ....
> del: ...
> modify ....
> ...
>
> The user is constrained to only include aspects in the set of supported
> aspects above. No problem though, the user can add his or her custom aspect
> to the set, then can start adding that aspect to the operation aspect lists
> in the configuration. If no interceptor exists to supply functionality for
> that aspect, no problem it's just not injected during actual physical chain
> construction time. Once an interceptor appears it can be considered for
> injection when calculating the interceptor ordering in chains ... see below.
>
> This is good for the OSGi model where services (interceptors in this case)
> can come and go.
>
> (3) The server tracks the actual interceptor implementation execution order
> by calculating this order using these aspects on a per operation basis. If
> interceptor Foo.getAspect = Normalization and interceptor Bar.getAspect =
> Authentication, then for bind the interceptor implementation order would
> be:
>
> Foo, Bar
>
> The result of this calculation will be dynamically configurable as
> described above by altering configurations for aspect order per operation.
> This way we can add new aspects, that have not even been conceived of while
> creating ApacheDS. Users will have this freedom. And at chain construction
> time the right implementations will be properly selected and injected in
> the right order.
>
> (3) At session creation time, the server constructs interceptor reference
> lists with actual references to interceptor instances for each operation.
> Sessions do not need unique interceptor instances: the interceptors are
> shared across sessions and chains. The server uses the aspect information
> from an Interceptor and operation aspect lists to determine this reference
> list order and construct it.
>
> For Bind operation the interceptor reference list would be Foo, Bar as in
> the example above.
>
> Each session has an interceptor reference list calculated for each
> operation and this is stored within each session.   This way sessions can
> modify their interceptor reference lists for various operations to have
> fine grained auditing for example for a single operation in a single
> connection without impacting all sessions or the entire server.
>
> The overhead for managing separate interceptor reference lists for each
> operation in each session is minimal.
>
> (4) The interceptor chain changes character somewhat. It is modified to not
> be statically hardwired but to use the interceptor reference list of the
> operation invoked from a session to conduct invocations with the correct
> interceptor order.
>
> I think this can be done without causing inefficiencies. I don't have
> suggestions on how best we can do this in the code right now.
>
> Thoughts? Additions?

A few additions :

- the default order should be stored in the config (DIT)
- up to a user to modify this order, but then, it's his responsibility.
- we have to store a aspect <-> interceptor map in the config too (DIT)
- we must get rid of bypasses. They are far too numerous, and probably 
out of control. Here is the list of all the bypasses we are using : 
http://pastebin.com/tYDMvGMZ

>
> On Wed, Nov 2, 2011 at 10:04 PM, Emmanuel Lecharny<elecharny@gmail.com>wrote:
>
>> Hi guys,
>>
>> I had a bit of time and I reviewed the interceptors today. And I had an
>> idea which may be interesting to discuss.
>>
>> First, here is a table where all the interceptors operation are listed,
>> and for each interceptor, I listed the operation they are processing :
>>
>> AciAuthorizationInterceptor : ACI
>> AdministrativePointInterceptor : API
>> AuthenticationInterceptor : AI
>> ChangeLogInterceptor : CLI
>> CollectiveAttributeInterceptor : CAI
>> DefaultAuthorizationIntercepto**r : DAI
>> EventInterceptor : EI
>> ExceptionInterceptor : EXI
>> JournalInterceptor : JI
>> KeyDerivationInterceptor : KDI
>> NormalizationInterceptor : NI
>> OperationalAttributeIntercepto**r : OAI
>> PasswordHashingInterceptor : PHI
>> ReferralInterceptor : RI
>> SchemaInterceptor : SI
>> SubentryInterceptor : SEI
>> TriggerInterceptor : TI
>>
>>                 ACI API  AI CLI CAI DAI  EI EXI  JI KDI  NI OAI PHI  RI  SI
>> SEI  TI
>> add           :  x   x   x   x   x   ?   x   x   x   x   x   x   x   x   x
>>    x   x
>> bind          :  -   -   x   -   -   -   -   -   -   -   x   -   -   -   -
>>    -   -
>> compare       :  x   -   x   -   -   -   -   -   -   -   x   -   -   -   x
>>    -   -
>> delete        :  x   x   x   x   -   x   x   x   x   -   x   -   -   x   -
>>    x   x
>> getRootDSE    :  -   -   x   -   -   -   -   -   -   -   -   -   -   -   -
>>    -   -
>> hasEntry      :  x   -   x   -   -   -   -   -   -   -   x   -   -   -   -
>>    -   -
>> list          :  x   -   x   -   x   x   -   x   -   -   x   x   -   -   x
>>    x   -
>> lookup        :  x   -   x   -   x   x   -   x   -   -   x   x   -   -   x
>>    -   -
>> modify        :  x   x   x   x   x   x   x   x   x   x   x   x   x   x   x
>>    x   x
>> move          :  x   x   x   x   -   x   x   x   x   -   x   x   -   x   -
>>    x   x
>> moveAndRename :  x   x   x   x   -   x   x   x   x   -   x   x   -   x   ?
>>    x   x
>> rename        :  x   x   x   x   -   x   x   x   x   -   x   x   -   x   x
>>    x   x
>> search        :  x   -   x   -   x   x   -   -   -   -   x   x   -   -   x
>>    x   -
>> unbind        :  -   -   x   -   -   -   -   -   -   -   -   -   -   -   -
>>    -   -
>>
>> (It's interesting that there are two operations that should be processed
>> by some interceptors, and that are not : it's most certainly a bug. They
>> are marked with a '?' in this table)
>>
>> Now, we can see that all the operation are only processed by a few
>> interceptors. I was thinking that it could be an option to list the
>> mandatory interceptors for each operation, instead of letting the chain
>> determinate if an interceptor will process this operation.
>>
>> In the Operation manager, we will then call all the needed interceptors
>> chain for each operation. For instance, for a delete operation, we will
>> proceed this way :
>>
>> operationManager.delete( DeleteOperationContext deleteContext )
>> {
>>     // ThedeleteContext.getOperation(**) is used to get the correct list
>> of interceptors for the operation,
>>     // as we may have more than one delete operation (see below)
>>     InterceptorChain deleteChain = directoryService.**getInterceptors(
>> deleteContext.getOperation() );
>>
>>     deleteChain.delete( deleteContext );
>> }
>> The biggest advantage is that we know have a clear list of interceptors
>> for each operation, and we cna expose this list to the user, who can add
>> its own interceptor. We can even compute this chain by checking which
>> operation an interceptor will handle, using reflection, when the
>> interceptor is added in the chain.
>>
>> For internal operation, I'm quiet sure we should ask the nexus directly,
>> instead of going through the chain again. However, we can perfectly proceed
>> exactly the same way, by defining some other operation, like
>> lookupInternal, which describes the list of needed interceptors.
>>
>> One other advantage is that we will not go through N useless interceptor
>> for each operation, speeding up (ok, marginaly but still) the operations.
>>
>> Lats, not least, I'm quite sure that if we expose the list of interceptors
>> involved by each operation, we make it easier for someone who want to add
>> an interceptor, as all those lists will be available through teh
>> configuration, and not in the code, as it is atm. It also remove the need
>> for interceptors bypasses, if we inject the type of operation we want to
>> execute in the context (xxxContext.getOperation()  will return the type of
>> operation).
>>
>> It may sound a bit crazy, but I think it would work with a little impact
>> on the existing code...
>>
>> thoughts ?
>>
>> -- Regards, Cordialement, Emmanuel L├ęcharny www.iktek.com
>>
>
>


-- 
Regards,
Cordialement,
Emmanuel L├ęcharny
www.iktek.com


Mime
View raw message