Monday August 20, 2007 | cn=Directory Manager All about Directory Server |
Internal operations in OpenDSIf you're interested in writing an extension to OpenDS (like a plugin, password validator, identity mapper, virtual attribute provider, etc.), then there's a decent chance that you'll want to be able to search for or make changes to content in the directory as part of your processing. And if you intend on using OpenDS in an embedded manner, then it's almost certainly going to be a requirement for you. One option could be to simply establish a connection to the LDAP listener and issue a request, but that's inefficient and can also have undesirable side effects (e.g., if your plugin creates a new LDAP operation, then the server will try to invoke plugins on that operation, which can create a kind of infinite recursion loop). A better alternative, however, is to perform internal operations within the server. Performing an internal operation is more efficient than creating a new external operation, and internal operations can do things that aren't allowed for external operations (e.g., update attributes marked as NO-USER-MODIFICATION) and they are also marked as internal operations so that it's possible to do things like skip plugin processing for them.The Internal Client Connection Object For quite a while now, OpenDS has provided the org.opends.server.protocols.internal.InternalClientConnection class, which offers a relatively simple way to perform internal operations in the server. To use it, you first need to obtain an internal client connection, which you can do in one of the following ways:
We've added lots of convenience methods in the InternalClientConnection class to help make performing internal operations easy, and we hope to have official documentation on this in the near future. For now, however, you can look at the Javadoc from our latest daily build to see what's available.
The Internal LDAP Socket The internal operations API referenced above should be easy to use, and should allow you to do pretty much anything that you need. I would expect that someone who has ever done any programming involving an existing LDAP SDK (e.g., JDNI or the Mozilla LDAP SDK for Java) should find it especially easy to pick up. However, last week I was talking with some people who were interested in embedding OpenDS and had a bit of a dilemma because they wanted to be able to embed OpenDS and communicate efficiently with it, but they also wanted to have the ability for their application to communicate with external directory servers, and they wanted to avoid having to write all of their client code twice (once using the OpenDS internal API, and another time using the Mozilla LDAP SDK for Java which is their API of choice for external LDAP communication). I gave this a little thought and came up with a solution that I think is a rather elegant approach to the problem: I created a custom socket implementation that is able to convert LDAP requests into internal operations, process the operation, and then convert the response back into LDAP. This code is implemented in the org.opends.server.protocols.internal.InternalLDAPSocket class, which extends the java.net.Socket superclass. Going along with this socket (and doing all the real work behind the scenes) are the InternalLDAPInputStream and InternaLDAPOutputStream classes. As long as the LDAP SDK that you are using supports the use of a custom socket factory, you can use this custom socket implementation to allow you to use that LDAP SDK to perform internal operations. Both JNDI and the Mozilla LDAP SDK for Java support this, and I've tested my implementation with both of them.
For JNDI, if you want to use this custom socket implementation, the only thing that you have to do out of the ordinary is to make sure that your environment properties have the " java.naming.ldap.factory.socket" property set to "org.opends.server.protocols.internal.InternalLDAPSocketFactory". For example:
Hashtable For the Mozilla LDAP SDK for Java, there's just a tiny bit more that you have to do, because it uses its own socket factory implementation ( netscape.ldap.LDAPSocketFactory) instead of the one provided by the JDK (javax.net.SocketFactory, although to be fair that class didn't exist when the Mozilla SDK was written). That interface requires a single makeSocket method, which you can implement as follows:
When you're creating a connection with the Mozilla LDAP SDK for Java, then all you need to do is to use the LDAPConnection(LDAPSocketFactory) constructor to have it use that socket factory for its communication. As an example, I have written a simple EmbeddedMozillaLDAPSDKTest program that can be used to start an embedded OpenDS instance, perform some internal operations using the Mozilla LDAP SDK for Java, and shut down the server. In order to create an appropriate environment for this test, all I needed to do was:
config directory, and if we disable loggers then we wouldn't have needed the logs directory, etc.), but I wanted to keep this example simple.
Limitations of the Internal LDAP Socket Implementation In general, if you're using the internal LDAP socket implementation you can do pretty much anything that you could do if you were talking to OpenDS using actual LDAP network communication. However, there are a few important things to note about this implementation:
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||