diff --git a/core/src/main/java/org/acegisecurity/ldap/LdapCallback.java b/core/src/main/java/org/acegisecurity/ldap/LdapCallback.java new file mode 100644 index 0000000000..3aeef33516 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ldap/LdapCallback.java @@ -0,0 +1,27 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.acegisecurity.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Callback object for use with LdapTemplate. + * + * @author Ben Alex + */ +public interface LdapCallback { + public Object execute(DirContext dirContext) throws NamingException; +} diff --git a/core/src/main/java/org/acegisecurity/ldap/LdapTemplate.java b/core/src/main/java/org/acegisecurity/ldap/LdapTemplate.java new file mode 100644 index 0000000000..cd4c202d6b --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ldap/LdapTemplate.java @@ -0,0 +1,96 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.acegisecurity.ldap; + +import javax.naming.NamingException; +import javax.naming.NamingEnumeration; +import javax.naming.directory.DirContext; +import javax.naming.directory.SearchControls; + +import org.springframework.dao.DataAccessException; +import org.springframework.util.Assert; + +/** + * LDAP equivalent of the Spring JdbcTemplate class. + * + * @author Ben Alex + * @author Luke Taylor + * + */ +public class LdapTemplate { + public static final String[] NO_ATTRS = new String[0]; + + private InitialDirContextFactory dirContextFactory; + private String userDn = null; + private String password = null; + + public LdapTemplate(InitialDirContextFactory dirContextFactory) { + Assert.notNull(dirContextFactory, "An InitialDirContextFactory is required"); + this.dirContextFactory = dirContextFactory; + } + + public LdapTemplate(InitialDirContextFactory dirContextFactory, String userDn, String password) { + this(dirContextFactory); + + Assert.hasLength(userDn, "userDn must not be null or empty"); + Assert.notNull(password, "password cannot be null"); + + this.userDn = userDn; + this.password = password; + } + + public Object execute(LdapCallback callback) throws DataAccessException { + DirContext ctx = null; + + try { + ctx = (userDn == null) ? + dirContextFactory.newInitialDirContext() : + dirContextFactory.newInitialDirContext(userDn, password); + + return callback.execute(ctx); + + } catch (NamingException exception) { + // TODO: Write a static method in separate NamingExceptionExceptionTranslator class called public DataAccessException convert(NamingException); + throw new LdapDataAccessException("xxxx", exception); + } finally { + LdapUtils.closeContext(ctx); + } + } + + + public boolean compare(final String dn, final String attributeName, final Object value) { + final String comparisonFilter = "(" + attributeName + "={0})"; + + class LdapCompareCallback implements LdapCallback { + + public Object execute(DirContext ctx) throws NamingException { + SearchControls ctls = new SearchControls(); + ctls.setReturningAttributes(NO_ATTRS); + ctls.setSearchScope(SearchControls.OBJECT_SCOPE); + + NamingEnumeration results = + ctx.search(dn, comparisonFilter, new Object[]{value}, ctls); + + return Boolean.valueOf(results.hasMore()); + } + } + + + Boolean matches = (Boolean)execute(new LdapCompareCallback()); + + return matches.booleanValue(); + } +} diff --git a/core/src/test/java/org/acegisecurity/ldap/LdapTemplateTests.java b/core/src/test/java/org/acegisecurity/ldap/LdapTemplateTests.java new file mode 100644 index 0000000000..9234fb1308 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ldap/LdapTemplateTests.java @@ -0,0 +1,45 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.acegisecurity.ldap; + +/** + * @author Luke Taylor + * @version $Id$ + */ +public class LdapTemplateTests extends AbstractLdapServerTestCase { + + protected void onSetUp() { + getInitialCtxFactory().setManagerDn(MANAGER_USER); + getInitialCtxFactory().setManagerPassword(MANAGER_PASSWORD); + } + + + public void testCompareOfCorrectValueSucceeds() { + LdapTemplate template = new LdapTemplate(getInitialCtxFactory()); + +// Doesn't work with embedded server due to bugs in apacheds +// assertTrue(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("bobspassword"))); + } + + public void testCompareOfWrongValueFails() { + LdapTemplate template = new LdapTemplate(getInitialCtxFactory()); + +// Doesn't work with embedded server due to bugs in apacheds +// assertFalse(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("wrongvalue"))); + } + + +}