directory-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Emmanuel Lecharny <elecha...@gmail.com>
Subject Some experiment result about the chain management
Date Mon, 07 Nov 2011 20:55:56 GMT
Hi guys,

I played around some of the ideas we discussed last week on the mailing 
list, about the way we handle the chain and the interceptors.

What I did was pretty simple : I modified the way we process the 
getRootDse() operation. This impact many classes :
o OperationContext :
This interface exposes 4 more methods :
   List<String> getInterceptors() which returns the list of interceptors 
to execute for this operation
   void setInterceptors( List<String> interceptors ) which sets the list 
of interceptors to execute for this operation
   int getCurrentInterceptor() : returns the current interceptor for 
this context
   void nextInterceptor() : move the current interceptor to the next 
interceptor

o AbstractOperationContext :
This is where we implement the four added methods.

...
     /** The interceptors to call for this operation */
     protected List<String> interceptors;

     /** The current interceptor position */
     protected int currentInterceptor;
...
     public AbstractOperationContext( CoreSession session )
     {
         this.session = session;
         currentInterceptor = 0;
     }
...
     public List<String> getInterceptors()
     {
         return interceptors;
     }

     public void setInterceptors( List<String> interceptors )
     {
         this.interceptors = interceptors;
     }

     public int getCurrentInterceptor()
     {
         return currentInterceptor;
     }

     public void nextInterceptor()
     {
         currentInterceptor++;
     }

Nothing big here, just accessors.


o ServerContext.doGetRootDSEOperation :
the GetRootDseOperationContext now contains the list of interceptors to 
call :

     protected Entry doGetRootDSEOperation( Dn target ) throws Exception
     {
         GetRootDSEOperationContext getRootDseContext = new 
GetRootDSEOperationContext( session, target );
         getRootDseContext.addRequestControls( convertControls( true, 
requestControls ) );

-->     // We should get this list from the DS !!!
-->     List<String> interceptors = new ArrayList<String>();
-->     interceptors.add( AuthenticationInterceptor.class.getSimpleName() );
-->     getRootDseContext.setInterceptors( interceptors );

         // do not reset request controls since this is not an external
         // operation and not do bother setting the response controls either
         OperationManager operationManager = service.getOperationManager();

         return operationManager.getRootDSE( getRootDseContext );
     }

Here, it's hard wired, but the logic would be to ask the DS to provide 
the interceptor list, which will be copied and stored into the 
OperationContext. Otherwise, the code is the same.

o DefaultOperationManager :
The first main difference :
     public Entry getRootDSE( GetRootDSEOperationContext 
getRootDseContext ) throws LdapException
     {
         ...
         try
         {
             Interceptor head = directoryService.getInterceptor( 
getRootDseContext.getInterceptors().get( 0 ) );
             getRootDseContext.nextInterceptor();

             return head.getRootDSE( getRootDseContext );
             ...

Here, we compute the first interceptor to call by getting the first of 
the list from the OperationContext, and we call it. As we can see, we 
don't use the InterceptorChain anymore. (Note that we can improve the 
code by adding a method in the OperationContext to return the 
Interceptor directly.)

o Interceptor :
The second main difference. We don't pass anymore the NextInterceptor 
parameter :
     Entry getRootDSE( GetRootDSEOperationContext getRootDseContext ) 
throws LdapException;

o The inherited classes (here, AuthenticatorInterceptor) :
We have to change the getRootDSE method in order to call the next 
interceptor. This is done by substituing this line :
         return next.getRootDSE( getRootDseContext );
by this one :
         return next( getRootDseContext );

where the next() method is a final method in the BaseInterceptor class

o BaseInterceptor :
This is where we compute the next interceptor to call :

     protected final Entry next( GetRootDSEOperationContext 
getRootDseContext ) throws LdapException
     {
         Interceptor interceptor = getNextInterceptor( getRootDseContext );

         return interceptor.getRootDSE( getRootDseContext );
     }

and

     private Interceptor getNextInterceptor( OperationContext 
operationContext )
     {
         int currentInterceptor = operationContext.getCurrentInterceptor();

         if ( currentInterceptor == 
operationContext.getInterceptors().size() )
         {
             return FINAL_INTERCEPTOR;
         }

         operationContext.nextInterceptor();

         Interceptor interceptor = directoryService.getInterceptor( 
operationContext.getInterceptors().get( currentInterceptor ) );

         return interceptor;
     }


The FINAL_INTERCEPTOR interceptor is the one which reroute calls to the 
nexus (It's the same class we have in the InterceptorChain).


That's it, the code works, and when it comes to debug it, it's just easy 
: we don't have to go through multiple classes when stepping through, 
and we don't have to go through the BaseInterceptor for each disabled or 
bypassed interceptor.

It's not totally finished though : the list creation is just horrible in 
the given code. It must be generated in the DirectoryService by using 
introspection over all the activated Interceptors.

Thoughts ?

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


Mime
View raw message