diff --git a/spring-ldap-odm/build.xml b/spring-ldap-odm/build.xml
index 280ce466..3fcce091 100644
--- a/spring-ldap-odm/build.xml
+++ b/spring-ldap-odm/build.xml
@@ -19,7 +19,7 @@
-
+
@@ -31,7 +31,8 @@
-->
-
@@ -42,7 +43,7 @@
we want to optionally run all tests and report on the whole
batch, then we need to set a failure property as in the server
tests. -->
-
+
@@ -64,7 +65,7 @@
-
+
@@ -82,4 +83,13 @@ The HTML report is ${target.testresults.html.dir}/index.html
+
+
+
+
+
+
+
+
+
diff --git a/spring-ldap-odm/ivy.xml b/spring-ldap-odm/ivy.xml
index 8c617626..e8a32357 100644
--- a/spring-ldap-odm/ivy.xml
+++ b/spring-ldap-odm/ivy.xml
@@ -22,7 +22,7 @@
-
+
@@ -31,14 +31,14 @@
-
+
-
-
-
-
-
+
+
+
+
+
@@ -48,9 +48,11 @@
-
-
-
+
+
+
+
+
-
+
@@ -91,5 +93,5 @@
-
+
diff --git a/spring-ldap-odm/src/itest/java/conf/apacheDsContext.xml b/spring-ldap-odm/src/itest/java/conf/apacheDsContext.xml
new file mode 100644
index 00000000..80910e7e
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/conf/apacheDsContext.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+ simple
+
+
+ ${userDn}
+
+
+ ${password}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ objectClass: top
+ objectClass: domain
+ objectClass: extensibleObject
+ dc: example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-ldap-odm/src/itest/java/conf/beans.xml b/spring-ldap-odm/src/itest/java/conf/beans.xml
index 8f84cd19..f74961c4 100644
--- a/spring-ldap-odm/src/itest/java/conf/beans.xml
+++ b/spring-ldap-odm/src/itest/java/conf/beans.xml
@@ -2,12 +2,20 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-ldap-odm/src/itest/java/conf/ldap.properties b/spring-ldap-odm/src/itest/java/conf/ldap.properties
new file mode 100644
index 00000000..a0bbef1a
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/conf/ldap.properties
@@ -0,0 +1,4 @@
+urls=ldap://127.0.0.1:3900
+userDn=uid=admin,ou=system
+password=secret
+base=dc=example,dc=com
diff --git a/spring-ldap-odm/src/itest/java/conf/log4j.xml b/spring-ldap-odm/src/itest/java/conf/log4j.xml
new file mode 100644
index 00000000..23d78f02
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/conf/log4j.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-ldap-odm/src/itest/java/conf/setup_data.ldif b/spring-ldap-odm/src/itest/java/conf/setup_data.ldif
new file mode 100644
index 00000000..560cffb9
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/conf/setup_data.ldif
@@ -0,0 +1,19 @@
+dn: ou=people,dc=example,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: ou=roles,dc=example,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: roles
+
+dn: cn=webUser,ou=roles,dc=example,dc=com
+objectclass: top
+objectclass: organizationalRole
+cn: webUser
+description: Everyday site visitor
+
+
+
+
diff --git a/spring-ldap-odm/src/itest/java/conf/teardown_data.ldif b/spring-ldap-odm/src/itest/java/conf/teardown_data.ldif
new file mode 100644
index 00000000..16f41052
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/conf/teardown_data.ldif
@@ -0,0 +1,9 @@
+dn: ou=people,dc=example,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: ou=roles,dc=example,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: roles
\ No newline at end of file
diff --git a/spring-ldap-odm/src/itest/java/org/springframework/ldap/AbstractLdapTemplateIntegrationTest.java b/spring-ldap-odm/src/itest/java/org/springframework/ldap/AbstractLdapTemplateIntegrationTest.java
new file mode 100644
index 00000000..96b309b8
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/org/springframework/ldap/AbstractLdapTemplateIntegrationTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2005-2007 the original author or authors.
+ *
+ * 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.springframework.ldap;
+
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+public abstract class AbstractLdapTemplateIntegrationTest extends
+ AbstractDependencyInjectionSpringContextTests {
+
+ private LdapServerManager ldapServerManager;
+
+ protected void onSetUp() throws Exception {
+ super.onSetUp();
+
+ ldapServerManager.cleanAndSetup("setup_data.ldif");
+ }
+
+ public void setLdapServerManager(LdapServerManager ldapServerManager) {
+ this.ldapServerManager = ldapServerManager;
+ }
+}
diff --git a/spring-ldap-odm/src/itest/java/org/springframework/ldap/ConfigEnvHelper.java b/spring-ldap-odm/src/itest/java/org/springframework/ldap/ConfigEnvHelper.java
new file mode 100644
index 00000000..9fd2034b
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/org/springframework/ldap/ConfigEnvHelper.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2005-2007 the original author or authors.
+ *
+ * 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.springframework.ldap;
+
+import java.io.File;
+import java.util.Hashtable;
+
+import javax.naming.Context;
+
+import org.apache.directory.server.configuration.MutableServerStartupConfiguration;
+import org.apache.directory.server.jndi.ServerContextFactory;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * Helper class to simplify Spring configuration of ApacheDS.
+ *
+ * @author Mattias Arthursson
+ */
+public class ConfigEnvHelper implements InitializingBean {
+ private final MutableServerStartupConfiguration configuration;
+
+ private final Hashtable initialEnv;
+
+ private final File workingDir = new File(System
+ .getProperty("java.io.tmpdir")
+ + File.separator + "ldaptemplate_apacheds");
+
+ public ConfigEnvHelper(Hashtable initialEnv,
+ MutableServerStartupConfiguration configuration) {
+
+ this.initialEnv = initialEnv;
+ this.configuration = configuration;
+ }
+
+ public Hashtable getEnv() {
+ return initialEnv;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ initialEnv.put(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName());
+ configuration.setWorkingDirectory(workingDir);
+ initialEnv.putAll(configuration.toJndiEnvironment());
+ }
+}
diff --git a/spring-ldap-odm/src/itest/java/org/springframework/ldap/LdapServerManager.java b/spring-ldap-odm/src/itest/java/org/springframework/ldap/LdapServerManager.java
new file mode 100644
index 00000000..df62b00a
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/org/springframework/ldap/LdapServerManager.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2005-2007 the original author or authors.
+ *
+ * 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.springframework.ldap;
+
+import java.util.Properties;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.ContextNotEmptyException;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.directory.server.core.configuration.ShutdownConfiguration;
+import org.apache.directory.server.jndi.ServerContextFactory;
+import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.ldap.core.ContextSource;
+import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.ldap.core.support.DefaultDirObjectFactory;
+
+/**
+ * Utility class to initialize the apache directory server for use in the
+ * integration tests.
+ *
+ * @author Mattias Arthursson
+ *
+ */
+public class LdapServerManager implements DisposableBean {
+ private static Log log = LogFactory.getLog(LdapServerManager.class);
+
+ private ContextSource contextSource;
+
+ public void setContextSource(ContextSource contextSource) {
+ this.contextSource = contextSource;
+ }
+
+ public void destroy() throws Exception {
+ Properties env = new Properties();
+ env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+ ServerContextFactory.class.getName());
+ env.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
+ env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
+ env.setProperty(Context.SECURITY_CREDENTIALS, "secret");
+
+ ShutdownConfiguration configuration = new ShutdownConfiguration();
+ env.putAll(configuration.toJndiEnvironment());
+
+ new InitialContext(env);
+ }
+
+ public void cleanAndSetup(String ldifFile) throws Exception {
+ DirContext ctx = contextSource.getReadWriteContext();
+
+ // First of all, make sure the database is empty.
+ Name startingPoint = null;
+
+ // Different test cases have different base paths. This means that the
+ // starting point will be different.
+ if (ctx.getEnvironment().get(
+ DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY) != null) {
+ startingPoint = DistinguishedName.EMPTY_PATH;
+ } else {
+ startingPoint = new DistinguishedName("dc=jayway,dc=se");
+ }
+
+ try {
+ log.info("Cleaning all present data.");
+ clearSubContexts(ctx, startingPoint);
+ // Load the ldif to the recently started server
+ log.info("Loading setup data");
+ LdifFileLoader loader = new LdifFileLoader(ctx, ldifFile);
+ loader.execute();
+ } finally {
+ ctx.close();
+ }
+ }
+
+ private void clearSubContexts(DirContext ctx, Name name)
+ throws NamingException {
+
+ NamingEnumeration enumeration = null;
+ try {
+ enumeration = ctx.listBindings(name);
+ while (enumeration.hasMore()) {
+ Binding element = (Binding) enumeration.next();
+ DistinguishedName childName = new DistinguishedName(element
+ .getName());
+ childName.prepend((DistinguishedName) name);
+
+ try {
+ ctx.destroySubcontext(childName);
+ } catch (ContextNotEmptyException e) {
+ clearSubContexts(ctx, childName);
+ ctx.destroySubcontext(childName);
+ }
+ }
+ } catch (NamingException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ enumeration.close();
+ } catch (Exception e) {
+ // Never mind this
+ }
+ }
+ }
+}
diff --git a/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/contextmapping/AnnotationObjectDirectoryMapperTest.java b/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/contextmapping/AnnotationObjectDirectoryMapperTest.java
new file mode 100644
index 00000000..b29ba35e
--- /dev/null
+++ b/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/contextmapping/AnnotationObjectDirectoryMapperTest.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2006 by Majitek. All Rights Reserved.
+ *
+ * This software is the proprietary information of Majitek. Use is subject to license terms.
+ */
+package org.springframework.ldap.odm.contextmapping;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.ldap.core.DirContextAdapter;
+import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.ldap.odm.annotations.DirAttribute;
+import org.springframework.ldap.odm.annotations.NamingAttribute;
+import org.springframework.ldap.odm.annotations.NamingSuffix;
+import org.springframework.ldap.odm.annotations.ObjectClasses;
+import org.springframework.ldap.odm.attributetypes.LdapTypeConverter;
+import org.springframework.ldap.odm.attributetypes.ReferencedEntryEditorFactory;
+import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
+import org.springframework.ldap.odm.entity.MockEntity;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+import org.testng.Assert;
+
+import javax.naming.Name;
+import java.util.Date;
+import java.util.Map;
+
+public class AnnotationObjectDirectoryMapperTest extends
+ AbstractDependencyInjectionSpringContextTests
+{
+ private static final Log LOGGER = LogFactory
+ .getLog(AnnotationObjectDirectoryMapperTest.class);
+
+ private LdapTypeConverter typeConverter;
+
+ private ReferencedEntryEditorFactory refEditorFactory;
+
+ public void setRefEditorFactory(
+ ReferencedEntryEditorFactory refEditorFactory)
+ {
+ this.refEditorFactory = refEditorFactory;
+ }
+
+ public void setTypeConverter(LdapTypeConverter typeConverter)
+ {
+ this.typeConverter = typeConverter;
+ }
+
+ @Override
+ protected String[] getConfigLocations()
+ {
+ return new String[]{"conf/beans.xml"};
+ }
+
+ public void testMapsDirectoryAttributesToBeanProperties()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockEntity.class, typeConverter, refEditorFactory);
+ ContextMap contextMap = contextMapper.getContextMap();
+ Assert.assertEquals("cn", contextMap.attributeNameFor("Name"),
+ "Name mapping not as expected");
+ Assert.assertEquals("mail", contextMap.attributeNameFor("Mail"),
+ "Mail mapping not as expected");
+ Assert.assertEquals("addr", contextMap.attributeNameFor("Address"),
+ "Address mapping not as expected");
+ Assert.assertEquals("userpassword", contextMap
+ .attributeNameFor("Password"),
+ "Password mapping not as expected");
+ Assert.assertEquals("desc", contextMap
+ .attributeNameFor("Description"),
+ "Description mapping not as expected");
+ }
+ catch (ContextMapperException e)
+ {
+ LOGGER.debug(e.getMessage());
+ Assert.fail(e.getMessage(), e);
+ }
+ }
+
+ public void testReturnsCorrectNamingAttribute()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockEntity.class, typeConverter, refEditorFactory);
+ Assert.assertEquals("cn", contextMapper.getNamingAttribute(),
+ "Context mapper naming attribute not as expected");
+
+ }
+ catch (ContextMapperException e)
+ {
+ LOGGER.debug(e.getMessage());
+ Assert.fail(e.getMessage(), e);
+ }
+ }
+
+ public void testReturnsCorrectObjectClasses()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockEntity.class, typeConverter, refEditorFactory);
+ Assert.assertEquals(new String[]{"top", "person",
+ "organizationalPerson", "inetorgperson"}, contextMapper
+ .getObjectClasses(),
+ "Context mapper naming attribute not as expected");
+
+ }
+ catch (ContextMapperException e)
+ {
+ LOGGER.debug(e.getMessage());
+ Assert.fail(e.getMessage());
+ }
+ }
+
+ public void testBuildDn()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockEntity.class, typeConverter, refEditorFactory);
+ MockEntity entity = new MockEntity();
+ entity.setName("Mr Bean");
+ entity.setAddress("Somewhere in england");
+ entity.setDescription(new String[]{"The quick brown fox jumped",
+ "over the lazy dog"});
+ Name dn = contextMapper.buildDn(entity);
+ Assert.assertEquals("cn=Mr Bean, ou=people, dc=example, dc=com", dn
+ .toString(), "dn not as expected");
+
+ }
+ catch (ContextMapperException e)
+ {
+ LOGGER.debug(e.getMessage());
+ Assert.fail(e.getMessage());
+ }
+ }
+
+ public void testMapToContext()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockEntity.class, typeConverter, refEditorFactory);
+ MockEntity entity = new MockEntity();
+ entity.setName("Mr Bean");
+ entity.setMail("bean@bean.com");
+ entity.setAddress("Somewhere in england");
+ entity.setPassword("fred".getBytes());
+ entity.setDescription(new String[]{"The quick brown fox jumped",
+ "over the lazy dog"});
+ entity.setAcceptEmails(false);
+ entity.setResetLogin(new Date(1L));
+ entity.setCreator(new DistinguishedName(
+ "uid=amAdmin,ou=people,dc=myretsu,dc=com"));
+ entity.setFailedLogins(3);
+ DirContextAdapter ctxAdapter = new DirContextAdapter();
+ contextMapper.mapToContext(entity, ctxAdapter);
+
+ Assert.assertEquals("Mr Bean", ctxAdapter.getStringAttribute("cn"),
+ "Name mapping not as expected");
+ Assert
+ .assertEquals("bean@bean.com", ctxAdapter
+ .getStringAttribute("mail"),
+ "Mail mapping not as expected");
+ Assert.assertEquals("Somewhere in england", ctxAdapter
+ .getObjectAttribute("addr"),
+ "Address mapping not as expected");
+ Assert.assertEquals("fred", new String((byte[]) ctxAdapter
+ .getObjectAttribute("userpassword")),
+ "Password mapping not as expected");
+ Assert.assertEquals("The quick brown fox jumped", ctxAdapter
+ .getStringAttributes("desc")[0],
+ "Description mapping not as expected");
+ Assert.assertEquals("false", ctxAdapter
+ .getStringAttribute("acceptemails"),
+ "AcceptEmails mapping not as expected");
+ Assert.assertEquals("19700101100000.1", ctxAdapter
+ .getStringAttribute("loginresettime"),
+ "ResetLogin mapping not as expected");
+ Assert.assertEquals("3", ctxAdapter
+ .getStringAttribute("failedlogins"),
+ "FailedLogins mapping not as expected");
+ Assert.assertEquals("uid=amAdmin, ou=people, dc=myretsu, dc=com",
+ ctxAdapter.getStringAttribute("creatorname"),
+ "Creator mapping not as expected");
+ }
+ catch (ContextMapperException e)
+ {
+ LOGGER.debug(e.getMessage());
+ Assert.fail(e.getMessage(), e);
+ }
+ }
+
+ public void testMapFromContext() throws ContextMapperException
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockEntity.class, typeConverter, refEditorFactory);
+ DirContextAdapter ctxAdapter = new DirContextAdapter();
+ ctxAdapter.setAttributeValue("cn", "Mr Bean");
+ ctxAdapter.setAttributeValue("mail", "bean@bean.com");
+ ctxAdapter.setAttributeValue("addr", "Somewhere in england");
+ ctxAdapter.setAttributeValue("userpassword", "fred".getBytes());
+ ctxAdapter
+ .setAttributeValues("desc", new String[]{"elem1", "elem2"});
+ ctxAdapter.setAttributeValue("userpassword", "fred".getBytes());
+ ctxAdapter.setAttributeValue("acceptemails", "true");
+ ctxAdapter.setAttributeValue("loginresettime", "19700101100000.1");
+ ctxAdapter.setAttributeValue("failedlogins", "3");
+ ctxAdapter.setAttributeValue("creatorname",
+ "uid=amAdmin,ou=people,dc=myretsu,dc=com");
+
+ MockEntity entity = (MockEntity) contextMapper
+ .mapFromContext(ctxAdapter);
+ Assert.assertEquals(entity.getMail(), "bean@bean.com",
+ "The mocked entity should match what has been mapped");
+ Assert.assertEquals("Mr Bean", entity.getName(),
+ "Name mapping not as expected");
+ Assert.assertEquals(entity.getMail(), "bean@bean.com",
+ "Mail mapping not as expected");
+ Assert.assertEquals(entity.getAddress(), "Somewhere in england",
+ "Address mapping not as expected");
+ Assert.assertEquals("fred", new String(entity.getPassword()),
+ "Password mapping not as expected");
+ Assert.assertEquals("elem1", entity.getDescription()[0],
+ "Description mapping not as expected");
+ Assert.assertEquals(Boolean.TRUE, entity.getAcceptEmails(),
+ "AcceptEmails mapping not as expected");
+ Assert.assertEquals(new Date(1L), entity.getResetLogin(),
+ "ResetLogin mapping not as expected");
+ Assert.assertEquals(new Integer(3), entity.getFailedLogins(),
+ "FailedLogin mapping not as expected");
+ Assert.assertEquals(new DistinguishedName(
+ "uid=amAdmin,ou=people,dc=myretsu,dc=com"),
+ entity.getCreator(), "Creator mapping not as expected");
+
+ }
+
+
+ public void testThrowsExceptionWhenNamingSuffixHasSyntaxError()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockModelNamingSuffixSyntaxError.class, typeConverter,
+ refEditorFactory);
+ Assert.fail(
+ "AnnotationObjectDirectoryMapper should throw an exception when naming " +
+ "path annotation syntax is incorrect.");
+ }
+ catch (ContextMapperException e)
+ {
+ //pass
+ }
+
+ }
+
+
+ public void testThrowsExceptionWhenNamingSuffixNotInSeparateElements()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockModelNamingSuffixNotInSeparateElements.class,
+ typeConverter, refEditorFactory);
+ Assert.fail("AnnotationObjectDirectoryMapper should throw an exception when naming" +
+ " path annotation syntax is incorrect.");
+ }
+ catch (ContextMapperException e)
+ {
+ //pass
+ }
+ }
+
+
+ public void testThrowsExceptionWhenModelObjectMissingGetterOrSetter()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockModelMissingSetter.class, typeConverter, refEditorFactory);
+ Assert.fail("Should've thrown exception due to missing getter/setter");
+ }
+ catch (ContextMapperException e)
+ {
+ //pass
+ }
+
+ }
+
+
+ public void testThrowsExceptionWhenBeanPropertyNotAValidTranslationType()
+ {
+ try
+ {
+ AnnotationObjectDirectoryMapper contextMapper = new AnnotationObjectDirectoryMapper(
+ MockModelInvalidTranslationType.class, typeConverter,
+ refEditorFactory);
+ Assert.fail("Should've thrown exception due to missing getter/setter");
+ }
+ catch (ContextMapperException e)
+ {
+ Assert.assertTrue(e.getMessage().contains(
+ "MockModelInvalidTranslationType.getMap() has invalid return type"));
+ }
+
+ }
+
+ @NamingAttribute("cn")
+ @NamingSuffix({"ou=people", "dc=example", "dc=com"})
+ @ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
+ public class MockModelMissingSetter
+ {
+ @DirAttribute("cn")
+ private String name;
+
+ @DirAttribute("addr")
+ private String address;
+
+ @DirAttribute("mail")
+ private String mail;
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getAddress()
+ {
+ return address;
+ }
+
+ public String getMail()
+ {
+ return mail;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public void setAddress(String address)
+ {
+ this.address = address;
+ }
+ }
+
+ @NamingAttribute("cn")
+ @NamingSuffix({"ou=people", "dc=example", "dc=com"})
+ @ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
+ public class MockModelBadMethodName
+ {
+
+ @DirAttribute("cn")
+ private String name;
+
+ @DirAttribute("addr")
+ private String address;
+
+ public String zzzName()
+ {
+ return name;
+ }
+
+ public String getAddress()
+ {
+ return address;
+ }
+ }
+
+ @NamingAttribute("cn")
+ @NamingSuffix({"ou=people,dc=example ,dc=com"})
+ @ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
+ public class MockModelNamingSuffixNotInSeparateElements
+ {
+ }
+
+ @NamingAttribute("cn")
+ @NamingSuffix({"ou=people", "dc 0);
}
- @Test(groups = "LdapDao")
- public void filterByBeanProperty()
+ public void testFilterByBeanProperty()
{
ldapDao.create(testPerson);
List results = ldapDao.filterByBeanProperty(testPerson.getEmailAddress(), "EmailAddress", TestPerson.class);
@@ -156,9 +144,7 @@ public class LdapDaoTest
Assert.assertTrue(results.size() > 0, "Filter should return collection containing more than one result. ");
}
-
- @Test(groups = "LdapDao")
- public void updateEntity()
+ public void testUpdateEntity()
{
try
{
@@ -176,9 +162,7 @@ public class LdapDaoTest
}
}
-
- @Test(groups = "LdapDao")
- public void updateEntityThrowsExceptionWhenNameNotBound()
+ public void testUpdateEntityThrowsExceptionWhenNameNotBound()
{
try
{
@@ -187,15 +171,13 @@ public class LdapDaoTest
ldapDao.update(testPerson);
Assert.fail("Should've failed since the entry doesn't exist");
}
- catch (EntryNotFoundException e)
+ catch (Exception e)
{
- Assert.assertTrue(e instanceof EntryNotFoundException);
- Assert.assertTrue(e.getMessage().contains("Entry not found"), "Error message not as expected.");
+ Assert.assertTrue(e instanceof NameNotFoundException);
}
}
- @Test(groups = "LdapDao")
- public void deleteEntity()
+ public void testDeleteEntity()
{
ldapDao.create(testPerson);
LOGGER.debug(testPerson);
diff --git a/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/MockEntity.java b/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/MockEntity.java
index 968b7039..40b1025e 100644
--- a/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/MockEntity.java
+++ b/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/MockEntity.java
@@ -5,14 +5,14 @@
*/
package org.springframework.ldap.odm.entity;
-import java.util.Date;
-
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.odm.annotations.DirAttribute;
import org.springframework.ldap.odm.annotations.NamingAttribute;
import org.springframework.ldap.odm.annotations.NamingSuffix;
import org.springframework.ldap.odm.annotations.ObjectClasses;
+import java.util.Date;
+
@NamingAttribute("cn")
@NamingSuffix({"ou = people", "dc = example", "dc=com"})
@ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
diff --git a/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/TestPerson.java b/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/TestPerson.java
index bdc066ae..80ce264b 100644
--- a/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/TestPerson.java
+++ b/spring-ldap-odm/src/itest/java/org/springframework/ldap/odm/entity/TestPerson.java
@@ -9,13 +9,14 @@ import org.springframework.ldap.odm.annotations.DirAttribute;
import org.springframework.ldap.odm.annotations.NamingAttribute;
import org.springframework.ldap.odm.annotations.NamingSuffix;
import org.springframework.ldap.odm.annotations.ObjectClasses;
+import org.apache.commons.lang.builder.EqualsBuilder;
import com.thoughtworks.xstream.XStream;
@NamingAttribute("uid")
@NamingSuffix({"ou=people"})
-@ObjectClasses({"top", "person", "organizationalPerson", "inetorgperson"})
+@ObjectClasses({"person", "organizationalPerson", "inetorgperson"})
public class TestPerson
{
/*********************************** Directory mapped fields ************************************/
@@ -106,5 +107,10 @@ public class TestPerson
return "\n" + xStream.toXML(this);
}
+ public boolean equals(Object o)
+ {
+ return EqualsBuilder.reflectionEquals(this, o);
+ }
+
}
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverter.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverter.java
index 4d9228e7..ce199f77 100644
--- a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverter.java
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverter.java
@@ -5,28 +5,39 @@
*/
package org.springframework.ldap.odm.attributetypes;
-import java.beans.PropertyEditor;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import javax.naming.ldap.LdapName;
-
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.ldap.core.DistinguishedName;
+import javax.naming.ldap.LdapName;
+import java.beans.PropertyEditor;
+import java.text.SimpleDateFormat;
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * LdapTypeConverter is responsible for the conversion of LDAP attributes returned in String form
+ * to native java types and vice versa. Mostly it leverages Spring's property editors, however
+ * it registers some custom editors to:
+ *
+ * convert from Generalized Time strings to java.util.Date
+ * convert dn strings to javax.naming.ldap.LdapName or
+ * org.springframework.ldap.core.DistinguishedName.
+ *
+ */
public class LdapTypeConverter extends SimpleTypeConverter
{
+ private static final DateFormat GENERALIZED_TIME = new SimpleDateFormat("yyyyMMddHHmmss.S");
public LdapTypeConverter()
{
super();
- registerCustomEditor(Date.class,
- new CustomDateEditor(new SimpleDateFormat("yyyyMMddHHmmss.S"), true));
+ registerCustomEditor(Date.class, new CustomDateEditor(GENERALIZED_TIME, true));
registerCustomEditor(LdapName.class, new NameEditor(LdapName.class));
registerCustomEditor(DistinguishedName.class, new NameEditor(DistinguishedName.class));
}
+ /** Convert Object to String */
public String getAsText(Object value)
{
if (value instanceof String)
@@ -45,6 +56,7 @@ public class LdapTypeConverter extends SimpleTypeConverter
}
}
+ /** Convert Object array to String array */
public String[] getAllAsText(Object[] values)
{
String[] textValues = new String[values.length];
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/NameEditor.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/NameEditor.java
index ae17ecdb..0a16c734 100644
--- a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/NameEditor.java
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/NameEditor.java
@@ -5,31 +5,40 @@
*/
package org.springframework.ldap.odm.attributetypes;
-import java.beans.PropertyEditorSupport;
-
-import javax.naming.ldap.LdapName;
-
import org.springframework.ldap.core.DistinguishedName;
+import java.beans.PropertyEditorSupport;
+import javax.naming.ldap.LdapName;
+
+/** NameEditor is responsible for converting Strings to the type LdapName or DistinguishedName.
+ * And, conversely LdapNames and DistinguishedNames to the type String.
+ */
public class NameEditor extends PropertyEditorSupport
{
private Class conversionClass;
+ /**
+ * @param conversionClass LdapName.class for String <--> LdapName and
+ * DistinguishedName.class for String <--> DistinguishedName
+ */
public NameEditor(Class conversionClass)
{
this.conversionClass = conversionClass;
if (!conversionClass.equals(DistinguishedName.class) && !conversionClass.equals(LdapName.class))
{
- throw new RuntimeException("NameEditor can only be created for LdapName or DistinguishedName");
+ throw new IllegalArgumentException(
+ "NameEditor can only be created for LdapName or DistinguishedName");
}
}
+ /** Invokes toString() on the LdapName or DistinguishedName */
public String getAsText()
{
Object value = conversionClass.cast(getValue());
return value != null ? value.toString() : "";
}
+ /** Attempts to parse and String and return an LdapName or DistinguishedName */
public void setAsText(String text) throws IllegalArgumentException
{
try
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditor.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditor.java
index 30996977..be972956 100644
--- a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditor.java
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditor.java
@@ -5,21 +5,20 @@
*/
package org.springframework.ldap.odm.attributetypes;
-import java.beans.PropertyEditorSupport;
+import org.springframework.ldap.core.LdapTemplate;
+import org.springframework.ldap.odm.contextmapping.ObjectDirectoryMapper;
+import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
-
-import org.springframework.ldap.core.LdapTemplate;
-import org.springframework.ldap.odm.contextmapping.AnnotatedClassContextMapper;
-import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
+import java.beans.PropertyEditorSupport;
public class ReferencedEntryEditor extends PropertyEditorSupport
-{
+{
private LdapTemplate ldapTemplate;
- private AnnotatedClassContextMapper contextMapper;
+ private ObjectDirectoryMapper contextMapper;
- public ReferencedEntryEditor(LdapTemplate ldapTemplate, AnnotatedClassContextMapper contextMapper)
+ public ReferencedEntryEditor(LdapTemplate ldapTemplate, ObjectDirectoryMapper contextMapper)
{
this.ldapTemplate = ldapTemplate;
this.contextMapper = contextMapper;
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditorFactory.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditorFactory.java
index 50c3408a..b997ee7a 100644
--- a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditorFactory.java
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ReferencedEntryEditorFactory.java
@@ -10,11 +10,12 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.ldap.core.LdapTemplate;
+
import org.springframework.ldap.odm.attributetypes.exception.ReferencedEntryEditorCreationException;
-import org.springframework.ldap.odm.contextmapping.AnnotatedClassContextMapper;
import org.springframework.ldap.odm.contextmapping.ContextMapperFactory;
+import org.springframework.ldap.odm.contextmapping.ObjectDirectoryMapper;
import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
+import org.springframework.ldap.core.LdapTemplate;
public class ReferencedEntryEditorFactory
{
@@ -42,7 +43,7 @@ public class ReferencedEntryEditorFactory
{
LOGGER.debug("Attempting to create a referenced entry editor for class: "
+ clazz.getSimpleName());
- AnnotatedClassContextMapper contextMapper = null;
+ ObjectDirectoryMapper contextMapper = null;
try
{
contextMapper = contextMapperFactory.contextMapperForClass(clazz);
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ValidConversionType.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ValidConversionType.java
index 3b835892..0c268b94 100644
--- a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ValidConversionType.java
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/attributetypes/ValidConversionType.java
@@ -5,11 +5,11 @@
*/
package org.springframework.ldap.odm.attributetypes;
-import java.util.Date;
+import org.springframework.ldap.core.DistinguishedName;
import javax.naming.ldap.LdapName;
+import java.util.Date;
-import org.springframework.ldap.core.DistinguishedName;
/* Should be able to support any of Spring's conversion types. Add a test case if you add one */
public enum ValidConversionType
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/AnnotationObjectDirectoryMapper.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/AnnotationObjectDirectoryMapper.java
new file mode 100644
index 00000000..3d6fbaae
--- /dev/null
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/AnnotationObjectDirectoryMapper.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2006 by Majitek. All Rights Reserved.
+ *
+ * This software is the proprietary information of Majitek. Use is subject to license terms.
+ */
+package org.springframework.ldap.odm.contextmapping;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.ldap.core.DirContextAdapter;
+import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.ldap.odm.annotations.DirAttribute;
+import org.springframework.ldap.odm.annotations.NamingAttribute;
+import org.springframework.ldap.odm.annotations.NamingSuffix;
+import org.springframework.ldap.odm.annotations.ObjectClasses;
+import org.springframework.ldap.odm.attributetypes.LdapTypeConverter;
+import org.springframework.ldap.odm.attributetypes.ValidConversionType;
+import org.springframework.ldap.odm.attributetypes.ReferencedEntryEditorFactory;
+import org.springframework.ldap.odm.attributetypes.exception.ReferencedEntryEditorCreationException;
+import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
+import org.springframework.util.StringUtils;
+
+import javax.naming.Name;
+import javax.naming.directory.Attribute;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AnnotationObjectDirectoryMapper implements ObjectDirectoryMapper
+{
+ private static final Log LOGGER = LogFactory.getLog(AnnotationObjectDirectoryMapper.class);
+
+ private LdapTypeConverter typeConverter;
+ private ReferencedEntryEditorFactory refEditorFactory;
+
+ private Class> clazz;
+ private String namingAttribute;
+ private String[] objectClasses;
+ private String[] namingSuffixElements;
+ private DistinguishedName namingSuffix;
+
+ private ContextMap contextMap;
+ private Map propertyGetters;
+ private Map propertySetters;
+
+
+ public AnnotationObjectDirectoryMapper(Class> clazz, LdapTypeConverter typeConverter,
+ ReferencedEntryEditorFactory refEditorFactory) throws ContextMapperException
+ {
+ this.clazz = clazz;
+ this.typeConverter = typeConverter;
+ this.refEditorFactory = refEditorFactory;
+ checkConfigured();
+ checkRequiredMetaData();
+ buildNamingSuffix();
+ mapAttributesToBeanProperties();
+ cacheGettersAndSetters();
+ registerReferencedEntries();
+ }
+
+ private void checkConfigured() throws ContextMapperException
+ {
+ if (clazz == null)
+ {
+ throw new ContextMapperException("Error creating context mapper."
+ + ". Class> arugment is null");
+ }
+
+ if (this.typeConverter == null)
+ {
+ throw new ContextMapperException("Error creating context mapper for class: "
+ + clazz.getSimpleName()
+ + ". AttributeTypeTranslator arugment is null");
+ }
+
+ if (this.refEditorFactory == null)
+ {
+ throw new ContextMapperException("Error creating context mapper for class: "
+ + clazz.getSimpleName()
+ + ". ReferencedEntryEditorFactory arugment is null");
+ }
+ }
+
+ private void checkRequiredMetaData() throws ContextMapperException
+ {
+ NamingAttribute attnNamingAttr = clazz.getAnnotation(NamingAttribute.class);
+ ObjectClasses attnObjectClasses = clazz.getAnnotation(ObjectClasses.class);
+ NamingSuffix attnNamingSuffix = clazz.getAnnotation(NamingSuffix.class);
+ this.namingAttribute = attnNamingAttr != null ? attnNamingAttr.value() : null;
+ this.objectClasses = attnObjectClasses != null ? attnObjectClasses.value() : null;
+ this.namingSuffixElements = attnNamingSuffix != null ? attnNamingSuffix.value() : null;
+
+ if (this.namingAttribute == null)
+ {
+ throw new ContextMapperException("Error creating context mapper for class: "
+ + clazz.getSimpleName()
+ + ". The @NamingAttribute annotation is required.");
+ }
+
+ if (this.objectClasses == null)
+ {
+ throw new ContextMapperException("Error creating context mapper for class: "
+ + clazz.getSimpleName()
+ + ". The @ObjectClasses annotation is required.");
+ }
+
+ if (namingSuffixElements == null || namingSuffixElements.length == 0)
+ {
+ throw new ContextMapperException("Error creating context mapper for class: "
+ + clazz.getSimpleName()
+ + ". The @NamingSuffix annotation is required.");
+ }
+
+ if (namingSuffixElements[0].contains(","))
+ {
+ throw new ContextMapperException("Error creating context mapper for class: "
+ + clazz.getSimpleName()
+ + ". Naming path nodes must be defined as separate elements, "
+ + "for example: @NamingSuffix({\"ou=people\", \"dc=example\", \"dc=com\"}), and not: "
+ + "@NamingSuffix({\"ou=people,dc=example,dc=com\"})");
+ }
+ }
+
+ private void buildNamingSuffix() throws ContextMapperException
+ {
+ namingSuffix = new DistinguishedName();
+ for (int i = namingSuffixElements.length - 1; i >= 0; i--)
+ {
+ String[] nameValue = namingSuffixElements[i].split("=");
+ if (nameValue.length != 2)
+ {
+ throw new ContextMapperException("Error creating context mapper for class: " + clazz.getSimpleName()
+ + ". Syntax error in naming suffix element: " + namingSuffixElements[i]);
+ }
+ namingSuffix.add(nameValue[0].trim(), nameValue[1].trim());
+ }
+ }
+
+ private void mapAttributesToBeanProperties()
+ {
+ contextMap = new ContextMap();
+ for (Field field : clazz.getDeclaredFields())
+ {
+ DirAttribute dirAttribute = field.getAnnotation(DirAttribute.class);
+ if (dirAttribute != null)
+ {
+ String beanPropertyName = StringUtils.capitalize(field.getName());
+ String attributeName = dirAttribute.value().equals("") ? field.getName() : dirAttribute.value();
+ contextMap.map(beanPropertyName, attributeName);
+ }
+ }
+ }
+
+ private void cacheGettersAndSetters() throws ContextMapperException
+ {
+ propertyGetters = new HashMap();
+ propertySetters = new HashMap();
+
+ for (String beanPropertyName : contextMap.beanPropertyNames())
+ {
+ try
+ {
+ Method getter = clazz.getMethod("get" + beanPropertyName);
+ propertyGetters.put(beanPropertyName, getter);
+ Method setter = clazz.getMethod("set" + beanPropertyName, getter.getReturnType());
+ propertySetters.put(beanPropertyName, setter);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new ContextMapperException("Error creating context mapper for class: "
+ + clazz.getSimpleName()
+ + ". " + clazz.getSimpleName() + " is missing a getter/setter for property: "
+ + beanPropertyName, e);
+ }
+ }
+ }
+
+ private void registerReferencedEntries() throws ContextMapperException
+ {
+ for (Method getter : propertyGetters.values())
+ {
+ Class> returnType = getter.getReturnType();
+ if (!ValidConversionType.isValidConversionType(returnType))
+ {
+ try
+ {
+ Class componentType = returnType.isArray() ? returnType.getComponentType() : returnType;
+ typeConverter.registerCustomEditor(componentType,
+ refEditorFactory.referencedEntryEditorForClass(componentType));
+ }
+ catch (ReferencedEntryEditorCreationException e)
+ {
+ throw new ContextMapperException(clazz.getSimpleName() + "."
+ + getter.getName()
+ + "() has invalid return type. Return type must be a context mapped "
+ + "directory object, or one of the following: "
+ + ValidConversionType.listTypes(), e);
+ }
+ }
+ }
+ }
+
+ public Object mapFromContext(Object ctx)
+ {
+ DirContextAdapter ctxAdapter = (DirContextAdapter) ctx;
+ Object instance;
+ try
+ {
+ instance = clazz.newInstance();
+ for (String beanPropertyName : contextMap.beanPropertyNames())
+ {
+ Class attributeType = propertyGetters.get(beanPropertyName).getReturnType();
+ Attribute attribute =
+ ctxAdapter.getAttributes().get(contextMap.attributeNameFor(beanPropertyName));
+ if (attribute != null)
+ {
+ try
+ {
+ Object beanPropertyValue = typeConverter.convertIfNecessary(
+ new AttributeDecorator(attribute).getAllAsObject(), attributeType);
+ propertySetters.get(beanPropertyName).invoke(instance, beanPropertyValue);
+ }
+ catch (TypeMismatchException e)
+ {
+ throw new ContextMapperException("Cannot set bean property '" + beanPropertyName
+ + "' in class " + clazz.getSimpleName() + ", " + e.getMessage(), e);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ return instance;
+ }
+
+ // TODO: Simplify this method: When bug with DirContextAdapter.setAttribute() (LDAP-15) is fixed,
+ // TODO: register a type converter to convert to type Attribute
+ public void mapToContext(Object beanInstance, Object ctx)
+ {
+ DirContextAdapter ctxAdapter = (DirContextAdapter) ctx;
+ ctxAdapter.setAttributeValues("objectclass", objectClasses);
+ for (String attributeName : contextMap.attributeNames())
+ {
+ try
+ {
+ Object beanPropertyValue = propertyGetters.get(
+ contextMap.beanPropertyNameFor(attributeName)).invoke(beanInstance);
+ LOGGER.trace("mapToContext() attribute:" + attributeName + ", value: " + beanPropertyValue);
+
+ if (beanPropertyValue != null)
+ {
+ if (beanPropertyValue instanceof byte[])
+ {
+ ctxAdapter.setAttributeValue(attributeName, beanPropertyValue);
+ }
+ else if (beanPropertyValue instanceof Object[])
+ {
+ ctxAdapter.setAttributeValues(attributeName,
+ typeConverter.getAllAsText((Object[]) beanPropertyValue));
+ }
+ else
+ {
+ ctxAdapter.setAttributeValue(attributeName,
+ typeConverter.getAsText(beanPropertyValue));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+ }
+
+ public Name buildDn(Object beanInstance) throws ContextMapperException
+ {
+ if (beanInstance == null)
+ {
+ throw new ContextMapperException("Can't build Dn from beanInstance, beanInstance is null");
+ }
+ return buildDn(namingAttributeValue(beanInstance));
+ }
+
+ public Name buildDn(String namingAttributeValue) throws ContextMapperException
+ {
+ if (namingAttributeValue == null)
+ {
+ throw new ContextMapperException("Can't build Dn from namingAttributeValue, namingAttributeValue is null");
+ }
+ DistinguishedName dn = (DistinguishedName) namingSuffix.clone();
+ dn.add(namingAttribute, namingAttributeValue);
+ LOGGER.trace("buildDn(): " + dn);
+ return dn;
+ }
+
+ public String namingAttributeValue(Object beanInstance)
+ {
+ Method method = propertyGetters.get(contextMap.beanPropertyNameFor(namingAttribute));
+ try
+ {
+ return (String) method.invoke(clazz.cast(beanInstance));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public ContextMap getContextMap()
+ {
+ return contextMap;
+ }
+
+ public String[] getObjectClasses()
+ {
+ return objectClasses;
+ }
+
+ public String getNamingAttribute()
+ {
+ return namingAttribute;
+ }
+
+ public DistinguishedName getNamingSuffix()
+ {
+ return namingSuffix;
+ }
+}
\ No newline at end of file
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/ContextMapperFactory.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/ContextMapperFactory.java
index bf234a62..f4893d82 100644
--- a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/ContextMapperFactory.java
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/ContextMapperFactory.java
@@ -17,20 +17,20 @@ import java.util.Map;
public class ContextMapperFactory
{
private static final Log LOGGER = LogFactory.getLog(ContextMapperFactory.class);
- private Map contextMappers;
+ private Map contextMappers;
private LdapTypeConverter typeConverter;
private ReferencedEntryEditorFactory referencedEntryEditorFactory;
public ContextMapperFactory(LdapTypeConverter typeConverter,
ReferencedEntryEditorFactory referencedEntryEditorFactory)
{
- contextMappers = new HashMap();
+ contextMappers = new HashMap();
this.typeConverter = typeConverter;
this.referencedEntryEditorFactory = referencedEntryEditorFactory;
this.referencedEntryEditorFactory.setContextMapperFactory(this);
}
- public AnnotatedClassContextMapper contextMapperForClass(Class clazz)
+ public ObjectDirectoryMapper contextMapperForClass(Class clazz)
throws ContextMapperException
{
if (contextMappers.containsKey(clazz))
@@ -41,8 +41,8 @@ public class ContextMapperFactory
else
{
LOGGER.debug("Attempting to create a context mapper for class: " + clazz.getSimpleName());
- AnnotatedClassContextMapper contextMapper =
- new AnnotatedClassContextMapper(clazz, typeConverter, referencedEntryEditorFactory);
+ AnnotationObjectDirectoryMapper contextMapper =
+ new AnnotationObjectDirectoryMapper(clazz, typeConverter, referencedEntryEditorFactory);
contextMappers.put(clazz, contextMapper);
return contextMapper;
}
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/ObjectDirectoryMapper.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/ObjectDirectoryMapper.java
new file mode 100644
index 00000000..f4ddd451
--- /dev/null
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/contextmapping/ObjectDirectoryMapper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005 by Majitek. All Rights Reserved.
+ *
+ * This software is the proprietary information of Majitek. Use is subject to license terms.
+ */
+
+package org.springframework.ldap.odm.contextmapping;
+
+import org.springframework.ldap.core.ContextMapper;
+import org.springframework.ldap.core.ContextAssembler;
+import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
+
+import javax.naming.Name;
+
+public interface ObjectDirectoryMapper extends ContextMapper, ContextAssembler
+{
+ Object mapFromContext(Object ctx);
+
+ void mapToContext(Object beanInstance, Object ctx);
+
+ Name buildDn(Object beanInstance) throws ContextMapperException;
+
+ Name buildDn(String namingAttributeValue) throws ContextMapperException;
+
+ String namingAttributeValue(Object beanInstance);
+
+ ContextMap getContextMap();
+
+ String[] getObjectClasses();
+
+ String getNamingAttribute();
+
+ DistinguishedName getNamingSuffix();
+}
diff --git a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/dao/LdapDaoImpl.java b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/dao/LdapDaoImpl.java
index fe478807..ed8f4744 100644
--- a/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/dao/LdapDaoImpl.java
+++ b/spring-ldap-odm/src/main/java/org/springframework/ldap/odm/dao/LdapDaoImpl.java
@@ -5,21 +5,19 @@
*/
package org.springframework.ldap.odm.dao;
-import java.util.List;
-
-import javax.naming.Name;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.DirContextAdapter;
-import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
-import org.springframework.ldap.odm.contextmapping.AnnotatedClassContextMapper;
+import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.odm.contextmapping.ContextMapperFactory;
+import org.springframework.ldap.odm.contextmapping.ObjectDirectoryMapper;
import org.springframework.ldap.odm.contextmapping.exception.ContextMapperException;
import org.springframework.ldap.odm.dao.exception.DaoException;
import org.springframework.ldap.odm.dao.exception.DataIntegrityViolationException;
-import org.springframework.ldap.odm.dao.exception.EntryNotFoundException;
+
+import javax.naming.Name;
+import java.util.List;
public class LdapDaoImpl implements LdapDao
{
@@ -38,7 +36,7 @@ public class LdapDaoImpl implements LdapDao
DirContextAdapter context = new DirContextAdapter();
try
{
- AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
+ ObjectDirectoryMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
ctxMapper.mapToContext(dirObject, context);
ldapTemplate.bind(ctxMapper.buildDn(dirObject), context, null);
}
@@ -56,18 +54,12 @@ public class LdapDaoImpl implements LdapDao
{
try
{
- AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
+ ObjectDirectoryMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
Name dn = ctxMapper.buildDn(dirObject);
DirContextAdapter contextAdapter = (DirContextAdapter) ldapTemplate.lookup(dn);
ctxMapper.mapToContext(dirObject, contextAdapter);
ldapTemplate.modifyAttributes(dn, contextAdapter.getModificationItems());
}
- catch (org.springframework.ldap.NameNotFoundException e)
- {
- //We need to rethrow a serializable exception if we are going to invoke
- //this as a remote service.
- throw new EntryNotFoundException(e.getMessage());
- }
catch (ContextMapperException e)
{
throw new DaoException(e.getMessage(), e);
@@ -78,7 +70,7 @@ public class LdapDaoImpl implements LdapDao
{
try
{
- AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
+ ObjectDirectoryMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
if (findByDn(ctxMapper.buildDn(dirObject), dirObject.getClass()) == null)
{
create(dirObject);
@@ -99,7 +91,7 @@ public class LdapDaoImpl implements LdapDao
{
try
{
- AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
+ ObjectDirectoryMapper ctxMapper = ctxMapperFactory.contextMapperForClass(dirObject.getClass());
ldapTemplate.unbind(ctxMapper.buildDn(dirObject));
}
catch (ContextMapperException e)
@@ -113,7 +105,7 @@ public class LdapDaoImpl implements LdapDao
{
try
{
- AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(returnType);
+ ObjectDirectoryMapper ctxMapper = ctxMapperFactory.contextMapperForClass(returnType);
Name dn = ctxMapper.buildDn(namingAttributeValue);
return findByDn(dn, returnType);
}
@@ -127,7 +119,7 @@ public class LdapDaoImpl implements LdapDao
{
try
{
- AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(returnType);
+ ObjectDirectoryMapper ctxMapper = ctxMapperFactory.contextMapperForClass(returnType);
return ldapTemplate.lookup(dn, ctxMapper);
}
catch (ContextMapperException e)
@@ -146,7 +138,7 @@ public class LdapDaoImpl implements LdapDao
try
{
LOGGER.debug("Filtering on property: " + beanPropertyName + ", for value: " + value);
- AnnotatedClassContextMapper ctxMapper =
+ ObjectDirectoryMapper ctxMapper =
ctxMapperFactory.contextMapperForClass(returnType);
try
@@ -173,7 +165,7 @@ public class LdapDaoImpl implements LdapDao
{
try
{
- AnnotatedClassContextMapper ctxMapper = ctxMapperFactory.contextMapperForClass(ofType);
+ ObjectDirectoryMapper ctxMapper = ctxMapperFactory.contextMapperForClass(ofType);
StringBuilder filterBuilder = new StringBuilder();
filterBuilder.append("(&");
for (String objectClass : ctxMapper.getObjectClasses())
diff --git a/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverterTest.java b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverterTest.java
index 88966e2e..0979e4a0 100644
--- a/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverterTest.java
+++ b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/LdapTypeConverterTest.java
@@ -5,260 +5,365 @@
*/
package org.springframework.ldap.odm.attributetypes;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-
import junit.framework.TestCase;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.ldap.core.DistinguishedName;
import org.testng.Assert;
-public class LdapTypeConverterTest extends TestCase {
- private static final Log LOGGER = LogFactory
- .getLog(LdapTypeConverterTest.class);
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
- private LdapTypeConverter typeConverter;
+//TODO: There's probably a lot of redundant tests in here
+public class LdapTypeConverterTest extends TestCase
+{
+ private static final Log LOGGER = LogFactory.getLog(LdapTypeConverterTest.class);
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- typeConverter = new LdapTypeConverter();
- }
+ private LdapTypeConverter typeConverter;
- public void testConvertToByteArray() {
- byte[] objectToTranslate = "fred".getBytes();
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ typeConverter = new LdapTypeConverter();
+ }
- try {
- byte[] translated = (byte[]) typeConverter.convertIfNecessary(
- objectToTranslate, byte[].class);
- Assert.assertTrue(Arrays.equals(objectToTranslate, translated),
- "byte[] attributes should pass through unchanged.");
- } catch (TypeMismatchException e) {
- Assert
- .fail(
- "Unexpected exception: byte[] attributes should pass through unchanged.",
- e);
- }
- }
+ public void testConvertToByteArray()
+ {
+ byte[] objectToTranslate = "fred".getBytes();
- public void testConvertToBoolean() {
- String objectToTranslate = "true";
- try {
- Object translated = typeConverter.convertIfNecessary(
- objectToTranslate, Boolean.class);
- Assert
- .assertEquals(true, translated,
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ try
+ {
+ byte[] translated = (byte[]) typeConverter.convertIfNecessary(
+ objectToTranslate, byte[].class);
+ Assert.assertTrue(Arrays.equals(objectToTranslate, translated),
+ "byte[] attributes should pass through unchanged.");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception: byte[] attributes should pass through unchanged.",
+ e);
+ }
+ }
- public void testConvertFromBoolean() {
- boolean objectToTranslate = false;
- try {
- Object translated = typeConverter.getAsText(objectToTranslate);
- Assert.assertEquals(translated, "false",
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ public void testConvertToBoolean()
+ {
+ String objectToTranslate = "true";
+ try
+ {
+ Object translated = typeConverter.convertIfNecessary(
+ objectToTranslate, Boolean.class);
+ Assert
+ .assertEquals(true, translated,
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- public void testConvertToString() {
- String objectToTranslate = "onetwothree";
- try {
- Object translated = typeConverter.convertIfNecessary(
- objectToTranslate, String.class);
- Assert.assertEquals("onetwothree", translated,
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ public void testConvertFromBoolean()
+ {
+ boolean objectToTranslate = false;
+ try
+ {
+ Object translated = typeConverter.getAsText(objectToTranslate);
+ Assert.assertEquals(translated, "false",
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- public void testConvertToStringArray() {
- String object1 = "onetwothree";
- String object2 = "fourfivesix";
- String object3 = "seveneightnine";
- Object objectToTranslate = new String[] { object1, object2, object3 };
+ public void testConvertToString()
+ {
+ String objectToTranslate = "onetwothree";
+ try
+ {
+ Object translated = typeConverter.convertIfNecessary(
+ objectToTranslate, String.class);
+ Assert.assertEquals("onetwothree", translated,
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- try {
- Object[] translated = (Object[]) typeConverter.convertIfNecessary(
- objectToTranslate, String[].class);
- Assert.assertEquals("fourfivesix", translated[1],
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ public void testConvertToStringArray()
+ {
+ String object1 = "onetwothree";
+ String object2 = "fourfivesix";
+ String object3 = "seveneightnine";
+ Object objectToTranslate = new String[]{object1, object2, object3};
- public void testConvertToGeneralizedTime() throws ParseException {
- String object1 = "20061005093637.44";
- DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss.S");
- Date expected = df.parse("20061005093637.44");
+ try
+ {
+ Object[] translated = (Object[]) typeConverter.convertIfNecessary(
+ objectToTranslate, String[].class);
+ Assert.assertEquals("fourfivesix", translated[1],
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- try {
- Object translated = typeConverter.convertIfNecessary(object1,
- Date.class);
- Assert.assertEquals(translated, expected,
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ public void testConvertToGeneralizedTime() throws ParseException
+ {
+ String object1 = "20061005093637.44";
+ DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss.S");
+ Date expected = df.parse("20061005093637.44");
- public void testConvertToGeneralizedTimeArray() throws ParseException {
- String object1 = "20071105093655.44";
- String object2 = "20061005093637.44";
- Object objectToTranslate = new String[] { object1, object2 };
+ try
+ {
+ Object translated = typeConverter.convertIfNecessary(object1,
+ Date.class);
+ Assert.assertEquals(translated, expected,
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss.S");
- Date expected = df.parse("20061005093637.44");
+ public void testConvertFromDate()
+ {
+ Date source = new Date(1184283822285L); //Friday July 13, 2007 9:43:42 AM
+ Assert.assertEquals(typeConverter.getAsText(source), "20070713094342.285");
+ }
- try {
- Object[] translated = (Object[]) typeConverter.convertIfNecessary(
- objectToTranslate, Date[].class);
- Assert.assertEquals(translated[1], expected,
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation");
- }
- }
+ public void testConvertToGeneralizedTimeArray() throws ParseException
+ {
+ String object1 = "20071105093655.44";
+ String object2 = "20061005093637.44";
+ Object objectToTranslate = new String[]{object1, object2};
- public void testConvertToLdapName() {
- String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
- try {
- Object translated = typeConverter.convertIfNecessary(object1,
- LdapName.class);
- Assert.assertEquals(translated, new LdapName(object1),
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- } catch (InvalidNameException e) {
- Assert.fail("Problem with test: Ldap name can't be parsed.", e);
- }
- }
+ DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss.S");
+ Date expected = df.parse("20061005093637.44");
- public void testConvertToLdapNameArray() {
- String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
- String object2 = "uid=fred, ou = people, dc = myretsu,dc=com";
- Object objectToTranslate = new String[] { object1, object2 };
+ try
+ {
+ Object[] translated = (Object[]) typeConverter.convertIfNecessary(
+ objectToTranslate, Date[].class);
+ Assert.assertEquals(translated[1], expected,
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation");
+ }
+ }
- try {
- Object[] translated = (Object[]) typeConverter.convertIfNecessary(
- objectToTranslate, LdapName[].class);
- Assert.assertEquals(new LdapName(object2), translated[1],
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- } catch (InvalidNameException e) {
- Assert.fail("Problem with test: Ldap name can't be parsed.", e);
- }
- }
+ public void testConvertFromDateArray()
+ {
+ Date date1 = new Date(1184283822285L); //Friday July 13, 2007 9:43:42 AM
+ Date date2 = new Date(0); //epoch
- public void testConvertToDistinguishedName() {
- String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
- try {
- Object translated = typeConverter.convertIfNecessary(object1,
- DistinguishedName.class);
- Assert.assertEquals(new DistinguishedName(object1), translated,
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ Date[] dates = new Date[]{date1, date2};
+ String[] converted = typeConverter.getAllAsText(dates);
+ Assert.assertEquals(converted[0], "20070713094342.285");
+ Assert.assertEquals(converted[1], "19700101100000.0");
+ }
- public void testConvertToDistinguishedNameArray() {
- String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
- String object2 = "uid=fred, ou = people, dc = myretsu,dc=com";
- Object objectToTranslate = new String[] { object1, object2 };
+ public void testConvertToLdapName()
+ {
+ String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
+ try
+ {
+ Object translated = typeConverter.convertIfNecessary(object1,
+ LdapName.class);
+ Assert.assertEquals(translated, new LdapName(object1),
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ catch (InvalidNameException e)
+ {
+ Assert.fail("Problem with test: Ldap name can't be parsed.", e);
+ }
+ }
- try {
- Object[] translated = (Object[]) typeConverter.convertIfNecessary(
- objectToTranslate, DistinguishedName[].class);
- Assert.assertEquals(new DistinguishedName(object2), translated[1],
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ public void testConvertToLdapNameArray()
+ {
+ String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
+ String object2 = "uid=fred, ou = people, dc = myretsu,dc=com";
+ Object objectToTranslate = new String[]{object1, object2};
- public void testConvertToLong() {
- String object1 = "9887342";
- try {
- Object translated = typeConverter.convertIfNecessary(object1,
- Long.class);
- Assert.assertEquals(9887342L, translated,
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ try
+ {
+ Object[] translated = (Object[]) typeConverter.convertIfNecessary(
+ objectToTranslate, LdapName[].class);
+ Assert.assertEquals(new LdapName(object2), translated[1],
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ catch (InvalidNameException e)
+ {
+ Assert.fail("Problem with test: Ldap name can't be parsed.", e);
+ }
+ }
- public void testConvertToLongArray() {
- String object1 = "878787";
- String object2 = "23948787";
- Object objectToTranslate = new String[] { object1, object2 };
+ public void testConvertToDistinguishedName()
+ {
+ String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
+ try
+ {
+ Object translated = typeConverter.convertIfNecessary(object1,
+ DistinguishedName.class);
+ Assert.assertEquals(new DistinguishedName(object1), translated,
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- try {
- Object[] translated = (Object[]) typeConverter.convertIfNecessary(
- objectToTranslate, Long[].class);
- Assert.assertEquals(23948787L, translated[1],
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ public void testConvertToDistinguishedNameArray()
+ {
+ String object1 = "uid=amAdmin, ou = people, dc = myretsu,dc=com";
+ String object2 = "uid=fred, ou = people, dc = myretsu,dc=com";
+ Object objectToTranslate = new String[]{object1, object2};
- public void testConvertToInteger() {
- String object1 = "9887342";
+ try
+ {
+ Object[] translated = (Object[]) typeConverter.convertIfNecessary(
+ objectToTranslate, DistinguishedName[].class);
+ Assert.assertEquals(new DistinguishedName(object2), translated[1],
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- try {
- Object translated = typeConverter.convertIfNecessary(object1,
- Integer.class);
- Assert.assertEquals(9887342, translated,
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ public void testConvertToLong()
+ {
+ String object1 = "9887342";
+ try
+ {
+ Object translated = typeConverter.convertIfNecessary(object1,
+ Long.class);
+ Assert.assertEquals(9887342L, translated,
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- public void testConvertToIntegerArray() {
- String object1 = "878787";
- String object2 = "23948787";
- Object objectToTranslate = new String[] { object1, object2 };
+ public void testConvertToLongArray()
+ {
+ String object1 = "878787";
+ String object2 = "23948787";
+ Object objectToTranslate = new String[]{object1, object2};
- try {
- Object[] translated = (Object[]) typeConverter.convertIfNecessary(
- objectToTranslate, Integer[].class);
- Assert.assertEquals(23948787, translated[1],
- "Unexpected translated value");
- } catch (TypeMismatchException e) {
- Assert.fail("Unexpected exception during translation", e);
- }
- }
+ try
+ {
+ Object[] translated = (Object[]) typeConverter.convertIfNecessary(
+ objectToTranslate, Long[].class);
+ Assert.assertEquals(23948787L, translated[1],
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
- public void testThrowsTypeMismatchExceptionWhenTypeTranslationFails() {
- String object1 = "asdlkjkalkjl";
+ public void testConvertToInteger()
+ {
+ String object1 = "9887342";
- Object[] translated;
- try {
- translated = (Object[]) typeConverter.convertIfNecessary(object1,
- LdapName.class);
- Assert.fail("Should've thrown exception");
- } catch (TypeMismatchException e) {
- // Pass
- }
- }
+ try
+ {
+ Object translated = typeConverter.convertIfNecessary(object1,
+ Integer.class);
+ Assert.assertEquals(9887342, translated,
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
+
+ public void testConvertToIntegerArray()
+ {
+ String object1 = "878787";
+ String object2 = "23948787";
+ Object objectToTranslate = new String[]{object1, object2};
+
+ try
+ {
+ Object[] translated = (Object[]) typeConverter.convertIfNecessary(
+ objectToTranslate, Integer[].class);
+ Assert.assertEquals(23948787, translated[1],
+ "Unexpected translated value");
+ }
+ catch (TypeMismatchException e)
+ {
+ Assert.fail("Unexpected exception during translation", e);
+ }
+ }
+
+ public void testThrowsTypeMismatchExceptionWhenTypeTranslationFails()
+ {
+ String object1 = "asdlkjkalkjl";
+
+ Object[] translated;
+ try
+ {
+ translated = (Object[]) typeConverter.convertIfNecessary(object1,
+ LdapName.class);
+ Assert.fail("Should've thrown exception");
+ }
+ catch (TypeMismatchException e)
+ {
+ // Pass
+ }
+ }
+
+ public void testGetAsTextReturnsStringsUnchanged()
+ {
+ String string = "onetwothree123";
+ Assert.assertEquals(typeConverter.getAsText(string), "onetwothree123");
+ }
+
+ public void testGetAsTextReturnsNullWhenNoPropertyEditorRegistered()
+ {
+ Assert.assertNull(typeConverter.getAsText(new Foo("fooString")));
+ }
+
+ //Something there'll definitely be no property editor registered for
+ private class Foo
+ {
+ private String fooString;
+
+ public Foo(String fooString)
+ {
+ this.fooString = fooString;
+ }
+ }
}
diff --git a/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/NameEditorTest.java b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/NameEditorTest.java
new file mode 100644
index 00000000..072f5cf3
--- /dev/null
+++ b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/NameEditorTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005 by Majitek. All Rights Reserved.
+ *
+ * This software is the proprietary information of Majitek. Use is subject to license terms.
+ */
+
+package org.springframework.ldap.odm.attributetypes;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.springframework.ldap.core.DistinguishedName;
+
+public class NameEditorTest extends TestCase
+{
+
+ public void testThrowsExceptionWhenConstructorArgumentNotAName()
+ {
+ try
+ {
+ NameEditor nameEditor = new NameEditor(String.class);
+ fail("Should've thrown exception.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ Assert.assertEquals(e.getMessage(),
+ "NameEditor can only be created for LdapName or DistinguishedName");
+ }
+ }
+
+ public void testGetAsText()
+ {
+ NameEditor editor = new NameEditor(DistinguishedName.class);
+ DistinguishedName name = new DistinguishedName("uid=zzz, ou=people");
+ editor.setValue(name);
+ Assert.assertEquals(editor.getAsText(), "uid=zzz, ou=people");
+
+ editor.setValue(null);
+ Assert.assertEquals(editor.getAsText(), "");
+ }
+
+ public void testSetAsText()
+ {
+ NameEditor editor = new NameEditor(DistinguishedName.class);
+ editor.setAsText("uid=zzz, ou=people");
+ DistinguishedName expected = new DistinguishedName("uid=zzz, ou=people");
+ Assert.assertEquals(editor.getValue(), expected);
+
+
+ }
+
+
+}
diff --git a/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/ReferencedEditorFactoryTest.java b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/ReferencedEditorFactoryTest.java
new file mode 100644
index 00000000..486200c5
--- /dev/null
+++ b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/ReferencedEditorFactoryTest.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2005 by Majitek. All Rights Reserved.
+ *
+ * This software is the proprietary information of Majitek. Use is subject to license terms.
+ */
+
+package org.springframework.ldap.odm.attributetypes;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+
+public class ReferencedEditorFactoryTest extends TestCase
+{
+
+ public void testReferencedEditorForClass()
+ {
+ Assert.assertTrue(true);
+ }
+
+}
diff --git a/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/ValidConversionTypeTest.java b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/ValidConversionTypeTest.java
new file mode 100644
index 00000000..35a3c2c2
--- /dev/null
+++ b/spring-ldap-odm/src/test/java/org/springframework/ldap/odm/attributetypes/ValidConversionTypeTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005 by Majitek. All Rights Reserved.
+ *
+ * This software is the proprietary information of Majitek. Use is subject to license terms.
+ */
+
+package org.springframework.ldap.odm.attributetypes;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.testng.Assert;
+import org.springframework.ldap.core.DistinguishedName;
+
+import javax.naming.ldap.LdapName;
+import java.util.List;
+import java.util.Date;
+
+public class ValidConversionTypeTest extends TestCase
+{
+ private static final Log LOGGER = LogFactory.getLog(ValidConversionTypeTest.class);
+
+ public void testListTypes()
+ {
+ LOGGER.debug(ValidConversionType.listTypes());
+ }
+
+ public void testIsValidConversionType()
+ {
+ Assert.assertFalse(ValidConversionType.isValidConversionType(List.class));
+
+ Assert.assertTrue(ValidConversionType.isValidConversionType(byte[].class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(Boolean.class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(String.class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(String[].class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(Date.class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(Date[].class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(LdapName.class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(LdapName[].class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(DistinguishedName.class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(DistinguishedName[].class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(Integer.class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(Integer[].class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(Long.class));
+ Assert.assertTrue(ValidConversionType.isValidConversionType(Long[].class));
+ }
+
+
+}