LDAP-227: Now accepting classes annotated with subsets of actual objectclasses in tree.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
86
odm/src/test/java/org/springframework/ldap/odm/test/PlainPerson.java
Executable file
86
odm/src/test/java/org/springframework/ldap/odm/test/PlainPerson.java
Executable 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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user