Hallo all,
I'm working on the Acegi Security project for the Spring Framework and
we're keen to use ApacheDS for testing our LDAP security provider.
I've written a pile of code for this and have a set of JUnit tests which
I now have running successfully against OpenLDAP and also against an
ApacheDS server instance which is started from the unit test base class
(using the Sun provider as the client).
Ideally we would prefer to run with an in-memory embedded server
(similar to using HSQLDB in this fashion) because it is a lot faster and
avoids issues like having to shut down the server (our Maven build in
particular gets very upset about the embedded server). It seems that
this may be possible by just by having the client use CoreContextFactory
to obtain contexts directly rather than the Sun provider. I've managed
to get some way to achieving this but the behaviour isn't consistent
with the full stack version and I'm not sure whether this is expected or
if I'm doing something wrong.
My setup is like this:
I have a simple DIT with a root "dc=acegisecurity,dc=org". This has two
subcontexts "ou=people" and "ou=groups" for my users and roles
respectively. When the test base class instantiated, I create a
MutableStartupConfiguration and add a partition to it with the suffix
"dc=acegisecurity,dc=org". I then create a context with this
configuration as follows:
env.setProperty( Context.PROVIDER_URL, "dc=acegisecurity,dc=org" );
env.setProperty( Context.INITIAL_CONTEXT_FACTORY,
CoreContextFactory.class.getName());
env.putAll( cfg.toJndiEnvironment() );
serverContext = new InitialDirContext( env );
When I need a context in my tests it is created the same way.
Bind authentication works fine in both scenarios. I have problems with
two things when trying to use CoreContextFactory :
1. The name returned by a search. When I do a search for a user in the
directory, I get back the full DN rather than the name relative to the
context I search in. So if I call
ctx.search("ou=people", "(uid={0})", new String[] {"bob"}, ctls);
on a context obtained as above, I get back a SearchResult with name
"uid=bob,ou=people,dc=acegisecurity,dc=org"
whereas with the full server (or OpenLDAP) I get
"uid=bob"
as expected. This then unfortunately leads to an attempt to bind with an
an unknown DN which causes the infinite recursion problem.
2. Performing "compare" operations. I had problems with this before, as
reported in
http://issues.apache.org/jira/browse/DIRLDAP-77
but this now works with the full server, thanks to Emmanuel's speedy
response. Running the same search code against a context obtained from
CoreContextFactory fails however. A compare is never performed and the
search returns an empty enumeration. Is there some way I can get my
client code (as posted in JIRA):
SearchControls ctls = new SearchControls();
ctls.setReturningAttributes(new String[0]);
ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
String filter = "(userPassword={0})";
NamingEnumeration results = ctx.search(dn, filter, new
Object[]{password.getBytes()}, ctls);
to trigger a compare call on the context? The compare/search also fails
for non-binary attributes.
I was also wondering if there was any way of running fully in-memory
without any persistent storage as it isn't needed for this kind of usage
and it would avoid the need for clearing up the data files during the build.
Any help would be greatly appreciated as we're looking to include LDAP
support in the forthcoming 1.0 release and ApacheDS seems like our best
option for an integrated server both for testing and sample applications.
cheers,
Luke.
--
Luke Taylor. Monkey Machine Ltd.
PGP Key ID: 0x57E9523C http://www.monkeymachine.ltd.uk