Fix for LDAP-78: add lookupContext and alternate modifyAttributes in LdapOperations

This commit is contained in:
Mattias Arthursson
2007-09-07 12:43:15 +00:00
parent 0ff2ad6c56
commit 788154a8f8
3 changed files with 225 additions and 15 deletions

View File

@@ -24,6 +24,7 @@ import javax.naming.NameClassPair;
import javax.naming.directory.Attributes;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.spi.DirObjectFactory;
import org.springframework.ldap.ContextNotEmptyException;
import org.springframework.ldap.NamingException;
@@ -1017,34 +1018,30 @@ public interface LdapOperations {
throws NamingException;
/**
* Lookup the supplied DN and return the found object. <b>WARNING</b>: This
* method should only be used if a DirObjectFactory has been specified on
* the ContextFactory. If this is not the case, you will get a new instance
* of the actual DirContext, which is probably not what you want. If,
* however this <b>is</b> what you want, be careful to close the context
* after you finished working with it.
* Lookup the supplied DN and return the found object. This will typically
* be a {@link DirContextAdapter}, unless the DirObjectFactory has been
* modified in the ContextSource.
*
* @param dn
* The distinguished name of the object to find.
* @return the found object.
* @return the found object, typically a {@link DirContextAdapter} instance.
* @throws NamingException
* if any error occurs.
* @see #lookupContext(Name)
*/
public Object lookup(Name dn) throws NamingException;
/**
* Lookup the supplied DN and return the found object. <b>WARNING</b>: This
* method should only be used if a DirObjectFactory has been specified on
* the ContextFactory. If this is not the case, you will get a new instance
* of the actual DirContext, which is probably not what you want. If,
* however this <b>is</b> what you want, be careful to close the context
* after you finished working with it.
* Lookup the supplied DN and return the found object. This will typically
* be a {@link DirContextAdapter}, unless the DirObjectFactory has been
* modified in the ContextSource.
*
* @param dn
* The distinguished name of the object to find.
* @return the found object.
* @return the found object, typically a {@link DirContextAdapter} instance.
* @throws NamingException
* if any error occurs.
* @see #lookupContext(Name)
*/
public Object lookup(String dn) throws NamingException;
@@ -1366,4 +1363,77 @@ public interface LdapOperations {
*/
public void rename(final String oldDn, final String newDn)
throws NamingException;
/**
* Convenience method to lookup the supplied DN and automatically cast it to
* {@link DirContextOperations}.
*
* @param dn
* The distinguished name of the object to find.
* @return The found object, cast to {@link DirContextOperations}.
* @throws ClassCastException
* if an alternative DirObjectFactory has been registered woth
* the ContextSource, causing the actual class of the returned
* object to be something else than {@link DirContextOperations}.
* @throws NamingException
* if any other error occurs.
* @see #lookup(Name)
*/
public DirContextOperations lookupContext(Name dn) throws NamingException,
ClassCastException;
/**
* Convenience method to lookup the supplied DN and automatically cast it to
* {@link DirContextOperations}.
*
* @param dn
* The distinguished name of the object to find.
* @return The found object, cast to {@link DirContextOperations}.
* @throws ClassCastException
* if an alternative DirObjectFactory has been registered woth
* the ContextSource, causing the actual class of the returned
* object to be something else than {@link DirContextOperations}.
* @throws NamingException
* if any other error occurs.
* @see #lookup(String)
*/
public DirContextOperations lookupContext(String dn)
throws NamingException, ClassCastException;
/**
* Modify the attributes of the entry referenced by the supplied
* {@link DirContextOperations} instance. The DN to update will be the DN of
* the <code>DirContextOperations</code>instance, and the
* <code>ModificationItem</code> array is retrieved from the
* <code>DirContextOperations</code> instance using a call to
* {@link AttributeModificationsAware#getModificationItems()}. <b>NB:</b>
* The supplied instance needs to have been properly initialized; this means
* that if it hasn't been received from a <code>lookup</code> operation,
* its DN needs to be initialized and it must have been put in update mode ({@link DirContextAdapter#setUpdateMode(boolean)}).
* <p>
* Typical use of this method would be as follows:
*
* <pre>
* public void update(Person person) {
* DirContextOperations ctx = ldapOperations.lookupContext(person.getDn());
*
* ctx.setAttributeValue(&quot;description&quot;, person.getDescription());
* ctx.setAttributeValue(&quot;telephoneNumber&quot;, person.getPhone());
* // More modifications here
*
* ldapOperations.modifyAttributes(ctx);
* }
* </pre>
*
* @param ctx
* the DirContextOperations instance to use in the update.
* @throws IllegalStateException
* if the supplied instance is not in update mode or has not
* been properly initialized.
* @throws NamingException
* if any other error occurs.
*
*/
public void modifyAttributes(DirContextOperations ctx)
throws IllegalStateException, NamingException;
}

View File

@@ -1294,4 +1294,23 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
}
}
public DirContextOperations lookupContext(Name dn) {
return (DirContextOperations) lookup(dn);
}
public DirContextOperations lookupContext(String dn) {
return (DirContextOperations) lookup(dn);
}
public void modifyAttributes(DirContextOperations ctx) {
Name dn = ctx.getDn();
if (dn != null && ctx.isUpdateMode()) {
modifyAttributes(dn, ctx.getModificationItems());
} else {
throw new IllegalStateException(
"The DirContextOperations instance needs to be properly initialized.");
}
}
}

