Extended Operations
Extended operations are operations exposed by an LDAP server. They contain an OID to uniquely identify the operation an a free form binary field for request and respons information. Extended operations in many respects are the manifestation of LDAP stored procedures at the protocol level. We would like to allow users to expose arbitrary operations using a specific extended operation for executing procedures on the server. This is discussed in detail in Stored Procedures.
However any functionality which we would like to expose in the server can be made into an ExtendedOperation. In fact several functions like synching the server or shuting it down could be exposed as ExtendedOperations.
Implementation Details
Extended operations have been implemented within the protocol provider using two classes:
These handlers handle the protocol/networking specific aspects of 'handling' an ExtendedRequest. Note that additional ExtendedOperationHandlers can be registered using a mutable server configuration object. Take a look at the setExtendedOperationHandlers(<Collection>) method of the MutableServerStartupConfiguration class.
JNDI's extendedOperation()
JNDI's LdapContext has a method called extendedOperation(ExtendedRequest) which returns and ExtendedResponse. Our JNDI provider in the core also must implement this method to implement LdapContext. What is the point to this method if we have handlers already within the protocol module that sits on top of the core?
This little anomoly is a result of what happens when JNDI, a predominantly client side API, is used on the server side. However even if it is a problem, users embedding the server might want to execute stored procedures on the server or other operations using this interface method. In fact one can go as far as to say that the SynchConfiguration and ShutdownConfiguration objects used to synch and shutdown the server should have been implemented as extendedOperations() in the JNDI provider.
Up until now, this method was not implemented and we had no clue what to do with it. First of all the ExtendedRequest object presented issues for us since we did not want to do ASN1 decoding inside the core. Likewise we do not want to do encoding to generate the ExtendedResponse. All ExtendedRequest objects should be subtypes of the interface that contain Java properties to access the fields within the extended data. Meaning the extended data has already been decoded within the protocol layer. Likewise the returned ExtendedResponse is not yet encoded. Just the properties of the response are set as a POJO property. It still needs to be encoded by the protocol layer before being returned to the client. Up until now, the protocol layer was handling decoding and other aspects of ExtendedRequests for us so why would we bother handling them yet again within the core. Some ExtendedRequests list StartTLS never needed to even hit the core.
Next arises the tricky question of whether or not extendedOperation() really represents a simple procedure call into the core. At first glance it seemed as though stored procedures were a special case for an extendedOperation() in the core. Meaning extendedOperation() was more general than a specialized stored procedure operation. However after inspecting it more closely I realize that extendedOperations are still method calls made into the server however they may not be stored procedures added to the DIT by a user. In the end they still represent methods called within the server. ExtendedOperations can essentially be modelled as stored procedures. Really there is no point to having extendedOperation() unless it is to process a stored procedure ExtendedOperation. This is what we should force this method on the JNDI provider to do. Other extended operations should not be allowed and don't even make sense. Why for example would someone issue a StartTls ExtendedRequest while embedding the server? Even if they wanted that the SUN JNDI provider would be used instead of the serverside provider.
The ClassLoader used to load classes from the DIT should be able to resolve classes on the System ClassPath. This way standard methods within the server can be exposed as stored procedures. This will also however require the a Java SecurityManager to protect access to sensitive methods within the server.
Introducing Provider Specific Operations
Executing stored procedures from the extendedOperation() method will not be so hard. We can easily define a special ExtendedRequest/Response pair of interfaces to encapsulate a procedure call. The StoredProcedureRequest bean can be populated and the appropriate OID can be used for the general SP operation exposed by ApacheDS. Note that one stored procedure extended operation is used to encapsulate every possible stored procedure call that can be defined and exposed in the server. So calling extendedOperation() to execute a stored procedure will be easy to do.
However we can go one step further. Rather than encapsulate operation parameters in an ExtendedRequest object why not just supply those parameters to a method. A watered down version of extendedOperation() can be introduced for handling raw procedure calls. Here's what the signature might look like:
Object executeProcedure( Method, Class[] paramTypes, Object[] paramValues ); Object executeProcedure( String className, String methodName, Class[] paramTypes, Object[] paramValues );
This may however be a bit too Java centric if more than just Java based stored procedures will be supported. It might be a good idea to replace Method with a CallSpecification and the two array parameters with a Parameter object which contains both the type and value fields for the parameter. Additional methods can be added to the Parameter to interpret the value as different types. The value may be stored as a byte[] within the parameter. So the method may now look like:
Object executeProcedure( CallSpecification, Parameter[] );
Why can't we expose both methods as overloads? Meaning one can be used for Java centric calls and the other can be used for all others.
