LDAP-227: Now accepting classes annotated with subsets of actual objectclasses in tree.

This commit is contained in:
Mattias Hellborg Arthursson
2013-08-15 11:40:41 +02:00
parent fdf3ed7654
commit 2aa37a975a
6 changed files with 154 additions and 42 deletions

View File

@@ -158,7 +158,7 @@ public final class OdmManagerImpl implements OdmManager {
T result = clazz.cast(ldapTemplate.lookup(dn, new GenericContextMapper<T>(clazz)));
if (result==null) {
throw new OdmException(String.format("Entry %1$s has excess object classes", dn));
throw new OdmException(String.format("Entry %1$s does not have the required objectclasses ", dn));
}
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Found entry - %s$1", result));
@@ -280,16 +280,21 @@ public final class OdmManagerImpl implements OdmManager {
*/
private void mapToContext(Object entry, DirContextOperations context) {
ObjectMetaData metaData=getEntityData(entry.getClass()).metaData;
// Object classes are set from the metadata obtained from the @Entity annotation
int numOcs=metaData.getObjectClasses().size();
CaseIgnoreString[] metaDataObjectClasses=metaData.getObjectClasses().toArray(new CaseIgnoreString[numOcs]);
String[] stringOcs=new String[numOcs];
for (int ocIndex=0; ocIndex<numOcs; ocIndex++) {
stringOcs[ocIndex]=metaDataObjectClasses[ocIndex].toString();
Attribute objectclassAttribute = context.getAttributes().get(OBJECT_CLASS_ATTRIBUTE);
if(objectclassAttribute == null || objectclassAttribute.size() == 0) {
// Object classes are set from the metadata obtained from the @Entity annotation,
// but only if this is a new entry.
int numOcs=metaData.getObjectClasses().size();
CaseIgnoreString[] metaDataObjectClasses=metaData.getObjectClasses().toArray(new CaseIgnoreString[numOcs]);
String[] stringOcs=new String[numOcs];
for (int ocIndex=0; ocIndex<numOcs; ocIndex++) {
stringOcs[ocIndex]=metaDataObjectClasses[ocIndex].toString();
}
context.setAttributeValues(OBJECT_CLASS_ATTRIBUTE, stringOcs);
}
context.setAttributeValues(OBJECT_CLASS_ATTRIBUTE, stringOcs);
// Loop through each of the fields in the object to write to LDAP
for (Field field : metaData) {
@@ -446,11 +451,9 @@ public final class OdmManagerImpl implements OdmManager {
objectClassesFromJndi.add(new CaseIgnoreString((String)objectClassesFromJndiEnum.nextElement()));
}
// OK - checks its the same as the meta-data we have
if (!objectClassesFromJndi.equals(metaData.getObjectClasses())) {
// The items found has classes in addition to those searched for - so ditch it
if(!collectionContainsAll(objectClassesFromJndi, metaData.getObjectClasses())) {
return null;
}
} else {
throw new InvalidEntryException(String.format("No object classes were returned for class %1$s",
managedClass.getName()));
@@ -474,4 +477,14 @@ public final class OdmManagerImpl implements OdmManager {
}
}
static boolean collectionContainsAll(Collection<?> collection, Set<?> shouldBePresent) {
for (Object o : shouldBePresent) {
if(!collection.contains(o)) {
return false;
}
}
return true;
}
}

View File

@@ -25,10 +25,10 @@ public final class Person {
this.telephoneNumber = telephoneNumber;
this.jpegPhoto = jpegPhoto;
objectClasses = new ArrayList<String>();
objectClasses.add("top");
objectClasses.add("person");
objectClasses.add("organizationalPerson");
objectClasses.add("inetOrgPerson");
objectClasses.add("organizationalPerson");
objectClasses.add("person");
objectClasses.add("top");
int size = dn.size();
if (size > 1) {
cn = dn.get(size - 1).split("=")[1];
@@ -176,7 +176,7 @@ public final class Person {
if (objectClasses == null) {
if (other.objectClasses != null)
return false;
} else if (desc.size()!=other.desc.size() || !(new HashSet<String>(objectClasses)).equals(new HashSet<String>(other.objectClasses)))
} else if (objectClasses.size()!=other.objectClasses.size() || !(new HashSet<String>(objectClasses)).equals(new HashSet<String>(other.objectClasses)))
return false;
if (someRandomField == null) {
if (other.someRandomField != null)

View File

@@ -0,0 +1,86 @@
package org.springframework.ldap.odm.test;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import javax.naming.Name;
import java.util.ArrayList;
import java.util.List;
// Simple LDAP entry for testing
@Entry(objectClasses = { "person", "top" })
public final class PlainPerson {
public PlainPerson() {
}
public PlainPerson(Name dn, String commonName, String surname) {
this.dn = dn;
this.surname = surname;
objectClasses = new ArrayList<String>();
objectClasses.add("top");
objectClasses.add("person");
cn = commonName;
}
@Attribute(name = "objectClass")
private List<String> objectClasses;
@Id
private Name dn;
@Attribute(name = "cn")
private String cn;
@Attribute(name = "sn")
private String surname;
public Name getDn() {
return dn;
}
public void setDn(Name dn) {
this.dn = dn;
}
public String getCn() {
return cn;
}
public void setCn(String cn) {
this.cn = cn;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlainPerson that = (PlainPerson) o;
if (cn != null ? !cn.equals(that.cn) : that.cn != null) return false;
if (dn != null ? !dn.equals(that.dn) : that.dn != null) return false;
if (objectClasses != null ? !objectClasses.equals(that.objectClasses) : that.objectClasses != null)
return false;
if (surname != null ? !surname.equals(that.surname) : that.surname != null) return false;
return true;
}
@Override
public int hashCode() {
int result = objectClasses != null ? objectClasses.hashCode() : 0;
result = 31 * result + (dn != null ? dn.hashCode() : 0);
result = 31 * result + (cn != null ? cn.hashCode() : 0);
result = 31 * result + (surname != null ? surname.hashCode() : 0);
return result;
}
}

View File

@@ -36,6 +36,7 @@ import org.springframework.ldap.odm.typeconversion.impl.ConverterManagerImpl;
import org.springframework.ldap.odm.typeconversion.impl.converters.FromStringConverter;
import org.springframework.ldap.odm.typeconversion.impl.converters.ToStringConverter;
import org.springframework.ldap.test.LdapTestUtils;
import org.springframework.util.CollectionUtils;
import javax.naming.Name;
import javax.naming.directory.SearchControls;
@@ -48,6 +49,7 @@ import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
// Tests all OdmManager functions
public final class TestLdap {
@@ -170,6 +172,7 @@ public final class TestLdap {
// Create our OdmManager
Set<Class<?>> managedClasses=new HashSet<Class<?>>();
managedClasses.add(Person.class);
managedClasses.add(PlainPerson.class);
managedClasses.add(OrganizationalUnit.class);
odmManager = new OdmManagerImpl(converterManager, contextSource, managedClasses);
}
@@ -323,6 +326,38 @@ public final class TestLdap {
assertEquals(new HashSet<Person>(Arrays.asList(personTestData)), new HashSet<Person>(allPeople));
}
@Test
public void findAllAsPlainPersons() {
List<PlainPerson> allPeople = odmManager.findAll(PlainPerson.class, baseName, searchControls);
assertEquals(9, allPeople.size());
assertFalse("No nulls should have been returned", CollectionUtils.containsInstance(allPeople, null));
}
@Test
public void verifySearchOnPlainPerson() {
List<PlainPerson> result = odmManager.search(PlainPerson.class, baseName, "(cn=William Hartnell)", searchControls);
assertEquals(1, result.size());
PlainPerson foundPerson = result.get(0);
assertEquals("William Hartnell", foundPerson.getCn());
assertEquals("Hartnell", foundPerson.getSurname());
}
@Test
public void updatePlainPerson() {
List<PlainPerson> result = odmManager.search(PlainPerson.class, baseName, "(cn=William Hartnell)", searchControls);
assertEquals(1, result.size());
PlainPerson foundPerson = result.get(0);
foundPerson.setSurname("Tjolahopp");
odmManager.update(foundPerson);
// Verify that the objectclass was not changed on the target object
List<Person> updatedResult = odmManager.search(Person.class, baseName, "(cn=William Hartnell)", searchControls);
assertEquals(1, updatedResult.size());
}
private Person[] createTestData = {
new Person(new DistinguishedName("cn=Colin Baker,ou=Doctors,o=Whoniverse"), "Baker", Arrays
.asList(new String[] { "Sixth Doctor" }), 6, null),
@@ -390,8 +425,8 @@ public final class TestLdap {
// Read an entry with classes in addition to those supported by the Entry
@Test(expected = OdmException.class)
public void readAdditionalObjectClasses() throws Exception {
odmManager.read(Person.class, new DistinguishedName("cn=Paul Harvey,ou=Doctors,o=Whoniverse"));
public void readNonMatchingObjectclasses() throws Exception {
odmManager.read(Person.class, new DistinguishedName("ou=Doctors,o=Whoniverse"));
}
private final static class NoEntry {
@@ -516,7 +551,7 @@ public final class TestLdap {
// The OdmManager should flag any attempt to use a "unmanaged" class
@Test(expected = UnmanagedClassException.class)
public void unManagedClass() {
((OdmManagerImpl)odmManager).read(Integer.class, baseName);
odmManager.read(Integer.class, baseName);
}
@Test

View File

@@ -73,17 +73,6 @@ description: Fifth Doctor
sn: Davison
telephonenumber: 5
dn: cn=Paul Harvey,ou=Doctors,o=Whoniverse
objectClass: person
objectClass: inetorgperson
objectclass: organizationalperson
objectClass: top
objectClass: userSecurityInformation
cn: Paul Harvey
description: Not a Doctor
sn: Harvey
telephonenumber: 11
dn: cn=Bramble Harvey,ou=Doctors,o=Whoniverse
objectClass: person
objectClass: top

View File

@@ -67,17 +67,6 @@ description: Fifth Doctor
sn: Davison
telephonenumber: 5
dn: cn=Paul Harvey,ou=Doctors,o=Whoniverse
objectClass: person
objectClass: inetorgperson
objectclass: organizationalperson
objectClass: top
objectClass: userSecurityInformation
cn: Paul Harvey
description: Not a Doctor
sn: Harvey
telephonenumber: 11
dn: cn=Bramble Harvey,ou=Doctors,o=Whoniverse
objectClass: person
objectClass: top