View File

@@ -82,6 +82,10 @@ public class LdapTemplateTest extends TestCase {
private DirContextProcessor dirContextProcessorMock;
private MockControl dirContextOperationsConrol;
private DirContextOperations dirContextOperationsMock;
protected void setUp() throws Exception {
super.setUp();
@@ -129,6 +133,11 @@ public class LdapTemplateTest extends TestCase {
dirContextProcessorMock = (DirContextProcessor) dirContextProcessorControl
.getMock();
dirContextOperationsConrol = MockControl
.createControl(DirContextOperations.class);
dirContextOperationsMock = (DirContextOperations) dirContextOperationsConrol
.getMock();
tested = new LdapTemplate(contextSourceMock);
}
@@ -164,6 +173,10 @@ public class LdapTemplateTest extends TestCase {
dirContextProcessorControl = null;
dirContextProcessorMock = null;
dirContextOperationsConrol = null;
dirContextOperationsMock = null;
}
protected void replay() {
@@ -177,6 +190,7 @@ public class LdapTemplateTest extends TestCase {
contextExecutorControl.replay();
searchExecutorControl.replay();
dirContextProcessorControl.replay();
dirContextOperationsConrol.replay();
}
protected void verify() {
@@ -190,6 +204,7 @@ public class LdapTemplateTest extends TestCase {
contextExecutorControl.verify();
searchExecutorControl.verify();
dirContextProcessorControl.verify();
dirContextOperationsConrol.verify();
}
private void expectGetReadWriteContext() {
@@ -1584,7 +1599,8 @@ public class LdapTemplateTest extends TestCase {
expectGetReadOnlyContext();
searchExecutorControl.expectAndThrow(searchExecutorMock
.executeSearch(dirContextMock), new javax.naming.NameNotFoundException());
.executeSearch(dirContextMock),
new javax.naming.NameNotFoundException());
dirContextMock.close();
replay();
@@ -1639,6 +1655,111 @@ public class LdapTemplateTest extends TestCase {
verify();
}
public void testLookupContextWithName() {
final DirContextAdapter expectedResult = new DirContextAdapter();
LdapTemplate tested = new LdapTemplate() {
public Object lookup(Name dn) {
assertSame(DistinguishedName.EMPTY_PATH, dn);
return expectedResult;
}
};
DirContextOperations result = tested
.lookupContext(DistinguishedName.EMPTY_PATH);
assertSame(expectedResult, result);
}
public void testLookupContextWithString() {
final DirContextAdapter expectedResult = new DirContextAdapter();
final String expectedName = "cn=John Doe";
LdapTemplate tested = new LdapTemplate() {
public Object lookup(String dn) {
assertSame(expectedName, dn);
return expectedResult;
}
};
DirContextOperations result = tested.lookupContext(expectedName);
assertSame(expectedResult, result);
}
public void testModifyAttributesWithDirContextOperations() throws Exception {
final ModificationItem[] expectedModifications = new ModificationItem[0];
dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
.getDn(), DistinguishedName.EMPTY_PATH);
dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
.isUpdateMode(), true);
dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
.getModificationItems(), expectedModifications);
LdapTemplate tested = new LdapTemplate() {
public void modifyAttributes(Name dn, ModificationItem[] mods) {
assertSame(DistinguishedName.EMPTY_PATH, dn);
assertSame(expectedModifications, mods);
}
};
replay();
tested.modifyAttributes(dirContextOperationsMock);
verify();
}
public void testModifyAttributesWithDirContextOperationsNotInitializedDn()
throws Exception {
final ModificationItem[] expectedModifications = new ModificationItem[0];
dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
.getDn(), DistinguishedName.EMPTY_PATH);
dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
.isUpdateMode(), false);
LdapTemplate tested = new LdapTemplate() {
public void modifyAttributes(Name dn, ModificationItem[] mods) {
fail("The call to the base modifyAttributes should not have occured.");
}
};
replay();
try {
tested.modifyAttributes(dirContextOperationsMock);
fail("IllegalStateException expected");
} catch (IllegalStateException expected) {
assertTrue(true);
}
verify();
}
public void testModifyAttributesWithDirContextOperationsNotInitializedInUpdateMode()
throws Exception {
final ModificationItem[] expectedModifications = new ModificationItem[0];
dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock
.getDn(), null);
LdapTemplate tested = new LdapTemplate() {
public void modifyAttributes(Name dn, ModificationItem[] mods) {
fail("The call to the base modifyAttributes should not have occured.");
}
};
replay();
try {
tested.modifyAttributes(dirContextOperationsMock);
fail("IllegalStateException expected");
} catch (IllegalStateException expected) {
assertTrue(true);
}
verify();
}
/**
* Needed to verify search control values.
*