diff --git a/core/src/main/java/org/springframework/ldap/core/LdapOperations.java b/core/src/main/java/org/springframework/ldap/core/LdapOperations.java
index 43d993a5..d9a3d9dc 100644
--- a/core/src/main/java/org/springframework/ldap/core/LdapOperations.java
+++ b/core/src/main/java/org/springframework/ldap/core/LdapOperations.java
@@ -26,7 +26,6 @@ import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
-import org.springframework.ldap.AuthenticationException;
import org.springframework.ldap.ContextNotEmptyException;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.support.AbstractContextSource;
@@ -1261,7 +1260,7 @@ public interface LdapOperations {
/**
* Bind the data in the supplied context in the tree. All specified
- * Attributes in will be bound to the DN set on the instance.
+ * attributes ctxin will be bound to the DN set on ctx.
*
* Example:
*
@@ -1280,6 +1279,29 @@ public interface LdapOperations {
*/
void bind(DirContextOperations ctx);
+ /**
+ * Remove an entry and replace it with a new one. The attributes used to
+ * create the entry are retrieved from the ctx parameter. This
+ * method assumes that the specified context already exists - if not it will
+ * fail. The entry will be bound to the DN set on ctx.
+ *
+ * Example:
+ *
+ *
+ * DirContextOperations ctx = new DirContextAdapter(dn);
+ * ctx.setAttributeValue("cn", "john doe");
+ * ctx.setAttributeValue("description", "some description");
+ * //More initialization here.
+ *
+ * ldapTemplate.rebind(ctx);
+ *
+ * @param ctx the context to rebind
+ * @throws IllegalStateException if no DN is set or if the instance is in
+ * update mode.
+ * @since 1.3
+ */
+ void rebind(DirContextOperations ctx);
+
/**
* Utility method to perform a simple LDAP 'bind' authentication. Search for
* the LDAP entry to authenticate using the supplied base DN and filter; use
diff --git a/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java b/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java
index 55fae4ad..6111e5b2 100644
--- a/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java
+++ b/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java
@@ -1337,7 +1337,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
/*
* (non-Javadoc)
*
- * @seeorg.springframework.ldap.core.simple.SimpleLdapOperations#bind(org.
+ * @seeorg.springframework.ldap.core.LdapOperations#bind(org.
* springframework.ldap.core.DirContextOperations)
*/
public void bind(DirContextOperations ctx) {
@@ -1350,6 +1350,23 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
}
+
+ /*
+ * @see
+ * org.springframework.ldap.core.LdapOperations#rebind(org.springframework.
+ * ldap.core.DirContextOperations)
+ */
+ public void rebind(DirContextOperations ctx) {
+ Name dn = ctx.getDn();
+ if (dn != null && !ctx.isUpdateMode()) {
+ rebind(dn, ctx, null);
+ }
+ else {
+ throw new IllegalStateException(
+ "The DirContextOperations instance needs to be properly initialized.");
+ }
+ }
+
/*
* (non-Javadoc)
*
diff --git a/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java b/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java
index 3d7570f7..ad464b82 100644
--- a/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java
+++ b/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java
@@ -39,6 +39,12 @@ import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.PartialResultException;
import org.springframework.ldap.UncategorizedLdapException;
+/**
+ * Unit tests for the LdapTemplate class.
+ *
+ * @author Mattias Hellborg Arthursson
+ * @author Ulrik Sandberg
+ */
public class LdapTemplateTest extends TestCase {
private static final String DEFAULT_BASE_STRING = "o=example.com";
@@ -168,7 +174,6 @@ public class LdapTemplateTest extends TestCase {
dirContextOperationsConrol = null;
dirContextOperationsMock = null;
-
}
protected void replay() {
@@ -1118,7 +1123,6 @@ public class LdapTemplateTest extends TestCase {
tested.bind(nameMock, expectedObject, expectedAttributes);
verify();
-
}
public void testBind_String() throws Exception {
@@ -1134,7 +1138,6 @@ public class LdapTemplateTest extends TestCase {
tested.bind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes);
verify();
-
}
public void testBind_NamingException() throws Exception {
@@ -1158,7 +1161,23 @@ public class LdapTemplateTest extends TestCase {
}
verify();
+ }
+
+ public void testBindWithContext() throws Exception {
+ expectGetReadWriteContext();
+ dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
+ .getDn(), nameMock);
+ dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
+ .isUpdateMode(), false);
+ dirContextMock.bind(nameMock, dirContextOperationsMock, null);
+ dirContextMock.close();
+
+ replay();
+
+ tested.bind(dirContextOperationsMock);
+
+ verify();
}
public void testUnbind() throws Exception {
@@ -1184,6 +1203,23 @@ public class LdapTemplateTest extends TestCase {
verify();
}
+
+ public void testRebindWithContext() throws Exception {
+ expectGetReadWriteContext();
+
+ dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
+ .getDn(), nameMock);
+ dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
+ .isUpdateMode(), false);
+ dirContextMock.rebind(nameMock, dirContextOperationsMock, null);
+ dirContextMock.close();
+
+ replay();
+
+ tested.rebind(dirContextOperationsMock);
+
+ verify();
+ }
public void testUnbindRecursive() throws Exception {
expectGetReadWriteContext();
@@ -1864,16 +1900,17 @@ public class LdapTemplateTest extends TestCase {
assertFalse(result);
}
+
/**
* Needed to verify search control values.
*
* @author Mattias Hellborg Arthursson
*/
private static class SearchControlsMatcher extends AbstractMatcher {
- protected boolean argumentMatches(Object arg0, Object arg1) {
- if (arg0 instanceof SearchControls && arg1 instanceof SearchControls) {
- SearchControls s0 = (SearchControls) arg0;
- SearchControls s1 = (SearchControls) arg1;
+ protected boolean argumentMatches(Object expected, Object actual) {
+ if (expected instanceof SearchControls && actual instanceof SearchControls) {
+ SearchControls s0 = (SearchControls) expected;
+ SearchControls s1 = (SearchControls) actual;
return s0.getSearchScope() == s1.getSearchScope()
&& s0.getReturningObjFlag() == s1.getReturningObjFlag()
@@ -1882,7 +1919,7 @@ public class LdapTemplateTest extends TestCase {
&& s0.getReturningAttributes() == s1.getReturningAttributes();
}
else {
- return super.argumentMatches(arg0, arg1);
+ return super.argumentMatches(expected, actual);
}
}
}
diff --git a/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java b/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java
index b242e659..2eb56b62 100644
--- a/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java
+++ b/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java
@@ -36,21 +36,20 @@ import org.springframework.test.context.ContextConfiguration;
* class tests a little too much, but we need to clean up after binding, so the
* most efficient way to test is to do it all in one test method. Also, the
* methods in this class relies on that the lookup method works as it should -
- * that should be ok, since that is verified in a separate test class. NOTE: if
- * any of the tests in this class fails, it may be necessary to run the cleanup
- * script as described in README.txt under /src/iutest/.
+ * that should be ok, since that is verified in a separate test class.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = { "/conf/ldapTemplateTestContext.xml" })
-public class LdapTemplateBindUnbindITest extends AbstractLdapTemplateIntegrationTest {
+public class LdapTemplateBindUnbindITest extends
+ AbstractLdapTemplateIntegrationTest {
@Autowired
private LdapTemplate tested;
private static String DN = "cn=Some Person4,ou=company1,c=Sweden";
@Test
- public void testBindAndUnbind_Attributes_Plain() {
+ public void testBindAndUnbindWithAttributes() {
Attributes attributes = setupAttributes();
tested.bind(DN, null, attributes);
verifyBoundCorrectData();
@@ -59,7 +58,7 @@ public class LdapTemplateBindUnbindITest extends AbstractLdapTemplateIntegration
}
@Test
- public void testBindAndUnbind_Attributes_DIstinguishedName() {
+ public void testBindAndUnbindWithAttributesUsingDistinguishedName() {
Attributes attributes = setupAttributes();
tested.bind(new DistinguishedName(DN), null, attributes);
verifyBoundCorrectData();
@@ -68,9 +67,10 @@ public class LdapTemplateBindUnbindITest extends AbstractLdapTemplateIntegration
}
@Test
- public void testBindAndUnbind_DirContextAdapter_Plain() {
+ public void testBindAndUnbindWithDirContextAdapter() {
DirContextAdapter adapter = new DirContextAdapter();
- adapter.setAttributeValues("objectclass", new String[] { "top", "person" });
+ adapter.setAttributeValues("objectclass", new String[] { "top",
+ "person" });
adapter.setAttributeValue("cn", "Some Person4");
adapter.setAttributeValue("sn", "Person4");
@@ -81,9 +81,10 @@ public class LdapTemplateBindUnbindITest extends AbstractLdapTemplateIntegration
}
@Test
- public void testBindAndUnbind_DirContextAdapter_DIstinguishedName() {
+ public void testBindAndUnbindWithDirContextAdapterUsingDistinguishedName() {
DirContextAdapter adapter = new DirContextAdapter();
- adapter.setAttributeValues("objectclass", new String[] { "top", "person" });
+ adapter.setAttributeValues("objectclass", new String[] { "top",
+ "person" });
adapter.setAttributeValue("cn", "Some Person4");
adapter.setAttributeValue("sn", "Person4");
@@ -94,9 +95,11 @@ public class LdapTemplateBindUnbindITest extends AbstractLdapTemplateIntegration
}
@Test
- public void testBindAndUnbindPlainDirContextAdapter() {
- DirContextAdapter adapter = new DirContextAdapter(new DistinguishedName(DN));
- adapter.setAttributeValues("objectclass", new String[] { "top", "person" });
+ public void testBindAndUnbindWithDirContextAdapterOnly() {
+ DirContextAdapter adapter = new DirContextAdapter(
+ new DistinguishedName(DN));
+ adapter.setAttributeValues("objectclass", new String[] { "top",
+ "person" });
adapter.setAttributeValue("cn", "Some Person4");
adapter.setAttributeValue("sn", "Person4");
@@ -106,6 +109,24 @@ public class LdapTemplateBindUnbindITest extends AbstractLdapTemplateIntegration
verifyCleanup();
}
+ @Test
+ public void testBindAndRebindWithDirContextAdapterOnly() {
+ DirContextAdapter adapter = new DirContextAdapter(
+ new DistinguishedName(DN));
+ adapter.setAttributeValues("objectclass", new String[] { "top",
+ "person" });
+ adapter.setAttributeValue("cn", "Some Person4");
+ adapter.setAttributeValue("sn", "Person4");
+
+ tested.bind(adapter);
+ verifyBoundCorrectData();
+ adapter.setAttributeValue("sn", "Person4.Changed");
+ tested.rebind(adapter);
+ verifyReboundCorrectData();
+ tested.unbind(DN);
+ verifyCleanup();
+ }
+
private Attributes setupAttributes() {
Attributes attributes = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
@@ -123,6 +144,12 @@ public class LdapTemplateBindUnbindITest extends AbstractLdapTemplateIntegration
assertEquals("Person4", result.getStringAttribute("sn"));
}
+ private void verifyReboundCorrectData() {
+ DirContextAdapter result = (DirContextAdapter) tested.lookup(DN);
+ assertEquals("Some Person4", result.getStringAttribute("cn"));
+ assertEquals("Person4.Changed", result.getStringAttribute("sn"));
+ }
+
private void verifyCleanup() {
try {
tested.lookup(DN);