Work in progress. Any feedback highly appreciated! |
The following is for developers who plan to implement their own interceptors in order to extend or modify the functionality of Apache Directory Server. It contains a simple example as a starting point.
An interceptor filters method calls performed on on the DefaultPartitionNexus just like Servlet filters do. The ApacheDS configuration contains a chain of filters performing several tasks. In order to illustrate this, here is the list of interceptors from the default server configuration of ApacheDS 1.5.5
Interceptors should usually pass the control of current invocation to the next interceptor by calling an appropriate method on NextInterceptor. The flow control is returned when the next interceptor's filter method returns. You can therefore implement pre-, post-, around- invocation handler by how you place the statement.
Interceptors are a powerful way to extend and modify the server behavior. But be warned. A mistakenly written interceptor may lead to a dis-functional or corrupt server.
In order to demonstrate how to write an interceptor, here is a simple but realistic example. The following requirement should be fulfilled by an interceptor.
Currently, the sources are checked in here
In order to build it, simply check it out and type "mvn install".
The following UML class diagram depicts the structure of the little example.
The class HashTools contains two simple methods w.r.t. hashing. isAlreadyHashed detects whether a value has already been hashed with a known message digest algorithm. applyHashAlgorithm applies a hash algorithm to a sequence of bytes. See the source code and the unit tests of this class for details, it has not that much todo with the interceptor stuff.
The central class is PasswordHashInterceptor. Every interceptor has to implement the Interceptor interface from package org.apache.directory.server.core.interceptor. PasswordHashInterceptor does so by extended the convenience class BaseInterceptor from the same package.
package org.apache.directory.samples.interceptor.pwdhash; import java.util.List; import org.apache.directory.server.core.DefaultDirectoryService; import org.apache.directory.server.core.DirectoryService; import org.apache.directory.server.core.interceptor.Interceptor; import org.apache.directory.server.ldap.LdapServer; import org.apache.directory.server.protocol.shared.transport.TcpTransport; /** * Main class which starts an embedded server with the interceptor added to the * chain. */ public class Main { public static void main(String[] args) throws Exception { DirectoryService directoryService = new DefaultDirectoryService(); directoryService.setShutdownHookEnabled(true); LdapServer ldapServer = new LdapServer(); ldapServer.setDirectoryService(directoryService); ldapServer.setAllowAnonymousAccess(true); List<Interceptor> is = directoryService.getInterceptors(); is.add(new PasswordHashInterceptor()); directoryService.setInterceptors(is); TcpTransport ldapTransport = new TcpTransport(10389); ldapServer.setTransports(ldapTransport); directoryService.startup(); ldapServer.start(); } } |